fix(admin): integrations save uses rendered list (fixes dropped Zarinpal merchantId)
CI/CD / CI · API (dotnet build + test) (push) Successful in 58s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 33s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m6s
CI/CD / CI · Admin Web (tsc) (push) Successful in 38s
CI/CD / CI · Website (tsc) (push) Successful in 44s
CI/CD / CI · Koja (tsc) (push) Successful in 49s
CI/CD / Deploy · all services (push) Successful in 1m42s
CI/CD / CI · API (dotnet build + test) (push) Successful in 58s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 33s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m6s
CI/CD / CI · Admin Web (tsc) (push) Successful in 38s
CI/CD / CI · Website (tsc) (push) Successful in 44s
CI/CD / CI · Koja (tsc) (push) Successful in 49s
CI/CD / Deploy · all services (push) Successful in 1m42s
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 <noreply@anthropic.com>
This commit is contained in:
@@ -605,11 +605,18 @@ export function AdminIntegrationsScreen() {
|
||||
});
|
||||
}, [data]);
|
||||
|
||||
const list = gateways.length > 0 ? gateways : data?.paymentGateways ?? [];
|
||||
|
||||
const save = useMutation({
|
||||
mutationFn: () =>
|
||||
adminPut<PlatformIntegrations>("/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<PaymentGatewayConfig>) => {
|
||||
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 (
|
||||
<div className="space-y-6">
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
|
||||
Reference in New Issue
Block a user