diff --git a/admin-spa/src/routes/Settings/Payments.tsx b/admin-spa/src/routes/Settings/Payments.tsx index 298a7d3..796a977 100644 --- a/admin-spa/src/routes/Settings/Payments.tsx +++ b/admin-spa/src/routes/Settings/Payments.tsx @@ -109,6 +109,16 @@ export default function PaymentsPage() { staleTime: 5 * 60 * 1000, // 5 minutes }); + // Initialize order from gateways + React.useEffect(() => { + if (gateways.length > 0 && manualOrder.length === 0 && onlineOrder.length === 0) { + const manual = gateways.filter((g: PaymentGateway) => g.type === 'manual').map((g: PaymentGateway) => g.id); + const online = gateways.filter((g: PaymentGateway) => g.type === 'provider' || g.type === 'other').map((g: PaymentGateway) => g.id); + setManualOrder(manual); + setOnlineOrder(online); + } + }, [gateways, manualOrder.length, onlineOrder.length]); + // Toggle gateway mutation const toggleMutation = useMutation({ mutationFn: ({ id, enabled }: { id: string; enabled: boolean }) => { @@ -151,15 +161,65 @@ export default function PaymentsPage() { setIsModalOpen(true); }; + // Handle drag end for manual gateways + const handleManualDragEnd = (event: DragEndEvent) => { + const { active, over } = event; + if (!over || active.id === over.id) return; + + const oldIndex = manualOrder.indexOf(active.id as string); + const newIndex = manualOrder.indexOf(over.id as string); + + const newOrder = arrayMove(manualOrder, oldIndex, newIndex); + setManualOrder(newOrder); + + // TODO: Save order to backend + toast.success('Payment methods reordered'); + }; + + // Handle drag end for online gateways + const handleOnlineDragEnd = (event: DragEndEvent) => { + const { active, over } = event; + if (!over || active.id === over.id) return; + + const oldIndex = onlineOrder.indexOf(active.id as string); + const newIndex = onlineOrder.indexOf(over.id as string); + + const newOrder = arrayMove(onlineOrder, oldIndex, newIndex); + setOnlineOrder(newOrder); + + // TODO: Save order to backend + toast.success('Payment methods reordered'); + }; + const handleSaveGateway = async (settings: Record) => { if (!selectedGateway) return; await saveMutation.mutateAsync({ id: selectedGateway.id, settings }); }; - // Categorize gateways - const manualGateways = gateways.filter((g: PaymentGateway) => g.type === 'manual'); - // Combine provider and other into single "3rd party" category - const thirdPartyGateways = gateways.filter((g: PaymentGateway) => g.type === 'provider' || g.type === 'other'); + // Separate and sort gateways by type and custom order + const manualGateways = React.useMemo(() => { + const manual = gateways.filter((g: PaymentGateway) => g.type === 'manual'); + if (manualOrder.length === 0) return manual; + return [...manual].sort((a, b) => { + const indexA = manualOrder.indexOf(a.id); + const indexB = manualOrder.indexOf(b.id); + if (indexA === -1) return 1; + if (indexB === -1) return -1; + return indexA - indexB; + }); + }, [gateways, manualOrder]); + + const thirdPartyGateways = React.useMemo(() => { + const online = gateways.filter((g: PaymentGateway) => g.type === 'provider' || g.type === 'other'); + if (onlineOrder.length === 0) return online; + return [...online].sort((a, b) => { + const indexA = onlineOrder.indexOf(a.id); + const indexB = onlineOrder.indexOf(b.id); + if (indexA === -1) return 1; + if (indexB === -1) return -1; + return indexA - indexB; + }); + }, [gateways, onlineOrder]); if (isLoading) { return ( @@ -197,48 +257,51 @@ export default function PaymentsPage() { {manualGateways.length === 0 ? (

No manual payment methods available

) : ( -
- {manualGateways.map((gateway: PaymentGateway) => ( -
-
-
-
- + + g.id)} strategy={verticalListSortingStrategy}> +
+ {manualGateways.map((gateway: PaymentGateway) => ( + +
+
+
+
+ +
+
+

{gateway.method_title || gateway.title}

+ {gateway.description && ( +

+ {gateway.description} +

+ )} +
+
+
+ {gateway.enabled && ( + + )} + handleToggle(gateway.id, checked)} + disabled={togglingGateway === gateway.id} + /> +
+
-
-

{gateway.method_title || gateway.title}

- {gateway.description && ( -

- {gateway.description} -

- )} -
-
-
- {gateway.enabled && ( - - )} - handleToggle(gateway.id, checked)} - disabled={togglingGateway === gateway.id} - /> -
-
+ + ))}
- ))} -
+ + )} @@ -248,60 +311,63 @@ export default function PaymentsPage() { title="Online Payment Methods" description="Accept credit cards, digital wallets, and other online payments" > -
- {thirdPartyGateways.map((gateway: PaymentGateway) => ( -
-
-
-
- -
-
-
-

- {gateway.method_title || gateway.title} -

+ + g.id)} strategy={verticalListSortingStrategy}> +
+ {thirdPartyGateways.map((gateway: PaymentGateway) => ( + +
+
+
+
+ +
+
+
+

+ {gateway.method_title || gateway.title} +

+
+ {gateway.method_description && ( +

+ {gateway.method_description} +

+ )} + {!gateway.requirements.met && ( + + + + Requirements not met: {gateway.requirements.missing.join(', ')} + + + )} +
+
+
+ {gateway.enabled && ( + + )} + handleToggle(gateway.id, checked)} + disabled={!gateway.requirements.met || togglingGateway === gateway.id} + /> +
- {gateway.method_description && ( -

- {gateway.method_description} -

- )} - {!gateway.requirements.met && ( - - - - Requirements not met: {gateway.requirements.missing.join(', ')} - - - )}
-
-
- {gateway.enabled && ( - - )} - handleToggle(gateway.id, checked)} - disabled={!gateway.requirements.met || togglingGateway === gateway.id} - /> -
-
+ + ))}
- ))} -
+ + )}