fix: add defensive checks for map errors and global currencies loading

- Add Array.isArray checks to getGlobalCurrencies helper
- Store global currencies in state to avoid timing issues
- Add null checks when mapping over currencies
- Add defensive checks to TabNav and TabPanel components
- Improve error handling in data loading
This commit is contained in:
dwindown
2026-04-19 07:14:02 +07:00
parent d1de0015be
commit fe9efdfeec
4 changed files with 40 additions and 18 deletions

View File

@@ -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/message', 'wp-icons/build/trash', 'wp-primitives'), 'version' => 'f1f91f1cc72d44a0469e'); <?php return array('dependencies' => array('react', 'wp-components', 'wp-element', 'wp-i18n', 'wp-icons/build/arrow-left', 'wp-icons/build/bell', 'wp-icons/build/message', 'wp-icons/build/trash', 'wp-primitives'), 'version' => '1a2b3d6682654786741a');

File diff suppressed because one or more lines are too long

View File

@@ -9,24 +9,28 @@ import { MetaboxLayout, TabNav, TabPanel, Field, Input, Checkbox, Textarea, Butt
// Currency helper functions // Currency helper functions
const getGlobalCurrencies = () => { const getGlobalCurrencies = () => {
if (window.formipayGlobalCurrencies) { if (window.formipayGlobalCurrencies && Array.isArray(window.formipayGlobalCurrencies)) {
return window.formipayGlobalCurrencies; return window.formipayGlobalCurrencies;
} }
console.warn('[Formipay] Global currencies not available or not an array');
return []; return [];
}; };
const getCurrencySymbol = (currencyRaw) => { const getCurrencySymbol = (currencyRaw) => {
if (!currencyRaw || typeof currencyRaw !== 'string') return '';
const parts = currencyRaw.split(':::'); const parts = currencyRaw.split(':::');
return parts[1] || currencyRaw; return parts[1] || currencyRaw;
}; };
const getCurrencyCode = (currencyRaw) => { const getCurrencyCode = (currencyRaw) => {
if (!currencyRaw || typeof currencyRaw !== 'string') return '';
const parts = currencyRaw.split(':::'); const parts = currencyRaw.split(':::');
return parts[0] || currencyRaw; return parts[0] || currencyRaw;
}; };
const getFlagByCurrency = (currencyRaw) => { const getFlagByCurrency = (currencyRaw) => {
if (window.formipayGetFlag) { if (!currencyRaw || typeof currencyRaw !== 'string') return '';
if (window.formipayGetFlag && typeof window.formipayGetFlag === 'function') {
return window.formipayGetFlag(currencyRaw); return window.formipayGetFlag(currencyRaw);
} }
return ''; return '';
@@ -37,6 +41,7 @@ export default function CouponMetabox({ postId }) {
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [saving, setSaving] = useState(false); const [saving, setSaving] = useState(false);
const [message, setMessage] = useState(null); const [message, setMessage] = useState(null);
const [globalCurrencies, setGlobalCurrencies] = useState([]);
// Form state // Form state
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
@@ -60,8 +65,13 @@ export default function CouponMetabox({ postId }) {
{ id: 'restriction', label: __('Restrictions', 'formipay'), icon: 'fa fa-lock' }, { id: 'restriction', label: __('Restrictions', 'formipay'), icon: 'fa fa-lock' },
]; ];
// Load coupon data // Load coupon data and global currencies
useEffect(() => { useEffect(() => {
// Load global currencies from window object
const currencies = getGlobalCurrencies();
console.log('[Formipay Coupon] Global currencies:', currencies);
setGlobalCurrencies(currencies);
if (postId > 0) { if (postId > 0) {
loadCouponData(); loadCouponData();
} else { } else {
@@ -95,17 +105,17 @@ export default function CouponMetabox({ postId }) {
quantity_active: data.quantity_active || '', quantity_active: data.quantity_active || '',
use_limit: data.use_limit || '', use_limit: data.use_limit || '',
date_limit: data.date_limit || '', date_limit: data.date_limit || '',
amounts_fixed: data.amounts_fixed?.reduce((acc, item) => { amounts_fixed: Array.isArray(data.amounts_fixed) ? data.amounts_fixed.reduce((acc, item) => {
acc[item.symbol] = item.amount; if (item && item.symbol) acc[item.symbol] = item.amount;
return acc; return acc;
}, {}) || {}, }, {}) : {},
max_amounts: data.max_amounts?.reduce((acc, item) => { max_amounts: Array.isArray(data.max_amounts) ? data.max_amounts.reduce((acc, item) => {
acc[item.symbol] = item.amount; if (item && item.symbol) acc[item.symbol] = item.amount;
return acc; return acc;
}, {}) || {}, }, {}) : {},
forms: data.forms || [], forms: Array.isArray(data.forms) ? data.forms : [],
products: data.products || [], products: Array.isArray(data.products) ? data.products : [],
customers: data.customers || [], customers: Array.isArray(data.customers) ? data.customers : [],
})); }));
} }
} catch (error) { } catch (error) {
@@ -256,14 +266,15 @@ export default function CouponMetabox({ postId }) {
<> <>
<GroupTitle title={__('Discount Amount', 'formipay')} icon="fa fa-money" /> <GroupTitle title={__('Discount Amount', 'formipay')} icon="fa fa-money" />
{getGlobalCurrencies().map((currency) => { {globalCurrencies.map((currency) => {
if (!currency || !currency.currency) return null;
const symbol = getCurrencySymbol(currency.currency); const symbol = getCurrencySymbol(currency.currency);
const currencyCode = getCurrencyCode(currency.currency); const currencyCode = getCurrencyCode(currency.currency);
const flag = getFlagByCurrency(currency.currency); const flag = getFlagByCurrency(currency.currency);
const step = currency.decimal_digits > 0 ? 1 / (currency.decimal_digits * 10) : 1; const step = currency.decimal_digits > 0 ? 1 / (currency.decimal_digits * 10) : 1;
return ( return (
<div key={currencyCode} className="formipay-generic-field"> <div key={currencyCode || symbol} className="formipay-generic-field">
<div className="formipay-field-aside"> <div className="formipay-field-aside">
<div className="formipay-field-label required"> <div className="formipay-field-label required">
<span className="formipay-field-label-text"> <span className="formipay-field-label-text">
@@ -297,7 +308,8 @@ export default function CouponMetabox({ postId }) {
icon="fa fa-calculator" icon="fa fa-calculator"
/> />
{getGlobalCurrencies().map((currency) => { {globalCurrencies.map((currency) => {
if (!currency || !currency.currency) return null;
const symbol = getCurrencySymbol(currency.currency); const symbol = getCurrencySymbol(currency.currency);
const currencyCode = getCurrencyCode(currency.currency); const currencyCode = getCurrencyCode(currency.currency);
const flag = getFlagByCurrency(currency.currency); const flag = getFlagByCurrency(currency.currency);
@@ -305,7 +317,7 @@ export default function CouponMetabox({ postId }) {
return ( return (
<Field <Field
key={`max_${currencyCode}`} key={`max_${currencyCode || symbol}`}
label={ label={
<span> <span>
{flag && <img src={flag} alt="" width="18" style={{ verticalAlign: 'middle', marginRight: '4px' }} />} {flag && <img src={flag} alt="" width="18" style={{ verticalAlign: 'middle', marginRight: '4px' }} />}

View File

@@ -26,6 +26,11 @@ export function BoxChild({ children, className = '', ...props }) {
// Tab Navigation Component - WPCFTO sidebar style // Tab Navigation Component - WPCFTO sidebar style
export function TabNav({ tabs, activeTab, onTabChange, orientation = 'vertical' }) { export function TabNav({ tabs, activeTab, onTabChange, orientation = 'vertical' }) {
if (!tabs || !Array.isArray(tabs)) {
console.warn('[Formipay] TabNav: tabs is not an array', tabs);
return null;
}
return ( return (
<div className={`formipay-wpcfto-tab-nav ${orientation === 'vertical' ? 'formipay-wpcfto-sidebar' : ''}`}> <div className={`formipay-wpcfto-tab-nav ${orientation === 'vertical' ? 'formipay-wpcfto-sidebar' : ''}`}>
<div className="formipay-wpcfto-tab-nav-inner"> <div className="formipay-wpcfto-tab-nav-inner">
@@ -66,6 +71,11 @@ export function TabNav({ tabs, activeTab, onTabChange, orientation = 'vertical'
// Tab Panel Component // Tab Panel Component
export function TabPanel({ tabs, activeTab, children }) { export function TabPanel({ tabs, activeTab, children }) {
if (!tabs || !Array.isArray(tabs)) {
console.warn('[Formipay] TabPanel: tabs is not an array', tabs);
return null;
}
return ( return (
<div className="formipay-tabs"> <div className="formipay-tabs">
{tabs.map((tab, index) => ( {tabs.map((tab, index) => (