Skip to content

Commit a872b62

Browse files
committed
refactor: decouple fields from state in DynamicForms
1 parent e5a03f6 commit a872b62

9 files changed

Lines changed: 78 additions & 57 deletions

File tree

core/app/[locale]/(default)/(auth)/register/_actions/register-customer.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -335,9 +335,9 @@ function parseRegisterCustomerInput(
335335
}
336336

337337
export async function registerCustomer<F extends Field>(
338+
fields: Array<F | FieldGroup<F>>,
338339
prevState: {
339340
lastResult: SubmissionResult | null;
340-
fields: Array<F | FieldGroup<F>>;
341341
passwordComplexity?: Parameters<typeof schema>[1];
342342
},
343343
formData: FormData,
@@ -347,19 +347,19 @@ export async function registerCustomer<F extends Field>(
347347
const cartId = await getCartId();
348348

349349
const submission = parseWithZod(formData, {
350-
schema: schema(prevState.fields, prevState.passwordComplexity),
350+
schema: schema(fields, prevState.passwordComplexity),
351351
});
352352

353353
if (submission.status !== 'success') {
354354
return {
355355
lastResult: submission.reply(),
356-
fields: prevState.fields,
356+
fields,
357357
passwordComplexity: prevState.passwordComplexity,
358358
};
359359
}
360360

361361
try {
362-
const input = parseRegisterCustomerInput(submission.value, prevState.fields);
362+
const input = parseRegisterCustomerInput(submission.value, fields);
363363
const response = await client.fetch({
364364
document: RegisterCustomerMutation,
365365
variables: {
@@ -375,7 +375,7 @@ export async function registerCustomer<F extends Field>(
375375
lastResult: submission.reply({
376376
formErrors: response.data.customer.registerCustomer.errors.map((error) => error.message),
377377
}),
378-
fields: prevState.fields,
378+
fields,
379379
passwordComplexity: prevState.passwordComplexity,
380380
};
381381
}
@@ -397,22 +397,22 @@ export async function registerCustomer<F extends Field>(
397397
lastResult: submission.reply({
398398
formErrors: error.errors.map(({ message }) => message),
399399
}),
400-
fields: prevState.fields,
400+
fields,
401401
passwordComplexity: prevState.passwordComplexity,
402402
};
403403
}
404404

405405
if (error instanceof Error) {
406406
return {
407407
lastResult: submission.reply({ formErrors: [error.message] }),
408-
fields: prevState.fields,
408+
fields,
409409
passwordComplexity: prevState.passwordComplexity,
410410
};
411411
}
412412

413413
return {
414414
lastResult: submission.reply({ formErrors: [t('somethingWentWrong')] }),
415-
fields: prevState.fields,
415+
fields,
416416
passwordComplexity: prevState.passwordComplexity,
417417
};
418418
}

core/app/[locale]/(default)/account/addresses/_actions/address-action.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,28 @@ export interface State {
1111
addresses: Address[];
1212
lastResult: SubmissionResult | null;
1313
defaultAddress?: DefaultAddressConfiguration;
14-
fields: Array<Field | FieldGroup<Field>>;
1514
}
1615

17-
export async function addressAction(prevState: Awaited<State>, formData: FormData): Promise<State> {
16+
export async function addressAction(
17+
fields: Array<Field | FieldGroup<Field>>,
18+
prevState: Awaited<State>,
19+
formData: FormData,
20+
): Promise<State> {
1821
'use server';
1922

2023
const intent = formData.get('intent');
2124

2225
switch (intent) {
2326
case 'create': {
24-
return await createAddress(prevState, formData);
27+
return await createAddress(fields, prevState, formData);
2528
}
2629

2730
case 'update': {
28-
return await updateAddress(prevState, formData);
31+
return await updateAddress(fields, prevState, formData);
2932
}
3033

3134
case 'delete': {
32-
return await deleteAddress(prevState, formData);
35+
return await deleteAddress(fields, prevState, formData);
3336
}
3437

3538
default: {

core/app/[locale]/(default)/account/addresses/_actions/create-address.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,11 @@ function parseAddAddressInput(
196196
return inputSchema.parse(mappedInput);
197197
}
198198

199-
export async function createAddress(prevState: Awaited<State>, formData: FormData): Promise<State> {
199+
export async function createAddress(
200+
fields: Array<Field | FieldGroup<Field>>,
201+
prevState: Awaited<State>,
202+
formData: FormData,
203+
): Promise<State> {
200204
const t = await getTranslations('Account.Addresses');
201205
const customerAccessToken = await getSessionCustomerAccessToken();
202206

@@ -210,7 +214,7 @@ export async function createAddress(prevState: Awaited<State>, formData: FormDat
210214
}
211215

212216
try {
213-
const input = parseAddAddressInput(submission.value, prevState.fields);
217+
const input = parseAddAddressInput(submission.value, fields);
214218

215219
const response = await client.fetch({
216220
document: AddCustomerAddressMutation,
@@ -242,7 +246,6 @@ export async function createAddress(prevState: Awaited<State>, formData: FormDat
242246
],
243247
lastResult: submission.reply({ resetForm: true }),
244248
defaultAddress: prevState.defaultAddress,
245-
fields: prevState.fields,
246249
};
247250
} catch (error) {
248251
// eslint-disable-next-line no-console

core/app/[locale]/(default)/account/addresses/_actions/delete-address.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { unstable_expireTag as expireTag } from 'next/cache';
44
import { getTranslations } from 'next-intl/server';
55
import { z } from 'zod';
66

7+
import { Field, FieldGroup } from '@/vibes/soul/form/dynamic-form/schema';
78
import { schema } from '@/vibes/soul/sections/address-list-section/schema';
89
import { getSessionCustomerAccessToken } from '~/auth';
910
import { client } from '~/client';
@@ -44,7 +45,11 @@ function parseDeleteAddressInput(
4445
});
4546
}
4647

47-
export async function deleteAddress(prevState: Awaited<State>, formData: FormData): Promise<State> {
48+
export async function deleteAddress(
49+
_fields: Array<Field | FieldGroup<Field>>,
50+
prevState: Awaited<State>,
51+
formData: FormData,
52+
): Promise<State> {
4853
const t = await getTranslations('Account.Addresses');
4954
const customerAccessToken = await getSessionCustomerAccessToken();
5055

@@ -86,7 +91,6 @@ export async function deleteAddress(prevState: Awaited<State>, formData: FormDat
8691
),
8792
lastResult: submission.reply({ resetForm: true }),
8893
defaultAddress: prevState.defaultAddress,
89-
fields: prevState.fields,
9094
};
9195
} catch (error) {
9296
// eslint-disable-next-line no-console

core/app/[locale]/(default)/account/addresses/_actions/update-address.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,11 @@ function parseUpdateAddressInput(
209209
return inputSchema.parse(mappedInput);
210210
}
211211

212-
export async function updateAddress(prevState: Awaited<State>, formData: FormData): Promise<State> {
212+
export async function updateAddress(
213+
fields: Array<Field | FieldGroup<Field>>,
214+
prevState: Awaited<State>,
215+
formData: FormData,
216+
): Promise<State> {
213217
const t = await getTranslations('Account.Addresses');
214218
const customerAccessToken = await getSessionCustomerAccessToken();
215219

@@ -223,7 +227,7 @@ export async function updateAddress(prevState: Awaited<State>, formData: FormDat
223227
}
224228

225229
try {
226-
const input = parseUpdateAddressInput(submission.value, prevState.fields);
230+
const input = parseUpdateAddressInput(submission.value, fields);
227231

228232
const response = await client.fetch({
229233
document: UpdateCustomerAddressMutation,
@@ -251,7 +255,6 @@ export async function updateAddress(prevState: Awaited<State>, formData: FormDat
251255
),
252256
lastResult: submission.reply({ resetForm: true }),
253257
defaultAddress: prevState.defaultAddress,
254-
fields: prevState.fields,
255258
};
256259
} catch (error) {
257260
// eslint-disable-next-line no-console

core/app/[locale]/(default)/gift-certificates/purchase/_actions/add-to-cart.tsx

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import { getPreferredCurrencyCode } from '~/lib/currency';
1919
import { GiftCertificateSettingsFragment } from '../fragment';
2020

2121
interface State {
22-
fields: Array<Field | FieldGroup<Field>>;
2322
lastResult: SubmissionResult | null;
2423
successMessage?: ReactNode;
2524
}
@@ -101,7 +100,8 @@ const schema = (
101100
};
102101

103102
export async function addGiftCertificateToCart(
104-
prevState: State,
103+
_fields: Array<Field | FieldGroup<Field>>,
104+
_prevState: State,
105105
formData: FormData,
106106
): Promise<State> {
107107
const t = await getTranslations('GiftCertificates.Purchase');
@@ -117,7 +117,7 @@ export async function addGiftCertificateToCart(
117117
});
118118

119119
if (submission.status !== 'success') {
120-
return { lastResult: submission.reply(), fields: prevState.fields };
120+
return { lastResult: submission.reply() };
121121
}
122122

123123
const amountFormatted = format.number(submission.value.amount, {
@@ -148,7 +148,6 @@ export async function addGiftCertificateToCart(
148148

149149
return {
150150
lastResult: submission.reply(),
151-
fields: prevState.fields,
152151
successMessage: t.rich('successMessage', {
153152
cartLink: (chunks) => (
154153
<Link className="underline" href="/cart" prefetch="viewport" prefetchKind="full">
@@ -168,27 +167,23 @@ export async function addGiftCertificateToCart(
168167
return message;
169168
}),
170169
}),
171-
fields: prevState.fields,
172170
};
173171
}
174172

175173
if (error instanceof MissingCartError) {
176174
return {
177175
lastResult: submission.reply({ formErrors: [t('missingCart')] }),
178-
fields: prevState.fields,
179176
};
180177
}
181178

182179
if (error instanceof Error) {
183180
return {
184181
lastResult: submission.reply({ formErrors: [error.message] }),
185-
fields: prevState.fields,
186182
};
187183
}
188184

189185
return {
190186
lastResult: submission.reply({ formErrors: [t('unknownError')] }),
191-
fields: prevState.fields,
192187
};
193188
}
194189
}

core/app/[locale]/(default)/webpages/[id]/contact/_actions/submit-contact-form.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,19 @@ function parseContactFormInput(
5858
}
5959

6060
export async function submitContactForm<F extends Field>(
61-
prevState: { lastResult: SubmissionResult | null; fields: Array<F | FieldGroup<F>> },
61+
fields: Array<F | FieldGroup<F>>,
62+
_prevState: { lastResult: SubmissionResult | null },
6263
formData: FormData,
6364
) {
6465
const t = await getTranslations('WebPages.ContactUs.Form');
6566
const locale = await getLocale();
6667

67-
const submission = parseWithZod(formData, { schema: schema(prevState.fields) });
68+
const submission = parseWithZod(formData, { schema: schema(fields) });
6869

6970
if (submission.status !== 'success') {
7071
return {
7172
lastResult: submission.reply(),
72-
fields: prevState.fields,
73+
fields,
7374
};
7475
}
7576

@@ -88,7 +89,7 @@ export async function submitContactForm<F extends Field>(
8889
if (result.errors.length > 0) {
8990
return {
9091
lastResult: submission.reply({ formErrors: result.errors.map((error) => error.message) }),
91-
fields: prevState.fields,
92+
fields,
9293
};
9394
}
9495
} catch (error) {
@@ -100,20 +101,20 @@ export async function submitContactForm<F extends Field>(
100101
lastResult: submission.reply({
101102
formErrors: error.errors.map(({ message }) => message),
102103
}),
103-
fields: prevState.fields,
104+
fields,
104105
};
105106
}
106107

107108
if (error instanceof Error) {
108109
return {
109110
lastResult: submission.reply({ formErrors: [error.message] }),
110-
fields: prevState.fields,
111+
fields,
111112
};
112113
}
113114

114115
return {
115116
lastResult: submission.reply({ formErrors: [t('somethingWentWrong')] }),
116-
fields: prevState.fields,
117+
fields,
117118
};
118119
}
119120

core/vibes/soul/form/dynamic-form/index.tsx

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,19 @@ import { Button, ButtonProps } from '@/vibes/soul/primitives/button';
3838

3939
import { Field, FieldGroup, PasswordComplexitySettings, schema } from './schema';
4040

41-
type Action<S, P> = (state: Awaited<S>, payload: P) => S | Promise<S>;
41+
type Action<F extends Field, S, P> = (
42+
fields: Array<F | FieldGroup<F>>,
43+
state: Awaited<S>,
44+
payload: P,
45+
) => S | Promise<S>;
4246

43-
interface State<F extends Field> {
44-
fields: Array<F | FieldGroup<F>>;
47+
interface State {
4548
lastResult: SubmissionResult | null;
4649
successMessage?: ReactNode;
4750
passwordComplexity?: PasswordComplexitySettings | null;
4851
}
4952

50-
export type DynamicFormAction<F extends Field> = Action<State<F>, FormData>;
53+
export type DynamicFormAction<F extends Field> = Action<F, State, FormData>;
5154

5255
export interface DynamicFormProps<F extends Field> {
5356
fields: Array<F | FieldGroup<F>>;
@@ -65,7 +68,7 @@ export interface DynamicFormProps<F extends Field> {
6568

6669
export function DynamicForm<F extends Field>({
6770
action,
68-
fields: defaultFields,
71+
fields,
6972
buttonSize = 'medium',
7073
cancelLabel = 'Cancel',
7174
submitLabel = 'Submit',
@@ -76,10 +79,11 @@ export function DynamicForm<F extends Field>({
7679
onSuccess,
7780
passwordComplexity: defaultPasswordComplexity,
7881
}: DynamicFormProps<F>) {
79-
const [{ lastResult, fields, successMessage, passwordComplexity }, formAction] = useActionState(
80-
action,
82+
const actionWithFields = action.bind(null, fields);
83+
84+
const [{ lastResult, successMessage, passwordComplexity }, formAction] = useActionState(
85+
actionWithFields,
8186
{
82-
fields: defaultFields,
8387
lastResult: null,
8488
passwordComplexity: defaultPasswordComplexity,
8589
},

0 commit comments

Comments
 (0)