Files
formipay/MIGRATION_STRATEGY.md
dwindown bd9cdac02e 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>
2026-04-18 16:55:56 +07:00

283 lines
9.7 KiB
Markdown

# Formipay — Migration Strategy
**Date:** April 18, 2026 (Updated)
**Context:** Phase 2 — React Admin Foundation
---
## Overview
This document explains how to approach migrating existing Formipay admin interfaces to React while **ensuring zero feature loss**.
**Key Principle:** **Coexistence until Feature Parity** — New React versions must match or exceed old functionality before deprecating old code. No "delete and replace" without validation.
---
## Existing Technology Inventory
| Technology | Location | Purpose | Feature Count | Migration Priority |
|-------------|----------|---------|---------------|-------------------|
| **WPCFTO Framework** | `vendor/` | Settings form builder | N/A | Low (replaced by React settings) |
| **Grid.js** | `admin/assets/js/page-*.js` | All admin tables | ~20 features per page | **HIGH** (current gap) |
| **SweetAlert2** | `vendor/SweetAlert2/` | Modal dialogs | N/A | None (keep using) |
| **Custom Vue 2 App** | `admin/assets/js/admin-product-editor.js` | Product variation pricing | ~7 features | Medium |
| **jQuery** | Core WP dependency | DOM manipulation | N/A | Phase out gradually |
---
## Critical: Grid.js Migration Strategy
### Current Grid.js Features (Must Preserve)
**Every admin page with Grid.js has these features:**
| Feature | Forms | Coupons | Access | Orders | Products |
|---------|-------|--------|-------|--------|----------|
| Checkbox column + "Select All" | ✅ | ✅ | ✅ | ✅ | ✅ |
| Bulk delete button | ✅ | ✅ | ✅ | ✅ | ✅ |
| Inline row actions (hover) | ✅ | ✅ | ✅ | ✅ | ✅ |
| Status filter tabs (All/Published/Draft) | ✅ | ✅ | ✅ | ❌ | ✅ |
| Search input | ✅ | ✅ | ✅ | ✅ | ✅ |
| Sort dropdown | ✅ | ✅ | ✅ | ❌ | ✅ |
| Order (ASC/DESC) | ✅ | ✅ | ✅ | ❌ | ✅ |
| Server-side pagination | ✅ | ✅ | ✅ | ✅ | ✅ |
| "Add New" modal (SweetAlert2) | ✅ | ✅ | ✅ | ❌ | ✅ |
| Inline delete action | ✅ | ✅ | ✅ | ✅ | ✅ |
| Inline duplicate action | ✅ | ✅ | ✅ | ❌ | ✅ |
| Shortcode copy button | ✅ | ❌ | ❌ | ❌ | ❌ |
| Multi-currency display | ❌ | ✅ | ❌ | ❌ | ✅ |
**Total: ~20 table features per page**
### Migration Approach: Coexistence
**DO NOT:** Delete old Grid.js code until React replacement is feature-complete
**DO:** Use query param or feature flag to run both versions side-by-side
```
Phase 1: Coexistence (Required)
┌─────────────────────────────────────────────────────────┐
│ Formipay Admin │
├─────────────────────────────────────────────────────────┤
│ Old: Grid.js Tables → Fully functional │
│ New: React Tables → Under development, feature-incomplete │
│ │
│ Access: ?old=1 → Grid.js | ?old=0 → React (default when ready) │
└─────────────────────────────────────────────────────────┘
```
### Implementation Steps
**Step 1: Feature Parity Checklist**
Create `MIGRATION_CHECKLIST.md` with per-page feature requirements (see template below).
**Step 2: Dual-Mode Rendering**
In PHP page callback, check for query param:
```php
public function formipay_form() {
$use_react = isset($_GET['react']) || get_option('formipay_use_react_admin', false);
if ($use_react) {
\Formipay\Admin\ReactAdmin::render_mount_point('forms');
} else {
include_once FORMIPAY_PATH . 'admin/page-forms.php';
}
}
```
**Step 3: Feature Flag for Default**
```php
// In settings or option
public function use_react_admin() {
return get_option('formipay_use_react_admin', false);
}
```
**Step 4: Toggle Link in Admin**
```php
// Add to admin footer or menu bar
<?php if (!get_option('formipay_use_react_admin')) : ?>
<a href="<?php echo admin_url('admin.php?page=formipay&react=1'); ?>">
Try React Admin (Beta)
</a>
<?php else: ?>
<a href="<?php echo admin_url('admin.php?page=formipay&react=0'); ?>">
Use Classic Admin
</a>
<?php endif; ?>
```
### Testing Protocol
Before setting `use_react_admin` to true as default:
1. **Manual Feature Testing**: Go through checklist item by item
2. **Regression Testing**: Old Grid.js version still works
3. **Data Compatibility**: Both versions read/write same data format
4. **Performance**: React version not significantly slower
5. **Browser Testing**: Test in Chrome, Firefox, Safari
**Only when ALL checkboxes pass → Enable React by default**
---
## React Component Library Strategy
### Approved Libraries
| Library | Purpose | Why |
|---------|---------|-----|
| **@wordpress/components** | UI primitives (Button, Modal, SelectControl, TextControl) | Native WP styling, already bundled |
| **@tanstack/react-table** (v8) | Headless table engine | Flexible, performant, React 18 compatible |
| **SweetAlert2** (existing) | Modals, confirmations, toasts | Already in use, keep as-is |
| **@wordpress/icons** | Icons | Already bundled, correct WP styling |
### Libraries to AVOID
| Library | Reason to Avoid |
|---------|-----------------|
| **shadcn/ui** | Wrong styling (Tailwind vs WP), requires Tailwind setup |
| **Material UI (@mui/x-data-grid)** | Wrong styling, 100KB+ bundle, overkill |
| **react-table** (v7) | Deprecated, use @tanstack/react-table |
| **react-data-table** | Heavy bundle, opinionated styling |
### Building the Table Component
```jsx
// Use @tanstack/react-table for the engine
import { useReactTable } from '@tanstack/react-table';
// Use @wordpress/components for UI
import { Modal, Button, CheckboxControl } from '@wordpress/components';
// Style with WordPress classes
<table className="wp-list-table widefat fixed striped">
```
---
## Data Compatibility Requirements
### AJAX Endpoints (Must Preserve)
| Endpoint | Request | Response Format |
|----------|---------|------------------|
| `formipay-tabledata-forms` | GET + params | `{results, total, posts_report}` |
| `formipay-create-form-post` | POST + title | `{success, data: {edit_post_url}}` |
| `formipay-delete-form` | POST + id | `{success, data: {title, message, icon}}` |
| `formipay-duplicate-form` | POST + id | `{success, data: {title, message, icon}}` |
| `formipay-bulk-delete-form` | POST + ids[] | `{success, data: {title, message, icon}}` |
| `get_product_variables` | GET + post_id | Variation data object |
| `formipay-tabledata-coupons` | GET + params | `{results, total, posts_report}` |
| `formipay-tabledata-access-items` | GET + params | `{results, total, posts_report}` |
| `formipay-tabledata-orders` | GET + params | `{results, total, posts_report}` |
| `formipay-tabledata-customers` | GET + params | `{results, total, posts_report}` |
**Critical:** Response formats must remain identical for compatibility!
---
## Rollback Plan
If React version has issues:
1. **Immediate:** Set `formipay_use_react_admin` to false
2. **Users see:** Classic Grid.js version (fully functional)
3. **Fix React:** Debug and fix in development
4. **Retest:** Go through checklist again
5. **Re-enable:** Set flag back to true
**Critical:** Never deploy without working fallback!
---
## Migration Checklist Template
Copy this template for each page migration:
### [Page Name] Migration Checklist
#### Table Core Features
- [ ] Data loads and displays correctly
- [ ] Loading spinner shown during fetch
- [ ] Empty state shown when no data
- [ ] Error state handled gracefully
#### Selection Features
- [ ] Checkbox column renders
- [ ] "Select All" checkbox works
- [ ] Individual row checkboxes work
- [ ] Checkboxes persist across page changes
- [ ] Bulk delete button appears when rows selected
- [ ] Bulk delete confirmation modal
- [ ] Bulk delete refreshes table
#### Row Actions
- [ ] Hover shows action links
- [ ] Edit action navigates correctly
- [ ] Delete action shows confirmation
- [ ] Delete action removes row and refreshes
- [ ] Duplicate action shows confirmation
- [ ] Duplicate action adds new row and refreshes
#### Filtering & Sorting
- [ ] Status filter tabs work
- [ ] Status counts display correctly
- [ ] Active filter highlighted
- [ ] Search input filters results
- [ ] Search debounce (don't spam server)
- [ ] Sort dropdown works
- [ ] Order toggle works
- [ ] Combined filters work (search + status + sort)
#### Pagination
- [ ] Pagination controls display
- [ ] Page numbers correct
- [ ] Next/Previous buttons work
- [ ] Limit per page respected
- [ ] Total count accurate
#### Create Features
- [ ] "Add New" button visible
- [ ] Modal/dialog opens on click
- [ ] Modal has required fields
- [ ] Modal validation works
- [ ] Create action succeeds
- [ ] Post creation redirects to edit
- [ ] Error handling in modal
#### UX Details
- [ ] Row hover effects work
- [ ] Selected row highlighting
- [ ] Toast notifications for actions
- [ ] Confirmation dialogs for destructive actions
- [ ] Keyboard accessibility (Enter, Escape)
- [ ] Loading states during actions
#### Data Compatibility
- [ ] Same AJAX endpoints as old version
- [ ] Same request format
- [ ] Same response format handling
- [ ] Hidden inputs updated (if applicable)
- [ ] WordPress nonces handled correctly
---
## Notes
- **Grid.js Library:** ~20KB, well-tested, handles server-side pagination well
- **@tanstack/react-table:** ~9KB, headless, requires more setup but more flexible
- **jQuery:** Still used by WordPress core, will remain for now
- **SweetAlert2:** Keep using, integrates well with React
- **Migration is NOT a race:** Take time to get it right
---
*End of Migration Strategy.*