Skip to content

Commit c67aac3

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

9 files changed

Lines changed: 80 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 }: { 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 }: { 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 }: { 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: 7 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,12 @@ function parseDeleteAddressInput(
4445
});
4546
}
4647

47-
export async function deleteAddress(prevState: Awaited<State>, formData: FormData): Promise<State> {
48+
export async function deleteAddress(
49+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
50+
{ fields }: { fields: Array<Field | FieldGroup<Field>> },
51+
prevState: Awaited<State>,
52+
formData: FormData,
53+
): Promise<State> {
4854
const t = await getTranslations('Account.Addresses');
4955
const customerAccessToken = await getSessionCustomerAccessToken();
5056

@@ -86,7 +92,6 @@ export async function deleteAddress(prevState: Awaited<State>, formData: FormDat
8692
),
8793
lastResult: submission.reply({ resetForm: true }),
8894
defaultAddress: prevState.defaultAddress,
89-
fields: prevState.fields,
9095
};
9196
} catch (error) {
9297
// 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 }: { 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: 4 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,9 @@ const schema = (
101100
};
102101

103102
export async function addGiftCertificateToCart(
104-
prevState: State,
103+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
104+
{ fields }: { fields: Array<Field | FieldGroup<Field>> },
105+
_prevState: State,
105106
formData: FormData,
106107
): Promise<State> {
107108
const t = await getTranslations('GiftCertificates.Purchase');
@@ -117,7 +118,7 @@ export async function addGiftCertificateToCart(
117118
});
118119

119120
if (submission.status !== 'success') {
120-
return { lastResult: submission.reply(), fields: prevState.fields };
121+
return { lastResult: submission.reply() };
121122
}
122123

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

149150
return {
150151
lastResult: submission.reply(),
151-
fields: prevState.fields,
152152
successMessage: t.rich('successMessage', {
153153
cartLink: (chunks) => (
154154
<Link className="underline" href="/cart" prefetch="viewport" prefetchKind="full">
@@ -168,27 +168,23 @@ export async function addGiftCertificateToCart(
168168
return message;
169169
}),
170170
}),
171-
fields: prevState.fields,
172171
};
173172
}
174173

175174
if (error instanceof MissingCartError) {
176175
return {
177176
lastResult: submission.reply({ formErrors: [t('missingCart')] }),
178-
fields: prevState.fields,
179177
};
180178
}
181179

182180
if (error instanceof Error) {
183181
return {
184182
lastResult: submission.reply({ formErrors: [error.message] }),
185-
fields: prevState.fields,
186183
};
187184
}
188185

189186
return {
190187
lastResult: submission.reply({ formErrors: [t('unknownError')] }),
191-
fields: prevState.fields,
192188
};
193189
}
194190
}

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 }: { 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 }: { 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)