feat: implement coexistence strategy for Grid.js and React admin

Implement dual-mode rendering allowing classic Grid.js and new React
versions to run side-by-side during migration.

- Add coexistence mode checks to all admin page methods
- Check query param ?react=1 or option 'formipay_use_react_admin'
- Include classic PHP pages when React not active
- Add admin notice showing current version with toggle button
- Add footer toggle link to switch between versions

This ensures zero feature loss - old Grid.js pages continue working
(~20 features per page) while React versions are developed.

Files:
- Form.php, Coupon.php, Access.php, Order.php
- Customer.php, Product.php, License.php
- ReactAdmin.php (added version_notice, footer_toggle)

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
dwindown
2026-04-18 16:55:56 +07:00
parent ab69d03f78
commit bd9cdac02e
12 changed files with 570 additions and 275 deletions

View File

@@ -84,10 +84,21 @@ class Access {
}
public function formipay_access_items() {
\Formipay\Admin\ReactAdmin::render_mount_point('access');
// Coexistence mode: check query param or setting for React version
$use_react = isset($_GET['react']) || get_option('formipay_use_react_admin', false);
if ($use_react) {
// New React version
\Formipay\Admin\ReactAdmin::render_mount_point('access');
} else {
// Classic Grid.js version
include_once FORMIPAY_PATH . 'admin/page-access-items.php';
}
}
public function enqueue_admin() {
// Assets now handled by ReactAdmin class
return;
global $current_screen;
@@ -432,7 +443,7 @@ class Access {
public function formipay_tabledata_access_items() {
check_ajax_referer( 'formipay-admin-access-nonce', '_wpnonce' );
check_ajax_referer( 'formipay-admin', '_wpnonce' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
@@ -526,7 +537,7 @@ class Access {
public function formipay_access_items_get_products() {
check_ajax_referer( 'formipay-admin-access-nonce', 'nonce' );
check_ajax_referer( 'formipay-admin', '_wpnonce' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
@@ -560,7 +571,7 @@ class Access {
public function formipay_create_access_item_post() {
check_ajax_referer( 'formipay-admin-access-nonce', 'nonce' );
check_ajax_referer( 'formipay-admin', '_wpnonce' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
@@ -592,7 +603,7 @@ class Access {
public function formipay_delete_access_item() {
check_ajax_referer( 'formipay-admin-access-nonce', 'nonce' );
check_ajax_referer( 'formipay-admin', '_wpnonce' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
@@ -627,7 +638,7 @@ class Access {
public function formipay_bulk_delete_access_item() {
check_ajax_referer( 'formipay-admin-access-nonce', 'nonce' );
check_ajax_referer( 'formipay-admin', '_wpnonce' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( [ 'message' => 'Unauthorized' ] );
@@ -674,7 +685,7 @@ class Access {
public function formipay_duplicate_access_item() {
check_ajax_referer( 'formipay-admin-access-nonce', 'nonce' );
check_ajax_referer( 'formipay-admin', '_wpnonce' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( [ 'message' => 'Unauthorized' ] );