2025-12-23 07:48:45 +01:00
/ * *
* Admin JavaScript for Informatiq Smart Pricing
* /
2026-01-22 19:24:05 +01:00
console . log ( 'Informatiq Smart Pricing: Script loaded' ) ;
2025-12-23 07:48:45 +01:00
( function ( $ ) {
'use strict' ;
2026-01-22 19:24:05 +01:00
console . log ( 'Informatiq Smart Pricing: IIFE executed, jQuery available:' , typeof $ !== 'undefined' ) ;
2025-12-23 07:48:45 +01:00
var InformatiqSP = {
/ * *
* Initialize
* /
init : function ( ) {
2026-01-22 19:24:05 +01:00
console . log ( 'Informatiq Smart Pricing: init() called' ) ;
console . log ( 'informatiqSP object:' , typeof informatiqSP !== 'undefined' ? informatiqSP : 'NOT DEFINED' ) ;
2025-12-23 07:48:45 +01:00
this . bindEvents ( ) ;
} ,
/ * *
* Bind event handlers
* /
bindEvents : function ( ) {
2026-01-22 19:24:05 +01:00
console . log ( 'Informatiq Smart Pricing: bindEvents() called' ) ;
var $compareBtn = $ ( '#informatiq-sp-compare-products' ) ;
console . log ( 'Compare products button found:' , $compareBtn . length > 0 ) ;
2025-12-23 07:48:45 +01:00
$ ( '#informatiq-sp-manual-sync' ) . on ( 'click' , this . handleManualSync ) ;
$ ( '#informatiq-sp-test-connection' ) . on ( 'click' , this . handleTestConnection ) ;
2026-01-21 08:52:57 +01:00
$ ( '#informatiq-sp-revoke-auth' ) . on ( 'click' , this . handleRevokeAuth ) ;
2026-01-22 19:24:05 +01:00
$compareBtn . on ( 'click' , this . handleCompareProducts ) ;
console . log ( 'Informatiq Smart Pricing: All event handlers bound' ) ;
2025-12-23 07:48:45 +01:00
} ,
/ * *
* Handle manual sync button click
* /
handleManualSync : function ( e ) {
e . preventDefault ( ) ;
var $button = $ ( this ) ;
var $status = $ ( '#informatiq-sp-sync-status' ) ;
// Confirm action
if ( ! confirm ( informatiqSP . strings . confirmSync || 'Are you sure you want to run a manual price sync? This may take several minutes.' ) ) {
return ;
}
// Disable button and show loading state
$button . prop ( 'disabled' , true ) . addClass ( 'informatiq-sp-loading' ) ;
// Show status message
$status
. removeClass ( 'notice-success notice-error' )
. addClass ( 'notice-info' )
. html ( '<p>' + ( informatiqSP . strings . syncInProgress || 'Sync in progress...' ) + '</p>' )
. show ( ) ;
// Make AJAX request
$ . ajax ( {
url : informatiqSP . ajaxUrl ,
type : 'POST' ,
data : {
action : 'informatiq_sp_manual_sync' ,
nonce : informatiqSP . nonce
} ,
success : function ( response ) {
if ( response . success ) {
$status
. removeClass ( 'notice-info notice-error' )
. addClass ( 'notice-success' )
. html ( '<p>' + response . data . message + '</p>' ) ;
// Reload page after 2 seconds to show updated logs
setTimeout ( function ( ) {
location . reload ( ) ;
} , 2000 ) ;
} else {
$status
. removeClass ( 'notice-info notice-success' )
. addClass ( 'notice-error' )
. html ( '<p>Error: ' + ( response . data . message || 'Unknown error' ) + '</p>' ) ;
}
} ,
error : function ( jqXHR , textStatus , errorThrown ) {
$status
. removeClass ( 'notice-info notice-success' )
. addClass ( 'notice-error' )
. html ( '<p>Error: ' + errorThrown + '</p>' ) ;
} ,
complete : function ( ) {
$button . prop ( 'disabled' , false ) . removeClass ( 'informatiq-sp-loading' ) ;
}
} ) ;
} ,
/ * *
* Handle test connection button click
* /
handleTestConnection : function ( e ) {
e . preventDefault ( ) ;
var $button = $ ( this ) ;
var $status = $ ( '#informatiq-sp-sync-status' ) ;
// Disable button and show loading state
$button . prop ( 'disabled' , true ) . addClass ( 'informatiq-sp-loading' ) ;
// Show status message
$status
. removeClass ( 'notice-success notice-error' )
. addClass ( 'notice-info' )
. html ( '<p>' + ( informatiqSP . strings . testInProgress || 'Testing connection...' ) + '</p>' )
. show ( ) ;
// Make AJAX request
$ . ajax ( {
url : informatiqSP . ajaxUrl ,
type : 'POST' ,
data : {
action : 'informatiq_sp_test_connection' ,
nonce : informatiqSP . nonce
} ,
success : function ( response ) {
if ( response . success ) {
$status
. removeClass ( 'notice-info notice-error' )
. addClass ( 'notice-success' )
. html ( '<p>' + response . data . message + '</p>' ) ;
} else {
$status
. removeClass ( 'notice-info notice-success' )
. addClass ( 'notice-error' )
. html ( '<p>Error: ' + ( response . data . message || 'Unknown error' ) + '</p>' ) ;
}
} ,
error : function ( jqXHR , textStatus , errorThrown ) {
$status
. removeClass ( 'notice-info notice-success' )
. addClass ( 'notice-error' )
. html ( '<p>Error: ' + errorThrown + '</p>' ) ;
} ,
complete : function ( ) {
$button . prop ( 'disabled' , false ) . removeClass ( 'informatiq-sp-loading' ) ;
// Hide status message after 5 seconds
setTimeout ( function ( ) {
$status . fadeOut ( ) ;
} , 5000 ) ;
}
} ) ;
2026-01-21 08:52:57 +01:00
} ,
/ * *
* Handle revoke authorization button click
* /
handleRevokeAuth : function ( e ) {
e . preventDefault ( ) ;
var $button = $ ( this ) ;
// Confirm action
if ( ! confirm ( informatiqSP . strings . revokeConfirm || 'Are you sure you want to revoke Google authorization?' ) ) {
return ;
}
// Disable button and show loading state
$button . prop ( 'disabled' , true ) . text ( informatiqSP . strings . revokeInProgress || 'Revoking...' ) ;
// Make AJAX request
$ . ajax ( {
url : informatiqSP . ajaxUrl ,
type : 'POST' ,
data : {
action : 'informatiq_sp_revoke_auth' ,
nonce : informatiqSP . nonce
} ,
success : function ( response ) {
if ( response . success ) {
// Reload page to show updated status
location . reload ( ) ;
} else {
alert ( 'Error: ' + ( response . data . message || 'Unknown error' ) ) ;
$button . prop ( 'disabled' , false ) . text ( 'Revoke Authorization' ) ;
}
} ,
error : function ( jqXHR , textStatus , errorThrown ) {
alert ( 'Error: ' + errorThrown ) ;
$button . prop ( 'disabled' , false ) . text ( 'Revoke Authorization' ) ;
}
} ) ;
2026-01-22 19:16:57 +01:00
} ,
/ * *
* Handle compare products button click
* /
handleCompareProducts : function ( e ) {
e . preventDefault ( ) ;
2026-01-22 19:24:05 +01:00
console . log ( '=== COMPARE PRODUCTS CLICKED ===' ) ;
2026-01-22 19:16:57 +01:00
var $button = $ ( this ) ;
var $spinner = $button . next ( '.spinner' ) ;
var $results = $ ( '#informatiq-sp-comparison-results' ) ;
var $tbody = $ ( '#informatiq-sp-comparison-tbody' ) ;
2026-01-22 19:24:05 +01:00
var $status = $ ( '#informatiq-sp-sync-status' ) ;
console . log ( 'Button:' , $button . length ) ;
console . log ( 'Spinner:' , $spinner . length ) ;
console . log ( 'Results container:' , $results . length ) ;
console . log ( 'informatiqSP:' , informatiqSP ) ;
// Show loading status
$status
. removeClass ( 'notice-success notice-error' )
. addClass ( 'notice-info' )
. html ( '<p><strong>Loading product comparison...</strong> This may take a moment.</p>' )
. show ( ) ;
2026-01-22 19:16:57 +01:00
// Disable button and show spinner
$button . prop ( 'disabled' , true ) ;
$spinner . addClass ( 'is-active' ) ;
2026-01-22 19:24:05 +01:00
console . log ( 'Making AJAX request to:' , informatiqSP . ajaxUrl ) ;
console . log ( 'With nonce:' , informatiqSP . nonce ) ;
2026-01-22 19:16:57 +01:00
// Make AJAX request
$ . ajax ( {
url : informatiqSP . ajaxUrl ,
type : 'POST' ,
2026-01-22 19:24:05 +01:00
timeout : 120000 , // 2 minute timeout
2026-01-22 19:16:57 +01:00
data : {
action : 'informatiq_sp_compare_products' ,
nonce : informatiqSP . nonce
} ,
2026-01-22 19:24:05 +01:00
beforeSend : function ( xhr ) {
console . log ( 'AJAX beforeSend - request starting' ) ;
} ,
2026-01-22 19:16:57 +01:00
success : function ( response ) {
2026-01-22 19:24:05 +01:00
console . log ( 'AJAX success callback' ) ;
console . log ( 'AJAX response:' , response ) ;
2026-01-23 17:45:35 +01:00
// Log debug info if available.
if ( response . data && response . data . debug ) {
console . log ( '=== DEBUG INFO ===' ) ;
console . log ( 'Sample Google product:' , response . data . debug . sample _google _product ) ;
console . log ( 'Sample indexed keys:' , response . data . debug . sample _google _keys ) ;
console . log ( 'Total indexed entries:' , response . data . debug . index _count ) ;
console . log ( '==================' ) ;
}
2026-01-22 19:24:05 +01:00
$status . hide ( ) ;
2026-01-22 19:16:57 +01:00
if ( response . success ) {
var data = response . data ;
var html = '' ;
2026-01-23 18:05:17 +01:00
// Stats counters.
var stats = {
total : 0 ,
withBenchmark : 0 ,
cheaper : 0 ,
competitive : 0 ,
expensive : 0 ,
totalPotentialGain : 0
} ;
2026-01-22 19:16:57 +01:00
if ( data . products . length === 0 ) {
html = '<tr><td colspan="6">No in-stock products with SKU found.</td></tr>' ;
} else {
$ . each ( data . products , function ( i , product ) {
2026-01-23 18:05:17 +01:00
stats . total ++ ;
2026-01-22 19:16:57 +01:00
var localPrice = product . local _price ? data . currency + parseFloat ( product . local _price ) . toFixed ( 2 ) : '-' ;
2026-01-23 18:05:17 +01:00
var benchmarkPrice = product . benchmark _price ? data . currency + parseFloat ( product . benchmark _price ) . toFixed ( 2 ) : '-' ;
var recommendedPrice = product . recommended _price ? data . currency + parseFloat ( product . recommended _price ) . toFixed ( 2 ) : '-' ;
var potentialGain = '-' ;
var priceLabel = product . price _type === 'sale' ? ' <small>(sale)</small>' : '' ;
// Status and colors.
var statusText = '-' ;
var statusStyle = '' ;
var localPriceStyle = '' ;
var gainStyle = '' ;
if ( product . has _benchmark ) {
stats . withBenchmark ++ ;
if ( product . price _status === 'cheaper' ) {
stats . cheaper ++ ;
statusText = 'Cheaper' ;
statusStyle = 'color: #00a32a; font-weight: bold;' ;
localPriceStyle = 'color: #00a32a;' ;
} else if ( product . price _status === 'competitive' ) {
stats . competitive ++ ;
statusText = 'Competitive' ;
statusStyle = 'color: #2271b1; font-weight: bold;' ;
localPriceStyle = 'color: #2271b1;' ;
} else if ( product . price _status === 'expensive' ) {
stats . expensive ++ ;
statusText = 'Expensive' ;
statusStyle = 'color: #d63638; font-weight: bold;' ;
localPriceStyle = 'color: #d63638;' ;
}
if ( product . potential _gain !== null ) {
var gain = parseFloat ( product . potential _gain ) ;
stats . totalPotentialGain += gain ;
if ( gain > 0 ) {
potentialGain = '+' + data . currency + gain . toFixed ( 2 ) ;
gainStyle = 'color: #00a32a; font-weight: bold;' ;
} else if ( gain < 0 ) {
potentialGain = '-' + data . currency + Math . abs ( gain ) . toFixed ( 2 ) ;
gainStyle = 'color: #d63638;' ;
} else {
potentialGain = data . currency + '0.00' ;
}
}
} else if ( product . found ) {
statusText = 'No benchmark' ;
statusStyle = 'color: #dba617;' ;
} else {
statusText = 'Not in Google' ;
statusStyle = 'color: #888;' ;
2026-01-22 19:16:57 +01:00
}
html += '<tr>' ;
2026-01-23 18:05:17 +01:00
html += '<td><a href="post.php?post=' + product . id + '&action=edit" title="SKU: ' + product . sku + '">' + product . name + '</a></td>' ;
html += '<td style="' + localPriceStyle + '">' + localPrice + priceLabel + '</td>' ;
html += '<td>' + benchmarkPrice + '</td>' ;
html += '<td>' + recommendedPrice + '</td>' ;
html += '<td style="' + gainStyle + '">' + potentialGain + '</td>' ;
html += '<td style="' + statusStyle + '">' + statusText + '</td>' ;
2026-01-22 19:16:57 +01:00
html += '</tr>' ;
} ) ;
}
$tbody . html ( html ) ;
$results . show ( ) ;
2026-01-23 18:05:17 +01:00
// Show summary with statistics.
var $summary = $ ( '#informatiq-sp-comparison-summary' ) ;
var summaryHtml = '<strong>Summary:</strong> ' ;
summaryHtml += stats . withBenchmark + ' of ' + stats . total + ' products have competitor data. ' ;
summaryHtml += '<span style="color:#00a32a;">' + stats . cheaper + ' cheaper</span>, ' ;
summaryHtml += '<span style="color:#2271b1;">' + stats . competitive + ' competitive</span>, ' ;
summaryHtml += '<span style="color:#d63638;">' + stats . expensive + ' expensive</span>. ' ;
if ( stats . totalPotentialGain > 0 ) {
summaryHtml += '<br><strong style="color:#00a32a;">Total potential gain if optimized: +' + data . currency + stats . totalPotentialGain . toFixed ( 2 ) + ' per sale</strong>' ;
} else if ( stats . totalPotentialGain < 0 ) {
summaryHtml += '<br><strong>Current margin vs recommended: ' + data . currency + stats . totalPotentialGain . toFixed ( 2 ) + '</strong>' ;
}
$summary . html ( summaryHtml ) . show ( ) ;
2026-01-22 19:16:57 +01:00
} else {
2026-01-22 19:24:05 +01:00
$status
. removeClass ( 'notice-info notice-success' )
. addClass ( 'notice-error' )
. html ( '<p>Error: ' + ( response . data . message || 'Unknown error' ) + '</p>' )
. show ( ) ;
2026-01-22 19:16:57 +01:00
}
} ,
error : function ( jqXHR , textStatus , errorThrown ) {
2026-01-22 19:24:05 +01:00
console . error ( 'AJAX error:' , textStatus , errorThrown , jqXHR . responseText ) ;
$status
. removeClass ( 'notice-info notice-success' )
. addClass ( 'notice-error' )
. html ( '<p>Error: ' + errorThrown + ' - ' + textStatus + '</p>' )
. show ( ) ;
2026-01-22 19:16:57 +01:00
} ,
complete : function ( ) {
2026-01-22 19:24:05 +01:00
console . log ( 'AJAX request complete' ) ;
2026-01-22 19:16:57 +01:00
$button . prop ( 'disabled' , false ) ;
$spinner . removeClass ( 'is-active' ) ;
}
} ) ;
2025-12-23 07:48:45 +01:00
}
} ;
// Initialize when document is ready
$ ( document ) . ready ( function ( ) {
InformatiqSP . init ( ) ;
} ) ;
} ) ( jQuery ) ;