Skip to content

Commit

Permalink
Merge pull request #46 from arifshariati/banking
Browse files Browse the repository at this point in the history
refactor(banking): forms and dynamicform rendering
  • Loading branch information
arifshariati authored Aug 26, 2024
2 parents 8ee0fb3 + c83978e commit 32b2859
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 13 deletions.
2 changes: 1 addition & 1 deletion apps/banking/src/app/(root)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type RootLayoutProps = {

const RootLayout = async ({ children }: RootLayoutProps) => {
const loggedIn = await getLoggedInUsers();
if (!loggedIn) redirect('/sign-in');
if (!loggedIn) redirect('/sign-up');

return (
<div className="grid min-h-screen w-full md:grid-cols-[220px_1fr] lg:grid-cols-[280px_1fr]">
Expand Down
10 changes: 9 additions & 1 deletion apps/banking/src/components/forms/sign-in/sign-in-form.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use client';

import { useState } from 'react';
import Link from 'next/link';
import { useRouter } from 'next/navigation';
import { DynamicForm } from '@monor/ui/dynamic-form';
import { formConfig } from './sign-in-form-config';
Expand All @@ -22,12 +23,19 @@ const SignInForm = () => {
}
};
return (
<div className="p-4 w-full lg:w-[500px]">
<div className="flex flex-col gap-2 p-4 w-full lg:w-[500px]">
<DynamicForm
config={formConfig}
onSubmit={handleSubmit}
isLoading={isLoading}
/>
<div className="flex gap-2 items-center justify-center text-sm">
{"Don't have an account?"}
<Link href={'/sign-up'} className="underline">
{' '}
Sign Up
</Link>
</div>
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const formConfig: FormConfig = {
type: 'string',
rules: [{ method: 'min', params: [1] }],
},
group: 'name',
},
{
name: 'lastName',
Expand All @@ -24,6 +25,7 @@ export const formConfig: FormConfig = {
type: 'string',
rules: [{ method: 'min', params: [1] }],
},
group: 'name',
},
{
name: 'address1',
Expand Down Expand Up @@ -54,6 +56,7 @@ export const formConfig: FormConfig = {
type: 'string',
rules: [],
},
group: 'address',
},
{
name: 'postalCode',
Expand All @@ -64,6 +67,7 @@ export const formConfig: FormConfig = {
type: 'string',
rules: [],
},
group: 'address',
},
{
name: 'dateOfBirth',
Expand Down
10 changes: 9 additions & 1 deletion apps/banking/src/components/forms/sign-up/sign-up-form.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use client';

import { useState } from 'react';
import Link from 'next/link';
import { useRouter } from 'next/navigation';
import { DynamicForm } from '@monor/ui/dynamic-form';
import { formConfig } from './sign-up-form-config';
Expand All @@ -25,12 +26,19 @@ const SignUpForm = () => {
}
};
return (
<div className="p-4 w-full lg:w-[500px]">
<div className="flex flex-col gap-2 p-4 w-full lg:w-[500px]">
<DynamicForm
config={formConfig}
onSubmit={handleSubmit}
isLoading={isLoading}
/>
<div className="flex gap-2 items-center justify-center text-sm">
Already have an account?
<Link href={'/sign-in'} className="underline">
{' '}
Sign In
</Link>
</div>
</div>
);
};
Expand Down
1 change: 1 addition & 0 deletions libs/types/src/form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export type FormFieldConfig = {
type: ZodMethodType;
rules: ValidationRule[];
};
group?: string;
};

export type FormConfig = {
Expand Down
43 changes: 33 additions & 10 deletions libs/ui/src/dynamic-form.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { SubmitHandler, useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { RefreshCcw } from 'lucide-react';
import { cn } from '@monor/utils/tailwind/cn';
import {
FormConfig,
FormFieldConfig,
Expand All @@ -22,7 +24,6 @@ import { DateFieled } from './form/date-field';
import { SelectField } from './form/select-field';
import { TextareaField } from './form/text-area-field';
import { TextField } from './form/text-field';
import { RefreshCcw } from 'lucide-react';

export const renderField = (field: FormFieldConfig, controllerField: any) => {
switch (field.type) {
Expand Down Expand Up @@ -86,6 +87,14 @@ export const DynamicForm = ({
defaultValues: config.defaultValues,
});

// group fields by 'group' property
const groupedFields = config.fields.reduce((acc, field) => {
const groupKey = field.group || field.name;
if (!acc[groupKey]) acc[groupKey] = [];
acc[groupKey].push(field);
return acc;
}, {} as Record<string, FormFieldConfig[]>);

return (
<Card>
<CardHeader>
Expand All @@ -97,15 +106,29 @@ export const DynamicForm = ({
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)}>
<CardContent className="space-y-1">
{config.fields.map((field) => (
<FormField
key={field.name}
control={form.control}
name={field.name}
render={({ field: controllerField }) =>
renderField(field, controllerField)
}
/>
{Object.entries(groupedFields).map(([groupKey, fields]) => (
<div
key={groupKey}
className={cn(
'flex',
fields.length > 1
? 'flex-row justify-between gap-2'
: 'flex-col'
)}
>
{fields.map((field) => (
<div className="w-full">
<FormField
key={field.name}
control={form.control}
name={field.name}
render={({ field: controllerField }) =>
renderField(field, controllerField)
}
/>
</div>
))}
</div>
))}
</CardContent>
<CardFooter>
Expand Down

0 comments on commit 32b2859

Please sign in to comment.