From 0d2c60429975bf4e242de12780a1602f2b55e0af Mon Sep 17 00:00:00 2001 From: Igor <114025058+igaryakqwe@users.noreply.github.com> Date: Sat, 22 Jun 2024 22:56:29 +0300 Subject: [PATCH 01/14] feature: add icon button component --- src/app/test/icon-button/page.tsx | 18 ++++ .../ui/icon-button/IconButton.styles.ts | 93 +++++++++++++++++++ .../common/ui/icon-button/IconButton.tsx | 42 +++++++++ .../common/ui/icon-button/types/index.ts | 31 +++++++ 4 files changed, 184 insertions(+) create mode 100644 src/app/test/icon-button/page.tsx create mode 100644 src/components/common/ui/icon-button/IconButton.styles.ts create mode 100644 src/components/common/ui/icon-button/IconButton.tsx create mode 100644 src/components/common/ui/icon-button/types/index.ts diff --git a/src/app/test/icon-button/page.tsx b/src/app/test/icon-button/page.tsx new file mode 100644 index 0000000..198f014 --- /dev/null +++ b/src/app/test/icon-button/page.tsx @@ -0,0 +1,18 @@ +import { Box } from '@mui/material'; + +import IconButton from '@/components/common/ui/icon-button/IconButton'; + +const Page = () => { + return ( + + + + + + + + + ); +}; + +export default Page; diff --git a/src/components/common/ui/icon-button/IconButton.styles.ts b/src/components/common/ui/icon-button/IconButton.styles.ts new file mode 100644 index 0000000..00cbf3f --- /dev/null +++ b/src/components/common/ui/icon-button/IconButton.styles.ts @@ -0,0 +1,93 @@ +import { SxProps, Theme } from '@mui/material/styles'; + +import { + ButtonColors, + IconButtonSize, + IconButtonVariant, +} from '@/components/common/ui/icon-button/types'; + +const buttonColour: ButtonColors = { + contained: { + default: { + color: 'orange.300', + border: 'orange.300', + }, + hover: { + color: 'orange.200', + border: 'orange.200', + }, + active: { + color: 'orange.400', + border: 'orange.400', + }, + focused: { + color: 'orange.300', + border: 'orange.100', + }, + disabled: { + color: 'gray.200', + border: 'gray.200', + }, + }, + outlined: { + default: { + color: 'transparent', + border: 'orange.300', + }, + hover: { + color: 'rgba(255, 84, 30, 0.15)', + border: 'orange.300', + }, + active: { + color: 'rgba(255, 84, 30, 0.50)', + border: 'orange.300', + }, + focused: { + color: 'rgba(255, 84, 30, 0.30)', + border: 'orange.300', + }, + disabled: { + color: 'transparent', + border: 'gray.200', + }, + }, +}; + +export const button = ( + size: IconButtonSize, + variant: IconButtonVariant, +): SxProps => ({ + borderRadius: '6px', + border: '2px solid', + p: 0, + width: size === 'small' ? '36px' : '48px', + height: size === 'small' ? '36px' : '48px', + + backgroundColor: buttonColour[variant].default.color, + borderColor: buttonColour[variant].default.border, + '&:hover': { + backgroundColor: buttonColour[variant].hover.color, + borderColor: buttonColour[variant].hover.border, + }, + '&:active': { + backgroundColor: buttonColour[variant].active.color, + borderColor: buttonColour[variant].active.border, + }, + '&:focus': { + backgroundColor: buttonColour[variant].focused.color, + borderColor: buttonColour[variant].focused.border, + }, + '&:disabled': { + backgroundColor: buttonColour[variant].disabled.color, + borderColor: buttonColour[variant].disabled.border, + svg: { + stroke: variant === 'contained' ? 'white' : '#949394', + }, + }, + + svg: { + width: '24px', + height: '24px', + stroke: variant === 'contained' ? 'white' : 'black', + }, +}); diff --git a/src/components/common/ui/icon-button/IconButton.tsx b/src/components/common/ui/icon-button/IconButton.tsx new file mode 100644 index 0000000..5f06c34 --- /dev/null +++ b/src/components/common/ui/icon-button/IconButton.tsx @@ -0,0 +1,42 @@ +import { FC, ReactNode } from 'react'; +import { PlusIcon } from '@heroicons/react/24/outline'; +import { + IconButton as IconButtonMUI, + IconButtonOwnProps as IconButtonPropsMUI, +} from '@mui/material'; +import { SxProps, Theme } from '@mui/material/styles'; + +import { + IconButtonSize, + IconButtonVariant, +} from '@/components/common/ui/icon-button/types'; +import mergeSx from '@/lib/utils/mergeSx'; + +import * as styles from './IconButton.styles'; + +interface IconButtonProps extends IconButtonPropsMUI { + children?: ReactNode; + size?: IconButtonSize; + variant?: IconButtonVariant; + sx?: SxProps; +} + +const IconButton: FC = ({ + children = , + size = 'medium', + variant = 'contained', + sx = {}, + ...props +}) => { + return ( + + {children} + + ); +}; + +export default IconButton; diff --git a/src/components/common/ui/icon-button/types/index.ts b/src/components/common/ui/icon-button/types/index.ts new file mode 100644 index 0000000..4eea48d --- /dev/null +++ b/src/components/common/ui/icon-button/types/index.ts @@ -0,0 +1,31 @@ +export type IconButtonSize = 'small' | 'medium'; + +export type IconButtonVariant = 'contained' | 'outlined'; + +export interface ButtonColors { + contained: Colors; + outlined: Colors; +} + +interface Colors { + default: { + color: string; + border: string; + }; + hover: { + color: string; + border: string; + }; + active: { + color: string; + border: string; + }; + focused: { + color: string; + border: string; + }; + disabled: { + color: string; + border: string; + }; +} From 2994c7408107a7a3d86bfdb94ca085d829f110fa Mon Sep 17 00:00:00 2001 From: Igor <114025058+igaryakqwe@users.noreply.github.com> Date: Tue, 2 Jul 2024 15:06:44 +0300 Subject: [PATCH 02/14] enhancement: added startAdornment for input --- .../page-layout/footer/constants/index.ts | 4 ++-- .../common/ui/input/Input.styles.ts | 2 +- src/components/common/ui/input/Input.tsx | 21 +++++++++++++++---- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/components/common/layout/page-layout/footer/constants/index.ts b/src/components/common/layout/page-layout/footer/constants/index.ts index 0d91d13..97444e6 100644 --- a/src/components/common/layout/page-layout/footer/constants/index.ts +++ b/src/components/common/layout/page-layout/footer/constants/index.ts @@ -8,8 +8,8 @@ export const links: Links = { href: '/', }, { - title: 'Організація', - href: '/organization', + title: 'Організації', + href: '/organizations', }, { title: 'Ціни', diff --git a/src/components/common/ui/input/Input.styles.ts b/src/components/common/ui/input/Input.styles.ts index eebae1a..7091e4e 100644 --- a/src/components/common/ui/input/Input.styles.ts +++ b/src/components/common/ui/input/Input.styles.ts @@ -4,7 +4,7 @@ import { InputVariant } from '@/components/common/ui/input/types'; export const formControl = (variant: InputVariant): SxProps => ({ '.MuiInputBase-root': { - m: '10px 0 0 0', + m: 0, border: '2px solid', borderColor: 'gray.400', diff --git a/src/components/common/ui/input/Input.tsx b/src/components/common/ui/input/Input.tsx index f87496d..7906dd3 100644 --- a/src/components/common/ui/input/Input.tsx +++ b/src/components/common/ui/input/Input.tsx @@ -1,7 +1,11 @@ 'use client'; import React, { FC, useState } from 'react'; -import { EyeIcon, EyeSlashIcon } from '@heroicons/react/24/outline'; +import { + EyeIcon, + EyeSlashIcon, + MagnifyingGlassIcon, +} from '@heroicons/react/24/outline'; import { FormControl, IconButton, @@ -28,6 +32,7 @@ interface InputProps extends InputPropsMUI { password?: boolean; sx?: SxProps; fullWidth?: boolean; + isSearch?: boolean; } const Input: FC = ({ @@ -39,6 +44,7 @@ const Input: FC = ({ password = false, sx = {}, fullWidth = false, + isSearch = false, ...props }) => { const [showPassword, setShowPassword] = useState(!password); @@ -47,16 +53,22 @@ const Input: FC = ({ setShowPassword((prevShowPassword) => !prevShowPassword); }; - const eyeColor = + const iconColor = variant === 'white' ? theme.palette.gray[300] : theme.palette.gray[400]; + const startAdornment = isSearch ? ( + + + + ) : null; + const endAdornment = password ? ( {showPassword ? ( - + ) : ( - + )} @@ -77,6 +89,7 @@ const Input: FC = ({ )} Date: Tue, 2 Jul 2024 15:07:02 +0300 Subject: [PATCH 03/14] feature: add organisation page --- src/app/organisations/Organisations.styles.ts | 21 +++++++++++++++++ src/app/organisations/page.tsx | 23 +++++++++++++++++++ .../header/menu/constants/menuItems.ts | 4 ++-- 3 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 src/app/organisations/Organisations.styles.ts create mode 100644 src/app/organisations/page.tsx diff --git a/src/app/organisations/Organisations.styles.ts b/src/app/organisations/Organisations.styles.ts new file mode 100644 index 0000000..db89cf8 --- /dev/null +++ b/src/app/organisations/Organisations.styles.ts @@ -0,0 +1,21 @@ +import { SxProps, Theme } from '@mui/material/styles'; + +export const wrapper: SxProps = { + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + width: '100%', +}; + +export const search: SxProps = { + maxWidth: '794px', + width: '100%', + mt: '26px', + display: 'inline-flex', + gap: '16px', +}; + +export const input: SxProps = { + maxWidth: '730px', + flexGrow: 1, +}; diff --git a/src/app/organisations/page.tsx b/src/app/organisations/page.tsx new file mode 100644 index 0000000..3221ceb --- /dev/null +++ b/src/app/organisations/page.tsx @@ -0,0 +1,23 @@ +import { Box, Typography } from '@mui/material'; + +import IconButton from '@/components/common/ui/icon-button/IconButton'; +import Input from '@/components/common/ui/input/Input'; + +import * as styles from './Organisations.styles'; + +const Organisations = () => { + return ( + + + Мої організації + + + + + + + + ); +}; + +export default Organisations; diff --git a/src/components/common/layout/page-layout/header/menu/constants/menuItems.ts b/src/components/common/layout/page-layout/header/menu/constants/menuItems.ts index 8a613f1..959786f 100644 --- a/src/components/common/layout/page-layout/header/menu/constants/menuItems.ts +++ b/src/components/common/layout/page-layout/header/menu/constants/menuItems.ts @@ -4,8 +4,8 @@ export const menuItems = [ url: '/', }, { - title: 'Організація', - url: '/organisation', + title: 'Організації', + url: '/organisations', }, { title: 'Ціни', From 08db19977ef3159210edb683cd5c42adaf37cf88 Mon Sep 17 00:00:00 2001 From: Igor <114025058+igaryakqwe@users.noreply.github.com> Date: Fri, 5 Jul 2024 10:26:04 +0300 Subject: [PATCH 04/14] feature: added organisation dashboard --- public/svgs/organisation-default.svg | 30 ++++++++++++++ src/app/not-found.tsx | 8 +--- src/app/organisations/Organisations.styles.ts | 8 ++++ .../organisations/[id]/Organisation.styles.ts | 7 ++++ .../components/info-card/InfoCard.styles.ts | 8 ++++ .../[id]/components/info-card/InfoCard.tsx | 22 ++++++++++ .../OrganisationDashboard.styles.ts | 13 ++++++ .../OrganisationDashboard.tsx | 40 +++++++++++++++++++ src/app/organisations/[id]/layout.tsx | 26 ++++++++++++ src/app/organisations/[id]/page.tsx | 5 +++ src/app/organisations/page.tsx | 34 ++++++++++++++++ 11 files changed, 194 insertions(+), 7 deletions(-) create mode 100644 public/svgs/organisation-default.svg create mode 100644 src/app/organisations/[id]/Organisation.styles.ts create mode 100644 src/app/organisations/[id]/components/info-card/InfoCard.styles.ts create mode 100644 src/app/organisations/[id]/components/info-card/InfoCard.tsx create mode 100644 src/app/organisations/[id]/components/organisation-dasboard/OrganisationDashboard.styles.ts create mode 100644 src/app/organisations/[id]/components/organisation-dasboard/OrganisationDashboard.tsx create mode 100644 src/app/organisations/[id]/layout.tsx create mode 100644 src/app/organisations/[id]/page.tsx diff --git a/public/svgs/organisation-default.svg b/public/svgs/organisation-default.svg new file mode 100644 index 0000000..60939e3 --- /dev/null +++ b/public/svgs/organisation-default.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/not-found.tsx b/src/app/not-found.tsx index f95d955..e0631a3 100644 --- a/src/app/not-found.tsx +++ b/src/app/not-found.tsx @@ -30,13 +30,7 @@ const NotFound: FC = () => {
Ви можете написати в підтримку, якщо ви впевнені, що виникла помилка - diff --git a/src/app/organisations/Organisations.styles.ts b/src/app/organisations/Organisations.styles.ts index db89cf8..028704b 100644 --- a/src/app/organisations/Organisations.styles.ts +++ b/src/app/organisations/Organisations.styles.ts @@ -18,4 +18,12 @@ export const search: SxProps = { export const input: SxProps = { maxWidth: '730px', flexGrow: 1, + mb: '26px', +}; + +export const organisations: SxProps = { + maxWidth: '994px', + display: 'grid', + gap: '16px', + mb: '64px', }; diff --git a/src/app/organisations/[id]/Organisation.styles.ts b/src/app/organisations/[id]/Organisation.styles.ts new file mode 100644 index 0000000..1679376 --- /dev/null +++ b/src/app/organisations/[id]/Organisation.styles.ts @@ -0,0 +1,7 @@ +import { SxProps, Theme } from '@mui/material/styles'; + +export const layout: SxProps = { + p: '48px 100px 36px 100px', + display: 'flex', + backgroundColor: 'gray.700', +}; diff --git a/src/app/organisations/[id]/components/info-card/InfoCard.styles.ts b/src/app/organisations/[id]/components/info-card/InfoCard.styles.ts new file mode 100644 index 0000000..62fd32e --- /dev/null +++ b/src/app/organisations/[id]/components/info-card/InfoCard.styles.ts @@ -0,0 +1,8 @@ +import { SxProps, Theme } from '@mui/material/styles'; + +export const wrapper: SxProps = { + display: 'flex', + alignItems: 'center', + justifyContent: 'flex-start', + gap: '20px', +}; diff --git a/src/app/organisations/[id]/components/info-card/InfoCard.tsx b/src/app/organisations/[id]/components/info-card/InfoCard.tsx new file mode 100644 index 0000000..298a6f7 --- /dev/null +++ b/src/app/organisations/[id]/components/info-card/InfoCard.tsx @@ -0,0 +1,22 @@ +import { FC } from 'react'; +import { Box, Typography } from '@mui/material'; + +import * as styles from './InfoCard.styles'; + +interface InfoCardProps { + name: string; + value: string; +} + +const InfoCard: FC = ({ name, value }) => { + return ( + + + {name} + + {value} + + ); +}; + +export default InfoCard; diff --git a/src/app/organisations/[id]/components/organisation-dasboard/OrganisationDashboard.styles.ts b/src/app/organisations/[id]/components/organisation-dasboard/OrganisationDashboard.styles.ts new file mode 100644 index 0000000..55f8991 --- /dev/null +++ b/src/app/organisations/[id]/components/organisation-dasboard/OrganisationDashboard.styles.ts @@ -0,0 +1,13 @@ +import { SxProps, Theme } from '@mui/material/styles'; + +export const wrapper: SxProps = { + maxWidth: '387px', + p: '16px', + display: 'flex', + flexDirection: 'column', + gap: '16px', + backgroundColor: 'white.main', + + borderRadius: '4px', + boxShadow: '6px 6px 4px 0px rgba(0, 0, 0, 0.25)', +}; diff --git a/src/app/organisations/[id]/components/organisation-dasboard/OrganisationDashboard.tsx b/src/app/organisations/[id]/components/organisation-dasboard/OrganisationDashboard.tsx new file mode 100644 index 0000000..0b1dd6f --- /dev/null +++ b/src/app/organisations/[id]/components/organisation-dasboard/OrganisationDashboard.tsx @@ -0,0 +1,40 @@ +import { FC } from 'react'; +import { Box, Typography } from '@mui/material'; +import Image from 'next/image'; + +import InfoCard from '@/app/organisations/[id]/components/info-card/InfoCard'; + +import * as styles from './OrganisationDashboard.styles'; + +interface OrganisationDashboardProps { + organisation: { + avatar: string; + name: string; + address: string; + owner: string; + description?: string; + }; +} + +const OrganisationDashboard: FC = ({ + organisation, +}) => { + return ( + + organisation picture + {organisation.name} + + + + + {organisation.description} + + ); +}; + +export default OrganisationDashboard; diff --git a/src/app/organisations/[id]/layout.tsx b/src/app/organisations/[id]/layout.tsx new file mode 100644 index 0000000..0874ad2 --- /dev/null +++ b/src/app/organisations/[id]/layout.tsx @@ -0,0 +1,26 @@ +import { FC, PropsWithChildren } from 'react'; +import { Box, Typography } from '@mui/material'; + +import OrganisationDashboard from '@/app/organisations/[id]/components/organisation-dasboard/OrganisationDashboard'; + +import * as styles from './Organisation.styles'; + +const organisation = { + avatar: '/svgs/organisation-default.svg', + name: 'Автосервіс Гепард', + address: 'м. Київ, проспект Перемоги 10', + owner: 'Новиков Ігор Михайлович', + description: + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur culpa cupiditate dignissimos dolorem dolores, error expedita fugit id itaque minima minus molestias nemo, nobis nostrum nulla placeat quis repudiandae! Quod.\n', +}; + +const OrganisationLayout: FC = ({ children }) => { + return ( + + + {children} + + ); +}; + +export default OrganisationLayout; diff --git a/src/app/organisations/[id]/page.tsx b/src/app/organisations/[id]/page.tsx new file mode 100644 index 0000000..3d58e59 --- /dev/null +++ b/src/app/organisations/[id]/page.tsx @@ -0,0 +1,5 @@ +const OrganisationPage = () => { + return
Organisation Page
; +}; + +export default OrganisationPage; diff --git a/src/app/organisations/page.tsx b/src/app/organisations/page.tsx index 3221ceb..fcabbc1 100644 --- a/src/app/organisations/page.tsx +++ b/src/app/organisations/page.tsx @@ -2,9 +2,32 @@ import { Box, Typography } from '@mui/material'; import IconButton from '@/components/common/ui/icon-button/IconButton'; import Input from '@/components/common/ui/input/Input'; +import OrganisationCard from '@/components/common/ui/organisation-card'; import * as styles from './Organisations.styles'; +const mocks = [ + { + avatar: + 'https://autolab-fs.s3.eu-north-1.amazonaws.com/default/avatar-org.svg', + name: 'Автосервіс Гепард', + position: 'Власник', + description: + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus accusantium aperiam delectus dolor dolores enim error est et excepturi ipsum iusto magni non pariatur, quibusdam reiciendis sapiente, sed sint tenetur!\n ', + }, + { + avatar: + 'https://autolab-fs.s3.eu-north-1.amazonaws.com/default/avatar-org.svg', + name: 'Автосервіс Чірік', + position: 'Співвласник', + }, + { + avatar: '/images/avatar.jpg', + name: 'Автосервіс Лісовик', + position: 'Співробітник', + }, +]; + const Organisations = () => { return ( @@ -16,6 +39,17 @@ const Organisations = () => { + + {mocks.map((mock, index) => ( + + ))} + ); }; From 828fb71477b5da8c693a1adc4cfe488d6f48fa4f Mon Sep 17 00:00:00 2001 From: Igor <114025058+igaryakqwe@users.noreply.github.com> Date: Sun, 7 Jul 2024 19:17:31 +0300 Subject: [PATCH 05/14] enhancement: improved responsive --- src/app/not-found.tsx | 6 ------ .../layout/page-layout/footer/Footer.styles.ts | 13 ++++++++----- .../layout/page-layout/header/Header.styles.ts | 6 +++++- src/components/pages/NotFound.styles.ts | 10 ++++------ 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/app/not-found.tsx b/src/app/not-found.tsx index e0631a3..c0feb5a 100644 --- a/src/app/not-found.tsx +++ b/src/app/not-found.tsx @@ -6,12 +6,6 @@ import Image from 'next/image'; import { useRouter } from 'next/navigation'; import Button from '@/components/common/ui/button'; -import { - ButtonColor, - ButtonIcon, - ButtonSize, - ButtonVariant, -} from '@/components/common/ui/button/types'; import * as styles from '../components/pages/NotFound.styles'; diff --git a/src/components/common/layout/page-layout/footer/Footer.styles.ts b/src/components/common/layout/page-layout/footer/Footer.styles.ts index 5a9537b..7383352 100644 --- a/src/components/common/layout/page-layout/footer/Footer.styles.ts +++ b/src/components/common/layout/page-layout/footer/Footer.styles.ts @@ -10,14 +10,11 @@ export const wrapper: SxProps = { desktop: 'flex-start', mobile: 'center', }, - justifyContent: { - desktop: 'space-between', - mobile: 'center', - }, zIndex: 11, padding: { - mobileMedium: '38px 100px', + desktop: '38px 100px', + mobileMedium: '38px 50px', mobile: '16px', }, height: 'auto', @@ -41,7 +38,13 @@ export const text: SxProps = { }; export const columns: SxProps = { + width: '100%', display: 'flex', + justifyContent: { + desktop: 'flex-end', + mobileMedium: 'center', + mobile: 'space-between', + }, gap: { desktop: '80px', mobileMedium: '40px', diff --git a/src/components/common/layout/page-layout/header/Header.styles.ts b/src/components/common/layout/page-layout/header/Header.styles.ts index 50475a2..4b51b9d 100644 --- a/src/components/common/layout/page-layout/header/Header.styles.ts +++ b/src/components/common/layout/page-layout/header/Header.styles.ts @@ -1,7 +1,11 @@ import { SxProps, Theme } from '@mui/material/styles'; export const wrapper: SxProps = { - p: '0px 100px', + py: 0, + px: { + mobile: '16px', + tablet: '100px', + }, width: '100%', height: '64px', boxShadow: 'rgba(0, 0, 0, 0.24) 0px 3px 8px', diff --git a/src/components/pages/NotFound.styles.ts b/src/components/pages/NotFound.styles.ts index f0d1971..1587a3f 100644 --- a/src/components/pages/NotFound.styles.ts +++ b/src/components/pages/NotFound.styles.ts @@ -1,16 +1,14 @@ import { SxProps, Theme } from '@mui/material/styles'; export const wrapper: SxProps = { - height: { - desktop: '100%', - mobile: '100vh', - }, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', - m: '14px 24px 106px 24px', - + m: { + mobile: '106px 24px', + tablet: '14px 24px 106px 24px', + }, img: { maxWidth: '100%', height: 'auto', From 1c63931dd07a56046f3bb98238ffdd5ed16aa421 Mon Sep 17 00:00:00 2001 From: Igor <114025058+igaryakqwe@users.noreply.github.com> Date: Sun, 7 Jul 2024 23:20:33 +0300 Subject: [PATCH 06/14] feature: added new button variant --- .../common/ui/button/Button.styles.ts | 74 +++++++++++-------- src/components/common/ui/button/Button.tsx | 6 +- 2 files changed, 49 insertions(+), 31 deletions(-) diff --git a/src/components/common/ui/button/Button.styles.ts b/src/components/common/ui/button/Button.styles.ts index a9160fa..fd20dd6 100644 --- a/src/components/common/ui/button/Button.styles.ts +++ b/src/components/common/ui/button/Button.styles.ts @@ -73,6 +73,27 @@ const outlinedWhiteColors: SxProps = { }, }; +const textColors: SxProps = { + backgroundColor: 'transparent', + borderColor: 'transparent', + color: 'black.main', + '&:hover': { + backgroundColor: 'rgba(255, 84, 30, 0.15);', + borderColor: 'transparent', + }, + '&:active': { + backgroundColor: 'rgba(255, 84, 30, 0.35)', + color: 'orange.100', + }, + '&:focus': { + backgroundColor: 'rgba(255, 84, 30, 0.15)', + borderColor: 'orange.300', + }, + '&.Mui-disabled': { + color: 'gray.500', + }, +}; + export const button = ( variant: ButtonVariant, size: ButtonSize, @@ -85,23 +106,25 @@ export const button = ( borderRadius: '6px', textTransform: 'none', display: 'flex', + + ...(size === 'small' && { + typography: 'body1Bold', + p: '10px 20px', + gap: '8px', + }), + ...(size === 'medium' && { + p: '12px 28px', + typography: 'h6Bold', + gap: '12px', + }), + ...(size === 'large' && { + p: '16px 32px', + gap: '12px', + typography: 'h6Bold', + }), + ...(variant === 'contained' && { ...containedColors, - ...(size === 'small' && { - typography: 'body1Bold', - p: '10px 20px', - gap: '8px', - }), - ...(size === 'medium' && { - p: '12px 28px', - typography: 'h6Bold', - gap: '12px', - }), - ...(size === 'large' && { - p: '16px 32px', - gap: '12px', - typography: 'h6Bold', - }), }), ...(variant === 'outlined' && { ...(color === 'primary' && { @@ -110,20 +133,11 @@ export const button = ( ...(color === 'secondary' && { ...outlinedWhiteColors, }), - ...(size === 'small' && { - typography: 'body1Bold', - p: '10px 20px', - gap: '8px', - }), - ...(size === 'medium' && { - p: '12px 28px', - typography: 'h6Bold', - gap: '12px', - }), - ...(size === 'large' && { - p: '16px 32px', - gap: '12px', - typography: 'h6Bold', - }), + }), + ...(variant === 'text' && { + p: '10px 24px', + border: '1px solid', + typography: 'body1Medium', + ...textColors, }), }); diff --git a/src/components/common/ui/button/Button.tsx b/src/components/common/ui/button/Button.tsx index 7b90ff1..d6ed4b9 100644 --- a/src/components/common/ui/button/Button.tsx +++ b/src/components/common/ui/button/Button.tsx @@ -27,7 +27,11 @@ const Button: FC = ({ ...rest }) => { return ( - + {icon === 'left' && iconComponent} {children} {icon === 'right' && iconComponent} From 3124b8871a29d70c0fc66bf6b6abc19de4aa30ef Mon Sep 17 00:00:00 2001 From: Igor <114025058+igaryakqwe@users.noreply.github.com> Date: Mon, 8 Jul 2024 10:24:34 +0300 Subject: [PATCH 07/14] feature: added basic organisation page --- .../organisations/[id]/Organisation.styles.ts | 15 ++++++++ .../OrganisationBar.styles.ts | 20 +++++++++++ .../organisation-bar/OrganisationBar.tsx | 36 +++++++++++++++++++ .../organisation-bar/constants/index.ts | 18 ++++++++++ .../[id]/components/organisation-bar/index.ts | 1 + .../OrganisationDashboard.styles.ts | 5 +++ src/app/organisations/[id]/layout.tsx | 3 +- src/app/organisations/[id]/page.tsx | 30 +++++++++++++++- src/app/test/button/page.tsx | 6 ++++ .../common/ui/button/types/index.ts | 2 +- 10 files changed, 133 insertions(+), 3 deletions(-) create mode 100644 src/app/organisations/[id]/components/organisation-bar/OrganisationBar.styles.ts create mode 100644 src/app/organisations/[id]/components/organisation-bar/OrganisationBar.tsx create mode 100644 src/app/organisations/[id]/components/organisation-bar/constants/index.ts create mode 100644 src/app/organisations/[id]/components/organisation-bar/index.ts diff --git a/src/app/organisations/[id]/Organisation.styles.ts b/src/app/organisations/[id]/Organisation.styles.ts index 1679376..5d1bed9 100644 --- a/src/app/organisations/[id]/Organisation.styles.ts +++ b/src/app/organisations/[id]/Organisation.styles.ts @@ -5,3 +5,18 @@ export const layout: SxProps = { display: 'flex', backgroundColor: 'gray.700', }; + +export const wrapper: SxProps = { + width: '100%', +}; + +export const search: SxProps = { + width: '100%', + my: '16px', + display: 'inline-flex', + gap: '16px', +}; + +export const input: SxProps = { + width: '100%', +}; diff --git a/src/app/organisations/[id]/components/organisation-bar/OrganisationBar.styles.ts b/src/app/organisations/[id]/components/organisation-bar/OrganisationBar.styles.ts new file mode 100644 index 0000000..74bc211 --- /dev/null +++ b/src/app/organisations/[id]/components/organisation-bar/OrganisationBar.styles.ts @@ -0,0 +1,20 @@ +import { SxProps, Theme } from '@mui/material/styles'; + +export const wrapper: SxProps = { + p: '8px', + display: 'flex', + alignItems: 'center', + gap: '20px', + float: 'left', + + backgroundColor: 'white.main', + boxShadow: '0px 4px 4px 0px rgba(0, 0, 0, 0.25)', + borderRadius: '6px', +}; + +export const button = (isActive: boolean): SxProps => ({ + ...(isActive && { + backgroundColor: 'rgba(255, 84, 30, 0.35)', + color: 'orange.100', + }), +}); diff --git a/src/app/organisations/[id]/components/organisation-bar/OrganisationBar.tsx b/src/app/organisations/[id]/components/organisation-bar/OrganisationBar.tsx new file mode 100644 index 0000000..a3ef197 --- /dev/null +++ b/src/app/organisations/[id]/components/organisation-bar/OrganisationBar.tsx @@ -0,0 +1,36 @@ +'use client'; +import { FC } from 'react'; +import { Box } from '@mui/material'; +import Link from 'next/link'; +import { usePathname, useSearchParams } from 'next/navigation'; + +import { tabs } from '@/app/organisations/[id]/components/organisation-bar/constants'; +import Button from '@/components/common/ui/button'; + +import * as styles from './OrganisationBar.styles'; + +interface OrganisationBarProps {} + +const OrganisationBar: FC = () => { + const pathname = usePathname(); + const searchParams = useSearchParams(); + const curTab = searchParams.get('tab'); + + return ( + + {tabs.map((tab) => ( + + + + ))} + + ); +}; + +export default OrganisationBar; diff --git a/src/app/organisations/[id]/components/organisation-bar/constants/index.ts b/src/app/organisations/[id]/components/organisation-bar/constants/index.ts new file mode 100644 index 0000000..9008e46 --- /dev/null +++ b/src/app/organisations/[id]/components/organisation-bar/constants/index.ts @@ -0,0 +1,18 @@ +export const tabs = [ + { + name: 'Працівники', + href: 'employees', + }, + { + name: 'Послуги', + href: 'services', + }, + { + name: 'Клієнти', + href: 'clients', + }, + { + name: 'Автомобілі', + href: 'cars', + }, +]; diff --git a/src/app/organisations/[id]/components/organisation-bar/index.ts b/src/app/organisations/[id]/components/organisation-bar/index.ts new file mode 100644 index 0000000..a4f54f9 --- /dev/null +++ b/src/app/organisations/[id]/components/organisation-bar/index.ts @@ -0,0 +1 @@ +export { default } from './OrganisationBar'; diff --git a/src/app/organisations/[id]/components/organisation-dasboard/OrganisationDashboard.styles.ts b/src/app/organisations/[id]/components/organisation-dasboard/OrganisationDashboard.styles.ts index 55f8991..e3ee127 100644 --- a/src/app/organisations/[id]/components/organisation-dasboard/OrganisationDashboard.styles.ts +++ b/src/app/organisations/[id]/components/organisation-dasboard/OrganisationDashboard.styles.ts @@ -3,6 +3,7 @@ import { SxProps, Theme } from '@mui/material/styles'; export const wrapper: SxProps = { maxWidth: '387px', p: '16px', + mr: '20px', display: 'flex', flexDirection: 'column', gap: '16px', @@ -10,4 +11,8 @@ export const wrapper: SxProps = { borderRadius: '4px', boxShadow: '6px 6px 4px 0px rgba(0, 0, 0, 0.25)', + + img: { + borderRadius: '4px', + }, }; diff --git a/src/app/organisations/[id]/layout.tsx b/src/app/organisations/[id]/layout.tsx index 0874ad2..cf80fa0 100644 --- a/src/app/organisations/[id]/layout.tsx +++ b/src/app/organisations/[id]/layout.tsx @@ -1,6 +1,7 @@ import { FC, PropsWithChildren } from 'react'; -import { Box, Typography } from '@mui/material'; +import { Box } from '@mui/material'; +import OrganisationBar from '@/app/organisations/[id]/components/organisation-bar'; import OrganisationDashboard from '@/app/organisations/[id]/components/organisation-dasboard/OrganisationDashboard'; import * as styles from './Organisation.styles'; diff --git a/src/app/organisations/[id]/page.tsx b/src/app/organisations/[id]/page.tsx index 3d58e59..0ae7ba7 100644 --- a/src/app/organisations/[id]/page.tsx +++ b/src/app/organisations/[id]/page.tsx @@ -1,5 +1,33 @@ +import { Box, Stack } from '@mui/material'; + +import OrganisationBar from '@/app/organisations/[id]/components/organisation-bar'; +import { mocks } from '@/app/profile/components/tabs/constants'; +import IconButton from '@/components/common/ui/icon-button/IconButton'; +import Input from '@/components/common/ui/input/Input'; +import OrganisationCard from '@/components/common/ui/organisation-card'; + +import * as styles from './Organisation.styles'; + const OrganisationPage = () => { - return
Organisation Page
; + return ( + + + + + + + + {mocks.map((mock, index) => ( + + ))} + + + ); }; export default OrganisationPage; diff --git a/src/app/test/button/page.tsx b/src/app/test/button/page.tsx index f070c09..cc5142a 100644 --- a/src/app/test/button/page.tsx +++ b/src/app/test/button/page.tsx @@ -114,6 +114,12 @@ const ButtonPage = () => { + {' '} + diff --git a/src/components/common/ui/button/types/index.ts b/src/components/common/ui/button/types/index.ts index d9f08a1..c7cc625 100644 --- a/src/components/common/ui/button/types/index.ts +++ b/src/components/common/ui/button/types/index.ts @@ -2,6 +2,6 @@ export type ButtonSize = 'small' | 'medium' | 'large'; export type ButtonIcon = 'none' | 'left' | 'right'; -export type ButtonVariant = 'contained' | 'outlined'; +export type ButtonVariant = 'contained' | 'outlined' | 'text'; export type ButtonColor = 'primary' | 'secondary'; From 3bb5d39cb219bcfc7958fb411274a44cce9ceb71 Mon Sep 17 00:00:00 2001 From: Igor <114025058+igaryakqwe@users.noreply.github.com> Date: Fri, 12 Jul 2024 14:56:46 +0300 Subject: [PATCH 08/14] feature: finished organisation tabs without logic --- .../organisations/[id]/Organisation.styles.ts | 19 ++++++++++++++++++- .../OrganisationBar.styles.ts | 15 +++++++++++++-- .../OrganisationDashboard.styles.ts | 8 ++++++-- .../OrganisationDashboard.tsx | 5 +++++ src/app/organisations/[id]/layout.tsx | 1 - .../page-layout/header/Header.styles.ts | 3 ++- 6 files changed, 44 insertions(+), 7 deletions(-) diff --git a/src/app/organisations/[id]/Organisation.styles.ts b/src/app/organisations/[id]/Organisation.styles.ts index 5d1bed9..e50d396 100644 --- a/src/app/organisations/[id]/Organisation.styles.ts +++ b/src/app/organisations/[id]/Organisation.styles.ts @@ -1,9 +1,22 @@ import { SxProps, Theme } from '@mui/material/styles'; export const layout: SxProps = { - p: '48px 100px 36px 100px', + p: { + mobile: '16px', + tablet: '32px', + desktop: '48px 100px 36px 100px', + }, display: 'flex', + justifyContent: 'center', backgroundColor: 'gray.700', + flexDirection: { + mobile: 'column', + desktop: 'row', + }, + gap: { + mobile: '10px', + desktop: '20px', + }, }; export const wrapper: SxProps = { @@ -19,4 +32,8 @@ export const search: SxProps = { export const input: SxProps = { width: '100%', + backgroundColor: 'white', + '.MuiInputBase-root': { + backgroundColor: 'white!important', + }, }; diff --git a/src/app/organisations/[id]/components/organisation-bar/OrganisationBar.styles.ts b/src/app/organisations/[id]/components/organisation-bar/OrganisationBar.styles.ts index 74bc211..038d52d 100644 --- a/src/app/organisations/[id]/components/organisation-bar/OrganisationBar.styles.ts +++ b/src/app/organisations/[id]/components/organisation-bar/OrganisationBar.styles.ts @@ -1,11 +1,22 @@ import { SxProps, Theme } from '@mui/material/styles'; export const wrapper: SxProps = { + maxWidth: { + mobile: '100%', + tablet: '603px', + }, p: '8px', - display: 'flex', - alignItems: 'center', + + display: 'inline-flex', gap: '20px', + float: 'left', + overflow: 'scroll', + scrollbarWidth: 'none', + '&::-webkit-scrollbar': { + width: '0', + height: '0', + }, backgroundColor: 'white.main', boxShadow: '0px 4px 4px 0px rgba(0, 0, 0, 0.25)', diff --git a/src/app/organisations/[id]/components/organisation-dasboard/OrganisationDashboard.styles.ts b/src/app/organisations/[id]/components/organisation-dasboard/OrganisationDashboard.styles.ts index e3ee127..c682978 100644 --- a/src/app/organisations/[id]/components/organisation-dasboard/OrganisationDashboard.styles.ts +++ b/src/app/organisations/[id]/components/organisation-dasboard/OrganisationDashboard.styles.ts @@ -1,9 +1,11 @@ import { SxProps, Theme } from '@mui/material/styles'; export const wrapper: SxProps = { - maxWidth: '387px', + maxWidth: { + mobile: '100%', + desktop: '400px', + }, p: '16px', - mr: '20px', display: 'flex', flexDirection: 'column', gap: '16px', @@ -14,5 +16,7 @@ export const wrapper: SxProps = { img: { borderRadius: '4px', + width: '100%', + height: 'auto', }, }; diff --git a/src/app/organisations/[id]/components/organisation-dasboard/OrganisationDashboard.tsx b/src/app/organisations/[id]/components/organisation-dasboard/OrganisationDashboard.tsx index 0b1dd6f..78e5b7c 100644 --- a/src/app/organisations/[id]/components/organisation-dasboard/OrganisationDashboard.tsx +++ b/src/app/organisations/[id]/components/organisation-dasboard/OrganisationDashboard.tsx @@ -3,6 +3,7 @@ import { Box, Typography } from '@mui/material'; import Image from 'next/image'; import InfoCard from '@/app/organisations/[id]/components/info-card/InfoCard'; +import Button from '@/components/common/ui/button'; import * as styles from './OrganisationDashboard.styles'; @@ -33,6 +34,10 @@ const OrganisationDashboard: FC = ({ {organisation.description} + + + + ); }; diff --git a/src/app/organisations/[id]/layout.tsx b/src/app/organisations/[id]/layout.tsx index cf80fa0..bb795b0 100644 --- a/src/app/organisations/[id]/layout.tsx +++ b/src/app/organisations/[id]/layout.tsx @@ -1,7 +1,6 @@ import { FC, PropsWithChildren } from 'react'; import { Box } from '@mui/material'; -import OrganisationBar from '@/app/organisations/[id]/components/organisation-bar'; import OrganisationDashboard from '@/app/organisations/[id]/components/organisation-dasboard/OrganisationDashboard'; import * as styles from './Organisation.styles'; diff --git a/src/components/common/layout/page-layout/header/Header.styles.ts b/src/components/common/layout/page-layout/header/Header.styles.ts index 4b51b9d..b175d7a 100644 --- a/src/components/common/layout/page-layout/header/Header.styles.ts +++ b/src/components/common/layout/page-layout/header/Header.styles.ts @@ -4,7 +4,8 @@ export const wrapper: SxProps = { py: 0, px: { mobile: '16px', - tablet: '100px', + tablet: '32px', + desktop: '100px', }, width: '100%', height: '64px', From 1fd9bb28e090a66f0d8172dbcc89aab715701a3d Mon Sep 17 00:00:00 2001 From: Igor <114025058+igaryakqwe@users.noreply.github.com> Date: Sat, 13 Jul 2024 10:22:45 +0300 Subject: [PATCH 09/14] enhancement: updated card component using compound components --- src/app/organisations/[id]/page.tsx | 14 ++--- .../tabs/contents/Organisations.tsx | 10 ++-- src/app/test/organisation-card/page.tsx | 57 +++++++++++++++++-- .../Card.styles.ts} | 21 +++++++ src/components/common/ui/card/Card.tsx | 50 ++++++++++++++++ .../common/ui/card/components/Auto.tsx | 20 +++++++ .../common/ui/card/components/Phone.tsx | 11 ++++ .../common/ui/card/components/Position.tsx | 11 ++++ .../common/ui/card/components/Price.tsx | 11 ++++ src/components/common/ui/card/index.ts | 1 + src/components/common/ui/card/types/index.ts | 27 +++++++++ .../ui/organisation-card/OrganisationCard.tsx | 56 ------------------ .../common/ui/organisation-card/index.ts | 1 - src/types/auto.ts | 10 ++++ 14 files changed, 227 insertions(+), 73 deletions(-) rename src/components/common/ui/{organisation-card/OrganisationCard.styles.ts => card/Card.styles.ts} (69%) create mode 100644 src/components/common/ui/card/Card.tsx create mode 100644 src/components/common/ui/card/components/Auto.tsx create mode 100644 src/components/common/ui/card/components/Phone.tsx create mode 100644 src/components/common/ui/card/components/Position.tsx create mode 100644 src/components/common/ui/card/components/Price.tsx create mode 100644 src/components/common/ui/card/index.ts create mode 100644 src/components/common/ui/card/types/index.ts delete mode 100644 src/components/common/ui/organisation-card/OrganisationCard.tsx delete mode 100644 src/components/common/ui/organisation-card/index.ts create mode 100644 src/types/auto.ts diff --git a/src/app/organisations/[id]/page.tsx b/src/app/organisations/[id]/page.tsx index 0ae7ba7..99ee333 100644 --- a/src/app/organisations/[id]/page.tsx +++ b/src/app/organisations/[id]/page.tsx @@ -2,9 +2,10 @@ import { Box, Stack } from '@mui/material'; import OrganisationBar from '@/app/organisations/[id]/components/organisation-bar'; import { mocks } from '@/app/profile/components/tabs/constants'; +import Card from '@/components/common/ui/card'; +import Position from '@/components/common/ui/card/components/Position'; import IconButton from '@/components/common/ui/icon-button/IconButton'; import Input from '@/components/common/ui/input/Input'; -import OrganisationCard from '@/components/common/ui/organisation-card'; import * as styles from './Organisation.styles'; @@ -17,13 +18,10 @@ const OrganisationPage = () => { - {mocks.map((mock, index) => ( - + {mocks.map((mock) => ( + + + ))} diff --git a/src/app/profile/components/tabs/contents/Organisations.tsx b/src/app/profile/components/tabs/contents/Organisations.tsx index cab8fd2..52775d3 100644 --- a/src/app/profile/components/tabs/contents/Organisations.tsx +++ b/src/app/profile/components/tabs/contents/Organisations.tsx @@ -4,8 +4,9 @@ import { Box, Stack, Typography } from '@mui/material'; import { mocks } from '@/app/profile/components/tabs/constants'; import Gear from '@/components/common/icons/Gear'; import Button from '@/components/common/ui/button'; +import Card from '@/components/common/ui/card'; +import Position from '@/components/common/ui/card/components/Position'; -import OrganisationCard from '../../../../../components/common/ui/organisation-card'; import * as styles from '../Tabs.styles'; const Organisations: FC = () => { @@ -35,12 +36,13 @@ const Organisations: FC = () => { return ( {mocks.map((organisation) => ( - + > + + ))} - + + + + + + У вас поки немає доданих організацій! +
+ Ви можете створити власну або власники інших організацій можуть + додати вас до свого складу :) +
+ + +
- -
+
+ ); } return ( - - {mocks.map((organisation) => ( - + + {mocks.map((organisation) => ( + + + + ))} + - + Створити + + + ); }; diff --git a/src/components/common/ui/card/Card.tsx b/src/components/common/ui/card/Card.tsx index e8a9037..b83fa06 100644 --- a/src/components/common/ui/card/Card.tsx +++ b/src/components/common/ui/card/Card.tsx @@ -7,6 +7,7 @@ import Position from '@/components/common/ui/card/components/Position'; import Price from '@/components/common/ui/card/components/Price'; import RoundButtonIcon from '@/components/common/ui/round-button-icon'; import useToast from '@/hooks/use-toast'; +import mergeSx from '@/lib/utils/mergeSx'; import * as styles from './Card.styles'; import type { CardProps } from './types'; @@ -17,6 +18,7 @@ const CardComponent: FC = ({ description = '', href = '', children, + sx = {}, }) => { const toast = useToast(); const handleDelete = (event: React.MouseEvent) => { @@ -25,7 +27,7 @@ const CardComponent: FC = ({ }; return ( - + diff --git a/src/components/common/ui/card/types/index.ts b/src/components/common/ui/card/types/index.ts index 8ac9950..3b08ad0 100644 --- a/src/components/common/ui/card/types/index.ts +++ b/src/components/common/ui/card/types/index.ts @@ -1,4 +1,5 @@ import { ReactNode } from 'react'; +import { SxProps, Theme } from '@mui/material/styles'; import { Auto } from '@/types/auto'; @@ -8,6 +9,7 @@ export interface CardProps { description?: string; href?: string; children?: ReactNode; + sx?: SxProps; } export interface PositionProps { diff --git a/src/components/common/ui/input/Input.styles.ts b/src/components/common/ui/input/Input.styles.ts index 7091e4e..492c1ae 100644 --- a/src/components/common/ui/input/Input.styles.ts +++ b/src/components/common/ui/input/Input.styles.ts @@ -4,7 +4,6 @@ import { InputVariant } from '@/components/common/ui/input/types'; export const formControl = (variant: InputVariant): SxProps => ({ '.MuiInputBase-root': { - m: 0, border: '2px solid', borderColor: 'gray.400', diff --git a/src/components/common/ui/pop-ups/organisation-popup/OrganisationPopup.styles.ts b/src/components/common/ui/pop-ups/organisation-popup/OrganisationPopup.styles.ts new file mode 100644 index 0000000..16cf975 --- /dev/null +++ b/src/components/common/ui/pop-ups/organisation-popup/OrganisationPopup.styles.ts @@ -0,0 +1,40 @@ +import { SxProps, Theme } from '@mui/material/styles'; + +export const modal: SxProps = { + zIndex: 10, + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', +}; + +export const window: SxProps = { + zIndex: 11, + width: '500px', + backgroundColor: 'white.main', + px: '40px', + py: '20px', + borderRadius: '6px', + border: '1px solid', + borderColor: 'grey.500', + background: 'white.main', +}; + +export const backdrop: SxProps = { + background: 'rgba(151, 151, 151, 0.40);', + backdropFilter: 'blur(4px)', +}; + +export const avatarWrapper: SxProps = { + mt: '20px', + width: '160px', + height: '160px', + position: 'relative', +}; + +export const buttonIcon: SxProps = { + position: 'absolute', + right: '0px', + top: '120px', + margin: 'auto', +}; diff --git a/src/components/common/ui/pop-ups/organisation-popup/OrganisationPopup.tsx b/src/components/common/ui/pop-ups/organisation-popup/OrganisationPopup.tsx new file mode 100644 index 0000000..55d7da1 --- /dev/null +++ b/src/components/common/ui/pop-ups/organisation-popup/OrganisationPopup.tsx @@ -0,0 +1,116 @@ +import { FC, PropsWithChildren, useRef, useState } from 'react'; +import { PencilSquareIcon } from '@heroicons/react/24/outline'; +import { Avatar, Box, Modal, Stack, Typography } from '@mui/material'; +import { useFormik } from 'formik'; + +import Button from '@/components/common/ui/button'; +import Input from '@/components/common/ui/input/Input'; +import RoundButtonIcon from '@/components/common/ui/round-button-icon'; + +import * as styles from './OrganisationPopup.styles'; + +interface OrganisationPopupProps { + open: boolean; + handleClick: () => void; +} + +const OrganisationPopup: FC> = ({ + children, + open, + handleClick, +}) => { + const [avatar, setAvatar] = useState( + '/svgs/organisation-default.svg', + ); + const fileInputRef = useRef(null); + + const formik = useFormik({ + initialValues: { + avatar: '', + }, + onSubmit: (values) => { + console.log(values); + }, + }); + + const handleFileChange = (event: React.ChangeEvent) => { + const file = event.currentTarget.files?.[0]; + if (file) { + const reader = new FileReader(); + reader.onloadend = () => { + setAvatar(reader.result as string); + formik.setFieldValue('avatar', reader.result); + }; + reader.readAsDataURL(file); + } + }; + + const handleChangeAvatar = () => { + fileInputRef.current?.click(); + }; + + return ( + <> + {children} + + + + Створення організації +
+ + + + + } + onClick={handleChangeAvatar} + /> + + + + + + +
+
+
+
+ + ); +}; + +export default OrganisationPopup; diff --git a/src/components/common/ui/pop-ups/organisation-popup/types/index.ts b/src/components/common/ui/pop-ups/organisation-popup/types/index.ts new file mode 100644 index 0000000..ad512c8 --- /dev/null +++ b/src/components/common/ui/pop-ups/organisation-popup/types/index.ts @@ -0,0 +1,4 @@ +export interface ICreateOrganisationContext { + open: boolean; + handleClick: () => void; +} From d04dd0ca9071a232e3e20c452ece62ba59279cd5 Mon Sep 17 00:00:00 2001 From: Ihor Novykov Date: Sun, 22 Sep 2024 16:31:58 +0300 Subject: [PATCH 14/14] feat: added creating organisations --- src/app/organisations/Organisations.styles.ts | 25 +--------- .../OrganisationsList.styles.ts | 30 ++++++++++++ .../organisations-llist/OrganisationsList.tsx | 43 +++++++++++++++++ .../components/organisations-llist/index.ts | 1 + src/app/organisations/page.tsx | 48 ++----------------- .../components/profile-card/ProfileCard.tsx | 4 +- .../profile-card/popup/ProfileEditPopup.tsx | 2 +- .../page-layout/footer/Footer.styles.ts | 2 +- .../common/ui/icon-button/IconButton.tsx | 3 ++ .../OrganisationPopup.styles.ts | 2 +- .../organisation-popup/OrganisationPopup.tsx | 45 +++++++++++++++-- src/lib/api/organisations/OrganisationsAPI.ts | 21 ++++++++ src/lib/api/organisations/types/index.ts | 6 +++ 13 files changed, 156 insertions(+), 76 deletions(-) create mode 100644 src/app/organisations/components/organisations-llist/OrganisationsList.styles.ts create mode 100644 src/app/organisations/components/organisations-llist/OrganisationsList.tsx create mode 100644 src/app/organisations/components/organisations-llist/index.ts create mode 100644 src/lib/api/organisations/OrganisationsAPI.ts create mode 100644 src/lib/api/organisations/types/index.ts diff --git a/src/app/organisations/Organisations.styles.ts b/src/app/organisations/Organisations.styles.ts index 0a38998..ccc1348 100644 --- a/src/app/organisations/Organisations.styles.ts +++ b/src/app/organisations/Organisations.styles.ts @@ -1,30 +1,7 @@ import { SxProps, Theme } from '@mui/material/styles'; export const wrapper: SxProps = { - display: 'flex', - flexDirection: 'column', - alignItems: 'center', width: '100%', -}; - -export const search: SxProps = { - maxWidth: '794px', - width: '100%', - mt: '26px', - display: 'inline-flex', - gap: '16px', -}; - -export const input: SxProps = { - maxWidth: '730px', - flexGrow: 1, - mb: '26px', -}; - -export const organisations: SxProps = { - width: '100%', - maxWidth: '994px', display: 'grid', - gap: '16px', - mb: '64px', + placeItems: 'center', }; diff --git a/src/app/organisations/components/organisations-llist/OrganisationsList.styles.ts b/src/app/organisations/components/organisations-llist/OrganisationsList.styles.ts new file mode 100644 index 0000000..5e5f868 --- /dev/null +++ b/src/app/organisations/components/organisations-llist/OrganisationsList.styles.ts @@ -0,0 +1,30 @@ +import { SxProps, Theme } from '@mui/material/styles'; + +export const wrapper: SxProps = { + width: '100%', + display: 'flex', + flexDirection: 'column', + alignItems: 'center', +}; + +export const search: SxProps = { + maxWidth: '794px', + width: '100%', + mt: '26px', + display: 'inline-flex', + gap: '16px', +}; + +export const input: SxProps = { + maxWidth: '730px', + flexGrow: 1, + mb: '26px', +}; + +export const organisations: SxProps = { + width: '100%', + maxWidth: '994px', + display: 'grid', + gap: '16px', + mb: '64px', +}; diff --git a/src/app/organisations/components/organisations-llist/OrganisationsList.tsx b/src/app/organisations/components/organisations-llist/OrganisationsList.tsx new file mode 100644 index 0000000..ce102cb --- /dev/null +++ b/src/app/organisations/components/organisations-llist/OrganisationsList.tsx @@ -0,0 +1,43 @@ +'use client'; +import { FC, useState } from 'react'; +import { Box } from '@mui/material'; + +import IconButton from '@/components/common/ui/icon-button/IconButton'; +import Input from '@/components/common/ui/input/Input'; +import OrganisationPopup from '@/components/common/ui/pop-ups/organisation-popup/OrganisationPopup'; + +import * as styles from './OrganisationsList.styles'; + +interface OrganisationsListProps {} + +const OrganisationsList: FC = () => { + const [open, setOpen] = useState(false); + + const handleClick = () => { + setOpen(!open); + }; + + return ( + + + + + + + + + {/*{mocks.map((organisation) => (*/} + {/* */} + {/* */} + {/* */} + {/*))}*/} + + + ); +}; + +export default OrganisationsList; diff --git a/src/app/organisations/components/organisations-llist/index.ts b/src/app/organisations/components/organisations-llist/index.ts new file mode 100644 index 0000000..119f03d --- /dev/null +++ b/src/app/organisations/components/organisations-llist/index.ts @@ -0,0 +1 @@ +export { default } from './OrganisationsList'; diff --git a/src/app/organisations/page.tsx b/src/app/organisations/page.tsx index 7207a62..06b1d28 100644 --- a/src/app/organisations/page.tsx +++ b/src/app/organisations/page.tsx @@ -1,58 +1,18 @@ import { Box, Typography } from '@mui/material'; -import Card from '@/components/common/ui/card'; -import Position from '@/components/common/ui/card/components/Position'; -import IconButton from '@/components/common/ui/icon-button/IconButton'; -import Input from '@/components/common/ui/input/Input'; +import OrganisationsList from '@/app/organisations/components/organisations-llist'; import * as styles from './Organisations.styles'; -const mocks = [ - { - avatar: - 'https://autolab-fs.s3.eu-north-1.amazonaws.com/default/avatar-org.svg', - name: 'Автосервіс Гепард', - position: 'Власник', - description: - 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus accusantium aperiam delectus dolor dolores enim error est et excepturi ipsum iusto magni non pariatur, quibusdam reiciendis sapiente, sed sint tenetur!\n ', - }, - { - avatar: - 'https://autolab-fs.s3.eu-north-1.amazonaws.com/default/avatar-org.svg', - name: 'Автосервіс Чірік', - position: 'Співвласник', - }, - { - avatar: '/images/avatar.jpg', - name: 'Автосервіс Лісовик', - position: 'Співробітник', - }, -]; - -const Organisations = () => { +const OrganisationsPage = () => { return ( Мої організації - - - - - - - {mocks.map((organisation) => ( - - - - ))} - + ); }; -export default Organisations; +export default OrganisationsPage; diff --git a/src/app/profile/components/profile-card/ProfileCard.tsx b/src/app/profile/components/profile-card/ProfileCard.tsx index 6865ad5..b78f5a7 100644 --- a/src/app/profile/components/profile-card/ProfileCard.tsx +++ b/src/app/profile/components/profile-card/ProfileCard.tsx @@ -27,7 +27,7 @@ export const ProfileCardContext = createContext( ); const ProfileCard: FC = () => { - const { user, isLoading } = useAuthContext(); + const { user, isLoading, isError } = useAuthContext(); const birthday = getDate(user?.birthDate as string); const years = getYears(user?.birthDate as string); const [open, setOpen] = useState(false); @@ -38,7 +38,7 @@ const ProfileCard: FC = () => { return ( - {isLoading ? ( + {isError || (!user && isLoading) ? ( ) : ( diff --git a/src/app/profile/components/profile-card/popup/ProfileEditPopup.tsx b/src/app/profile/components/profile-card/popup/ProfileEditPopup.tsx index 52c5930..f753420 100644 --- a/src/app/profile/components/profile-card/popup/ProfileEditPopup.tsx +++ b/src/app/profile/components/profile-card/popup/ProfileEditPopup.tsx @@ -32,7 +32,7 @@ const ProfileEditPopup: FC = () => { const [activeSection, setActiveSection] = useState('personalData'); const { user } = useAuthContext(); - const [avatar, setAvatar] = useState(user!.avatar); + const [avatar, setAvatar] = useState(user?.avatar || ''); const fileInputRef = useRef(null); const toast = useToast(); diff --git a/src/components/common/layout/page-layout/footer/Footer.styles.ts b/src/components/common/layout/page-layout/footer/Footer.styles.ts index 7383352..3c4e62f 100644 --- a/src/components/common/layout/page-layout/footer/Footer.styles.ts +++ b/src/components/common/layout/page-layout/footer/Footer.styles.ts @@ -10,7 +10,7 @@ export const wrapper: SxProps = { desktop: 'flex-start', mobile: 'center', }, - zIndex: 11, + zIndex: 10, padding: { desktop: '38px 100px', diff --git a/src/components/common/ui/icon-button/IconButton.tsx b/src/components/common/ui/icon-button/IconButton.tsx index 5f06c34..f8a9b8b 100644 --- a/src/components/common/ui/icon-button/IconButton.tsx +++ b/src/components/common/ui/icon-button/IconButton.tsx @@ -18,6 +18,7 @@ interface IconButtonProps extends IconButtonPropsMUI { children?: ReactNode; size?: IconButtonSize; variant?: IconButtonVariant; + onClick?: () => void; sx?: SxProps; } @@ -25,12 +26,14 @@ const IconButton: FC = ({ children = , size = 'medium', variant = 'contained', + onClick = () => {}, sx = {}, ...props }) => { return ( diff --git a/src/components/common/ui/pop-ups/organisation-popup/OrganisationPopup.styles.ts b/src/components/common/ui/pop-ups/organisation-popup/OrganisationPopup.styles.ts index 16cf975..19d0230 100644 --- a/src/components/common/ui/pop-ups/organisation-popup/OrganisationPopup.styles.ts +++ b/src/components/common/ui/pop-ups/organisation-popup/OrganisationPopup.styles.ts @@ -9,7 +9,7 @@ export const modal: SxProps = { }; export const window: SxProps = { - zIndex: 11, + zIndex: 10, width: '500px', backgroundColor: 'white.main', px: '40px', diff --git a/src/components/common/ui/pop-ups/organisation-popup/OrganisationPopup.tsx b/src/components/common/ui/pop-ups/organisation-popup/OrganisationPopup.tsx index 55d7da1..1202933 100644 --- a/src/components/common/ui/pop-ups/organisation-popup/OrganisationPopup.tsx +++ b/src/components/common/ui/pop-ups/organisation-popup/OrganisationPopup.tsx @@ -1,11 +1,14 @@ import { FC, PropsWithChildren, useRef, useState } from 'react'; import { PencilSquareIcon } from '@heroicons/react/24/outline'; import { Avatar, Box, Modal, Stack, Typography } from '@mui/material'; +import { isAxiosError } from 'axios'; import { useFormik } from 'formik'; import Button from '@/components/common/ui/button'; import Input from '@/components/common/ui/input/Input'; import RoundButtonIcon from '@/components/common/ui/round-button-icon'; +import useToast from '@/hooks/use-toast'; +import OrganisationsAPI from '@/lib/api/organisations/OrganisationsAPI'; import * as styles from './OrganisationPopup.styles'; @@ -19,6 +22,8 @@ const OrganisationPopup: FC> = ({ open, handleClick, }) => { + const toast = useToast(); + const [avatar, setAvatar] = useState( '/svgs/organisation-default.svg', ); @@ -26,10 +31,35 @@ const OrganisationPopup: FC> = ({ const formik = useFormik({ initialValues: { - avatar: '', + avatar: null, + name: '', + address: '', + info: '', }, - onSubmit: (values) => { + onSubmit: async (values) => { console.log(values); + const formData = new FormData(); + if (values.avatar) { + formData.append('avatar', values.avatar as Blob); + } + formData.append('name', values.name); + formData.append('address', values.address); + if (values.info) { + formData.append('info', values.info); + } + + try { + await OrganisationsAPI.create(formData); + toast.success('Організація створена успішно'); + handleClick(); + } catch (error) { + if (isAxiosError(error)) { + toast.error( + 'Помилка при створенні організації', + error?.response?.data?.message, + ); + } + } }, }); @@ -39,7 +69,7 @@ const OrganisationPopup: FC> = ({ const reader = new FileReader(); reader.onloadend = () => { setAvatar(reader.result as string); - formik.setFieldValue('avatar', reader.result); + formik.setFieldValue('avatar', file); }; reader.readAsDataURL(file); } @@ -81,21 +111,30 @@ const OrganisationPopup: FC> = ({ />