From 2cc5e2604a2c0c19f293b6e395d9c71bfda922b3 Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Wed, 13 Nov 2024 15:23:11 +0200 Subject: [PATCH 1/8] Added Progress Bae for Cooperation --- src/assets/img/cooperation-details/clock.svg | 3 ++ .../AppProgressBarLine.styles.ts | 27 +++++++++++- .../AppProgressBarLine.tsx | 43 ++++++++++++++++--- .../CooperationActivitiesView.tsx | 10 ++++- .../CooperationActivities.tsx | 2 - src/styles/app-theme/app.pallete.ts | 2 + 6 files changed, 77 insertions(+), 10 deletions(-) create mode 100644 src/assets/img/cooperation-details/clock.svg diff --git a/src/assets/img/cooperation-details/clock.svg b/src/assets/img/cooperation-details/clock.svg new file mode 100644 index 000000000..f1f9585d8 --- /dev/null +++ b/src/assets/img/cooperation-details/clock.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/app-progress-bar-line/AppProgressBarLine.styles.ts b/src/components/app-progress-bar-line/AppProgressBarLine.styles.ts index 5266a3978..3a7237910 100644 --- a/src/components/app-progress-bar-line/AppProgressBarLine.styles.ts +++ b/src/components/app-progress-bar-line/AppProgressBarLine.styles.ts @@ -31,5 +31,30 @@ export const styles = { ${palette.basic.yellowGreen} ${175 - progress}%, ${palette.basic.fruitSalad} ${200 - progress}%)` } - }) + }), + progressCoop: { + display: 'flex', + alignItems: 'center', + width: '100%', + height: '12px', + backgroundColor: `${palette.basic.turquoise100}`, + borderRadius: '5px', + '& .MuiLinearProgress-bar': { + borderRadius: '5px', + background: `${palette.basic.turquoise500}` + } + }, + wrapperProgressCoop: { + width: '100%', + display: 'flex', + flexDirection: { xs: 'row-reverse', sm: 'column' }, + alignItems: { xs: 'center' }, + marginBottom: { xs: '2px', sm: '24px' } + }, + wrapperTypographyProgressCoop: { + width: '100%', + display: 'flex', + justifyContent: 'space-between', + alignItems: 'flex-end' + } } diff --git a/src/components/app-progress-bar-line/AppProgressBarLine.tsx b/src/components/app-progress-bar-line/AppProgressBarLine.tsx index cc7e26f19..dd6c63ca8 100644 --- a/src/components/app-progress-bar-line/AppProgressBarLine.tsx +++ b/src/components/app-progress-bar-line/AppProgressBarLine.tsx @@ -7,23 +7,46 @@ import { styles } from '~/components/app-progress-bar-line/AppProgressBarLine.st import { LinearProgress } from '@mui/material' import { UserRoleEnum } from '~/types' +import Image from '~/assets/img/cooperation-details/clock.svg' + interface AppProgressBarLineProps { value: number userRole: UserRoleEnum | '' + isCooperationActivities?: boolean } const AppProgressBarLine: FC = ({ value, - userRole + userRole, + isCooperationActivities = false }) => { const { isMobile } = useBreakpoints() const labelsValue = userRole === UserRoleEnum.Student ? [0, 25, 50, 75, 100] : [0, 20, 40, 60, 80, 100] - - const labelsWithPercent = isMobile ? ( - + const labelsWithPercentForCooperation = ( + + + Your progress + + + + {`${value}% completed`} + + + + + {`${100 - value}% to complete`} + + + + + ) + const labelsWithPercent = isCooperationActivities ? ( + labelsWithPercentForCooperation + ) : isMobile ? ( + {`${value}%`} ) : ( @@ -39,10 +62,18 @@ const AppProgressBarLine: FC = ({ ) return ( - + {labelsWithPercent} diff --git a/src/containers/cooperation-details/cooperation-activities-view/CooperationActivitiesView.tsx b/src/containers/cooperation-details/cooperation-activities-view/CooperationActivitiesView.tsx index 52073d027..6b75cad50 100644 --- a/src/containers/cooperation-details/cooperation-activities-view/CooperationActivitiesView.tsx +++ b/src/containers/cooperation-details/cooperation-activities-view/CooperationActivitiesView.tsx @@ -11,6 +11,7 @@ import { cooperationsSelector } from '~/redux/features/cooperationsSlice' import { UserRoleEnum } from '~/types' import { useAppSelector } from '~/hooks/use-redux' +import AppProgressBarLine from '~/components/app-progress-bar-line/AppProgressBarLine' interface CooperationActivitiesViewProps { setEditMode: Dispatch> @@ -22,13 +23,20 @@ const CooperationActivitiesView: FC = ({ const { sections } = useAppSelector(cooperationsSelector) const { userRole } = useAppSelector((state) => state.appMain) const isTutor = userRole === UserRoleEnum.Tutor - + const percentValue = 23 const onEdit = () => { setEditMode(true) } return ( + + + {sections.map((item) => ( ))} diff --git a/src/containers/cooperation-details/cooperation-activities/CooperationActivities.tsx b/src/containers/cooperation-details/cooperation-activities/CooperationActivities.tsx index 6bdafeeee..0e22ead56 100644 --- a/src/containers/cooperation-details/cooperation-activities/CooperationActivities.tsx +++ b/src/containers/cooperation-details/cooperation-activities/CooperationActivities.tsx @@ -24,7 +24,6 @@ import { cooperationsSelector, setResourcesAvailability } from '~/redux/features/cooperationsSlice' - import { snackbarVariants } from '~/constants' import { ResourcesAvailabilityEnum, @@ -55,7 +54,6 @@ const CooperationActivities: FC = ({ const dispatch = useAppDispatch() const { sections, resourcesAvailability } = useAppSelector(cooperationsSelector) - const handleResourcesAvailabilityChange = ( status: ResourcesAvailabilityEnum ) => { diff --git a/src/styles/app-theme/app.pallete.ts b/src/styles/app-theme/app.pallete.ts index 15c34de20..af978b808 100644 --- a/src/styles/app-theme/app.pallete.ts +++ b/src/styles/app-theme/app.pallete.ts @@ -24,6 +24,8 @@ const palette = { turquoiseChat: '#A0F0F2', turquoiseLight: '#F5FFFF', turquoise50: '#F2FAFA', + turquoise100: '#DAF1F1', + turquoise500: '#47B8B8', turquoise700: '#2B6E6E', blueGray: '#607D8B', bismark: '#546E7A', From 4c580d7a1f533236308034be6e5aa7d4c31ad077 Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Wed, 13 Nov 2024 16:00:34 +0200 Subject: [PATCH 2/8] Changed labels sizes and margin bottom for labels --- .../AppProgressBarLine.styles.ts | 7 +++++++ .../app-progress-bar-line/AppProgressBarLine.tsx | 14 ++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/components/app-progress-bar-line/AppProgressBarLine.styles.ts b/src/components/app-progress-bar-line/AppProgressBarLine.styles.ts index 3a7237910..1342a3560 100644 --- a/src/components/app-progress-bar-line/AppProgressBarLine.styles.ts +++ b/src/components/app-progress-bar-line/AppProgressBarLine.styles.ts @@ -51,6 +51,13 @@ export const styles = { alignItems: { xs: 'center' }, marginBottom: { xs: '2px', sm: '24px' } }, + labelsCoop: { + width: { xs: 'auto', sm: '100%' }, + display: 'flex', + justifyContent: 'space-between', + marginBottom: { xs: '0', sm: '0px' }, + marginLeft: { xs: '20px', sm: '0' } + }, wrapperTypographyProgressCoop: { width: '100%', display: 'flex', diff --git a/src/components/app-progress-bar-line/AppProgressBarLine.tsx b/src/components/app-progress-bar-line/AppProgressBarLine.tsx index dd6c63ca8..44e42d5ae 100644 --- a/src/components/app-progress-bar-line/AppProgressBarLine.tsx +++ b/src/components/app-progress-bar-line/AppProgressBarLine.tsx @@ -27,16 +27,20 @@ const AppProgressBarLine: FC = ({ : [0, 20, 40, 60, 80, 100] const labelsWithPercentForCooperation = ( - + Your progress - + {`${value}% completed`} - + {`${100 - value}% to complete`} @@ -69,7 +73,9 @@ const AppProgressBarLine: FC = ({ : styles.wrapperProgress } > - {labelsWithPercent} + + {labelsWithPercent} + Date: Wed, 13 Nov 2024 16:05:33 +0200 Subject: [PATCH 3/8] Fixed Sonar issue --- .../app-progress-bar-line/AppProgressBarLine.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/app-progress-bar-line/AppProgressBarLine.tsx b/src/components/app-progress-bar-line/AppProgressBarLine.tsx index 44e42d5ae..8bfe745e7 100644 --- a/src/components/app-progress-bar-line/AppProgressBarLine.tsx +++ b/src/components/app-progress-bar-line/AppProgressBarLine.tsx @@ -47,9 +47,7 @@ const AppProgressBarLine: FC = ({ ) - const labelsWithPercent = isCooperationActivities ? ( - labelsWithPercentForCooperation - ) : isMobile ? ( + const labelsWithPercentForProfile = isMobile ? ( {`${value}%`} @@ -64,6 +62,9 @@ const AppProgressBarLine: FC = ({ )) ) + const labelsWithPercent = isCooperationActivities + ? labelsWithPercentForCooperation + : labelsWithPercentForProfile return ( Date: Thu, 14 Nov 2024 11:27:56 +0200 Subject: [PATCH 4/8] Refactored: CSS file improvement --- .../AppProgressBarLine.styles.ts | 33 +++++++++++++++---- .../AppProgressBarLine.tsx | 17 ++++------ .../CooperationActivitiesView.tsx | 2 +- 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/components/app-progress-bar-line/AppProgressBarLine.styles.ts b/src/components/app-progress-bar-line/AppProgressBarLine.styles.ts index 1342a3560..f36d93710 100644 --- a/src/components/app-progress-bar-line/AppProgressBarLine.styles.ts +++ b/src/components/app-progress-bar-line/AppProgressBarLine.styles.ts @@ -6,14 +6,14 @@ export const styles = { display: 'flex', flexDirection: { xs: 'row-reverse', sm: 'column' }, alignItems: { xs: 'center' }, - marginTop: { xs: '8px', sm: '40px' } + mt: { xs: '8px', sm: '40px' } }, labels: { width: { xs: 'auto', sm: '100%' }, display: 'flex', justifyContent: 'space-between', - marginBottom: { xs: '0', sm: '10px' }, - marginLeft: { xs: '20px', sm: '0' } + mb: { xs: '0', sm: '10px' }, + ml: { xs: '20px', sm: '0' } }, progress: (progress: number) => ({ display: 'flex', @@ -48,20 +48,39 @@ export const styles = { width: '100%', display: 'flex', flexDirection: { xs: 'row-reverse', sm: 'column' }, - alignItems: { xs: 'center' }, - marginBottom: { xs: '2px', sm: '24px' } + alignItems: 'center', + mb: { xs: '2px', sm: '24px' } }, labelsCoop: { width: { xs: 'auto', sm: '100%' }, display: 'flex', justifyContent: 'space-between', - marginBottom: { xs: '0', sm: '0px' }, - marginLeft: { xs: '20px', sm: '0' } + mb: '0', + ml: { xs: '20px', sm: '0' } }, wrapperTypographyProgressCoop: { width: '100%', display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end' + }, + accessTimeIcon: { + color: 'primary.500', + mr: '8px', + fontSize: '1rem', + display: 'flex', + alignItems: 'flex-end' + }, + primaryLabelsCoop: { + color: 'primary.500', + fontSize: '12px' + }, + completedLabel: { + color: `${palette.basic.turquoise700}`, + fontSize: '20px' + }, + wrapperTitleWithIconCoop: { + display: 'flex', + alignItems: 'center' } } diff --git a/src/components/app-progress-bar-line/AppProgressBarLine.tsx b/src/components/app-progress-bar-line/AppProgressBarLine.tsx index 8bfe745e7..574234ac1 100644 --- a/src/components/app-progress-bar-line/AppProgressBarLine.tsx +++ b/src/components/app-progress-bar-line/AppProgressBarLine.tsx @@ -7,8 +7,7 @@ import { styles } from '~/components/app-progress-bar-line/AppProgressBarLine.st import { LinearProgress } from '@mui/material' import { UserRoleEnum } from '~/types' -import Image from '~/assets/img/cooperation-details/clock.svg' - +import { AccessTime } from '@mui/icons-material' interface AppProgressBarLineProps { value: number userRole: UserRoleEnum | '' @@ -27,20 +26,16 @@ const AppProgressBarLine: FC = ({ : [0, 20, 40, 60, 80, 100] const labelsWithPercentForCooperation = ( - + Your progress - + {`${value}% completed`} - - - + + + {`${100 - value}% to complete`} diff --git a/src/containers/cooperation-details/cooperation-activities-view/CooperationActivitiesView.tsx b/src/containers/cooperation-details/cooperation-activities-view/CooperationActivitiesView.tsx index 6b75cad50..a0a877a22 100644 --- a/src/containers/cooperation-details/cooperation-activities-view/CooperationActivitiesView.tsx +++ b/src/containers/cooperation-details/cooperation-activities-view/CooperationActivitiesView.tsx @@ -33,7 +33,7 @@ const CooperationActivitiesView: FC = ({ From 5df89ad1aec70c368f92c15f7578136bb0180431 Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Thu, 14 Nov 2024 21:42:02 +0200 Subject: [PATCH 5/8] Added ua/en translation for labels --- .../app-progress-bar-line/AppProgressBarLine.tsx | 8 +++++--- src/constants/translations/en/cooperation-details.json | 7 ++++++- src/constants/translations/uk/cooperation-details.json | 7 ++++++- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/components/app-progress-bar-line/AppProgressBarLine.tsx b/src/components/app-progress-bar-line/AppProgressBarLine.tsx index 574234ac1..e41478ad3 100644 --- a/src/components/app-progress-bar-line/AppProgressBarLine.tsx +++ b/src/components/app-progress-bar-line/AppProgressBarLine.tsx @@ -8,6 +8,7 @@ import { LinearProgress } from '@mui/material' import { UserRoleEnum } from '~/types' import { AccessTime } from '@mui/icons-material' +import { useTranslation } from 'react-i18next' interface AppProgressBarLineProps { value: number userRole: UserRoleEnum | '' @@ -20,6 +21,7 @@ const AppProgressBarLine: FC = ({ isCooperationActivities = false }) => { const { isMobile } = useBreakpoints() + const { t } = useTranslation() const labelsValue = userRole === UserRoleEnum.Student ? [0, 25, 50, 75, 100] @@ -27,16 +29,16 @@ const AppProgressBarLine: FC = ({ const labelsWithPercentForCooperation = ( - Your progress + {t('cooperationDetailsPage.progressBar.yourProgress')} - {`${value}% completed`} + {`${value}% ${t('cooperationDetailsPage.progressBar.completed')}`} - {`${100 - value}% to complete`} + {`${100 - value}% ${t('cooperationDetailsPage.progressBar.needToComplete')}`} diff --git a/src/constants/translations/en/cooperation-details.json b/src/constants/translations/en/cooperation-details.json index 77dd057bd..5a92b8b50 100644 --- a/src/constants/translations/en/cooperation-details.json +++ b/src/constants/translations/en/cooperation-details.json @@ -24,5 +24,10 @@ "tutoringSubject": "Tutoring subject & level:", "aboutCooperation": "About cooperation:", "tutoringLanguages": "Tutoring languages:", - "pricing": "Pricing:" + "pricing": "Pricing:", + "progressBar": { + "yourProgress": "Your progress", + "completed": "completed", + "needToComplete": "to complete" + } } diff --git a/src/constants/translations/uk/cooperation-details.json b/src/constants/translations/uk/cooperation-details.json index 1749df513..ec734340e 100644 --- a/src/constants/translations/uk/cooperation-details.json +++ b/src/constants/translations/uk/cooperation-details.json @@ -24,5 +24,10 @@ "tutoringSubject": "Предмет і рівень:", "aboutCooperation": "Про співпрацю:", "tutoringLanguages": "Мови:", - "pricing": "Ціна:" + "pricing": "Ціна:", + "progressBar": { + "yourProgress": "Ваш прогрес", + "completed": "виконано", + "needToComplete": "до завершення" + } } From 43c70ef209dafa3c2b72c0d4e763096c4af78911 Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Thu, 14 Nov 2024 22:23:06 +0200 Subject: [PATCH 6/8] Deleted unused svg file --- src/assets/img/cooperation-details/clock.svg | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 src/assets/img/cooperation-details/clock.svg diff --git a/src/assets/img/cooperation-details/clock.svg b/src/assets/img/cooperation-details/clock.svg deleted file mode 100644 index f1f9585d8..000000000 --- a/src/assets/img/cooperation-details/clock.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - From 29bdc61727971267ee3036e65d0ab35136e83d97 Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Wed, 20 Nov 2024 19:35:22 +0200 Subject: [PATCH 7/8] Added component and CSS for Switch --- src/components/app-switch/AppSwitch.styles.ts | 71 +++++++++++++++++++ src/components/app-switch/AppSwitch.tsx | 35 +++++++++ 2 files changed, 106 insertions(+) create mode 100644 src/components/app-switch/AppSwitch.styles.ts create mode 100644 src/components/app-switch/AppSwitch.tsx diff --git a/src/components/app-switch/AppSwitch.styles.ts b/src/components/app-switch/AppSwitch.styles.ts new file mode 100644 index 000000000..6ae4b161f --- /dev/null +++ b/src/components/app-switch/AppSwitch.styles.ts @@ -0,0 +1,71 @@ +import { SizeEnum } from '~/types' + +const trackMixin = (width: number, borderWidth: number) => ({ + position: 'absolute', + backgroundColor: '#F7F7F7 !important', + border: `${borderWidth}px solid`, + borderColor: 'primary.200', + borderRadius: `${width / 3}px`, + opacity: 1, + transition: 'background-color 0.3s ease, border-color 0.3s ease', + '&.Mui-disabled': { + color: 'primary.200' + } +}) + +const thumbMixin = (diameter: number) => ({ + width: `${diameter}px`, + height: `${diameter}px`, + boxShadow: 'none', + transition: 'transform 0.3s ease, background-color 0.3s ease' +}) + +const switchBaseMixin = (rWidth: number, tWidth: number) => ({ + position: 'relative', + color: 'primary.400', + padding: 0, + left: `${rWidth / 10}px`, + '&.Mui-checked': { + color: 'primary.800', + left: `${rWidth - tWidth - rWidth / 10 - 20}px` //source forces +20px on transformX (literally 2 days spent to investigate it) https://github.com/mui/material-ui/blob/v6.1.8/packages/mui-material/src/Switch/Switch.js + }, + '&.Mui-disabled': { + color: 'primary.200' + } +}) + +const rootMixin = (width: number, height: number) => ({ + display: 'flex', + alignItems: 'center', + width: `${width}px`, + height: `${height}px`, + overflow: 'visible', + padding: 0, + margin: '5px', + '&:hover': { + '& .MuiSwitch-track': { + borderColor: 'primary.500' + } + } +}) +const getMixins = ( + trackWidth: number, + trackHeight: number, + thumbDiameter: number, + trackBorderWidth: number +): object => { + return { + '&': rootMixin(trackWidth, trackHeight), + '& .MuiSwitch-thumb': thumbMixin(thumbDiameter), + '& .MuiSwitch-track': trackMixin(trackWidth, trackBorderWidth), + '& .MuiSwitch-switchBase': switchBaseMixin( + trackWidth + trackBorderWidth * 2, + thumbDiameter + ) + } +} +export const styles: Record = { + [SizeEnum.Small.toString()]: getMixins(45, 21, 15, 1), + [SizeEnum.Medium.toString()]: getMixins(60, 28, 20, 2), + [SizeEnum.Large.toString()]: getMixins(75, 35, 25, 3) +} diff --git a/src/components/app-switch/AppSwitch.tsx b/src/components/app-switch/AppSwitch.tsx new file mode 100644 index 000000000..0903768b9 --- /dev/null +++ b/src/components/app-switch/AppSwitch.tsx @@ -0,0 +1,35 @@ +import { SizeEnum } from '~/types' +import Switch, { SwitchProps } from '@mui/material/Switch' +import { styles } from './AppSwitch.styles' +import { FormControlLabel } from '@mui/material' +interface AppSwitchProps extends Omit { + labelPosition?: 'start' | 'end' | 'top' | 'bottom' + size?: SizeEnum + label: string + loading?: boolean +} +export const AppSwitch = ({ + labelPosition, + size = SizeEnum.Medium, + label, + loading, + disabled, + ...props +}: AppSwitchProps) => { + const sizeStyle = styles[size] + return ( + + } + label={label} + labelPlacement={labelPosition} + sx={{ + display: 'flex', + alignItems: 'center', + gap: '10px', + overflow: 'visible' + }} + /> + ) +} From 0744774e5945fd25f238a9e69efb3f7f2b78a25f Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Thu, 21 Nov 2024 13:11:18 +0200 Subject: [PATCH 8/8] Added unit tests and added AppSwitch to storybook --- src/components/app-switch/AppSwitch.styles.ts | 10 +- src/components/app-switch/AppSwitch.tsx | 19 ++- src/stories/AppSwitch.stories.jsx | 110 ++++++++++++++++++ .../components/app-switch/AppSwitch.spec.jsx | 94 +++++++++++++++ 4 files changed, 220 insertions(+), 13 deletions(-) create mode 100644 src/stories/AppSwitch.stories.jsx create mode 100644 tests/unit/components/app-switch/AppSwitch.spec.jsx diff --git a/src/components/app-switch/AppSwitch.styles.ts b/src/components/app-switch/AppSwitch.styles.ts index 6ae4b161f..4e0626230 100644 --- a/src/components/app-switch/AppSwitch.styles.ts +++ b/src/components/app-switch/AppSwitch.styles.ts @@ -64,8 +64,16 @@ const getMixins = ( ) } } -export const styles: Record = { +export const switchStyles: Record = { [SizeEnum.Small.toString()]: getMixins(45, 21, 15, 1), [SizeEnum.Medium.toString()]: getMixins(60, 28, 20, 2), [SizeEnum.Large.toString()]: getMixins(75, 35, 25, 3) } +export const formLabelStyles = { + formLabelBox: { + display: 'flex', + alignItems: 'center', + gap: '10px', + overflow: 'visible' + } +} diff --git a/src/components/app-switch/AppSwitch.tsx b/src/components/app-switch/AppSwitch.tsx index 0903768b9..97ffc8b03 100644 --- a/src/components/app-switch/AppSwitch.tsx +++ b/src/components/app-switch/AppSwitch.tsx @@ -1,35 +1,30 @@ import { SizeEnum } from '~/types' import Switch, { SwitchProps } from '@mui/material/Switch' -import { styles } from './AppSwitch.styles' +import { switchStyles, formLabelStyles } from './AppSwitch.styles' import { FormControlLabel } from '@mui/material' interface AppSwitchProps extends Omit { labelPosition?: 'start' | 'end' | 'top' | 'bottom' size?: SizeEnum - label: string + label?: string loading?: boolean } export const AppSwitch = ({ - labelPosition, - size = SizeEnum.Medium, + labelPosition = 'end', + size = SizeEnum.Small, label, loading, disabled, ...props }: AppSwitchProps) => { - const sizeStyle = styles[size] + const sizeStyle = switchStyles[size] return ( } - label={label} + label={label ? label : ''} labelPlacement={labelPosition} - sx={{ - display: 'flex', - alignItems: 'center', - gap: '10px', - overflow: 'visible' - }} + sx={formLabelStyles.formLabelBox} /> ) } diff --git a/src/stories/AppSwitch.stories.jsx b/src/stories/AppSwitch.stories.jsx new file mode 100644 index 000000000..a31e649b6 --- /dev/null +++ b/src/stories/AppSwitch.stories.jsx @@ -0,0 +1,110 @@ +import { AppSwitch } from '~/components/app-switch/AppSwitch' +import { SizeEnum } from '~/types' + +export default { + title: 'Components/AppSwitch', + component: AppSwitch, + argTypes: { + label: { + control: 'text', + description: 'Label for the switch', + defaultValue: '' + }, + labelPosition: { + control: { type: 'radio' }, + options: ['start', 'end', 'top', 'bottom'], + description: 'Position of the label relative to the switch', + defaultValue: 'end' + }, + size: { + control: { type: 'radio' }, + options: [SizeEnum.Small, SizeEnum.Medium, SizeEnum.Large], + description: 'Size of the switch', + defaultValue: SizeEnum.Medium + }, + loading: { + control: 'boolean', + description: 'Disables the switch and displays loading state', + defaultValue: false + }, + disabled: { + control: 'boolean', + description: 'Disables the switch', + defaultValue: false + } + } +} + +const Template = (args) => + +export const Default = Template.bind({}) +Default.args = { + size: SizeEnum.Medium, + disabled: false, + loading: false +} + +export const DefaultWithLabel = Template.bind({}) +DefaultWithLabel.args = { + label: 'Default Switch with Label', + size: SizeEnum.Medium, + labelPosition: 'end', + disabled: false, + loading: false +} + +export const Disabled = Template.bind({}) +Disabled.args = { + label: 'Disabled Switch', + size: SizeEnum.Medium, + labelPosition: 'end', + disabled: true +} + +export const Loading = Template.bind({}) +Loading.args = { + label: 'Loading Switch', + size: SizeEnum.Medium, + labelPosition: 'end', + loading: true +} + +export const LargeSize = Template.bind({}) +LargeSize.args = { + label: 'Large Switch', + size: SizeEnum.Large, + labelPosition: 'end', + disabled: false +} + +export const SmallSize = Template.bind({}) +SmallSize.args = { + label: 'Small Switch', + size: SizeEnum.Small, + labelPosition: 'end', + disabled: false +} + +export const TopPosition = Template.bind({}) +TopPosition.args = { + label: 'Top Position', + size: SizeEnum.Medium, + labelPosition: 'top', + disabled: false +} + +export const StartPosition = Template.bind({}) +StartPosition.args = { + label: 'Start Position', + size: SizeEnum.Medium, + labelPosition: 'start', + disabled: false +} + +export const BottomPosition = Template.bind({}) +BottomPosition.args = { + label: 'Bottom Position', + size: SizeEnum.Medium, + labelPosition: 'bottom', + disabled: false +} diff --git a/tests/unit/components/app-switch/AppSwitch.spec.jsx b/tests/unit/components/app-switch/AppSwitch.spec.jsx new file mode 100644 index 000000000..abe7ac671 --- /dev/null +++ b/tests/unit/components/app-switch/AppSwitch.spec.jsx @@ -0,0 +1,94 @@ +import { render, screen } from '@testing-library/react' +import { fireEvent } from '@testing-library/react' +import {AppSwitch} from '~/components/app-switch/AppSwitch' +import {SizeEnum} from '~/types' + +describe('AppSwitch Component', () => { + it('renders correctly with default props', () => { + render() + + const switchEl = screen.getByRole('checkbox') + expect(switchEl).toBeInTheDocument() + }) + + it('triggers `onChange` when toggled', () => { + const handleChange = vi.fn() + render() + + const switchEl = screen.getByRole('checkbox') + fireEvent.click(switchEl) + + expect(handleChange).toHaveBeenCalledTimes(1) + }) + + it('displays the label when provided', () => { + render() + + const labelEl = screen.getByText('Test Label') + expect(labelEl).toBeInTheDocument() + }) + + it('applies the correct Large size style', () => { + render() + + const switchEl = screen.getByRole('checkbox') + expect(switchEl).toBeInTheDocument() + }) + + it('applies the correct Medium size style', () => { + render() + + const switchEl = screen.getByRole('checkbox') + expect(switchEl).toBeInTheDocument() + }) + + it('applies the correct Small size style', () => { + render() + + const switchEl = screen.getByRole('checkbox') + expect(switchEl).toBeInTheDocument() + }) + + it('is disabled when loading is true', () => { + render() + + const switchEl = screen.getByRole('checkbox') + expect(switchEl).toBeDisabled() + }) + + it('is disabled when disabled prop is true', () => { + render() + + const switchEl = screen.getByRole('checkbox') + expect(switchEl).toBeDisabled() + }) + + it('renders the label in the correct end position', () => { + render() + + const labelEl = screen.getByText('End Label') + expect(labelEl).toBeInTheDocument() + }) + + it('renders the label in the correct start position', () => { + render() + + const labelEl = screen.getByText('Start Label') + expect(labelEl).toBeInTheDocument() + }) + + it('renders the label in the correct top position', () => { + render() + + const labelEl = screen.getByText('Top Label') + expect(labelEl).toBeInTheDocument() + }) + + it('renders the label in the correct bottom position', () => { + render() + + const labelEl = screen.getByText('Bottom Label') + expect(labelEl).toBeInTheDocument() + }) + +})