From 2e9755f03eda88c0849b4cf75c83ddccdc80ba8b Mon Sep 17 00:00:00 2001 From: Wiktoria Salamon <39302106+wiktoriasalamon@users.noreply.github.com> Date: Wed, 10 Jul 2024 13:44:35 +0200 Subject: [PATCH 1/2] [FE][CPF-82] fe refactor code structure + add info to readme (#86) * refactor: project structure * refactor: add brackets * docs: add frontend structure to the readme * fix: delete redundant page * docs: reorganize readme * docs: add store to folder structure * refactor: move minor components to uti * refactor: split ProfileSetting into smaller chunks * fix: import module --- README.md | 44 ++++++- frontend/src/api/ladder.ts | 2 +- .../people/add-new/personal-details/page.tsx | 2 +- .../app/(app)/(root)/documentation/page.tsx | 6 +- .../(root)/library/[ladder]/[bucket]/page.tsx | 17 +-- .../(app)/(root)/library/[ladder]/page.tsx | 16 +-- .../src/app/(app)/(root)/library/page.tsx | 19 +-- .../src/app/(app)/(root)/my-space/page.tsx | 6 +- .../(app)/(root)/people/my-profile/page.tsx | 16 +-- .../common/PageTitle/PageTitle.interface.ts | 3 + .../components/common/PageTitle/PageTitle.tsx | 10 ++ .../src/components/common/PageTitle/index.ts | 1 + .../modules/BucketDetails/BucketDetails.tsx | 38 ------ .../LibraryDetailed.interface.ts | 9 -- .../modules/LibraryDetailed/index.ts | 1 - .../ProfileSetting/ProfileSettings.tsx | 120 ------------------ .../BucketDetails/BucketDetails.hooks.ts | 0 .../BucketDetails/BucketDetails.interface.ts | 3 + .../pages/BucketDetails/BucketDetails.tsx | 49 +++++++ .../{modules => pages}/BucketDetails/index.ts | 0 .../AdvancementLevel.hooks.ts | 0 .../AdvancementLevel/AdvancementLevel.tsx | 2 +- .../AdvancemetLevel.interface.ts | 0 .../modules/AdvancementLevel/index.ts | 0 .../LadderDetails/LadderDetails.hooks.ts} | 36 ++---- .../LadderDetails/LadderDetails.interface.tsx | 18 +++ .../pages/LadderDetails/LadderDetails.tsx | 42 ++++++ .../components/pages/LadderDetails/index.ts | 1 + .../BucketCard/BucketCard.interface.ts | 0 .../modules}/BucketCard/BucketCard.tsx | 0 .../modules}/BucketCard/index.ts | 0 .../LadderDetails/LadderDetails.interface.ts | 0 .../modules/LadderDetails/LadderDetails.tsx | 4 +- .../modules/LadderDetails/index.ts | 0 .../LadderTabs/LadderTabs.interface.ts | 0 .../modules/LadderTabs/LadderTabs.tsx | 0 .../modules/LadderTabs/index.ts | 0 .../modules/LadderTabs/utils.ts | 0 .../pages/Library/Library.interface.ts | 5 + .../src/components/pages/Library/Library.tsx | 20 +++ .../src/components/pages/Library/index.ts | 1 + .../LadderCard/LadderCard.interface.ts | 0 .../modules}/LadderCard/LadderCard.tsx | 0 .../Library/modules}/LadderCard/index.ts | 0 .../PersonalDetails/PersonalDetails.hooks.ts | 0 .../PersonalDetails.interface.ts | 0 .../PersonalDetails/PersonalDetails.tsx | 0 .../{views => pages}/PersonalDetails/index.ts | 0 .../ProfileSetting.interface.ts | 5 + .../pages/ProfileSetting/ProfileSettings.tsx | 26 ++++ .../ProfileSetting/index.ts | 0 .../CropImageModal/CropImageModal.hooks.ts | 0 .../CropImageModal.interface.ts | 0 .../modules/CropImageModal/CropImageModal.tsx | 0 .../modules/CropImageModal/constants.ts | 0 .../modules/CropImageModal/index.ts | 0 .../DeleteImageModal.interface.ts | 0 .../DeleteImageModal/DeleteImageModal.tsx | 0 .../modules/DeleteImageModal/index.ts | 0 .../modules/Ladders/Ladders.interface.ts | 7 + .../modules/Ladders/Ladders.tsx | 17 +++ .../ProfileSetting/modules/Ladders/index.ts | 1 + .../modules/Notifications/Notifications.tsx | 21 +++ .../modules/Notifications/index.ts | 1 + .../PersonalDetails/PersonalDetails.hooks.ts} | 4 +- .../PersonalDetails.interface.ts} | 12 +- .../PersonalDetails/PersonalDetails.tsx | 63 +++++++++ .../modules/PersonalDetails/index.ts | 1 + .../components/pages/ProfileSetting/utils.tsx | 37 ++++++ 69 files changed, 407 insertions(+), 279 deletions(-) create mode 100644 frontend/src/components/common/PageTitle/PageTitle.interface.ts create mode 100644 frontend/src/components/common/PageTitle/PageTitle.tsx create mode 100644 frontend/src/components/common/PageTitle/index.ts delete mode 100644 frontend/src/components/modules/BucketDetails/BucketDetails.tsx delete mode 100644 frontend/src/components/modules/LibraryDetailed/LibraryDetailed.interface.ts delete mode 100644 frontend/src/components/modules/LibraryDetailed/index.ts delete mode 100644 frontend/src/components/modules/ProfileSetting/ProfileSettings.tsx rename frontend/src/components/{modules => pages}/BucketDetails/BucketDetails.hooks.ts (100%) rename frontend/src/components/{modules => pages}/BucketDetails/BucketDetails.interface.ts (60%) create mode 100644 frontend/src/components/pages/BucketDetails/BucketDetails.tsx rename frontend/src/components/{modules => pages}/BucketDetails/index.ts (100%) rename frontend/src/components/{ => pages/BucketDetails}/modules/AdvancementLevel/AdvancementLevel.hooks.ts (100%) rename frontend/src/components/{ => pages/BucketDetails}/modules/AdvancementLevel/AdvancementLevel.tsx (96%) rename frontend/src/components/{ => pages/BucketDetails}/modules/AdvancementLevel/AdvancemetLevel.interface.ts (100%) rename frontend/src/components/{ => pages/BucketDetails}/modules/AdvancementLevel/index.ts (100%) rename frontend/src/components/{modules/LibraryDetailed/LibraryDetailed.tsx => pages/LadderDetails/LadderDetails.hooks.ts} (51%) create mode 100644 frontend/src/components/pages/LadderDetails/LadderDetails.interface.tsx create mode 100644 frontend/src/components/pages/LadderDetails/LadderDetails.tsx create mode 100644 frontend/src/components/pages/LadderDetails/index.ts rename frontend/src/components/{common => pages/LadderDetails/modules}/BucketCard/BucketCard.interface.ts (100%) rename frontend/src/components/{common => pages/LadderDetails/modules}/BucketCard/BucketCard.tsx (100%) rename frontend/src/components/{common => pages/LadderDetails/modules}/BucketCard/index.ts (100%) rename frontend/src/components/{ => pages/LadderDetails}/modules/LadderDetails/LadderDetails.interface.ts (100%) rename frontend/src/components/{ => pages/LadderDetails}/modules/LadderDetails/LadderDetails.tsx (94%) rename frontend/src/components/{ => pages/LadderDetails}/modules/LadderDetails/index.ts (100%) rename frontend/src/components/{ => pages/LadderDetails}/modules/LadderTabs/LadderTabs.interface.ts (100%) rename frontend/src/components/{ => pages/LadderDetails}/modules/LadderTabs/LadderTabs.tsx (100%) rename frontend/src/components/{ => pages/LadderDetails}/modules/LadderTabs/index.ts (100%) rename frontend/src/components/{ => pages/LadderDetails}/modules/LadderTabs/utils.ts (100%) create mode 100644 frontend/src/components/pages/Library/Library.interface.ts create mode 100644 frontend/src/components/pages/Library/Library.tsx create mode 100644 frontend/src/components/pages/Library/index.ts rename frontend/src/components/{common => pages/Library/modules}/LadderCard/LadderCard.interface.ts (100%) rename frontend/src/components/{common => pages/Library/modules}/LadderCard/LadderCard.tsx (100%) rename frontend/src/components/{common => pages/Library/modules}/LadderCard/index.ts (100%) rename frontend/src/components/{views => pages}/PersonalDetails/PersonalDetails.hooks.ts (100%) rename frontend/src/components/{views => pages}/PersonalDetails/PersonalDetails.interface.ts (100%) rename frontend/src/components/{views => pages}/PersonalDetails/PersonalDetails.tsx (100%) rename frontend/src/components/{views => pages}/PersonalDetails/index.ts (100%) create mode 100644 frontend/src/components/pages/ProfileSetting/ProfileSetting.interface.ts create mode 100644 frontend/src/components/pages/ProfileSetting/ProfileSettings.tsx rename frontend/src/components/{modules => pages}/ProfileSetting/index.ts (100%) rename frontend/src/components/{modules => pages}/ProfileSetting/modules/CropImageModal/CropImageModal.hooks.ts (100%) rename frontend/src/components/{modules => pages}/ProfileSetting/modules/CropImageModal/CropImageModal.interface.ts (100%) rename frontend/src/components/{modules => pages}/ProfileSetting/modules/CropImageModal/CropImageModal.tsx (100%) rename frontend/src/components/{modules => pages}/ProfileSetting/modules/CropImageModal/constants.ts (100%) rename frontend/src/components/{modules => pages}/ProfileSetting/modules/CropImageModal/index.ts (100%) rename frontend/src/components/{modules => pages}/ProfileSetting/modules/DeleteImageModal/DeleteImageModal.interface.ts (100%) rename frontend/src/components/{modules => pages}/ProfileSetting/modules/DeleteImageModal/DeleteImageModal.tsx (100%) rename frontend/src/components/{modules => pages}/ProfileSetting/modules/DeleteImageModal/index.ts (100%) create mode 100644 frontend/src/components/pages/ProfileSetting/modules/Ladders/Ladders.interface.ts create mode 100644 frontend/src/components/pages/ProfileSetting/modules/Ladders/Ladders.tsx create mode 100644 frontend/src/components/pages/ProfileSetting/modules/Ladders/index.ts create mode 100644 frontend/src/components/pages/ProfileSetting/modules/Notifications/Notifications.tsx create mode 100644 frontend/src/components/pages/ProfileSetting/modules/Notifications/index.ts rename frontend/src/components/{modules/ProfileSetting/ProfileSetting.hooks.ts => pages/ProfileSetting/modules/PersonalDetails/PersonalDetails.hooks.ts} (90%) rename frontend/src/components/{modules/ProfileSetting/ProfileSetting.interface.ts => pages/ProfileSetting/modules/PersonalDetails/PersonalDetails.interface.ts} (71%) create mode 100644 frontend/src/components/pages/ProfileSetting/modules/PersonalDetails/PersonalDetails.tsx create mode 100644 frontend/src/components/pages/ProfileSetting/modules/PersonalDetails/index.ts create mode 100644 frontend/src/components/pages/ProfileSetting/utils.tsx diff --git a/README.md b/README.md index 1d4f1625..fd81a65f 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,9 @@ goal-oriented work environment with a cutting-edge platform. - Usage - Wiki - Contributing +- Development + - Frontend + - Backend - License - Contact @@ -51,12 +54,6 @@ Instructions on how to use the project. For more information, check out the project's wiki under the link: https://github.com/Tivix/cpf/wiki -# swagger/redoc - -Swagger and redoc can be accessed using following urls: -- http://0.0.0.0:8000/docs -- http://0.0.0.0:8000/redoc - # Contributing Guidelines for contributing to the project. @@ -68,6 +65,41 @@ Guidelines for contributing to the project. - Push to the branch. - Open a pull request. +# Development + +## Frontend + +### Folder structure + +- `api` - Contains api calls. +- `app`- The App Router by Next.js. +- `components` - Contains all components used in the app. + - `common` - In the common folder, we keep all essential components like Button, Card, or Input. + - `modules` - Here we keep more complex components that are still reusable or are part of layouts. + - `pages` - Here we compose view together to create a page. If you want to extract some module of the page, create `modules` folder there and put it in it. +- `constants` - Contains all the constant values used in the app. +- `static`- Contains assets like icons. +- `store` - Contains all stores for state management. +- `types` - Contains all reusable types and interfaces that are shared between many pages and modules. +- `utils` - Contains all utility functions like data transformations or calculations. + +### Component structure + +Component folder should contain: + +- `index.ts` - importing and exporting the component. +- `ComponentName.tsx` - view part of a component. +- `ComponentName.interface.ts` - types related to that component. +- `ComponentName.hooks.tsx` - the logic of our component + +## Backend + +### swagger/redoc + +Swagger and redoc can be accessed using following urls: +- http://0.0.0.0:8000/docs +- http://0.0.0.0:8000/redoc + # License Specify the license under which the project is distributed. diff --git a/frontend/src/api/ladder.ts b/frontend/src/api/ladder.ts index 6a06845a..63c77073 100644 --- a/frontend/src/api/ladder.ts +++ b/frontend/src/api/ladder.ts @@ -1,6 +1,6 @@ import { mapKeysToCamelCase } from '@app/utils'; import { API_URLS } from '.'; -import { LadderCardInterface } from '@app/components/common/LadderCard'; +import { LadderCardInterface } from '@app/components/pages/Library/modules/LadderCard'; import { LadderBand } from '@app/types/library'; async function getLadders() { diff --git a/frontend/src/app/(app)/(peopleFlow)/people/add-new/personal-details/page.tsx b/frontend/src/app/(app)/(peopleFlow)/people/add-new/personal-details/page.tsx index 7215ae9f..41475a48 100644 --- a/frontend/src/app/(app)/(peopleFlow)/people/add-new/personal-details/page.tsx +++ b/frontend/src/app/(app)/(peopleFlow)/people/add-new/personal-details/page.tsx @@ -1,3 +1,3 @@ -import { PersonalDetails } from '@app/components/views/PersonalDetails/PersonalDetails'; +import { PersonalDetails } from '@app/components/pages/PersonalDetails/PersonalDetails'; export default PersonalDetails; diff --git a/frontend/src/app/(app)/(root)/documentation/page.tsx b/frontend/src/app/(app)/(root)/documentation/page.tsx index b530f52b..a581acdf 100644 --- a/frontend/src/app/(app)/(root)/documentation/page.tsx +++ b/frontend/src/app/(app)/(root)/documentation/page.tsx @@ -1,11 +1,9 @@ -import { Typography } from '@app/components/common/Typography'; +import { PageTitle } from '@app/components/common/PageTitle'; export default function Documentation() { return (
- - Documentation - +
); } diff --git a/frontend/src/app/(app)/(root)/library/[ladder]/[bucket]/page.tsx b/frontend/src/app/(app)/(root)/library/[ladder]/[bucket]/page.tsx index fa7254b0..c2d6906d 100644 --- a/frontend/src/app/(app)/(root)/library/[ladder]/[bucket]/page.tsx +++ b/frontend/src/app/(app)/(root)/library/[ladder]/[bucket]/page.tsx @@ -1,26 +1,13 @@ -import { Breadcrumbs } from '@app/components/modules/Breadcrumbs'; -import { BucketDetails } from '@app/components/modules/BucketDetails'; +import { BucketDetails } from '@app/components/pages/BucketDetails'; import { getLadderName } from '@app/api/ladder'; import { getBucketDetails } from '@app/api/bucket'; -import { routes } from '@app/constants'; export default async function BucketDetailed({ params }: { params: { bucket: string; ladder: string } }) { const { bucket, ladder } = params; const data = await getBucketDetails(bucket); const ladderName = await getLadderName(ladder); - return ( -
- - {data && } -
- ); + return ; } export const dynamic = 'force-dynamic'; diff --git a/frontend/src/app/(app)/(root)/library/[ladder]/page.tsx b/frontend/src/app/(app)/(root)/library/[ladder]/page.tsx index 662c5f5b..9310244f 100644 --- a/frontend/src/app/(app)/(root)/library/[ladder]/page.tsx +++ b/frontend/src/app/(app)/(root)/library/[ladder]/page.tsx @@ -1,22 +1,10 @@ -import { Breadcrumbs } from '@app/components/modules/Breadcrumbs'; -import { LibraryDetailed } from '@app/components/modules/LibraryDetailed'; import { getLadderDetails } from '@app/api/ladder'; -import { routes } from '@app/constants'; +import { LadderDetails } from '@app/components/pages/LadderDetails'; export default async function LadderDetailed({ params }: { params: { ladder: string } }) { const data = await getLadderDetails(params.ladder); - return ( -
- - {data && } -
- ); + return ; } export const dynamic = 'force-dynamic'; diff --git a/frontend/src/app/(app)/(root)/library/page.tsx b/frontend/src/app/(app)/(root)/library/page.tsx index a04ac124..beced5e2 100644 --- a/frontend/src/app/(app)/(root)/library/page.tsx +++ b/frontend/src/app/(app)/(root)/library/page.tsx @@ -1,25 +1,10 @@ -import { LadderCard } from '@app/components/common/LadderCard'; import { getLadders } from '@app/api/ladder'; -import { Typography } from '@app/components/common/Typography'; +import { Library } from '@app/components/pages/Library'; export default async function LibraryPage() { const data = await getLadders(); - return ( -
- - CPF Library - - - Select a career path to view the details. - -
- {data.map((ladder) => ( - - ))} -
-
- ); + return ; } export const dynamic = 'force-dynamic'; diff --git a/frontend/src/app/(app)/(root)/my-space/page.tsx b/frontend/src/app/(app)/(root)/my-space/page.tsx index 86bc590b..03d759d2 100644 --- a/frontend/src/app/(app)/(root)/my-space/page.tsx +++ b/frontend/src/app/(app)/(root)/my-space/page.tsx @@ -1,11 +1,9 @@ -import { Typography } from '@app/components/common/Typography'; +import { PageTitle } from '@app/components/common/PageTitle'; export default function MySpace() { return (
- - My Space - +
); } diff --git a/frontend/src/app/(app)/(root)/people/my-profile/page.tsx b/frontend/src/app/(app)/(root)/people/my-profile/page.tsx index 925d3e3e..28a68c0c 100644 --- a/frontend/src/app/(app)/(root)/people/my-profile/page.tsx +++ b/frontend/src/app/(app)/(root)/people/my-profile/page.tsx @@ -1,6 +1,4 @@ -import { Breadcrumbs } from '@app/components/modules/Breadcrumbs'; -import { ProfileSettings } from '@app/components/modules/ProfileSetting'; -import { routes } from '@app/constants'; +import { ProfileSettings } from '@app/components/pages/ProfileSetting'; // TODO: get data from api const data = { @@ -21,15 +19,5 @@ const data = { }; export default async function LibraryPage() { - return ( -
- - -
- ); + return ; } diff --git a/frontend/src/components/common/PageTitle/PageTitle.interface.ts b/frontend/src/components/common/PageTitle/PageTitle.interface.ts new file mode 100644 index 00000000..8dd4367e --- /dev/null +++ b/frontend/src/components/common/PageTitle/PageTitle.interface.ts @@ -0,0 +1,3 @@ +export interface PageTitleProps { + title: string; +} diff --git a/frontend/src/components/common/PageTitle/PageTitle.tsx b/frontend/src/components/common/PageTitle/PageTitle.tsx new file mode 100644 index 00000000..04afb984 --- /dev/null +++ b/frontend/src/components/common/PageTitle/PageTitle.tsx @@ -0,0 +1,10 @@ +import { Typography } from '@app/components/common/Typography'; +import { PageTitleProps } from './PageTitle.interface'; + +export const PageTitle: React.FC = ({ title }) => { + return ( + + {title} + + ); +}; diff --git a/frontend/src/components/common/PageTitle/index.ts b/frontend/src/components/common/PageTitle/index.ts new file mode 100644 index 00000000..2888306f --- /dev/null +++ b/frontend/src/components/common/PageTitle/index.ts @@ -0,0 +1 @@ +export { PageTitle } from './PageTitle'; diff --git a/frontend/src/components/modules/BucketDetails/BucketDetails.tsx b/frontend/src/components/modules/BucketDetails/BucketDetails.tsx deleted file mode 100644 index c721e037..00000000 --- a/frontend/src/components/modules/BucketDetails/BucketDetails.tsx +++ /dev/null @@ -1,38 +0,0 @@ -'use client'; -import { BucketDetailsProps } from './BucketDetails.interface'; -import { AdvancementLevel } from '@app/components/modules/AdvancementLevel'; -import { Typography } from '@app/components/common/Typography'; -import { useBucketDetails } from './BucketDetails.hooks'; - -export const BucketDetails: React.FC = ({ data }) => { - const { bucketName, description, advancementLevels } = data; - const { levelOpen, handleOpen } = useBucketDetails(); - - return ( -
-
-
-
- - {bucketName} - - - {description} - -
-
-
- {advancementLevels.map((level, index) => ( - handleOpen(level.advancementLevel)} - /> - ))} -
-
-
- ); -}; diff --git a/frontend/src/components/modules/LibraryDetailed/LibraryDetailed.interface.ts b/frontend/src/components/modules/LibraryDetailed/LibraryDetailed.interface.ts deleted file mode 100644 index 0802c9c1..00000000 --- a/frontend/src/components/modules/LibraryDetailed/LibraryDetailed.interface.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { LadderBand } from '@app/types/library'; - -export interface LibraryDetailedProps { - ladderSlug: string; - data: { - ladderName: string; - bands: Record; - }; -} diff --git a/frontend/src/components/modules/LibraryDetailed/index.ts b/frontend/src/components/modules/LibraryDetailed/index.ts deleted file mode 100644 index 39116cc0..00000000 --- a/frontend/src/components/modules/LibraryDetailed/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { LibraryDetailed } from './LibraryDetailed'; diff --git a/frontend/src/components/modules/ProfileSetting/ProfileSettings.tsx b/frontend/src/components/modules/ProfileSetting/ProfileSettings.tsx deleted file mode 100644 index 782f6d05..00000000 --- a/frontend/src/components/modules/ProfileSetting/ProfileSettings.tsx +++ /dev/null @@ -1,120 +0,0 @@ -'use client'; -import { ProfileSettingsProps } from './ProfileSetting.interface'; -import { Card } from '@app/components/common/Card'; -import { SlackIcon } from '@app/static/icons/SlackIcon'; -import { EnvelopeIcon } from '@app/static/icons/EnvelopeIcon'; -import { EditIcon } from '@app/static/icons/EditIcon'; -import { DeleteIcon } from '@app/static/icons/DeleteIcon'; -import { Avatar } from '@app/components/common/Avatar'; -import { useProfileSettings } from '@app/components/modules/ProfileSetting/ProfileSetting.hooks'; -import { CropImageModal } from './modules/CropImageModal'; -import { ReactNode } from 'react'; -import { DeleteImageModal } from './modules/DeleteImageModal'; -import { Typography } from '@app/components/common/Typography'; - -export const ProfileSettings: React.FC = ({ data }) => { - const { firstName, lastName, email, ladders, photo } = data; - const { - imageSrc, - handleOpenDeleteModal, - handleFileChange, - cropModalOpen, - handleCloseCropModal, - deleteModalOpen, - handleCloseDeleteModal, - handleDeleteImage, - handleSaveCroppedImage, - } = useProfileSettings(); - - const NotificationCheckbox: React.FC<{ icon: ReactNode }> = ({ icon }) => ( -
-
{icon}
-
- -
-
- ); - - const PersonalDetailsDataItem: React.FC<{ title: string; value: string | number }> = ({ title, value }) => ( -
-
- {title} -
-
- - {value} - -
-
- ); - - const LadderDataItem: React.FC<{ title: string; value: string | number }> = ({ title, value }) => ( -
-
- {title} -
-
- - {value} - -
-
- ); - - return ( -
- -
-
- - Profile photo - - -
-
- - -
-
- - -
- - {ladders.map(({ ladderName, technology, band }) => ( -
- - - -
- ))} -
- -
-
- Send me notifications via -
-
- } /> - } /> -
-
-
- - -
- ); -}; diff --git a/frontend/src/components/modules/BucketDetails/BucketDetails.hooks.ts b/frontend/src/components/pages/BucketDetails/BucketDetails.hooks.ts similarity index 100% rename from frontend/src/components/modules/BucketDetails/BucketDetails.hooks.ts rename to frontend/src/components/pages/BucketDetails/BucketDetails.hooks.ts diff --git a/frontend/src/components/modules/BucketDetails/BucketDetails.interface.ts b/frontend/src/components/pages/BucketDetails/BucketDetails.interface.ts similarity index 60% rename from frontend/src/components/modules/BucketDetails/BucketDetails.interface.ts rename to frontend/src/components/pages/BucketDetails/BucketDetails.interface.ts index edb84f48..d5dbcf59 100644 --- a/frontend/src/components/modules/BucketDetails/BucketDetails.interface.ts +++ b/frontend/src/components/pages/BucketDetails/BucketDetails.interface.ts @@ -2,4 +2,7 @@ import { Bucket } from '@app/types/library'; export interface BucketDetailsProps { data: Bucket; + bucketSlug: string; + ladderName: string; + ladderSlug: string; } diff --git a/frontend/src/components/pages/BucketDetails/BucketDetails.tsx b/frontend/src/components/pages/BucketDetails/BucketDetails.tsx new file mode 100644 index 00000000..bbc46230 --- /dev/null +++ b/frontend/src/components/pages/BucketDetails/BucketDetails.tsx @@ -0,0 +1,49 @@ +'use client'; +import { BucketDetailsProps } from './BucketDetails.interface'; +import { AdvancementLevel } from './modules/AdvancementLevel'; +import { Typography } from '@app/components/common/Typography'; +import { Breadcrumbs } from '@app/components/modules/Breadcrumbs'; +import { useBucketDetails } from './BucketDetails.hooks'; +import { routes } from '@app/constants'; + +export const BucketDetails: React.FC = ({ data, ladderName, ladderSlug, bucketSlug }) => { + const { bucketName, description, advancementLevels } = data; + const { levelOpen, handleOpen } = useBucketDetails(); + + return ( +
+ +
+
+
+
+ + {bucketName} + + + {description} + +
+
+
+ {advancementLevels.map((level, index) => ( + handleOpen(level.advancementLevel)} + /> + ))} +
+
+
+
+ ); +}; diff --git a/frontend/src/components/modules/BucketDetails/index.ts b/frontend/src/components/pages/BucketDetails/index.ts similarity index 100% rename from frontend/src/components/modules/BucketDetails/index.ts rename to frontend/src/components/pages/BucketDetails/index.ts diff --git a/frontend/src/components/modules/AdvancementLevel/AdvancementLevel.hooks.ts b/frontend/src/components/pages/BucketDetails/modules/AdvancementLevel/AdvancementLevel.hooks.ts similarity index 100% rename from frontend/src/components/modules/AdvancementLevel/AdvancementLevel.hooks.ts rename to frontend/src/components/pages/BucketDetails/modules/AdvancementLevel/AdvancementLevel.hooks.ts diff --git a/frontend/src/components/modules/AdvancementLevel/AdvancementLevel.tsx b/frontend/src/components/pages/BucketDetails/modules/AdvancementLevel/AdvancementLevel.tsx similarity index 96% rename from frontend/src/components/modules/AdvancementLevel/AdvancementLevel.tsx rename to frontend/src/components/pages/BucketDetails/modules/AdvancementLevel/AdvancementLevel.tsx index 5a0c4f5a..98beb23c 100644 --- a/frontend/src/components/modules/AdvancementLevel/AdvancementLevel.tsx +++ b/frontend/src/components/pages/BucketDetails/modules/AdvancementLevel/AdvancementLevel.tsx @@ -4,7 +4,7 @@ import { AccordionCard } from '@app/components/common/AccordionCard'; import { AccordionList } from '@app/components/common/AccordionList'; import { Modal } from '@app/components/common/Modal'; import { AdvancementLevelProps } from './AdvancemetLevel.interface'; -import { useAdvancementLevel } from '@app/components/modules/AdvancementLevel/AdvancementLevel.hooks'; +import { useAdvancementLevel } from './AdvancementLevel.hooks'; import { Markdown } from '@app/components/common/Markdown'; import { Typography } from '@app/components/common/Typography'; import { Button } from '@app/components/common/Button'; diff --git a/frontend/src/components/modules/AdvancementLevel/AdvancemetLevel.interface.ts b/frontend/src/components/pages/BucketDetails/modules/AdvancementLevel/AdvancemetLevel.interface.ts similarity index 100% rename from frontend/src/components/modules/AdvancementLevel/AdvancemetLevel.interface.ts rename to frontend/src/components/pages/BucketDetails/modules/AdvancementLevel/AdvancemetLevel.interface.ts diff --git a/frontend/src/components/modules/AdvancementLevel/index.ts b/frontend/src/components/pages/BucketDetails/modules/AdvancementLevel/index.ts similarity index 100% rename from frontend/src/components/modules/AdvancementLevel/index.ts rename to frontend/src/components/pages/BucketDetails/modules/AdvancementLevel/index.ts diff --git a/frontend/src/components/modules/LibraryDetailed/LibraryDetailed.tsx b/frontend/src/components/pages/LadderDetails/LadderDetails.hooks.ts similarity index 51% rename from frontend/src/components/modules/LibraryDetailed/LibraryDetailed.tsx rename to frontend/src/components/pages/LadderDetails/LadderDetails.hooks.ts index ce508928..ed369ba3 100644 --- a/frontend/src/components/modules/LibraryDetailed/LibraryDetailed.tsx +++ b/frontend/src/components/pages/LadderDetails/LadderDetails.hooks.ts @@ -1,18 +1,16 @@ -'use client'; -import { usePathname, useRouter, useSearchParams } from 'next/navigation'; -import { LadderDetails } from '@app/components/modules/LadderDetails'; -import { LadderTabs } from '@app/components/modules/LadderTabs'; -import { LibraryDetailedProps } from './LibraryDetailed.interface'; import { useCallback, useEffect, useMemo, useState } from 'react'; +import { usePathname, useRouter, useSearchParams } from 'next/navigation'; +import { LadderBand } from '@app/types/library'; +import { LadderDetailsHook } from './LadderDetails.interface'; -export const LibraryDetailed: React.FC = ({ data, ladderSlug }) => { +export const useLadderDetails = (bands?: Record): LadderDetailsHook => { const router = useRouter(); const pathname = usePathname(); const searchParams = useSearchParams(); const band = searchParams.get('band'); const [currentBand, setCurrentBand] = useState(typeof band === 'string' ? parseInt(band, 10) : 1); - const maximumLadders = useMemo(() => Object.keys(data.bands).length, [data]); + const maximumLadders = useMemo(() => (bands ? Object.keys(bands).length : 0), [bands]); const tabsProps = useMemo(() => ({ activeLadder: currentBand, maximumLadders }), [currentBand, maximumLadders]); const handleReplace = useCallback(() => { @@ -31,23 +29,9 @@ export const LibraryDetailed: React.FC = ({ data, ladderSl handleReplace(); }, [handleReplace]); - if (!currentBand || !data?.bands[currentBand]) { - return null; - } - - return ( -
-
- -
-
- -
-
- ); + return { + currentBand, + handleLadderChange, + tabsProps, + }; }; diff --git a/frontend/src/components/pages/LadderDetails/LadderDetails.interface.tsx b/frontend/src/components/pages/LadderDetails/LadderDetails.interface.tsx new file mode 100644 index 00000000..3c4489ea --- /dev/null +++ b/frontend/src/components/pages/LadderDetails/LadderDetails.interface.tsx @@ -0,0 +1,18 @@ +import { LadderBand } from '@app/types/library'; + +export interface LadderDetailsProps { + ladderSlug: string; + data?: { + ladderName: string; + bands: Record; + }; +} + +export interface LadderDetailsHook { + currentBand: number; + handleLadderChange: (ladder: number) => void; + tabsProps: { + activeLadder: number; + maximumLadders: number; + }; +} diff --git a/frontend/src/components/pages/LadderDetails/LadderDetails.tsx b/frontend/src/components/pages/LadderDetails/LadderDetails.tsx new file mode 100644 index 00000000..ae93578b --- /dev/null +++ b/frontend/src/components/pages/LadderDetails/LadderDetails.tsx @@ -0,0 +1,42 @@ +'use client'; + +import { Breadcrumbs } from '@app/components/modules/Breadcrumbs'; +import { routes } from '@app/constants'; +import { LadderTabs } from './modules/LadderTabs'; +import { LadderDetails } from './modules/LadderDetails'; +import { useLadderDetails } from './LadderDetails.hooks'; +import { LadderDetailsProps } from './LadderDetails.interface'; + +export const LadderDetailsPage: React.FC = ({ data, ladderSlug }) => { + const { currentBand, handleLadderChange, tabsProps } = useLadderDetails(data?.bands); + + if (!currentBand || !data || !data.bands[currentBand]) { + return null; + } + + return ( +
+ + {data && ( +
+
+ +
+
+ +
+
+ )} +
+ ); +}; diff --git a/frontend/src/components/pages/LadderDetails/index.ts b/frontend/src/components/pages/LadderDetails/index.ts new file mode 100644 index 00000000..3a1b622d --- /dev/null +++ b/frontend/src/components/pages/LadderDetails/index.ts @@ -0,0 +1 @@ +export { LadderDetailsPage as LadderDetails } from './LadderDetails'; diff --git a/frontend/src/components/common/BucketCard/BucketCard.interface.ts b/frontend/src/components/pages/LadderDetails/modules/BucketCard/BucketCard.interface.ts similarity index 100% rename from frontend/src/components/common/BucketCard/BucketCard.interface.ts rename to frontend/src/components/pages/LadderDetails/modules/BucketCard/BucketCard.interface.ts diff --git a/frontend/src/components/common/BucketCard/BucketCard.tsx b/frontend/src/components/pages/LadderDetails/modules/BucketCard/BucketCard.tsx similarity index 100% rename from frontend/src/components/common/BucketCard/BucketCard.tsx rename to frontend/src/components/pages/LadderDetails/modules/BucketCard/BucketCard.tsx diff --git a/frontend/src/components/common/BucketCard/index.ts b/frontend/src/components/pages/LadderDetails/modules/BucketCard/index.ts similarity index 100% rename from frontend/src/components/common/BucketCard/index.ts rename to frontend/src/components/pages/LadderDetails/modules/BucketCard/index.ts diff --git a/frontend/src/components/modules/LadderDetails/LadderDetails.interface.ts b/frontend/src/components/pages/LadderDetails/modules/LadderDetails/LadderDetails.interface.ts similarity index 100% rename from frontend/src/components/modules/LadderDetails/LadderDetails.interface.ts rename to frontend/src/components/pages/LadderDetails/modules/LadderDetails/LadderDetails.interface.ts diff --git a/frontend/src/components/modules/LadderDetails/LadderDetails.tsx b/frontend/src/components/pages/LadderDetails/modules/LadderDetails/LadderDetails.tsx similarity index 94% rename from frontend/src/components/modules/LadderDetails/LadderDetails.tsx rename to frontend/src/components/pages/LadderDetails/modules/LadderDetails/LadderDetails.tsx index 7cbae0c8..d47866e8 100644 --- a/frontend/src/components/modules/LadderDetails/LadderDetails.tsx +++ b/frontend/src/components/pages/LadderDetails/modules/LadderDetails/LadderDetails.tsx @@ -1,8 +1,8 @@ import { Tooltip } from 'react-tooltip'; -import { LadderDetailsProps } from '@app/components/modules/LadderDetails/LadderDetails.interface'; +import { LadderDetailsProps } from './LadderDetails.interface'; import { InfoIcon } from '@app/static/icons/InfoIcon'; import { LadderBandBucket } from '@app/types/library'; -import { BucketCard } from '@app/components/common/BucketCard'; +import { BucketCard } from '../BucketCard'; import { AccordionCard } from '@app/components/common/AccordionCard'; import { AccordionList } from '@app/components/common/AccordionList'; import { Typography } from '@app/components/common/Typography'; diff --git a/frontend/src/components/modules/LadderDetails/index.ts b/frontend/src/components/pages/LadderDetails/modules/LadderDetails/index.ts similarity index 100% rename from frontend/src/components/modules/LadderDetails/index.ts rename to frontend/src/components/pages/LadderDetails/modules/LadderDetails/index.ts diff --git a/frontend/src/components/modules/LadderTabs/LadderTabs.interface.ts b/frontend/src/components/pages/LadderDetails/modules/LadderTabs/LadderTabs.interface.ts similarity index 100% rename from frontend/src/components/modules/LadderTabs/LadderTabs.interface.ts rename to frontend/src/components/pages/LadderDetails/modules/LadderTabs/LadderTabs.interface.ts diff --git a/frontend/src/components/modules/LadderTabs/LadderTabs.tsx b/frontend/src/components/pages/LadderDetails/modules/LadderTabs/LadderTabs.tsx similarity index 100% rename from frontend/src/components/modules/LadderTabs/LadderTabs.tsx rename to frontend/src/components/pages/LadderDetails/modules/LadderTabs/LadderTabs.tsx diff --git a/frontend/src/components/modules/LadderTabs/index.ts b/frontend/src/components/pages/LadderDetails/modules/LadderTabs/index.ts similarity index 100% rename from frontend/src/components/modules/LadderTabs/index.ts rename to frontend/src/components/pages/LadderDetails/modules/LadderTabs/index.ts diff --git a/frontend/src/components/modules/LadderTabs/utils.ts b/frontend/src/components/pages/LadderDetails/modules/LadderTabs/utils.ts similarity index 100% rename from frontend/src/components/modules/LadderTabs/utils.ts rename to frontend/src/components/pages/LadderDetails/modules/LadderTabs/utils.ts diff --git a/frontend/src/components/pages/Library/Library.interface.ts b/frontend/src/components/pages/Library/Library.interface.ts new file mode 100644 index 00000000..f714a49a --- /dev/null +++ b/frontend/src/components/pages/Library/Library.interface.ts @@ -0,0 +1,5 @@ +import { LadderCardInterface } from './modules/LadderCard'; + +export interface LibraryProps { + data: LadderCardInterface[]; +} diff --git a/frontend/src/components/pages/Library/Library.tsx b/frontend/src/components/pages/Library/Library.tsx new file mode 100644 index 00000000..f52b8dd5 --- /dev/null +++ b/frontend/src/components/pages/Library/Library.tsx @@ -0,0 +1,20 @@ +import { Typography } from '@app/components/common/Typography'; +import { LibraryProps } from './Library.interface'; +import { PageTitle } from '@app/components/common/PageTitle'; +import { LadderCard, LadderCardInterface } from '@app/components/pages/Library/modules/LadderCard'; + +export const Library: React.FC = ({ data }) => { + return ( +
+ + + Select a career path to view the details. + +
+ {data.map((ladder: LadderCardInterface) => ( + + ))} +
+
+ ); +}; diff --git a/frontend/src/components/pages/Library/index.ts b/frontend/src/components/pages/Library/index.ts new file mode 100644 index 00000000..c9111180 --- /dev/null +++ b/frontend/src/components/pages/Library/index.ts @@ -0,0 +1 @@ +export { Library } from './Library'; diff --git a/frontend/src/components/common/LadderCard/LadderCard.interface.ts b/frontend/src/components/pages/Library/modules/LadderCard/LadderCard.interface.ts similarity index 100% rename from frontend/src/components/common/LadderCard/LadderCard.interface.ts rename to frontend/src/components/pages/Library/modules/LadderCard/LadderCard.interface.ts diff --git a/frontend/src/components/common/LadderCard/LadderCard.tsx b/frontend/src/components/pages/Library/modules/LadderCard/LadderCard.tsx similarity index 100% rename from frontend/src/components/common/LadderCard/LadderCard.tsx rename to frontend/src/components/pages/Library/modules/LadderCard/LadderCard.tsx diff --git a/frontend/src/components/common/LadderCard/index.ts b/frontend/src/components/pages/Library/modules/LadderCard/index.ts similarity index 100% rename from frontend/src/components/common/LadderCard/index.ts rename to frontend/src/components/pages/Library/modules/LadderCard/index.ts diff --git a/frontend/src/components/views/PersonalDetails/PersonalDetails.hooks.ts b/frontend/src/components/pages/PersonalDetails/PersonalDetails.hooks.ts similarity index 100% rename from frontend/src/components/views/PersonalDetails/PersonalDetails.hooks.ts rename to frontend/src/components/pages/PersonalDetails/PersonalDetails.hooks.ts diff --git a/frontend/src/components/views/PersonalDetails/PersonalDetails.interface.ts b/frontend/src/components/pages/PersonalDetails/PersonalDetails.interface.ts similarity index 100% rename from frontend/src/components/views/PersonalDetails/PersonalDetails.interface.ts rename to frontend/src/components/pages/PersonalDetails/PersonalDetails.interface.ts diff --git a/frontend/src/components/views/PersonalDetails/PersonalDetails.tsx b/frontend/src/components/pages/PersonalDetails/PersonalDetails.tsx similarity index 100% rename from frontend/src/components/views/PersonalDetails/PersonalDetails.tsx rename to frontend/src/components/pages/PersonalDetails/PersonalDetails.tsx diff --git a/frontend/src/components/views/PersonalDetails/index.ts b/frontend/src/components/pages/PersonalDetails/index.ts similarity index 100% rename from frontend/src/components/views/PersonalDetails/index.ts rename to frontend/src/components/pages/PersonalDetails/index.ts diff --git a/frontend/src/components/pages/ProfileSetting/ProfileSetting.interface.ts b/frontend/src/components/pages/ProfileSetting/ProfileSetting.interface.ts new file mode 100644 index 00000000..33bf47e7 --- /dev/null +++ b/frontend/src/components/pages/ProfileSetting/ProfileSetting.interface.ts @@ -0,0 +1,5 @@ +import { User } from '@app/types/people'; + +export interface ProfileSettingsProps { + data: User; +} diff --git a/frontend/src/components/pages/ProfileSetting/ProfileSettings.tsx b/frontend/src/components/pages/ProfileSetting/ProfileSettings.tsx new file mode 100644 index 00000000..1e87ce10 --- /dev/null +++ b/frontend/src/components/pages/ProfileSetting/ProfileSettings.tsx @@ -0,0 +1,26 @@ +import { ProfileSettingsProps } from './ProfileSetting.interface'; +import { Breadcrumbs } from '@app/components/modules/Breadcrumbs'; +import { routes } from '@app/constants'; +import { Notifications } from './modules/Notifications'; +import { Ladders } from './modules/Ladders'; +import { PersonalDetails } from './modules/PersonalDetails'; + +export const ProfileSettings: React.FC = ({ data }) => { + const { ladders } = data; + + return ( +
+ +
+ + + +
+
+ ); +}; diff --git a/frontend/src/components/modules/ProfileSetting/index.ts b/frontend/src/components/pages/ProfileSetting/index.ts similarity index 100% rename from frontend/src/components/modules/ProfileSetting/index.ts rename to frontend/src/components/pages/ProfileSetting/index.ts diff --git a/frontend/src/components/modules/ProfileSetting/modules/CropImageModal/CropImageModal.hooks.ts b/frontend/src/components/pages/ProfileSetting/modules/CropImageModal/CropImageModal.hooks.ts similarity index 100% rename from frontend/src/components/modules/ProfileSetting/modules/CropImageModal/CropImageModal.hooks.ts rename to frontend/src/components/pages/ProfileSetting/modules/CropImageModal/CropImageModal.hooks.ts diff --git a/frontend/src/components/modules/ProfileSetting/modules/CropImageModal/CropImageModal.interface.ts b/frontend/src/components/pages/ProfileSetting/modules/CropImageModal/CropImageModal.interface.ts similarity index 100% rename from frontend/src/components/modules/ProfileSetting/modules/CropImageModal/CropImageModal.interface.ts rename to frontend/src/components/pages/ProfileSetting/modules/CropImageModal/CropImageModal.interface.ts diff --git a/frontend/src/components/modules/ProfileSetting/modules/CropImageModal/CropImageModal.tsx b/frontend/src/components/pages/ProfileSetting/modules/CropImageModal/CropImageModal.tsx similarity index 100% rename from frontend/src/components/modules/ProfileSetting/modules/CropImageModal/CropImageModal.tsx rename to frontend/src/components/pages/ProfileSetting/modules/CropImageModal/CropImageModal.tsx diff --git a/frontend/src/components/modules/ProfileSetting/modules/CropImageModal/constants.ts b/frontend/src/components/pages/ProfileSetting/modules/CropImageModal/constants.ts similarity index 100% rename from frontend/src/components/modules/ProfileSetting/modules/CropImageModal/constants.ts rename to frontend/src/components/pages/ProfileSetting/modules/CropImageModal/constants.ts diff --git a/frontend/src/components/modules/ProfileSetting/modules/CropImageModal/index.ts b/frontend/src/components/pages/ProfileSetting/modules/CropImageModal/index.ts similarity index 100% rename from frontend/src/components/modules/ProfileSetting/modules/CropImageModal/index.ts rename to frontend/src/components/pages/ProfileSetting/modules/CropImageModal/index.ts diff --git a/frontend/src/components/modules/ProfileSetting/modules/DeleteImageModal/DeleteImageModal.interface.ts b/frontend/src/components/pages/ProfileSetting/modules/DeleteImageModal/DeleteImageModal.interface.ts similarity index 100% rename from frontend/src/components/modules/ProfileSetting/modules/DeleteImageModal/DeleteImageModal.interface.ts rename to frontend/src/components/pages/ProfileSetting/modules/DeleteImageModal/DeleteImageModal.interface.ts diff --git a/frontend/src/components/modules/ProfileSetting/modules/DeleteImageModal/DeleteImageModal.tsx b/frontend/src/components/pages/ProfileSetting/modules/DeleteImageModal/DeleteImageModal.tsx similarity index 100% rename from frontend/src/components/modules/ProfileSetting/modules/DeleteImageModal/DeleteImageModal.tsx rename to frontend/src/components/pages/ProfileSetting/modules/DeleteImageModal/DeleteImageModal.tsx diff --git a/frontend/src/components/modules/ProfileSetting/modules/DeleteImageModal/index.ts b/frontend/src/components/pages/ProfileSetting/modules/DeleteImageModal/index.ts similarity index 100% rename from frontend/src/components/modules/ProfileSetting/modules/DeleteImageModal/index.ts rename to frontend/src/components/pages/ProfileSetting/modules/DeleteImageModal/index.ts diff --git a/frontend/src/components/pages/ProfileSetting/modules/Ladders/Ladders.interface.ts b/frontend/src/components/pages/ProfileSetting/modules/Ladders/Ladders.interface.ts new file mode 100644 index 00000000..c80380f0 --- /dev/null +++ b/frontend/src/components/pages/ProfileSetting/modules/Ladders/Ladders.interface.ts @@ -0,0 +1,7 @@ +export interface LaddersProps { + ladders: { + ladderName: string; + technology: string; + band: string | number; + }[]; +} diff --git a/frontend/src/components/pages/ProfileSetting/modules/Ladders/Ladders.tsx b/frontend/src/components/pages/ProfileSetting/modules/Ladders/Ladders.tsx new file mode 100644 index 00000000..dff8e514 --- /dev/null +++ b/frontend/src/components/pages/ProfileSetting/modules/Ladders/Ladders.tsx @@ -0,0 +1,17 @@ +import { Card } from '@app/components/common/Card'; +import { LadderDataItem } from '../../utils'; +import { LaddersProps } from './Ladders.interface'; + +export const Ladders: React.FC = ({ ladders }) => { + return ( + + {ladders.map(({ ladderName, technology, band }) => ( +
+ + + +
+ ))} +
+ ); +}; diff --git a/frontend/src/components/pages/ProfileSetting/modules/Ladders/index.ts b/frontend/src/components/pages/ProfileSetting/modules/Ladders/index.ts new file mode 100644 index 00000000..f3de0afe --- /dev/null +++ b/frontend/src/components/pages/ProfileSetting/modules/Ladders/index.ts @@ -0,0 +1 @@ +export { Ladders } from './Ladders'; diff --git a/frontend/src/components/pages/ProfileSetting/modules/Notifications/Notifications.tsx b/frontend/src/components/pages/ProfileSetting/modules/Notifications/Notifications.tsx new file mode 100644 index 00000000..bd1a251c --- /dev/null +++ b/frontend/src/components/pages/ProfileSetting/modules/Notifications/Notifications.tsx @@ -0,0 +1,21 @@ +import { Typography } from '@app/components/common/Typography'; +import { NotificationCheckbox } from '../../utils'; +import { SlackIcon } from '@app/static/icons/SlackIcon'; +import { EnvelopeIcon } from '@app/static/icons/EnvelopeIcon'; +import { Card } from '@app/components/common/Card'; + +export const Notifications: React.FC = () => { + return ( + +
+
+ Send me notifications via +
+
+ } /> + } /> +
+
+
+ ); +}; diff --git a/frontend/src/components/pages/ProfileSetting/modules/Notifications/index.ts b/frontend/src/components/pages/ProfileSetting/modules/Notifications/index.ts new file mode 100644 index 00000000..ffcc74c1 --- /dev/null +++ b/frontend/src/components/pages/ProfileSetting/modules/Notifications/index.ts @@ -0,0 +1 @@ +export { Notifications } from './Notifications'; diff --git a/frontend/src/components/modules/ProfileSetting/ProfileSetting.hooks.ts b/frontend/src/components/pages/ProfileSetting/modules/PersonalDetails/PersonalDetails.hooks.ts similarity index 90% rename from frontend/src/components/modules/ProfileSetting/ProfileSetting.hooks.ts rename to frontend/src/components/pages/ProfileSetting/modules/PersonalDetails/PersonalDetails.hooks.ts index 85f9f50e..7ef67341 100644 --- a/frontend/src/components/modules/ProfileSetting/ProfileSetting.hooks.ts +++ b/frontend/src/components/pages/ProfileSetting/modules/PersonalDetails/PersonalDetails.hooks.ts @@ -1,9 +1,9 @@ -import { ProfileSettingsHook } from '@app/components/modules/ProfileSetting/ProfileSetting.interface'; import { ChangeEvent, useState } from 'react'; import { getCroppedImg, readFile } from '@app/utils'; import { Area } from 'react-easy-crop'; +import { PersonalDetailsHook } from './PersonalDetails.interface'; -export const useProfileSettings = (): ProfileSettingsHook => { +export const usePersonalDetails = (): PersonalDetailsHook => { const [imageSrc, setImageSrc] = useState(null); const [cropModalOpen, setCropModalOpen] = useState(false); const [deleteModalOpen, setDeleteModalOpen] = useState(false); diff --git a/frontend/src/components/modules/ProfileSetting/ProfileSetting.interface.ts b/frontend/src/components/pages/ProfileSetting/modules/PersonalDetails/PersonalDetails.interface.ts similarity index 71% rename from frontend/src/components/modules/ProfileSetting/ProfileSetting.interface.ts rename to frontend/src/components/pages/ProfileSetting/modules/PersonalDetails/PersonalDetails.interface.ts index 89246685..54d05d61 100644 --- a/frontend/src/components/modules/ProfileSetting/ProfileSetting.interface.ts +++ b/frontend/src/components/pages/ProfileSetting/modules/PersonalDetails/PersonalDetails.interface.ts @@ -1,12 +1,16 @@ import { ChangeEvent } from 'react'; import { Area } from 'react-easy-crop'; -import { User } from '@app/types/people'; -export interface ProfileSettingsProps { - data: User; +export interface PersonalDetailsProps { + data: { + photo?: string; + firstName: string; + lastName: string; + email: string; + }; } -export interface ProfileSettingsHook { +export interface PersonalDetailsHook { imageSrc: string | null; handleFileChange: (event: ChangeEvent) => Promise; cropModalOpen: boolean; diff --git a/frontend/src/components/pages/ProfileSetting/modules/PersonalDetails/PersonalDetails.tsx b/frontend/src/components/pages/ProfileSetting/modules/PersonalDetails/PersonalDetails.tsx new file mode 100644 index 00000000..1b7f7026 --- /dev/null +++ b/frontend/src/components/pages/ProfileSetting/modules/PersonalDetails/PersonalDetails.tsx @@ -0,0 +1,63 @@ +'use client'; +import { PersonalDetailsProps } from './PersonalDetails.interface'; +import { Typography } from '@app/components/common/Typography'; +import { Avatar } from '@app/components/common/Avatar'; +import { EditIcon } from '@app/static/icons/EditIcon'; +import { DeleteIcon } from '@app/static/icons/DeleteIcon'; +import { PersonalDetailsDataItem } from '@app/components/pages/ProfileSetting/utils'; +import { Card } from '@app/components/common/Card'; +import { usePersonalDetails } from './PersonalDetails.hooks'; +import { CropImageModal } from '../CropImageModal'; +import { DeleteImageModal } from '../DeleteImageModal'; + +export const PersonalDetails: React.FC = ({ data }) => { + const { firstName, lastName, email, photo } = data; + const { + imageSrc, + handleOpenDeleteModal, + handleFileChange, + cropModalOpen, + handleCloseCropModal, + deleteModalOpen, + handleCloseDeleteModal, + handleDeleteImage, + handleSaveCroppedImage, + } = usePersonalDetails(); + + return ( + <> + +
+
+ + Profile photo + + +
+
+ + +
+
+ + +
+ + + + ); +}; diff --git a/frontend/src/components/pages/ProfileSetting/modules/PersonalDetails/index.ts b/frontend/src/components/pages/ProfileSetting/modules/PersonalDetails/index.ts new file mode 100644 index 00000000..865eb9da --- /dev/null +++ b/frontend/src/components/pages/ProfileSetting/modules/PersonalDetails/index.ts @@ -0,0 +1 @@ +export { PersonalDetails } from './PersonalDetails'; diff --git a/frontend/src/components/pages/ProfileSetting/utils.tsx b/frontend/src/components/pages/ProfileSetting/utils.tsx new file mode 100644 index 00000000..6a322682 --- /dev/null +++ b/frontend/src/components/pages/ProfileSetting/utils.tsx @@ -0,0 +1,37 @@ +import { ReactNode } from 'react'; +import { Typography } from '@app/components/common/Typography'; + +export const NotificationCheckbox: React.FC<{ icon: ReactNode }> = ({ icon }) => ( +
+
{icon}
+
+ +
+
+); + +export const PersonalDetailsDataItem: React.FC<{ title: string; value: string | number }> = ({ title, value }) => ( +
+
+ {title} +
+
+ + {value} + +
+
+); + +export const LadderDataItem: React.FC<{ title: string; value: string | number }> = ({ title, value }) => ( +
+
+ {title} +
+
+ + {value} + +
+
+); From baff627e3f6573147768e47cddbed89930f8ba43 Mon Sep 17 00:00:00 2001 From: Wiktoria Salamon <39302106+wiktoriasalamon@users.noreply.github.com> Date: Wed, 10 Jul 2024 14:02:29 +0200 Subject: [PATCH 2/2] [FE][CPF-75] My space page (#90) * feat: add Typography component * feat: add element type to Typography props * linter * refactor: use typography for all copies in the app * linter * refactor * linter * feat: create MySpaceContext * feat: add My Space header * feat: add Tab navigation * linter * linter * fix: render MySpace page dynamically * refactor: move logic to hooks file --- .../src/app/(app)/(root)/my-space/page.tsx | 29 +++++++++--- .../common/AccordionCard/AccordionCard.tsx | 2 +- .../AccordionList/AccordionListItem.tsx | 27 ++++++----- .../components/common/Tabs/Tabs.interface.ts | 9 ++++ frontend/src/components/common/Tabs/Tabs.tsx | 47 +++++++++++++++++++ frontend/src/components/common/Tabs/index.ts | 1 + .../src/components/common/Tooltip/Tooltip.tsx | 2 +- .../components/pages/MySpace/MySpace.hooks.ts | 29 ++++++++++++ .../pages/MySpace/MySpace.interface.ts | 23 +++++++++ .../src/components/pages/MySpace/MySpace.tsx | 22 +++++++++ .../src/components/pages/MySpace/contants.ts | 31 ++++++++++++ .../src/components/pages/MySpace/index.ts | 1 + .../modules/Header/Header.interface.ts | 16 +++++++ .../pages/MySpace/modules/Header/Header.tsx | 43 +++++++++++++++++ .../pages/MySpace/modules/Header/index.ts | 1 + .../modules/LevelCard/LevelCard.interface.ts | 9 ++++ .../MySpace/modules/LevelCard/LevelCard.tsx | 27 +++++++++++ .../pages/MySpace/modules/LevelCard/index.ts | 1 + frontend/src/static/icons/CheckIcon.tsx | 11 +++++ frontend/src/static/icons/TargetIcon.tsx | 8 ++++ frontend/tailwind.config.ts | 1 + 21 files changed, 318 insertions(+), 22 deletions(-) create mode 100644 frontend/src/components/common/Tabs/Tabs.interface.ts create mode 100644 frontend/src/components/common/Tabs/Tabs.tsx create mode 100644 frontend/src/components/common/Tabs/index.ts create mode 100644 frontend/src/components/pages/MySpace/MySpace.hooks.ts create mode 100644 frontend/src/components/pages/MySpace/MySpace.interface.ts create mode 100644 frontend/src/components/pages/MySpace/MySpace.tsx create mode 100644 frontend/src/components/pages/MySpace/contants.ts create mode 100644 frontend/src/components/pages/MySpace/index.ts create mode 100644 frontend/src/components/pages/MySpace/modules/Header/Header.interface.ts create mode 100644 frontend/src/components/pages/MySpace/modules/Header/Header.tsx create mode 100644 frontend/src/components/pages/MySpace/modules/Header/index.ts create mode 100644 frontend/src/components/pages/MySpace/modules/LevelCard/LevelCard.interface.ts create mode 100644 frontend/src/components/pages/MySpace/modules/LevelCard/LevelCard.tsx create mode 100644 frontend/src/components/pages/MySpace/modules/LevelCard/index.ts create mode 100644 frontend/src/static/icons/CheckIcon.tsx create mode 100644 frontend/src/static/icons/TargetIcon.tsx diff --git a/frontend/src/app/(app)/(root)/my-space/page.tsx b/frontend/src/app/(app)/(root)/my-space/page.tsx index 03d759d2..118b4230 100644 --- a/frontend/src/app/(app)/(root)/my-space/page.tsx +++ b/frontend/src/app/(app)/(root)/my-space/page.tsx @@ -1,9 +1,24 @@ -import { PageTitle } from '@app/components/common/PageTitle'; +import { MySpace } from '@app/components/pages/MySpace'; -export default function MySpace() { - return ( -
- -
- ); +// TODO: get data from api +const data = { + user: { + firstName: 'Jane', + lastName: 'Edge', + position: 'Front End Developer, Junior', + }, + currentLevel: { + band: 2, + score: 10, + }, + nextLevel: { + band: 3, + threshold: 11, + }, +}; + +export default function MySpacePage() { + return ; } + +export const dynamic = 'force-dynamic'; diff --git a/frontend/src/components/common/AccordionCard/AccordionCard.tsx b/frontend/src/components/common/AccordionCard/AccordionCard.tsx index b333a973..2dde2705 100644 --- a/frontend/src/components/common/AccordionCard/AccordionCard.tsx +++ b/frontend/src/components/common/AccordionCard/AccordionCard.tsx @@ -26,7 +26,7 @@ export const AccordionCard = ({ className={generateClassNames( 'group flex w-full items-center justify-between rounded-2xl border border-navy-200 p-6', { - 'hover:bg-transparent rounded-b-none border-b-0 pb-0': isOpen, + 'rounded-b-none border-b-0 pb-0 hover:bg-transparent': isOpen, 'cursor-auto': !children, }, )} diff --git a/frontend/src/components/common/AccordionList/AccordionListItem.tsx b/frontend/src/components/common/AccordionList/AccordionListItem.tsx index 7a2ce444..c564ac54 100644 --- a/frontend/src/components/common/AccordionList/AccordionListItem.tsx +++ b/frontend/src/components/common/AccordionList/AccordionListItem.tsx @@ -19,24 +19,25 @@ export const AccordionListItem = ({ return (
- - - + + + {children ? (
{children} diff --git a/frontend/src/components/common/Tabs/Tabs.interface.ts b/frontend/src/components/common/Tabs/Tabs.interface.ts new file mode 100644 index 00000000..4894a7a9 --- /dev/null +++ b/frontend/src/components/common/Tabs/Tabs.interface.ts @@ -0,0 +1,9 @@ +export interface TabsProps { + tabs: { + key: string; + label: string; + href: string; + }[]; + currentTab: string; + onTabChange: (tab: string) => void; +} diff --git a/frontend/src/components/common/Tabs/Tabs.tsx b/frontend/src/components/common/Tabs/Tabs.tsx new file mode 100644 index 00000000..f22a7f4d --- /dev/null +++ b/frontend/src/components/common/Tabs/Tabs.tsx @@ -0,0 +1,47 @@ +import { FC } from 'react'; +import { TabsProps } from './Tabs.interface'; +import { generateClassNames } from '@app/utils'; + +export const Tabs: FC = ({ tabs, currentTab, onTabChange }) => { + return ( +
+
+ + +
+
+
+ +
+
+
+ ); +}; diff --git a/frontend/src/components/common/Tabs/index.ts b/frontend/src/components/common/Tabs/index.ts new file mode 100644 index 00000000..941e6bab --- /dev/null +++ b/frontend/src/components/common/Tabs/index.ts @@ -0,0 +1 @@ +export { Tabs } from './Tabs'; diff --git a/frontend/src/components/common/Tooltip/Tooltip.tsx b/frontend/src/components/common/Tooltip/Tooltip.tsx index e3d244a6..9c8ed881 100644 --- a/frontend/src/components/common/Tooltip/Tooltip.tsx +++ b/frontend/src/components/common/Tooltip/Tooltip.tsx @@ -7,7 +7,7 @@ export const TooltipPopover: FC> = ({ tooltipTex const [open, setOpen] = useState(false); return ( - + setOpen(true)} onMouseLeave={() => setOpen(false)} diff --git a/frontend/src/components/pages/MySpace/MySpace.hooks.ts b/frontend/src/components/pages/MySpace/MySpace.hooks.ts new file mode 100644 index 00000000..dad772a1 --- /dev/null +++ b/frontend/src/components/pages/MySpace/MySpace.hooks.ts @@ -0,0 +1,29 @@ +import { useCallback, useEffect, useState } from 'react'; +import { MySpaceHooks } from './MySpace.interface'; +import { useSearchParams, useRouter, usePathname } from 'next/navigation'; +import { DEFAULT_TAB } from './contants'; + +export const useMySpace = (): MySpaceHooks => { + const router = useRouter(); + const pathname = usePathname(); + const searchParams = useSearchParams(); + const tab = searchParams.get('tab'); + const [currentTab, setCurrentTab] = useState(tab ?? DEFAULT_TAB); + + const handleReplace = useCallback(() => { + if (!currentTab) { + router.replace(`${pathname}?tab=${DEFAULT_TAB}`); + } else { + router.replace(`${pathname}?tab=${currentTab}`); + } + }, [currentTab, pathname, router]); + + useEffect(() => { + handleReplace(); + }, [handleReplace]); + + return { + currentTab, + setCurrentTab, + }; +}; diff --git a/frontend/src/components/pages/MySpace/MySpace.interface.ts b/frontend/src/components/pages/MySpace/MySpace.interface.ts new file mode 100644 index 00000000..db7a9aeb --- /dev/null +++ b/frontend/src/components/pages/MySpace/MySpace.interface.ts @@ -0,0 +1,23 @@ +export interface MySpaceProps { + data: { + user: { + firstName: string; + lastName: string; + photo?: string; + position: string; + }; + currentLevel: { + band: number; + score: number; + }; + nextLevel: { + band: number; + threshold: number; + }; + }; +} + +export interface MySpaceHooks { + currentTab: string; + setCurrentTab: (tab: string) => void; +} diff --git a/frontend/src/components/pages/MySpace/MySpace.tsx b/frontend/src/components/pages/MySpace/MySpace.tsx new file mode 100644 index 00000000..4afe2def --- /dev/null +++ b/frontend/src/components/pages/MySpace/MySpace.tsx @@ -0,0 +1,22 @@ +'use client'; +import { Typography } from '@app/components/common/Typography'; +import { MySpaceProps } from './MySpace.interface'; +import { Header } from '@app/components/pages/MySpace/modules/Header'; +import { Tabs } from '@app/components/common/Tabs'; +import { useMySpace } from './MySpace.hooks'; +import { mySpaceTabs } from './contants'; + +export const MySpace: React.FC = ({ data }) => { + const { user, currentLevel, nextLevel } = data; + const { currentTab, setCurrentTab } = useMySpace(); + + return ( +
+ + My Space + +
+ +
+ ); +}; diff --git a/frontend/src/components/pages/MySpace/contants.ts b/frontend/src/components/pages/MySpace/contants.ts new file mode 100644 index 00000000..5792edd2 --- /dev/null +++ b/frontend/src/components/pages/MySpace/contants.ts @@ -0,0 +1,31 @@ +import { routes } from '@app/constants'; + +export const DEFAULT_TAB = 'ladder'; + +export const mySpaceTabs = [ + { + key: 'ladder', + label: 'Ladder', + href: `${routes.mySpace.index}?tab=ladder`, + }, + { + key: 'score-card', + label: 'Score Card', + href: `${routes.mySpace.index}?tab=score-card`, + }, + { + key: 'goals', + label: 'Goals', + href: `${routes.mySpace.index}?tab=goals`, + }, + { + key: 'projects', + label: 'Projects', + href: `${routes.mySpace.index}?tab=projects`, + }, + { + key: 'activity', + label: 'Activity', + href: `${routes.mySpace.index}?tab=activity`, + }, +]; diff --git a/frontend/src/components/pages/MySpace/index.ts b/frontend/src/components/pages/MySpace/index.ts new file mode 100644 index 00000000..ed1483fd --- /dev/null +++ b/frontend/src/components/pages/MySpace/index.ts @@ -0,0 +1 @@ +export { MySpace } from './MySpace'; diff --git a/frontend/src/components/pages/MySpace/modules/Header/Header.interface.ts b/frontend/src/components/pages/MySpace/modules/Header/Header.interface.ts new file mode 100644 index 00000000..51af9125 --- /dev/null +++ b/frontend/src/components/pages/MySpace/modules/Header/Header.interface.ts @@ -0,0 +1,16 @@ +export interface HeaderProps { + user: { + firstName: string; + lastName: string; + photo?: string; + position: string; + }; + currentLevel: { + band: number; + score: number; + }; + nextLevel: { + band: number; + threshold: number; + }; +} diff --git a/frontend/src/components/pages/MySpace/modules/Header/Header.tsx b/frontend/src/components/pages/MySpace/modules/Header/Header.tsx new file mode 100644 index 00000000..0c28a53c --- /dev/null +++ b/frontend/src/components/pages/MySpace/modules/Header/Header.tsx @@ -0,0 +1,43 @@ +import { Typography } from '@app/components/common/Typography'; +import { HeaderProps } from './Header.interface'; +import { Avatar } from '@app/components/common/Avatar'; +import { CheckIcon } from '@app/static/icons/CheckIcon'; +import { TargetIcon } from '@app/static/icons/TargetIcon'; +import { LevelCard } from '@app/components/pages/MySpace/modules/LevelCard'; + +export const Header: React.FC = ({ user, currentLevel, nextLevel }) => { + const { firstName, lastName, photo, position } = user; + + return ( +
+
+ +
+ + {firstName} {lastName} + + + {position} + +
+
+
+ } + scoreLabel="Score" + /> +
+ } + scoreLabel="Threshold" + /> +
+
+ ); +}; diff --git a/frontend/src/components/pages/MySpace/modules/Header/index.ts b/frontend/src/components/pages/MySpace/modules/Header/index.ts new file mode 100644 index 00000000..29429dc9 --- /dev/null +++ b/frontend/src/components/pages/MySpace/modules/Header/index.ts @@ -0,0 +1 @@ +export { Header } from './Header'; diff --git a/frontend/src/components/pages/MySpace/modules/LevelCard/LevelCard.interface.ts b/frontend/src/components/pages/MySpace/modules/LevelCard/LevelCard.interface.ts new file mode 100644 index 00000000..c6d7ee24 --- /dev/null +++ b/frontend/src/components/pages/MySpace/modules/LevelCard/LevelCard.interface.ts @@ -0,0 +1,9 @@ +import { ReactNode } from 'react'; + +export interface LevelCardProps { + title: string; + band: number; + score: number; + icon: ReactNode; + scoreLabel: string; +} diff --git a/frontend/src/components/pages/MySpace/modules/LevelCard/LevelCard.tsx b/frontend/src/components/pages/MySpace/modules/LevelCard/LevelCard.tsx new file mode 100644 index 00000000..2cf82c10 --- /dev/null +++ b/frontend/src/components/pages/MySpace/modules/LevelCard/LevelCard.tsx @@ -0,0 +1,27 @@ +import { Typography } from '@app/components/common/Typography'; +import { LevelCardProps } from './LevelCard.interface'; + +export const LevelCard: React.FC = ({ title, band, score, icon, scoreLabel }) => { + return ( +
+
+
{icon}
+ {title} +
+
+
+ + Band + + {band} +
+
+ + {scoreLabel} + + {score} +
+
+
+ ); +}; diff --git a/frontend/src/components/pages/MySpace/modules/LevelCard/index.ts b/frontend/src/components/pages/MySpace/modules/LevelCard/index.ts new file mode 100644 index 00000000..5cec3db0 --- /dev/null +++ b/frontend/src/components/pages/MySpace/modules/LevelCard/index.ts @@ -0,0 +1 @@ +export { LevelCard } from './LevelCard'; diff --git a/frontend/src/static/icons/CheckIcon.tsx b/frontend/src/static/icons/CheckIcon.tsx new file mode 100644 index 00000000..63f6eba5 --- /dev/null +++ b/frontend/src/static/icons/CheckIcon.tsx @@ -0,0 +1,11 @@ +export const CheckIcon: React.FC> = (props) => ( + + + +); diff --git a/frontend/src/static/icons/TargetIcon.tsx b/frontend/src/static/icons/TargetIcon.tsx new file mode 100644 index 00000000..fb2296fc --- /dev/null +++ b/frontend/src/static/icons/TargetIcon.tsx @@ -0,0 +1,8 @@ +export const TargetIcon: React.FC> = (props) => ( + + + +); diff --git a/frontend/tailwind.config.ts b/frontend/tailwind.config.ts index 8b633604..73765147 100644 --- a/frontend/tailwind.config.ts +++ b/frontend/tailwind.config.ts @@ -8,6 +8,7 @@ const config: Config = { ], theme: { colors: { + transparent: 'transparent', white: '#FFFFFF', navy: { 50: '#F7F7F7',