- Add ajax_search_wc_customers() – searches user_login, user_email, display_name AND first_name/last_name meta so any query returns hits - Add ajax_unlink_customer() to remove an existing Odoo link - Replace placeholder Customers tab with two-panel UI: Step 1 search WC customers → Step 2 search Odoo partners independently (WC email and Odoo email do not need to match) - Results table shows current link status; inline Link/Unlink actions update the row in-place without page reload - Admin JS fully wired: both search inputs respond to Enter key and button - Add two-panel layout CSS and results table styles Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
331 lines
15 KiB
JavaScript
331 lines
15 KiB
JavaScript
/* WooDoo Admin JS */
|
||
jQuery( function ( $ ) {
|
||
|
||
const cfg = window.WooDooAdmin || {};
|
||
const i18n = cfg.i18n || {};
|
||
const ajaxUrl = cfg.ajax_url;
|
||
const nonce = cfg.nonce;
|
||
|
||
// ── Tab navigation ──────────────────────────────────────────────────
|
||
$( '.woodoo-settings .nav-tab' ).on( 'click', function ( e ) {
|
||
e.preventDefault();
|
||
const target = $( this ).attr( 'href' );
|
||
$( '.woodoo-settings .nav-tab' ).removeClass( 'nav-tab-active' );
|
||
$( this ).addClass( 'nav-tab-active' );
|
||
$( '.woodoo-tab' ).hide();
|
||
$( target ).show();
|
||
} );
|
||
|
||
// ── Test Connection ──────────────────────────────────────────────────
|
||
$( '#woodoo-test-connection' ).on( 'click', function () {
|
||
const $btn = $( this );
|
||
const $result = $( '#woodoo-test-result' );
|
||
|
||
$btn.prop( 'disabled', true ).text( i18n.testing );
|
||
$result.html( '' );
|
||
|
||
ajax( 'woodoo_test_connection', {} )
|
||
.done( function ( res ) {
|
||
if ( res.success ) {
|
||
const d = res.data;
|
||
const cls = d.success ? 'green' : 'red';
|
||
$result.html( badge( cls, d.message ) );
|
||
} else {
|
||
$result.html( badge( 'red', res.data || i18n.error ) );
|
||
}
|
||
} )
|
||
.fail( function () { $result.html( badge( 'red', i18n.error ) ); } )
|
||
.always( function () {
|
||
$btn.prop( 'disabled', false ).text( 'Test Connection' );
|
||
} );
|
||
} );
|
||
|
||
// ══════════════════════════════════════════════════════════════════════
|
||
// CUSTOMER LINKING TAB
|
||
// ══════════════════════════════════════════════════════════════════════
|
||
|
||
let selectedWcUser = null; // { id, display_name, email }
|
||
|
||
// ── Step 1: search WooCommerce customers ─────────────────────────────
|
||
function searchWcCustomers() {
|
||
const q = $( '#woo-customer-search' ).val().trim();
|
||
if ( q.length < 2 ) return;
|
||
|
||
const $results = $( '#woo-customer-results' );
|
||
$results.html( '<em>' + esc( i18n.searching ) + '</em>' );
|
||
$( '#woodoo-odoo-col' ).hide();
|
||
selectedWcUser = null;
|
||
|
||
ajax( 'woodoo_search_wc_customers', { query: q } )
|
||
.done( function ( res ) {
|
||
if ( ! res.success || ! res.data.length ) {
|
||
$results.html( '<p class="woodoo-no-results">' + esc( i18n.no_wc_customers ) + '</p>' );
|
||
return;
|
||
}
|
||
|
||
let html = '<table class="woodoo-link-table widefat"><thead><tr>' +
|
||
'<th>Name</th><th>WC Email</th><th>Odoo Partner</th><th></th>' +
|
||
'</tr></thead><tbody>';
|
||
|
||
res.data.forEach( function ( u ) {
|
||
const linked = u.partner_id
|
||
? '<span class="woodoo-badge woodoo-badge--green">' + esc( u.partner_name || '#' + u.partner_id ) + '</span>'
|
||
: '<span class="woodoo-badge woodoo-badge--grey">' + esc( i18n.not_linked ) + '</span>';
|
||
|
||
html +=
|
||
'<tr data-user-id="' + u.id + '">' +
|
||
'<td><a href="' + u.edit_url + '" target="_blank">' + esc( u.display_name ) + '</a></td>' +
|
||
'<td>' + esc( u.email ) + '</td>' +
|
||
'<td class="woodoo-partner-status">' + linked + '</td>' +
|
||
'<td class="woodoo-link-actions">' +
|
||
'<button type="button" class="button button-small woodoo-select-wc-user"' +
|
||
' data-id="' + u.id + '"' +
|
||
' data-name="' + escAttr( u.display_name ) + '"' +
|
||
' data-email="' + escAttr( u.email ) + '">' +
|
||
'Link Odoo Partner</button>';
|
||
|
||
if ( u.partner_id ) {
|
||
html += ' <button type="button" class="button button-small woodoo-unlink-user"' +
|
||
' data-id="' + u.id + '" style="color:#dc2626;">Unlink</button>';
|
||
}
|
||
|
||
html += '</td></tr>';
|
||
} );
|
||
|
||
html += '</tbody></table>';
|
||
$results.html( html );
|
||
} )
|
||
.fail( function () { $results.html( '<p>' + esc( i18n.error ) + '</p>' ); } );
|
||
}
|
||
|
||
$( '#woo-customer-search-btn' ).on( 'click', searchWcCustomers );
|
||
$( '#woo-customer-search' ).on( 'keypress', function ( e ) {
|
||
if ( e.which === 13 ) { e.preventDefault(); searchWcCustomers(); }
|
||
} );
|
||
|
||
// ── Select a WC customer → open Odoo partner search panel ───────────
|
||
$( document ).on( 'click', '.woodoo-select-wc-user', function () {
|
||
const $btn = $( this );
|
||
selectedWcUser = {
|
||
id : $btn.data( 'id' ),
|
||
name : $btn.data( 'name' ),
|
||
email : $btn.data( 'email' ),
|
||
};
|
||
|
||
// Highlight selected row
|
||
$( '#woo-customer-results tr' ).css( 'background', '' );
|
||
$btn.closest( 'tr' ).css( 'background', '#eff6ff' );
|
||
|
||
// Show step 2 panel
|
||
$( '#woodoo-linking-for' ).html(
|
||
'Linking: <strong>' + esc( selectedWcUser.name ) +
|
||
'</strong> (' + esc( selectedWcUser.email ) + ')'
|
||
);
|
||
$( '#woodoo-odoo-col' ).show();
|
||
$( '#woodoo-odoo-partner-search' ).val( '' ).focus();
|
||
$( '#woodoo-odoo-partner-results' ).html( '' );
|
||
} );
|
||
|
||
// ── Step 2: search Odoo partners ─────────────────────────────────────
|
||
function searchOdooPartners() {
|
||
if ( ! selectedWcUser ) return;
|
||
|
||
const q = $( '#woodoo-odoo-partner-search' ).val().trim();
|
||
if ( q.length < 2 ) return;
|
||
|
||
const $results = $( '#woodoo-odoo-partner-results' );
|
||
$results.html( '<em>' + esc( i18n.searching ) + '</em>' );
|
||
|
||
ajax( 'woodoo_search_partners', { query: q } )
|
||
.done( function ( res ) {
|
||
if ( ! res.success || ! res.data.length ) {
|
||
$results.html( '<p class="woodoo-no-results">' + esc( i18n.no_odoo_partners ) + '</p>' );
|
||
return;
|
||
}
|
||
|
||
let html = '<table class="woodoo-link-table widefat"><thead><tr>' +
|
||
'<th>Name</th><th>Odoo Email</th><th>Type</th><th></th>' +
|
||
'</tr></thead><tbody>';
|
||
|
||
res.data.forEach( function ( p ) {
|
||
html +=
|
||
'<tr>' +
|
||
'<td><strong>' + esc( p.name ) + '</strong></td>' +
|
||
'<td>' + esc( p.email || '—' ) + '</td>' +
|
||
'<td>' + ( p.is_company ? 'Company' : 'Individual' ) + '</td>' +
|
||
'<td><button type="button" class="button button-primary button-small woodoo-confirm-link"' +
|
||
' data-partner-id="' + p.id + '"' +
|
||
' data-partner-name="' + escAttr( p.name ) + '">' +
|
||
'Link</button></td>' +
|
||
'</tr>';
|
||
} );
|
||
|
||
html += '</tbody></table>';
|
||
$results.html( html );
|
||
} )
|
||
.fail( function () { $results.html( '<p>' + esc( i18n.error ) + '</p>' ); } );
|
||
}
|
||
|
||
$( '#woodoo-odoo-partner-search-btn' ).on( 'click', searchOdooPartners );
|
||
$( '#woodoo-odoo-partner-search' ).on( 'keypress', function ( e ) {
|
||
if ( e.which === 13 ) { e.preventDefault(); searchOdooPartners(); }
|
||
} );
|
||
|
||
// ── Confirm link: save WC user ↔ Odoo partner ────────────────────────
|
||
$( document ).on( 'click', '.woodoo-confirm-link', function () {
|
||
if ( ! selectedWcUser ) return;
|
||
|
||
const $btn = $( this );
|
||
const partnerId = $btn.data( 'partner-id' );
|
||
const partnerName = $btn.data( 'partner-name' );
|
||
|
||
$btn.prop( 'disabled', true ).text( 'Saving…' );
|
||
|
||
ajax( 'woodoo_link_customer', {
|
||
user_id : selectedWcUser.id,
|
||
partner_id : partnerId,
|
||
} )
|
||
.done( function ( res ) {
|
||
if ( res.success ) {
|
||
// Update the partner status cell in the WC customers table
|
||
const $row = $( '#woo-customer-results tr[data-user-id="' + selectedWcUser.id + '"]' );
|
||
$row.find( '.woodoo-partner-status' ).html(
|
||
badge( 'green', partnerName )
|
||
);
|
||
$row.find( '.woodoo-link-actions' ).html(
|
||
'<button type="button" class="button button-small woodoo-select-wc-user"' +
|
||
' data-id="' + selectedWcUser.id + '"' +
|
||
' data-name="' + escAttr( selectedWcUser.name ) + '"' +
|
||
' data-email="' + escAttr( selectedWcUser.email ) + '">' +
|
||
'Change Link</button>' +
|
||
' <button type="button" class="button button-small woodoo-unlink-user"' +
|
||
' data-id="' + selectedWcUser.id + '" style="color:#dc2626;">Unlink</button>'
|
||
);
|
||
$row.css( 'background', '#ecfdf5' );
|
||
|
||
// Success feedback in step 2
|
||
$( '#woodoo-odoo-partner-results' ).prepend(
|
||
'<p style="color:#065f46;font-weight:600;">✓ ' +
|
||
esc( i18n.link_done ) + ': ' + esc( selectedWcUser.name ) +
|
||
' → ' + esc( partnerName ) + '</p>'
|
||
);
|
||
$btn.text( 'Linked!' );
|
||
} else {
|
||
$btn.prop( 'disabled', false ).text( 'Link' );
|
||
alert( res.data || i18n.error );
|
||
}
|
||
} )
|
||
.fail( function () {
|
||
$btn.prop( 'disabled', false ).text( 'Link' );
|
||
alert( i18n.error );
|
||
} );
|
||
} );
|
||
|
||
// ── Unlink ────────────────────────────────────────────────────────────
|
||
$( document ).on( 'click', '.woodoo-unlink-user', function () {
|
||
if ( ! confirm( i18n.unlink_confirm ) ) return;
|
||
|
||
const $btn = $( this );
|
||
const userId = $btn.data( 'id' );
|
||
$btn.prop( 'disabled', true );
|
||
|
||
ajax( 'woodoo_unlink_customer', { user_id: userId } )
|
||
.done( function ( res ) {
|
||
if ( res.success ) {
|
||
const $row = $( '#woo-customer-results tr[data-user-id="' + userId + '"]' );
|
||
$row.find( '.woodoo-partner-status' ).html( badge( 'grey', i18n.not_linked ) );
|
||
$row.find( '.woodoo-link-actions button.woodoo-unlink-user' ).remove();
|
||
$row.css( 'background', '' );
|
||
if ( selectedWcUser && selectedWcUser.id == userId ) {
|
||
$( '#woodoo-odoo-col' ).hide();
|
||
selectedWcUser = null;
|
||
}
|
||
} else {
|
||
$btn.prop( 'disabled', false );
|
||
alert( res.data || i18n.error );
|
||
}
|
||
} )
|
||
.fail( function () { $btn.prop( 'disabled', false ); } );
|
||
} );
|
||
|
||
// ══════════════════════════════════════════════════════════════════════
|
||
// USER PROFILE PAGE – partner search
|
||
// ══════════════════════════════════════════════════════════════════════
|
||
|
||
$( '#woodoo-partner-search-btn' ).on( 'click', function () {
|
||
const $input = $( '#woodoo-partner-search-input' );
|
||
const $results = $( '#woodoo-partner-search-results' );
|
||
const q = $input.val().trim();
|
||
const userId = $input.data( 'user-id' );
|
||
|
||
if ( ! q ) return;
|
||
|
||
$results.html( '<em>' + esc( i18n.searching ) + '</em>' );
|
||
|
||
ajax( 'woodoo_search_partners', { query: q } )
|
||
.done( function ( res ) {
|
||
if ( ! res.success || ! res.data.length ) {
|
||
$results.html( '<em>' + esc( i18n.no_odoo_partners ) + '</em>' );
|
||
return;
|
||
}
|
||
|
||
let html = '<ul style="margin:0;padding:0;list-style:none;">';
|
||
res.data.forEach( function ( p ) {
|
||
html +=
|
||
'<li style="padding:4px 0;border-bottom:1px solid #eee;">' +
|
||
'<strong>' + esc( p.name ) + '</strong>' +
|
||
( p.email ? ' <' + esc( p.email ) + '>' : '' ) +
|
||
' <button type="button" class="button button-small woodoo-pick-partner"' +
|
||
' data-id="' + p.id + '"' +
|
||
' data-name="' + escAttr( p.name ) + '"' +
|
||
' data-user-id="' + userId + '">' +
|
||
'Select</button>' +
|
||
'</li>';
|
||
} );
|
||
html += '</ul>';
|
||
$results.html( html );
|
||
} )
|
||
.fail( function () { $results.html( '<em>' + esc( i18n.error ) + '</em>' ); } );
|
||
} );
|
||
|
||
$( document ).on( 'click', '.woodoo-pick-partner', function () {
|
||
const $btn = $( this );
|
||
const partnerId = $btn.data( 'id' );
|
||
const name = $btn.data( 'name' );
|
||
const userId = $btn.data( 'user-id' );
|
||
|
||
$( '#woodoo_odoo_partner_id' ).val( partnerId );
|
||
$( '#woodoo-partner-name-display' ).text( name ).show();
|
||
$( '#woodoo-partner-search-results' ).html(
|
||
'<span style="color:green;">' + esc( i18n.link_done ) +
|
||
' → ' + esc( name ) + ' (#' + partnerId + ')</span>'
|
||
);
|
||
|
||
if ( userId ) {
|
||
ajax( 'woodoo_link_customer', { user_id: userId, partner_id: partnerId } );
|
||
}
|
||
} );
|
||
|
||
// ── Utilities ─────────────────────────────────────────────────────────
|
||
function ajax( action, data ) {
|
||
return $.post( ajaxUrl, Object.assign( { action, nonce }, data ) );
|
||
}
|
||
|
||
function badge( color, text ) {
|
||
return '<span class="woodoo-badge woodoo-badge--' + color + '">' + esc( text ) + '</span>';
|
||
}
|
||
|
||
function esc( str ) {
|
||
return String( str )
|
||
.replace( /&/g, '&' )
|
||
.replace( /</g, '<' )
|
||
.replace( />/g, '>' )
|
||
.replace( /"/g, '"' );
|
||
}
|
||
|
||
function escAttr( str ) {
|
||
return esc( str ).replace( /'/g, ''' );
|
||
}
|
||
|
||
} );
|