Complete React-based field rendering system that replaces WPCFTO Vue.js layer while maintaining PHP field configuration compatibility. Components: - FieldRenderer: Main renderer with tabs support (metabox) and direct mode (settings) - FieldTypes: 15+ field types (Text, Number, Select, Radio, Date, etc.) - RepeaterField: Collapsible repeater with currency label parsing - DependencyEngine: Show/hide fields based on conditions - ValidationEngine: Client-side validation with error messages - SettingsRenderer: Settings page with AJAX save to wp_options Features: - Repeater rows collapsed by default with readable currency titles - Searchable dropdowns using Popover + Command pattern - Proper label resolution for pre-selected values - Hidden input sync for WordPress form submission Also includes: - FieldConfigBridge: Transform PHP configs to React format - Updated Settings.php for React-based settings page - Radio-group UI component - wp-admin-restore.css for admin panel isolation
185 lines
5.7 KiB
PHP
185 lines
5.7 KiB
PHP
<?php
|
|
namespace Formipay\Admin;
|
|
use Formipay\Traits\SingletonTrait;
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) exit;
|
|
|
|
class ReactAdmin {
|
|
|
|
use SingletonTrait;
|
|
|
|
protected function __construct() {
|
|
|
|
add_action( 'admin_enqueue_scripts', [$this, 'enqueue_assets'] );
|
|
add_filter( 'formipay/admin/data', [$this, 'localize_data'] );
|
|
|
|
// AJAX endpoint for field configuration
|
|
add_action( 'wp_ajax_formipay-get-field-config', [$this, 'ajax_get_field_config'] );
|
|
|
|
}
|
|
|
|
public function enqueue_assets() {
|
|
|
|
$screen = get_current_screen();
|
|
|
|
// Load React assets on Formipay admin pages OR on post edit screens for our CPTs
|
|
$is_formipay_admin = strpos($screen->id, 'formipay') !== false;
|
|
$is_formipay_cpt = $screen->base === 'post' && in_array($screen->post_type, ['formipay-coupon', 'formipay-product', 'formipay-form']);
|
|
|
|
if (!$is_formipay_admin && !$is_formipay_cpt) {
|
|
return;
|
|
}
|
|
|
|
// Enqueue React build assets
|
|
$build_dir = FORMIPAY_PATH . 'build';
|
|
$build_url = FORMIPAY_URL . 'build';
|
|
|
|
if (!file_exists($build_dir . '/admin.asset.php')) {
|
|
error_log('[Formipay] Build files not found at: ' . $build_dir . '/admin.asset.php');
|
|
return; // Build not generated yet
|
|
}
|
|
|
|
$assets_file = require $build_dir . '/admin.asset.php';
|
|
$dependencies = $assets_file['dependencies'] ?? [];
|
|
|
|
// Filter out icon build dependencies - they're bundled, not separate scripts
|
|
$dependencies = array_values(array_filter($dependencies, function($dep) {
|
|
return strpos($dep, 'wp-icons/build/') === false;
|
|
}));
|
|
|
|
$version = $assets_file['version'] ?? FORMIPAY_VERSION;
|
|
|
|
wp_enqueue_style(
|
|
'formipay-admin-style',
|
|
$build_url . '/admin.css',
|
|
['wp-admin', 'colors', 'dashicons', 'common', 'forms', 'admin-menu', 'dashboard', 'list-tables', 'edit', 'revisions', 'media', 'themes', 'about', 'nav-menus'],
|
|
$version
|
|
);
|
|
|
|
wp_enqueue_script(
|
|
'formipay-admin',
|
|
$build_url . '/admin.js',
|
|
$dependencies,
|
|
$version,
|
|
true
|
|
);
|
|
|
|
// Localize script with required data
|
|
$data = apply_filters('formipay/admin/data', [
|
|
'ajaxUrl' => admin_url('admin-ajax.php'),
|
|
'restUrl' => rest_url('formipay/v1'),
|
|
'nonce' => wp_create_nonce('formipay-admin'),
|
|
'pluginUrl' => FORMIPAY_URL,
|
|
'siteUrl' => site_url(),
|
|
]);
|
|
|
|
wp_localize_script('formipay-admin', 'formipayAdmin', $data);
|
|
|
|
}
|
|
|
|
public function localize_data( $data ) {
|
|
|
|
$screen = get_current_screen();
|
|
$page = '';
|
|
|
|
// Determine current page based on screen ID
|
|
if ( $screen->id === 'formipay_page_formipay-orders' ) {
|
|
$page = 'orders';
|
|
} elseif ( $screen->id === 'formipay_page_formipay-customers' ) {
|
|
$page = 'customers';
|
|
} elseif ( $screen->id === 'formipay_page_formipay-products' ) {
|
|
$page = 'products';
|
|
} elseif ( $screen->id === 'toplevel_page_formipay' ) {
|
|
$page = 'forms';
|
|
} elseif ( $screen->id === 'formipay_page_formipay-coupons' ) {
|
|
$page = 'coupons';
|
|
} elseif ( $screen->id === 'formipay_page_formipay-access' ) {
|
|
$page = 'access';
|
|
} elseif ( $screen->id === 'formipay_page_formipay-licenses' ) {
|
|
$page = 'licenses';
|
|
}
|
|
|
|
if ( $page ) {
|
|
$data[$page] = $this->get_page_data( $page );
|
|
}
|
|
|
|
return $data;
|
|
|
|
}
|
|
|
|
private function get_page_data( $page ) {
|
|
|
|
$data = [];
|
|
|
|
switch ( $page ) {
|
|
|
|
case 'orders':
|
|
$data['statusOptions'] = formipay_order_status_list();
|
|
break;
|
|
|
|
case 'customers':
|
|
$data['columns'] = [
|
|
'id' => __( 'ID', 'formipay' ),
|
|
'name' => __( 'Name', 'formipay' ),
|
|
'email' => __( 'Email', 'formipay' ),
|
|
'phone' => __( 'Phone', 'formipay' ),
|
|
'total_order' => __( 'Total Orders', 'formipay' ),
|
|
];
|
|
break;
|
|
|
|
case 'products':
|
|
$data['currencies'] = formipay_global_currency_options();
|
|
break;
|
|
|
|
case 'forms':
|
|
case 'coupons':
|
|
case 'access':
|
|
case 'licenses':
|
|
// These pages fetch data via AJAX, no initial data needed
|
|
$data = [];
|
|
break;
|
|
|
|
}
|
|
|
|
return $data;
|
|
|
|
}
|
|
|
|
/**
|
|
* Render React mount point
|
|
*/
|
|
public static function render_mount_point( $page ) {
|
|
|
|
printf(
|
|
'<div class="wrap"><div id="formipay-admin-root" data-formipay-mount="%s">Loading %s...</div></div>',
|
|
esc_attr( $page ),
|
|
esc_html( ucfirst( $page ) )
|
|
);
|
|
|
|
}
|
|
|
|
/**
|
|
* AJAX handler for getting field configuration
|
|
*/
|
|
public function ajax_get_field_config() {
|
|
|
|
check_ajax_referer( 'formipay-admin', '_wpnonce', '', true );
|
|
|
|
if (!current_user_can('manage_options')) {
|
|
wp_send_json_error(['message' => __('Unauthorized', 'formipay')]);
|
|
}
|
|
|
|
$post_id = isset($_REQUEST['post_id']) ? intval($_REQUEST['post_id']) : 0;
|
|
$post_type = isset($_REQUEST['post_type']) ? sanitize_text_field($_REQUEST['post_type']) : '';
|
|
|
|
if (!$post_id || !$post_type) {
|
|
wp_send_json_error(['message' => __('Invalid request', 'formipay')]);
|
|
}
|
|
|
|
$config = FieldConfigBridge::get_config_for_post($post_id, $post_type);
|
|
|
|
wp_send_json_success($config);
|
|
}
|
|
|
|
}
|