import clsx from 'clsx'; import { useGetCheckoutLoyaltyBalanceQuery, usePayWithLoyaltyBalanceMutation } from '@akinon/next/data/client/checkout'; import { useAppSelector } from '@akinon/next/redux/hooks'; import { useEffect, useMemo, useState } from 'react'; import { useLocalization } from '@akinon/next/hooks'; import { twMerge } from 'tailwind-merge'; import { Icon, Price } from '@theme/components'; import { Trans } from '@akinon/next/components'; import { LoaderSpinner } from '@theme/components'; import { AccountUsage, LoyaltyBalanceItem } from '@akinon/next/types'; export const StoreCredits = () => { const { t } = useLocalization(); const [payWithLoyaltyBalance, { isLoading: isPayLoading }] = usePayWithLoyaltyBalanceMutation(); const { loyaltyBalance, loyaltyBalances, preOrder } = useAppSelector( (state) => state.checkout ); const { data: checkoutLoyaltyData, isLoading: isLoyaltyBalanceLoading } = useGetCheckoutLoyaltyBalanceQuery(undefined, { refetchOnMountOrArgChange: true, skip: !preOrder?.payment_option }); // New approach: read accounts from LoyaltyMoneyUsagePage context const loyaltyAccounts: LoyaltyBalanceItem[] = useMemo(() => { const loyaltyContext = checkoutLoyaltyData?.context_list?.find( (ctx) => ctx.page_name === 'LoyaltyMoneyUsagePage' ); return ( (loyaltyContext?.page_context?.accounts as LoyaltyBalanceItem[]) ?? [] ); }, [checkoutLoyaltyData]); const selectableAccounts = useMemo(() => { return loyaltyAccounts.filter((account) => parseFloat(account.balance) > 0); }, [loyaltyAccounts]); // Determine which mode to use: // - "accounts" mode: backend returns page_context.accounts (new) // - "legacy" mode: Redux loyaltyBalance/loyaltyBalances from page_context.balance/balances (old) const hasAccounts = selectableAccounts.length > 0; const hasLegacyGrouped = !hasAccounts && loyaltyBalances?.length > 0; const hasLegacySingle = !hasAccounts && !hasLegacyGrouped && parseFloat(loyaltyBalance || '0') > 0; const isLoyaltyBalanceUsed = useMemo(() => { return parseFloat(preOrder?.loyalty_money ?? '0') > 0; }, [preOrder?.loyalty_money]); // --- Accounts mode state --- const [selectedAccountIds, setSelectedAccountIds] = useState>( new Set() ); useEffect(() => { if (!hasAccounts) return; const usages = preOrder?.loyalty_account_usages; if (usages && Array.isArray(usages)) { setSelectedAccountIds( new Set( usages .filter((u) => parseFloat(String(u.amount)) > 0) .map((u) => String(u.label_id)) ) ); } else if ( parseFloat(preOrder?.loyalty_money ?? '0') > 0 && selectableAccounts.length > 0 ) { setSelectedAccountIds( new Set(selectableAccounts.map((a) => String(a.label_id))) ); } else { setSelectedAccountIds(new Set()); } }, [ hasAccounts, preOrder?.loyalty_account_usages, preOrder?.loyalty_money, selectableAccounts ]); // --- Legacy grouped mode state --- const [selectedLabels, setSelectedLabels] = useState>( {} ); const [isLoading, setIsLoading] = useState(false); const totalGroupedBalance = useMemo(() => { if (!loyaltyBalances) return 0; return loyaltyBalances.reduce( (sum, item) => sum + parseFloat(item.balance || '0'), 0 ); }, [loyaltyBalances]); // --- Handlers --- const handleToggleAccount = async (account: LoyaltyBalanceItem) => { if (isLoading) return; setIsLoading(true); try { const key = String(account.label_id); const newSelected = new Set(selectedAccountIds); if (newSelected.has(key)) { newSelected.delete(key); } else { newSelected.add(key); } setSelectedAccountIds(newSelected); const accountUsages: AccountUsage[] = selectableAccounts .filter((acc) => newSelected.has(String(acc.label_id))) .map((acc) => ({ label_id: acc.label_id, amount: parseFloat(acc.balance) })); await payWithLoyaltyBalance({ account_usages: accountUsages }); } finally { setIsLoading(false); } }; const handleToggleLegacyAll = async () => { if (isLoading) return; setIsLoading(true); try { if (isLoyaltyBalanceUsed) { if (hasLegacyGrouped) { const accountUsages: AccountUsage[] = loyaltyBalances.map((item) => ({ label_id: item.label_id, amount: 0 })); await payWithLoyaltyBalance({ account_usages: accountUsages }); setSelectedLabels({}); } else { await payWithLoyaltyBalance('0'); } } else { if (hasLegacyGrouped) { const accountUsages: AccountUsage[] = loyaltyBalances.map((item) => ({ label_id: item.label_id, amount: parseFloat(item.balance) })); await payWithLoyaltyBalance({ account_usages: accountUsages }); const allSelected = loyaltyBalances.reduce( (acc, item) => ({ ...acc, [String(item.label_id)]: true }), {} as Record ); setSelectedLabels(allSelected); } else { await payWithLoyaltyBalance(loyaltyBalance); } } } finally { setIsLoading(false); } }; const handleToggleLegacyLabel = async (item: LoyaltyBalanceItem) => { if (isLoading) return; setIsLoading(true); try { const key = String(item.label_id); const isCurrentlySelected = selectedLabels[key] ?? false; const newSelectedLabels = { ...selectedLabels, [key]: !isCurrentlySelected }; const accountUsages: AccountUsage[] = loyaltyBalances.map((b) => ({ label_id: b.label_id, amount: newSelectedLabels[String(b.label_id)] ? parseFloat(b.balance) : 0 })); await payWithLoyaltyBalance({ account_usages: accountUsages }); setSelectedLabels(newSelectedLabels); } finally { setIsLoading(false); } }; // --- Early returns --- if (preOrder?.is_guest) { return null; } if (isLoyaltyBalanceLoading) { return (
); } if (!hasAccounts && !hasLegacyGrouped && !hasLegacySingle) { return null; } // --- Accounts mode render (new: from page_context.accounts) --- if (hasAccounts) { return (
{selectableAccounts.map((account) => { const isSelected = selectedAccountIds.has(String(account.label_id)); return (

handleToggleAccount(account)} > {account.label ?? t('checkout.payment.store_credit.use_my_store_credits')}

{t('checkout.payment.store_credit.available_balance')}:

); })} {isLoyaltyBalanceUsed && parseFloat(preOrder?.unpaid_amount) > 0 && (

) }} />

)} ); } // --- Legacy grouped mode render (from Redux loyaltyBalances) --- if (hasLegacyGrouped) { return (

{t('checkout.payment.store_credit.use_my_store_credits')}

{t('checkout.payment.store_credit.total_balance')}:

{loyaltyBalances.map((item) => { const isSelected = selectedLabels[String(item.label_id)] ?? false; return (
handleToggleLegacyLabel(item)} > {item.label ?? t('checkout.payment.store_credit.use_my_store_credits')}
); })}
{isLoyaltyBalanceUsed && parseFloat(preOrder?.unpaid_amount) > 0 && (

) }} />

)} ); } // --- Legacy single balance mode render (from Redux loyaltyBalance) --- return (

{t('checkout.payment.store_credit.use_my_store_credits')}

{t('checkout.payment.store_credit.available_balance')}:

{isLoyaltyBalanceUsed && parseFloat(preOrder?.unpaid_amount) > 0 && (

) }} />

)} ); };