From a8f6e05a6ec385ceb45bd68279e98da9da2b224d Mon Sep 17 00:00:00 2001 From: Jeroen Branje Date: Wed, 14 Feb 2024 22:15:09 +0100 Subject: [PATCH 1/4] feat(envited.ascs.digital): Add Dashboard Profile Signed-off-by: Jeroen Branje --- .../Atoms/Form/Checkbox/Checkbox.stories.tsx | 33 ++ .../Atoms/Form/Checkbox/Checkbox.tsx | 51 +++ .../Atoms/Form/Checkbox/Checkbox.ui.test.tsx | 16 + .../Form/Checkbox/Checkboxes.stories.tsx | 50 +++ .../Atoms/Form/Checkbox/Checkboxes.tsx | 70 ++++ .../Form/Checkbox/Checkboxes.ui.test.tsx | 42 +++ .../components/Atoms/Form/Checkbox/index.ts | 2 + .../Atoms/Form/Input/TextField.stories.tsx | 32 ++ .../components/Atoms/Form/Input/TextField.tsx | 44 +++ .../Atoms/Form/Input/TextField.ui.test.tsx | 16 + .../src/components/Atoms/Form/Input/index.ts | 1 + .../Atoms/Form/Textarea/TextField.ui.test.tsx | 16 + .../Form/Textarea/TextareaField.stories.tsx | 34 ++ .../Atoms/Form/Textarea/TextareaField.tsx | 49 +++ .../components/Atoms/Form/Textarea/index.ts | 1 + .../src/components/Atoms/Form/index.ts | 3 + apps/design-system/src/index.ts | 1 + .../app/dashboard/profile/page.tsx | 10 +- .../common/database/queries/categories.ts | 4 + .../common/database/queries/queries.ts | 2 + .../common/i18n/useI18n.ts | 2 + .../common/serverActions/index.ts | 2 +- .../common/serverActions/profiles/get.ts | 24 +- .../common/serverActions/profiles/index.ts | 2 +- .../serverActions/profiles/update.test.ts | 12 +- .../common/serverActions/profiles/update.ts | 2 +- .../common/types/types.ts | 8 +- .../modules/Profile/Profile.actions.ts | 28 ++ .../modules/Profile/Profile.intl.ts | 12 + .../modules/Profile/Profile.schema.ts | 18 + .../modules/Profile/Profile.test.tsx | 29 ++ .../modules/Profile/Profile.tsx | 346 ++++++++++++++++++ .../modules/Profile/index.ts | 5 + .../modules/Profile/locales/de_DE.json | 23 ++ .../modules/Profile/locales/en_GB.json | 23 ++ package-lock.json | 29 +- package.json | 5 +- 37 files changed, 1032 insertions(+), 15 deletions(-) create mode 100644 apps/design-system/src/components/Atoms/Form/Checkbox/Checkbox.stories.tsx create mode 100644 apps/design-system/src/components/Atoms/Form/Checkbox/Checkbox.tsx create mode 100644 apps/design-system/src/components/Atoms/Form/Checkbox/Checkbox.ui.test.tsx create mode 100644 apps/design-system/src/components/Atoms/Form/Checkbox/Checkboxes.stories.tsx create mode 100644 apps/design-system/src/components/Atoms/Form/Checkbox/Checkboxes.tsx create mode 100644 apps/design-system/src/components/Atoms/Form/Checkbox/Checkboxes.ui.test.tsx create mode 100644 apps/design-system/src/components/Atoms/Form/Checkbox/index.ts create mode 100644 apps/design-system/src/components/Atoms/Form/Input/TextField.stories.tsx create mode 100644 apps/design-system/src/components/Atoms/Form/Input/TextField.tsx create mode 100644 apps/design-system/src/components/Atoms/Form/Input/TextField.ui.test.tsx create mode 100644 apps/design-system/src/components/Atoms/Form/Input/index.ts create mode 100644 apps/design-system/src/components/Atoms/Form/Textarea/TextField.ui.test.tsx create mode 100644 apps/design-system/src/components/Atoms/Form/Textarea/TextareaField.stories.tsx create mode 100644 apps/design-system/src/components/Atoms/Form/Textarea/TextareaField.tsx create mode 100644 apps/design-system/src/components/Atoms/Form/Textarea/index.ts create mode 100644 apps/design-system/src/components/Atoms/Form/index.ts create mode 100644 apps/envited.ascs.digital/common/database/queries/categories.ts create mode 100644 apps/envited.ascs.digital/modules/Profile/Profile.actions.ts create mode 100644 apps/envited.ascs.digital/modules/Profile/Profile.intl.ts create mode 100644 apps/envited.ascs.digital/modules/Profile/Profile.schema.ts create mode 100644 apps/envited.ascs.digital/modules/Profile/Profile.test.tsx create mode 100644 apps/envited.ascs.digital/modules/Profile/Profile.tsx create mode 100644 apps/envited.ascs.digital/modules/Profile/index.ts create mode 100644 apps/envited.ascs.digital/modules/Profile/locales/de_DE.json create mode 100644 apps/envited.ascs.digital/modules/Profile/locales/en_GB.json diff --git a/apps/design-system/src/components/Atoms/Form/Checkbox/Checkbox.stories.tsx b/apps/design-system/src/components/Atoms/Form/Checkbox/Checkbox.stories.tsx new file mode 100644 index 00000000..3c56c5b9 --- /dev/null +++ b/apps/design-system/src/components/Atoms/Form/Checkbox/Checkbox.stories.tsx @@ -0,0 +1,33 @@ +import { Meta, Story } from '@storybook/react' + +import { Checkbox } from './Checkbox' + +export default { + component: Checkbox, + title: 'Components/Form/Checkbox', +} as Meta + +const CheckboxTemplate: Story = ({ label, name, value, checked, description, inputRef, onChange }) => ( + +) + +export const CheckboxComponent = CheckboxTemplate.bind({}) + +CheckboxComponent.args = { + label: 'label', + name: 'name', + value: 'value', + description: 'DESCRIPTION', + error: 'ERROR', + checked: false, + inputRef: null, + onChange: () => {}, +} diff --git a/apps/design-system/src/components/Atoms/Form/Checkbox/Checkbox.tsx b/apps/design-system/src/components/Atoms/Form/Checkbox/Checkbox.tsx new file mode 100644 index 00000000..dc75361a --- /dev/null +++ b/apps/design-system/src/components/Atoms/Form/Checkbox/Checkbox.tsx @@ -0,0 +1,51 @@ +import { isEmpty } from 'ramda' +import { FC, JSXElementConstructor, ReactElement } from 'react' +import { RefCallBack } from 'react-hook-form' + +interface CheckboxProps { + name: string + value?: string | number + checked: boolean + label: string | ReactElement> + description?: string + inputRef: RefCallBack + onChange?: (event: React.ChangeEvent) => void +} + +export const Checkbox: FC = ({ + name, + value = '', + checked, + label, + description = '', + inputRef, + onChange, +}) => { + return ( +
+
+ +
+
+ + {!isEmpty(description) && ( +

+ {description} +

+ )} +
+
+ ) +} diff --git a/apps/design-system/src/components/Atoms/Form/Checkbox/Checkbox.ui.test.tsx b/apps/design-system/src/components/Atoms/Form/Checkbox/Checkbox.ui.test.tsx new file mode 100644 index 00000000..3f10c129 --- /dev/null +++ b/apps/design-system/src/components/Atoms/Form/Checkbox/Checkbox.ui.test.tsx @@ -0,0 +1,16 @@ +import { render, screen } from '@testing-library/react' + +import { Checkbox } from './Checkbox' + +describe('atoms/Checkbox', () => { + describe('render', () => { + it('should render Checkbox', () => { + // when ... we rendering component + render( {}} name="NAME" />) + + // then ... it should return as expected + const element = screen.getByText('CHECKBOX') + expect(element).toBeInTheDocument() + }) + }) +}) diff --git a/apps/design-system/src/components/Atoms/Form/Checkbox/Checkboxes.stories.tsx b/apps/design-system/src/components/Atoms/Form/Checkbox/Checkboxes.stories.tsx new file mode 100644 index 00000000..bf61f042 --- /dev/null +++ b/apps/design-system/src/components/Atoms/Form/Checkbox/Checkboxes.stories.tsx @@ -0,0 +1,50 @@ +import { Meta, Story } from '@storybook/react' + +import { Checkboxes } from './Checkboxes' + +export default { + component: Checkboxes, + title: 'Components/Form/Checkboxes', +} as Meta + +const CheckboxesTemplate: Story = ({ label, name, values, description, inputRef, onChange }) => ( + values.push(x)} + description={description} + inputRef={inputRef} + onChange={onChange} + /> +) + +export const CheckboxesComponent = CheckboxesTemplate.bind({}) + +CheckboxesComponent.args = { + label: 'label', + name: 'name', + values: ['item-1'], + description: 'DESCRIPTION', + error: 'ERROR', + checked: false, + inputRef: null, + onChange: () => {}, +} diff --git a/apps/design-system/src/components/Atoms/Form/Checkbox/Checkboxes.tsx b/apps/design-system/src/components/Atoms/Form/Checkbox/Checkboxes.tsx new file mode 100644 index 00000000..552bb274 --- /dev/null +++ b/apps/design-system/src/components/Atoms/Form/Checkbox/Checkboxes.tsx @@ -0,0 +1,70 @@ +import { includes, isEmpty, map } from 'ramda' +import { ChangeEvent, FC, JSXElementConstructor, ReactElement } from 'react' +import { RefCallBack } from 'react-hook-form' + +interface CheckboxItem { + id: string + name: string + description: string +} + +interface CheckboxProps { + name: string + values: [] + label: string | ReactElement> + description?: string + error?: string + inputRef: RefCallBack + handleCheckbox: (id: string) => any + onChange: (event: ChangeEvent) => void + items: CheckboxItem[] +} + +export const Checkboxes: FC = ({ + name, + values = [], + label, + description = '', + error = '', + inputRef, + handleCheckbox, + onChange, + items, +}) => ( + <> + + {!isEmpty(description) &&

{description}

} +
+ {map(({ id, name: itemName, description: itemDescription }: CheckboxItem) => ( +
+
+ onChange(handleCheckbox(id))} + ref={inputRef} + checked={includes(id)(values)} + type="checkbox" + className="h-4 w-4 rounded border-gray-300 text-orange-600 focus:ring-orange-600" + /> +
+
+ + {!isEmpty(itemDescription) && ( +

+ {itemDescription} +

+ )} +
+
+ ))(items)} +
+ {!isEmpty(error) &&

{error}

} + +) diff --git a/apps/design-system/src/components/Atoms/Form/Checkbox/Checkboxes.ui.test.tsx b/apps/design-system/src/components/Atoms/Form/Checkbox/Checkboxes.ui.test.tsx new file mode 100644 index 00000000..75abaff9 --- /dev/null +++ b/apps/design-system/src/components/Atoms/Form/Checkbox/Checkboxes.ui.test.tsx @@ -0,0 +1,42 @@ +import { render, screen } from '@testing-library/react' + +import { Checkboxes } from './Checkboxes' + +describe('atoms/Checkboxes', () => { + describe('render', () => { + it('should render Checkboxes', () => { + // when ... we rendering component + render( + {}} + onChange={() => {}} + inputRef={() => {}} + name="NAME" + />, + ) + + // then ... it should return as expected + const element = screen.getByText('CHECKBOXES') + expect(element).toBeInTheDocument() + }) + }) +}) diff --git a/apps/design-system/src/components/Atoms/Form/Checkbox/index.ts b/apps/design-system/src/components/Atoms/Form/Checkbox/index.ts new file mode 100644 index 00000000..939eb127 --- /dev/null +++ b/apps/design-system/src/components/Atoms/Form/Checkbox/index.ts @@ -0,0 +1,2 @@ +export { Checkbox } from './Checkbox' +export { Checkboxes } from './Checkboxes' diff --git a/apps/design-system/src/components/Atoms/Form/Input/TextField.stories.tsx b/apps/design-system/src/components/Atoms/Form/Input/TextField.stories.tsx new file mode 100644 index 00000000..3cf35f6f --- /dev/null +++ b/apps/design-system/src/components/Atoms/Form/Input/TextField.stories.tsx @@ -0,0 +1,32 @@ +import { Meta, Story } from '@storybook/react' + +import { TextField } from './TextField' + +export default { + component: TextField, + title: 'Components/Form/TextField', +} as Meta + +const TextTemplate: Story = ({ label, name, value, error, disabled, inputRef, onChange }) => ( + +) + +export const TextComponent = TextTemplate.bind({}) + +TextComponent.args = { + label: 'label', + name: 'name', + value: 'value', + error: 'ERROR', + disabled: false, + inputRef: null, + onChange: () => {}, +} diff --git a/apps/design-system/src/components/Atoms/Form/Input/TextField.tsx b/apps/design-system/src/components/Atoms/Form/Input/TextField.tsx new file mode 100644 index 00000000..8d5210c2 --- /dev/null +++ b/apps/design-system/src/components/Atoms/Form/Input/TextField.tsx @@ -0,0 +1,44 @@ +import { isEmpty } from 'ramda' +import { FC, JSXElementConstructor, ReactElement } from 'react' +import { RefCallBack } from 'react-hook-form' + +interface TextFieldProps { + label: string | ReactElement> + name: string + value: string + error?: string + disabled?: boolean + inputRef: RefCallBack + onChange?: (event: React.ChangeEvent) => void +} + +export const TextField: FC = ({ + label, + name, + value, + error = '', + disabled = false, + inputRef, + onChange, +}) => { + return ( + <> + +
+ +
+ {!isEmpty(error) &&

{error}

} + + ) +} diff --git a/apps/design-system/src/components/Atoms/Form/Input/TextField.ui.test.tsx b/apps/design-system/src/components/Atoms/Form/Input/TextField.ui.test.tsx new file mode 100644 index 00000000..f127e76c --- /dev/null +++ b/apps/design-system/src/components/Atoms/Form/Input/TextField.ui.test.tsx @@ -0,0 +1,16 @@ +import { render, screen } from '@testing-library/react' + +import { TextField } from './TextField' + +describe('atoms/TextField', () => { + describe('render', () => { + it('should render TextField', () => { + // when ... we rendering component + render( {}} name="NAME" />) + + // then ... it should return as expected + const element = screen.getByText('LABEL') + expect(element).toBeInTheDocument() + }) + }) +}) diff --git a/apps/design-system/src/components/Atoms/Form/Input/index.ts b/apps/design-system/src/components/Atoms/Form/Input/index.ts new file mode 100644 index 00000000..dea5f2d4 --- /dev/null +++ b/apps/design-system/src/components/Atoms/Form/Input/index.ts @@ -0,0 +1 @@ +export { TextField } from './TextField' diff --git a/apps/design-system/src/components/Atoms/Form/Textarea/TextField.ui.test.tsx b/apps/design-system/src/components/Atoms/Form/Textarea/TextField.ui.test.tsx new file mode 100644 index 00000000..3c9b7eeb --- /dev/null +++ b/apps/design-system/src/components/Atoms/Form/Textarea/TextField.ui.test.tsx @@ -0,0 +1,16 @@ +import { render, screen } from '@testing-library/react' + +import { TextareaField } from './TextareaField' + +describe('atoms/TextareaField', () => { + describe('render', () => { + it('should render TextareaField', () => { + // when ... we rendering component + render( {}} name="NAME" />) + + // then ... it should return as expected + const element = screen.getByText('LABEL') + expect(element).toBeInTheDocument() + }) + }) +}) diff --git a/apps/design-system/src/components/Atoms/Form/Textarea/TextareaField.stories.tsx b/apps/design-system/src/components/Atoms/Form/Textarea/TextareaField.stories.tsx new file mode 100644 index 00000000..2d520025 --- /dev/null +++ b/apps/design-system/src/components/Atoms/Form/Textarea/TextareaField.stories.tsx @@ -0,0 +1,34 @@ +import { Meta, Story } from '@storybook/react' + +import { TextareaField } from './TextareaField' + +export default { + component: TextareaField, + title: 'Components/Form/TextareaField', +} as Meta + +const TextareaTemplate: Story = ({ label, name, value, description, error, disabled, inputRef, onChange }) => ( + +) + +export const TextareaComponent = TextareaTemplate.bind({}) + +TextareaComponent.args = { + label: 'label', + name: 'name', + value: 'value', + description: 'DESCRIPTION', + error: 'ERROR', + disabled: false, + inputRef: null, + onChange: () => {}, +} diff --git a/apps/design-system/src/components/Atoms/Form/Textarea/TextareaField.tsx b/apps/design-system/src/components/Atoms/Form/Textarea/TextareaField.tsx new file mode 100644 index 00000000..880809a9 --- /dev/null +++ b/apps/design-system/src/components/Atoms/Form/Textarea/TextareaField.tsx @@ -0,0 +1,49 @@ +import { isEmpty } from 'ramda' +import { FC, JSXElementConstructor, ReactElement } from 'react' +import { RefCallBack } from 'react-hook-form' + +interface TextareaFieldProps { + label: string | ReactElement> + name: string + value: string + description?: ReactElement> + error?: string + disabled?: boolean + inputRef: RefCallBack + onChange?: (event: React.ChangeEvent) => void +} + +export const TextareaField: FC = ({ + label, + name, + value, + description = '', + error = '', + disabled = false, + inputRef, + onChange, +}) => { + return ( + <> + +
+