untrailingslashit(esc_url_raw(rest_url('woonoow/v1'))),
'nonce' => wp_create_nonce('wp_rest'),
'isDev' => true,
'devServer' => $dev_url,
'adminScreen' => 'woonoow',
'adminUrl' => admin_url('admin.php'),
]);
wp_add_inline_script($handle, 'window.WNW_API = window.WNW_API || WNW_API;', 'after');
// WNW_CONFIG for compatibility with standalone mode code
wp_localize_script($handle, 'WNW_CONFIG', [
'restUrl' => untrailingslashit(esc_url_raw(rest_url('woonoow/v1'))),
'nonce' => wp_create_nonce('wp_rest'),
'standaloneMode' => false,
'wpAdminUrl' => admin_url('admin.php?page=woonoow'),
'isAuthenticated' => is_user_logged_in(),
'pluginUrl' => trailingslashit(plugins_url('/', dirname(__DIR__))),
]);
wp_add_inline_script($handle, 'window.WNW_CONFIG = window.WNW_CONFIG || WNW_CONFIG;', 'after');
// WordPress REST API settings (for media upload compatibility)
wp_localize_script($handle, 'wpApiSettings', [
'root' => untrailingslashit(esc_url_raw(rest_url())),
'nonce' => wp_create_nonce('wp_rest'),
]);
wp_add_inline_script($handle, 'window.wpApiSettings = window.wpApiSettings || wpApiSettings;', 'after');
// Also expose compact global for convenience
wp_localize_script($handle, 'wnw', [
'isDev' => true,
'devServer' => $dev_url,
'adminUrl' => admin_url('admin.php'),
'siteTitle' => get_bloginfo('name') ?: 'WooNooW',
]);
wp_add_inline_script($handle, 'window.wnw = window.wnw || wnw;', 'after');
// Localize store currency data (same as prod)
wp_localize_script($handle, 'WNW_STORE', self::store_runtime());
wp_add_inline_script($handle, 'window.WNW_STORE = window.WNW_STORE || WNW_STORE;', 'after');
// Localize Woo menus snapshot for instant render
$menus_snapshot = class_exists(MenuProvider::class) ? MenuProvider::get_snapshot() : [];
wp_localize_script($handle, 'WNW_WC_MENUS', ['items' => $menus_snapshot]);
wp_add_inline_script($handle, 'window.WNW_WC_MENUS = window.WNW_WC_MENUS || WNW_WC_MENUS;', 'after');
// Addon system data
wp_localize_script($handle, 'WNW_ADDONS', AddonRegistry::get_frontend_registry());
wp_add_inline_script($handle, 'window.WNW_ADDONS = window.WNW_ADDONS || WNW_ADDONS;', 'after');
wp_localize_script($handle, 'WNW_ADDON_ROUTES', RouteRegistry::get_frontend_routes());
wp_add_inline_script($handle, 'window.WNW_ADDON_ROUTES = window.WNW_ADDON_ROUTES || WNW_ADDON_ROUTES;', 'after');
wp_localize_script($handle, 'WNW_NAV_TREE', NavigationRegistry::get_frontend_nav_tree());
wp_add_inline_script($handle, 'window.WNW_NAV_TREE = window.WNW_NAV_TREE || WNW_NAV_TREE;', 'after');
// Temporary compat aliases for old WNM_*
wp_add_inline_script($handle, 'window.WNM_API = window.WNM_API || window.WNW_API;', 'after');
wp_add_inline_script($handle, 'window.WNM_WC_MENUS = window.WNM_WC_MENUS || window.WNW_WC_MENUS;', 'after');
// 2) Print a real module tag in the footer to load Vite client + app
add_action('admin_print_footer_scripts', function () use ($dev_url) {
// 1) React Refresh preamble (required by @vitejs/plugin-react)
?>
' . "\n", esc_url($dev_url));
// 3) Your app entry
printf('' . "\n", esc_url($dev_url));
}, 1);
}
/** ----------------------------------------
* PROD MODE (built assets in admin-spa/dist)
* -------------------------------------- */
private static function enqueue_prod(): void
{
// Get plugin root directory (2 levels up from includes/Admin/)
$plugin_dir = dirname(dirname(__DIR__));
$dist_dir = $plugin_dir . '/admin-spa/dist/';
$base_url = plugins_url('admin-spa/dist/', $plugin_dir . '/woonoow.php');
$css = 'app.css';
$js = 'app.js';
$ver_css = file_exists($dist_dir . $css) ? (string) filemtime($dist_dir . $css) : self::asset_version();
$ver_js = file_exists($dist_dir . $js) ? (string) filemtime($dist_dir . $js) : self::asset_version();
// Debug logging
if (defined('WP_DEBUG') && WP_DEBUG) {
error_log('[WooNooW Assets] Dist dir: ' . $dist_dir);
error_log('[WooNooW Assets] CSS exists: ' . (file_exists($dist_dir . $css) ? 'yes' : 'no'));
error_log('[WooNooW Assets] JS exists: ' . (file_exists($dist_dir . $js) ? 'yes' : 'no'));
error_log('[WooNooW Assets] CSS URL: ' . $base_url . $css);
error_log('[WooNooW Assets] JS URL: ' . $base_url . $js);
}
if (file_exists($dist_dir . $css)) {
wp_enqueue_style('wnw-admin', $base_url . $css, [], $ver_css);
// Note: Icon fixes are now in index.css with proper specificity
}
if (file_exists($dist_dir . $js)) {
wp_enqueue_script('wnw-admin', $base_url . $js, ['wp-element'], $ver_js, true);
// Add type="module" attribute for Vite build
add_filter('script_loader_tag', function ($tag, $handle, $src) {
if ($handle === 'wnw-admin') {
$tag = str_replace('