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 && (
)
}}
/>
)}
);
};