feat: migrate Coupons, Access, Customers, Licenses pages to full DataTable
Update all admin listing pages to use the full-featured DataTable component: Coupons page: - All columns (ID, code, type, amount, usages, date limit, status) - Status filter (All, Active, Inactive) - Inline actions and bulk delete - Add New modal Access page: - All columns (ID, title, product, status, date) - Status filter (All, Published, Draft) - Inline actions and bulk delete - Add New modal Customers page: - All columns (ID, name, email, phone, total orders, date) - Read-only (no selection or inline actions) - Search and pagination Licenses page: - All columns (ID, license key, product, order, email, status) - Status labels (Active, Inactive, Expired) - Read-only (no selection or inline actions) - Search and pagination Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1 +1 @@
|
||||
<?php return array('dependencies' => array('react', 'wp-components', 'wp-element', 'wp-i18n', 'wp-icons/build/arrow-left', 'wp-icons/build/bell', 'wp-icons/build/eye-closed', 'wp-icons/build/eye-opened', 'wp-icons/build/list', 'wp-icons/build/message', 'wp-icons/build/minus', 'wp-icons/build/plus', 'wp-icons/build/trash', 'wp-icons/build/visible'), 'version' => '164b137f81dde0451242');
|
||||
<?php return array('dependencies' => array('react', 'wp-components', 'wp-element', 'wp-i18n', 'wp-icons/build/arrow-left', 'wp-icons/build/bell', 'wp-icons/build/eye-closed', 'wp-icons/build/eye-opened', 'wp-icons/build/list', 'wp-icons/build/message', 'wp-icons/build/minus', 'wp-icons/build/plus', 'wp-icons/build/trash', 'wp-icons/build/visible'), 'version' => 'ea8676d843297ad5e987');
|
||||
|
||||
File diff suppressed because one or more lines are too long
BIN
node_modules/.cache/babel-loader/0ad392e4a022a30eb82054a0147079d607e5a8c6e67cbdc541cb3eac6504933d.json.gz
generated
vendored
Normal file
BIN
node_modules/.cache/babel-loader/0ad392e4a022a30eb82054a0147079d607e5a8c6e67cbdc541cb3eac6504933d.json.gz
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/.cache/babel-loader/0b7882e19c8bdddd6808bd0b54fcd61374b225048ab0d451abbe333d09fab460.json.gz
generated
vendored
Normal file
BIN
node_modules/.cache/babel-loader/0b7882e19c8bdddd6808bd0b54fcd61374b225048ab0d451abbe333d09fab460.json.gz
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/.cache/babel-loader/5a27f19ce1f1ca46b061d1feeb1df31e799ee018b9105f438b90f6d82a19ca75.json.gz
generated
vendored
Normal file
BIN
node_modules/.cache/babel-loader/5a27f19ce1f1ca46b061d1feeb1df31e799ee018b9105f438b90f6d82a19ca75.json.gz
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/.cache/babel-loader/6c8d197c6aef81da583f60809805cf20d20be3ba21f3d898ef1239e5e2e77ee8.json.gz
generated
vendored
Normal file
BIN
node_modules/.cache/babel-loader/6c8d197c6aef81da583f60809805cf20d20be3ba21f3d898ef1239e5e2e77ee8.json.gz
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/.cache/babel-loader/757e005cd7d8064797f4acf3ee23694f9833484004d3ebd442de956e40f29c90.json.gz
generated
vendored
Normal file
BIN
node_modules/.cache/babel-loader/757e005cd7d8064797f4acf3ee23694f9833484004d3ebd442de956e40f29c90.json.gz
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/.cache/babel-loader/81bc671315573b551e0bfafda03cf846121966f836ee2a2fe60307338dc66c9a.json.gz
generated
vendored
Normal file
BIN
node_modules/.cache/babel-loader/81bc671315573b551e0bfafda03cf846121966f836ee2a2fe60307338dc66c9a.json.gz
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/.cache/babel-loader/8ff0b9507ffef823cde6831d73d204ad9f7cebce4fc4fb80b7669ec46448a356.json.gz
generated
vendored
Normal file
BIN
node_modules/.cache/babel-loader/8ff0b9507ffef823cde6831d73d204ad9f7cebce4fc4fb80b7669ec46448a356.json.gz
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/.cache/babel-loader/bf45c8260791bbd05d8126d6c8542df5948d308c8405ee75e2830902d6ede1e6.json.gz
generated
vendored
Normal file
BIN
node_modules/.cache/babel-loader/bf45c8260791bbd05d8126d6c8542df5948d308c8405ee75e2830902d6ede1e6.json.gz
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/.cache/babel-loader/d91b2b36e48ca7c0ebb556e15f0c5897c5192cc26b2eba9a88137a56f5241cad.json.gz
generated
vendored
Normal file
BIN
node_modules/.cache/babel-loader/d91b2b36e48ca7c0ebb556e15f0c5897c5192cc26b2eba9a88137a56f5241cad.json.gz
generated
vendored
Normal file
Binary file not shown.
@@ -1,43 +1,17 @@
|
||||
/**
|
||||
* Access Page - Access items management
|
||||
* Access Page - Access items management with full table features
|
||||
*/
|
||||
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { useState, useCallback, useEffect } from '@wordpress/element';
|
||||
import { Button } from '@wordpress/components';
|
||||
import { accessApi } from '../api/client';
|
||||
import DataTable from '../components/shared/DataTable';
|
||||
import './AdminPages.css';
|
||||
|
||||
export default function AccessPage({ initialData }) {
|
||||
const [items, setItems] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
const loadItems = useCallback(() => {
|
||||
setLoading(true);
|
||||
accessApi.list()
|
||||
.then(result => {
|
||||
// Handle both WordPress format and direct format
|
||||
const items = result.data?.results || result.results || result.data || [];
|
||||
setItems(items);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Load access items error:', error);
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
loadItems();
|
||||
}, [loadItems]);
|
||||
|
||||
export default function AccessPage() {
|
||||
const columns = [
|
||||
{
|
||||
key: 'id',
|
||||
key: 'ID',
|
||||
label: __('ID', 'formipay'),
|
||||
render: (row) => <strong>#{row.id}</strong>
|
||||
render: (row) => <strong>#{row.ID}</strong>
|
||||
},
|
||||
{
|
||||
key: 'title',
|
||||
@@ -57,7 +31,7 @@ export default function AccessPage({ initialData }) {
|
||||
draft: __('Draft', 'formipay'),
|
||||
}[status] || status;
|
||||
return (
|
||||
<span className={`status-badge status-${status}`}>
|
||||
<span className={`status-label ${status}`}>
|
||||
{statusLabel}
|
||||
</span>
|
||||
);
|
||||
@@ -78,15 +52,33 @@ export default function AccessPage({ initialData }) {
|
||||
<div className="formipay-page-access">
|
||||
<div className="formipay-page-header">
|
||||
<h1>{ __('Access Items', 'formipay') }</h1>
|
||||
<Button variant="primary" href={window.formipayAdmin?.siteUrl + '/wp-admin/post-new.php?post_type=formipay-access'}>
|
||||
{ __('+ Add New Item', 'formipay') }
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={items}
|
||||
loading={loading}
|
||||
ajaxUrl={window.formipayAdmin?.ajaxUrl || '/wp-admin/admin-ajax.php'}
|
||||
nonce={window.formipayAdmin?.nonce || ''}
|
||||
tableAction="formipay-tabledata-access-items"
|
||||
deleteAction="formipay-delete-access-item"
|
||||
duplicateAction="formipay-duplicate-access-item"
|
||||
filterOptions={{
|
||||
key: 'post_status',
|
||||
options: [
|
||||
{ value: 'all', label: __('All', 'formipay') },
|
||||
{ value: 'publish', label: __('Published', 'formipay') },
|
||||
{ value: 'draft', label: __('Draft', 'formipay') },
|
||||
]
|
||||
}}
|
||||
actions={{
|
||||
addNew: {
|
||||
label: __('+ Add New Item', 'formipay'),
|
||||
action: 'formipay-create-access-item-post',
|
||||
},
|
||||
bulkDelete: {
|
||||
action: 'formipay-bulk-delete-access-item',
|
||||
},
|
||||
inline: true,
|
||||
}}
|
||||
emptyMessage={__('No access items found', 'formipay')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,43 +1,17 @@
|
||||
/**
|
||||
* Coupons Page - Coupon management
|
||||
* Coupons Page - Coupon management with full table features
|
||||
*/
|
||||
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { useState, useCallback, useEffect } from '@wordpress/element';
|
||||
import { Button } from '@wordpress/components';
|
||||
import { couponsApi } from '../api/client';
|
||||
import DataTable from '../components/shared/DataTable';
|
||||
import './AdminPages.css';
|
||||
|
||||
export default function CouponsPage({ initialData }) {
|
||||
const [coupons, setCoupons] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
const loadCoupons = useCallback(() => {
|
||||
setLoading(true);
|
||||
couponsApi.list()
|
||||
.then(result => {
|
||||
// Handle both WordPress format and direct format
|
||||
const coupons = result.data?.results || result.results || result.data || [];
|
||||
setCoupons(coupons);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Load coupons error:', error);
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
loadCoupons();
|
||||
}, [loadCoupons]);
|
||||
|
||||
export default function CouponsPage() {
|
||||
const columns = [
|
||||
{
|
||||
key: 'id',
|
||||
key: 'ID',
|
||||
label: __('ID', 'formipay'),
|
||||
render: (row) => <strong>#{row.id}</strong>
|
||||
render: (row) => <strong>#{row.ID}</strong>
|
||||
},
|
||||
{
|
||||
key: 'code',
|
||||
@@ -55,18 +29,36 @@ export default function CouponsPage({ initialData }) {
|
||||
{
|
||||
key: 'amount',
|
||||
label: __('Amount', 'formipay'),
|
||||
render: (row) => {
|
||||
// Multi-currency display would go here
|
||||
return row.amount || '-';
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'usages',
|
||||
label: __('Usages', 'formipay'),
|
||||
render: (row) => row.usage_count || row.usages || 0
|
||||
},
|
||||
{
|
||||
key: 'date_limit',
|
||||
label: __('Date Limit', 'formipay'),
|
||||
render: (row) => {
|
||||
const dateLimit = row.date_limit;
|
||||
if (!dateLimit || dateLimit === 'none') return __('Unlimited', 'formipay');
|
||||
return new Date(dateLimit).toLocaleDateString();
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'status',
|
||||
label: __('Status', 'formipay'),
|
||||
render: (row) => {
|
||||
const status = row.post_status || row.status || 'unknown';
|
||||
return status === 'publish' ? __('Active', 'formipay') : __('Inactive', 'formipay');
|
||||
const isActive = row.active === 'on' || status === 'publish';
|
||||
return (
|
||||
<span className={`status-label ${isActive ? 'publish' : 'draft'}`}>
|
||||
{isActive ? __('Active', 'formipay') : __('Inactive', 'formipay')}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
},
|
||||
];
|
||||
@@ -75,26 +67,33 @@ export default function CouponsPage({ initialData }) {
|
||||
<div className="formipay-page-coupons">
|
||||
<div className="formipay-page-header">
|
||||
<h1>{ __('Coupons', 'formipay') }</h1>
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={() => {
|
||||
// Open create modal - for now just prompt
|
||||
const code = prompt(__('Enter coupon code:', 'formipay'));
|
||||
if (code) {
|
||||
couponsApi.create({ code })
|
||||
.then(() => loadCoupons())
|
||||
.catch(console.error);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{ __('+ Add New Coupon', 'formipay') }
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={coupons}
|
||||
loading={loading}
|
||||
ajaxUrl={window.formipayAdmin?.ajaxUrl || '/wp-admin/admin-ajax.php'}
|
||||
nonce={window.formipayAdmin?.nonce || ''}
|
||||
tableAction="formipay-tabledata-coupons"
|
||||
deleteAction="formipay-delete-coupon"
|
||||
duplicateAction="formipay-duplicate-coupon"
|
||||
filterOptions={{
|
||||
key: 'status',
|
||||
options: [
|
||||
{ value: 'all', label: __('All', 'formipay') },
|
||||
{ value: 'active', label: __('Active', 'formipay') },
|
||||
{ value: 'inactive', label: __('Inactive', 'formipay') },
|
||||
]
|
||||
}}
|
||||
actions={{
|
||||
addNew: {
|
||||
label: __('+ Add New Coupon', 'formipay'),
|
||||
action: 'formipay-create-coupon-post',
|
||||
},
|
||||
bulkDelete: {
|
||||
action: 'formipay-bulk-delete-coupon',
|
||||
},
|
||||
inline: true,
|
||||
}}
|
||||
emptyMessage={__('No coupons found', 'formipay')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,37 +1,12 @@
|
||||
/**
|
||||
* Customers Page - Customer list
|
||||
* Customers Page - Customer list with full table features
|
||||
*/
|
||||
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { useState, useCallback, useEffect } from '@wordpress/element';
|
||||
import { customersApi } from '../api/client';
|
||||
import DataTable from '../components/shared/DataTable';
|
||||
import './AdminPages.css';
|
||||
|
||||
export default function CustomersPage({ initialData }) {
|
||||
const [customers, setCustomers] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
const loadCustomers = useCallback(() => {
|
||||
setLoading(true);
|
||||
customersApi.list()
|
||||
.then(result => {
|
||||
// Handle both WordPress format and direct format
|
||||
const customers = result.data?.results || result.results || result.data || [];
|
||||
setCustomers(customers);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Load customers error:', error);
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
loadCustomers();
|
||||
}, [loadCustomers]);
|
||||
|
||||
export default function CustomersPage() {
|
||||
const columns = [
|
||||
{
|
||||
key: 'id',
|
||||
@@ -76,8 +51,11 @@ export default function CustomersPage({ initialData }) {
|
||||
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={customers}
|
||||
loading={loading}
|
||||
ajaxUrl={window.formipayAdmin?.ajaxUrl || '/wp-admin/admin-ajax.php'}
|
||||
nonce={window.formipayAdmin?.nonce || ''}
|
||||
tableAction="formipay-tabledata-customers"
|
||||
selectable={false}
|
||||
inline={false}
|
||||
emptyMessage={__('No customers found', 'formipay')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,46 +1,12 @@
|
||||
/**
|
||||
* Licenses Page - License management
|
||||
* Licenses Page - License management with full table features
|
||||
*/
|
||||
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { useState, useCallback, useEffect } from '@wordpress/element';
|
||||
import DataTable from '../components/shared/DataTable';
|
||||
import './AdminPages.css';
|
||||
|
||||
export default function LicensesPage({ initialData }) {
|
||||
const [licenses, setLicenses] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
const loadLicenses = useCallback(() => {
|
||||
setLoading(true);
|
||||
// Licenses API might use a different endpoint
|
||||
fetch(window.formipayAdmin?.ajaxUrl || '/wp-admin/admin-ajax.php', {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: new URLSearchParams({
|
||||
action: 'formipay-tabledata-licenses',
|
||||
_wpnonce: window.formipayAdmin?.nonce || '',
|
||||
}),
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(result => {
|
||||
// Handle both WordPress format and direct format
|
||||
const licenses = result.data?.results || result.results || result.data || [];
|
||||
setLicenses(licenses);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Load licenses error:', error);
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
loadLicenses();
|
||||
}, [loadLicenses]);
|
||||
|
||||
export default function LicensesPage() {
|
||||
const columns = [
|
||||
{
|
||||
key: 'id',
|
||||
@@ -76,13 +42,17 @@ export default function LicensesPage({ initialData }) {
|
||||
inactive: __('Inactive', 'formipay'),
|
||||
expired: __('Expired', 'formipay'),
|
||||
};
|
||||
return statusLabels[status] || status;
|
||||
const statusClass = status === 'active' ? 'publish' : status === 'expired' ? 'pending' : 'draft';
|
||||
return (
|
||||
<span className={`status-label ${statusClass}`}>
|
||||
{statusLabels[status] || status}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="formipay-page-licenses">
|
||||
<div className="formipay-page-licenses">
|
||||
<div className="formipay-page-header">
|
||||
<h1>{ __('Licenses', 'formipay') }</h1>
|
||||
@@ -90,11 +60,13 @@ export default function LicensesPage({ initialData }) {
|
||||
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={licenses}
|
||||
loading={loading}
|
||||
ajaxUrl={window.formipayAdmin?.ajaxUrl || '/wp-admin/admin-ajax.php'}
|
||||
nonce={window.formipayAdmin?.nonce || ''}
|
||||
tableAction="formipay-tabledata-licenses"
|
||||
selectable={false}
|
||||
inline={false}
|
||||
emptyMessage={__('No licenses found', 'formipay')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user