-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactored form component, added dedicated provider and context methods
- Loading branch information
Matt Mangan
committed
Jan 12, 2024
1 parent
3908945
commit ea8466d
Showing
9 changed files
with
197 additions
and
113 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,52 @@ | ||
export interface CreateDatasetFormData { | ||
export interface CreateDatasetFormFields { | ||
createDatasetTitle: string | ||
} | ||
|
||
export class CreateDataset { | ||
submitDataset = async (formData: CreateDatasetFormData): Promise<string> => { | ||
console.log('Submitting dataset:', formData) | ||
return Promise.resolve('Form submitted successfully!') | ||
export interface FormValidationResult { | ||
isValid: boolean | ||
errors: Record<keyof CreateDatasetFormFields, string | undefined> | ||
} | ||
|
||
export interface FormValidationService { | ||
validateForm: (fields: CreateDatasetFormFields) => FormValidationResult | ||
} | ||
|
||
export const formValidationService: FormValidationService = { | ||
validateForm: (fields: CreateDatasetFormFields): FormValidationResult => { | ||
const errors: Record<keyof CreateDatasetFormFields, string | undefined> = { | ||
createDatasetTitle: undefined | ||
} | ||
|
||
if (!fields.createDatasetTitle) { | ||
errors.createDatasetTitle = 'Name is required' | ||
} | ||
|
||
return { | ||
isValid: Object.values(errors).every((error) => error === undefined), | ||
errors | ||
} | ||
} | ||
} | ||
|
||
// formSubmissionService | ||
export interface FormSubmissionService { | ||
submitFormData: (fields: CreateDatasetFormFields) => Promise<void> | ||
} | ||
export const formSubmissionService: FormSubmissionService = { | ||
// If there's an asynchronous operation, use `await` here. | ||
submitFormData: async (fields: CreateDatasetFormFields): Promise<void> => { | ||
// For example, if submitting data to a server: | ||
console.log('Submitting form data:', fields) | ||
const sendDataMock = (fields: CreateDatasetFormFields) => { | ||
// Simulate a network delay, for example, 2 seconds | ||
const delay = 2000 | ||
|
||
validateCreateDatasetFormData = (formData: CreateDatasetFormData): boolean => { | ||
// Add validation logic here | ||
return formData.createDatasetTitle.trim() !== '' | ||
return new Promise((resolve) => { | ||
setTimeout(() => { | ||
resolve('Form Data Submitted: ' + JSON.stringify(fields)) | ||
}, delay) | ||
}) | ||
} | ||
await sendDataMock(fields) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,57 +1,30 @@ | ||
import React, { createContext, useContext, ReactNode } from 'react' | ||
import CreateDatasetFormPresenter from './CreateDatasetForm' | ||
import { useTranslation } from 'react-i18next' | ||
import { CreateDataset, CreateDatasetFormData } from '../../dataset/domain/useCases/createDataset' | ||
import styles from '/src/sections/dataset/Dataset.module.scss' | ||
import { SeparationLine } from '../../components/layout/SeparationLine/SeparationLine' | ||
import { createContext, useContext } from 'react' | ||
import { CreateDatasetFormFields } from '../../dataset/domain/useCases/createDataset' // Importing the FormFields type | ||
|
||
interface CreateDatasetFormProps { | ||
submitDataset: (formData: CreateDatasetFormData) => Promise<string> | ||
validateCreateDatasetFormData: (formData: CreateDatasetFormData) => boolean | ||
// Define the context and its interface | ||
interface FormContextInterface { | ||
formState: CreateDatasetFormFields | ||
updateFormState: (newState: CreateDatasetFormFields) => void | ||
} | ||
|
||
const DatasetContext = createContext<CreateDatasetFormProps>({} as CreateDatasetFormProps) | ||
interface DatasetProviderProps { | ||
children: ReactNode | ||
// Define default values for the context | ||
const defaultFormState: CreateDatasetFormFields = { | ||
// Initialize with default values for your form fields | ||
createDatasetTitle: '' | ||
} | ||
export const DatasetProvider: React.FC<DatasetProviderProps> = ({ children }) => { | ||
const createDatasetUseCase = new CreateDataset() | ||
|
||
return ( | ||
<DatasetContext.Provider | ||
value={{ | ||
submitDataset: createDatasetUseCase.submitDataset, | ||
validateCreateDatasetFormData: createDatasetUseCase.validateCreateDatasetFormData | ||
}}> | ||
{children} | ||
</DatasetContext.Provider> | ||
) | ||
const defaultContext: FormContextInterface = { | ||
formState: defaultFormState, | ||
updateFormState: () => { | ||
// This is a no-op function since the default context shouldn't update anything | ||
} | ||
} | ||
// Hook for easy consumption of the context | ||
export const useDataset = () => useContext(DatasetContext) | ||
|
||
export function CreateDatasetContainer() { | ||
const { t } = useTranslation('createDataset') | ||
return ( | ||
<> | ||
<article> | ||
<header className={styles.header}> | ||
<h1>{t('pageTitle')}</h1> | ||
</header> | ||
<SeparationLine /> | ||
<div className={styles.container}> | ||
<CreateDatasetFormPresenter /> | ||
</div> | ||
</article> | ||
</> | ||
) | ||
} | ||
|
||
export const DatasetCreateMaster: React.FC = () => { | ||
return ( | ||
<DatasetProvider> | ||
<CreateDatasetContainer /> | ||
</DatasetProvider> | ||
) | ||
export const FormContext = createContext<FormContextInterface>(defaultContext) | ||
// Custom hook to use the form context | ||
export const useFormContext = () => { | ||
const context = useContext(FormContext) | ||
if (!context) { | ||
throw new Error('useFormContext must be used within a FormProvider') | ||
} | ||
return context | ||
} | ||
export default DatasetCreateMaster |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,21 @@ | ||
import { CreateDatasetFormPresenter } from './CreateDatasetForm' | ||
import { CreateDatasetProvider } from './CreateDatasetProvider' | ||
import { formValidationService } from '../../dataset/domain/useCases/createDataset' | ||
import { formSubmissionService } from '../../dataset/domain/useCases/createDataset' | ||
import { ReactElement } from 'react' | ||
import { DatasetCreateMaster } from './CreateDatasetContext' | ||
export const CreateDatasetForm: React.FC = () => { | ||
return ( | ||
<CreateDatasetProvider> | ||
<CreateDatasetFormPresenter | ||
formValidationService={formValidationService} | ||
formSubmissionService={formSubmissionService} | ||
/> | ||
</CreateDatasetProvider> | ||
) | ||
} | ||
|
||
export class CreateDatasetFactory { | ||
static create(): ReactElement { | ||
return <DatasetCreateMaster /> | ||
return <CreateDatasetForm /> | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { PropsWithChildren, useState, ReactNode } from 'react' | ||
import { useTranslation } from 'react-i18next' | ||
import styles from '/src/sections/dataset/Dataset.module.scss' | ||
import { SeparationLine } from '../../components/layout/SeparationLine/SeparationLine' | ||
import { FormContext } from './CreateDatasetContext' | ||
import { CreateDatasetFormFields } from '../../dataset/domain/useCases/createDataset' | ||
// Add a type for the children prop | ||
type FormProviderProps = { | ||
children: ReactNode | ||
} | ||
// Context Provider Component | ||
export const CreateDatasetProvider: React.FC<FormProviderProps> = ({ | ||
children | ||
}: PropsWithChildren) => { | ||
const [formState, setFormState] = useState<CreateDatasetFormFields>({ | ||
createDatasetTitle: '' | ||
}) | ||
const { t } = useTranslation('createDataset') | ||
const updateFormState = (newState: CreateDatasetFormFields) => { | ||
setFormState((prevState) => ({ ...prevState, ...newState })) | ||
} | ||
|
||
return ( | ||
<> | ||
<article> | ||
<header className={styles.header}> | ||
<h1>{t('pageTitle')}</h1> | ||
</header> | ||
<SeparationLine /> | ||
<div className={styles.container}> | ||
<FormContext.Provider value={{ formState, updateFormState }}> | ||
{children} | ||
</FormContext.Provider> | ||
</div> | ||
</article> | ||
</> | ||
) | ||
} |
17 changes: 8 additions & 9 deletions
17
src/stories/dataset/dataset-create/DatasetCreate.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,17 @@ | ||
import type { Meta, StoryObj } from '@storybook/react' | ||
import { WithI18next } from '../../WithI18next' | ||
import type { StoryObj, Meta } from '@storybook/react' | ||
import { CreateDatasetForm } from '../../../sections/create-dataset/CreateDatasetFactory' | ||
import { WithLayout } from '../../WithLayout' | ||
import DatasetCreateMaster from '../../../sections/create-dataset/CreateDatasetContext' | ||
import { WithI18next } from '../../WithI18next' | ||
|
||
const meta: Meta<typeof DatasetCreateMaster> = { | ||
const meta: Meta<typeof CreateDatasetForm> = { | ||
title: 'Pages/Create Dataset', | ||
component: DatasetCreateMaster, | ||
component: CreateDatasetForm, | ||
decorators: [WithI18next, WithLayout] | ||
} | ||
|
||
export default meta | ||
type Story = StoryObj<typeof DatasetCreateMaster> | ||
type Story = StoryObj<typeof CreateDatasetForm> | ||
|
||
export const Default: Story = { | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment | ||
render: () => <DatasetCreateMaster /> | ||
decorators: [WithLayout, WithI18next], | ||
render: () => <CreateDatasetForm /> | ||
} |
Oops, something went wrong.