From 1aaab6c5939cc50c8ab76a55aaa4d829433e7cce Mon Sep 17 00:00:00 2001 From: "soroush.asadi" Date: Tue, 2 Jun 2026 08:15:16 +0330 Subject: [PATCH] fix(admin): integrations save uses rendered list (fixes dropped Zarinpal merchantId) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The integrations form rendered from (gateways state, falling back to fetched data) but SAVED from the state and edited via updateGateway on . If gateways hadn't hydrated, edits (e.g. Zarinpal merchantId) were written to an empty array and the save sent nothing. Now updateGateway seeds from fetched data on first edit, and the save maps over — render, edit, and save share one source. NOTE: prod admin had also been stale because recent deploys aborted on the main-API crash before the admin containers restarted. Co-Authored-By: Claude Opus 4.8 --- .../src/components/admin/admin-screens.tsx | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/web/admin/src/components/admin/admin-screens.tsx b/web/admin/src/components/admin/admin-screens.tsx index 2e18089..0e91226 100644 --- a/web/admin/src/components/admin/admin-screens.tsx +++ b/web/admin/src/components/admin/admin-screens.tsx @@ -605,11 +605,18 @@ export function AdminIntegrationsScreen() { }); }, [data]); + const list = gateways.length > 0 ? gateways : data?.paymentGateways ?? []; + const save = useMutation({ mutationFn: () => adminPut("/api/admin/integrations", { activePaymentGateway: activeGateway, - paymentGateways: gateways.map((g) => ({ + // Save from `list` (what's rendered/edited), not `gateways` — if the + // gateways state hasn't hydrated, `list` falls back to the fetched data, + // and edits go through updateGateway which seeds it. This keeps the + // rendered, edited, and saved arrays the same source (was dropping + // edits like the Zarinpal merchantId when gateways was empty). + paymentGateways: list.map((g) => ({ id: g.id, isEnabled: g.isEnabled, merchantId: g.id === "zarinpal" ? g.merchantId : undefined, @@ -638,11 +645,14 @@ export function AdminIntegrationsScreen() { }); const updateGateway = (id: string, patch: Partial) => { - setGateways((prev) => prev.map((g) => (g.id === id ? { ...g, ...patch } : g))); + setGateways((prev) => { + // Seed from fetched data on the first edit so an edit is never dropped + // because the state hadn't hydrated yet. + const base = prev.length > 0 ? prev : data?.paymentGateways?.map((g) => ({ ...g })) ?? []; + return base.map((g) => (g.id === id ? { ...g, ...patch } : g)); + }); }; - const list = gateways.length > 0 ? gateways : data?.paymentGateways ?? []; - return (