From fc984b4d2fb549774145eb7fecdff4c987797f39 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Sun, 15 Sep 2024 15:37:05 +0300 Subject: [PATCH 01/74] - Enhanced component documentation for better clarity and developer guidance. - Adopted Function Component pattern to streamline component structure. --- .../MembersPage/ui/MembersPage.tsx | 52 +++++++++++-------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/frontend-next-migration/src/preparedPages/MembersPage/ui/MembersPage.tsx b/frontend-next-migration/src/preparedPages/MembersPage/ui/MembersPage.tsx index 11b2aff2b..e5767a514 100644 --- a/frontend-next-migration/src/preparedPages/MembersPage/ui/MembersPage.tsx +++ b/frontend-next-migration/src/preparedPages/MembersPage/ui/MembersPage.tsx @@ -1,26 +1,34 @@ -'use client' -import {Navbar} from "@/widgets/Navbar"; -import cls from './MembersPage.module.scss' -import {SectionMembers} from "@/widgets/SectionMembers"; -import {classNames} from "@/shared/lib/classNames/classNames"; -// import backgroundImg from '@/shared/assets/images/clanBg/space.webp' -import backgroundImg from "@/shared/assets/images/backgrounds/background.webp"; -import {withBackgroundImage} from "@/shared/lib/hocs/withBackgroundImage"; -import {ScrollTop} from "@/features/ScrollTop"; +/** + * The above code defines a React functional component for a Members Page with a background image + * applied using a higher-order component. + * @returns The `MembersPage` component is being returned. It is a functional component that renders a + * `SectionMembers` component within a `div` element with specific class names. Additionally, the + * `MembersPage` component is being exported with a background image using the `withBackgroundImage` + * higher-order component, which provides properties such as alt text, image path, lazy loading, and a + * specific class name for + */ +'use client'; // Ensures this is a client-side component -const MembersPage = () => { - return ( -
- -
- ); +import { FC } from 'react'; +import { SectionMembers } from '@/widgets/SectionMembers'; +import { classNames } from '@/shared/lib/classNames/classNames'; +import cls from './MembersPage.module.scss'; +import backgroundImg from '@/shared/assets/images/backgrounds/background.webp'; +import { withBackgroundImage } from '@/shared/lib/hocs/withBackgroundImage'; + +const MembersPage: FC = () => { + return ( +
+ +
+ ); }; -export default withBackgroundImage({ - alt: "Members-Page space background", - imagePath: backgroundImg as unknown as string, - shouldBeLazyLoaded: true, - className: cls.wholePageBG +/* The code `export default withBackgroundImage({ ... })(MembersPage);` is applying a higher-order +component (HOC) called `withBackgroundImage` to the `MembersPage` component before exporting it. */ +export default withBackgroundImage({ + alt: 'Members-Page space background', + imagePath: backgroundImg as unknown as string, + shouldBeLazyLoaded: true, + className: cls.wholePageBG, })(MembersPage); - - From c17d5a7e5c7dd6f4b494bb5cf233153180e5ce2d Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Sun, 15 Sep 2024 15:37:36 +0300 Subject: [PATCH 02/74] - Defined the TeamMember interface to structure the data model for team members. - Implemented fetchTeamMembers function to retrieve team member data from the API. --- .../SectionMembers/model/membersApi.ts | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts new file mode 100644 index 000000000..a9893debc --- /dev/null +++ b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts @@ -0,0 +1,35 @@ +const BASE_URL = 'http://localhost:1337/api'; + +export interface TeamMember { + id: number; + Role: string; + Name: string; + Email: string; + Logo?: string; + website?: string; + github?: string; + createdAt: string; + updatedAt: string; + publishedAt: string; + locale: string; +} + +export const fetchTeamMembers = async (): Promise => { + try { + const response = await fetch(`${BASE_URL}/teams`); + if (!response.ok) { + throw new Error(`Error fetching data: ${response.statusText}`); + } + + const data = await response.json(); + + const members = Array.isArray(data.data) ? data.data : [data.data]; + + return members.map((item: any) => ({ + id: item.id, + ...item.attributes, + })) as TeamMember[]; + } catch (error) { + throw new Error('Error fetching team members data'); + } +}; From cf8346684a3e493c19ed498160ae33dec3c04cb6 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Sun, 15 Sep 2024 15:38:31 +0300 Subject: [PATCH 03/74] adjusting changed headers --- .../ui/SectionMembers.module.scss | 53 ++++++++----------- 1 file changed, 21 insertions(+), 32 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss index 4b961f2b6..f7c723b9c 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss @@ -1,4 +1,4 @@ -.MembersSection{ +.MembersSection { font-family: var(--font-family-texts); //min-height: 100% !important; text-align: center; @@ -9,53 +9,46 @@ //height: 100%; } - -.scrollBottomButton{ +.scrollBottomButton { //align-self: start; margin-bottom: 10px; - @include link-scale-effect + @include link-scale-effect; } -.membersListContainer{ +.membersListContainer { border-radius: var(--border-radius-custom); z-index: 2; //background-color: var(--transparent-bg-dark); - background-color: rgba(0, 0, 0, 0.55) - + background-color: rgba(0, 0, 0, 0.55); } -.groupComponent{ - +.groupComponent { display: flex; flex-direction: column; justify-content: center; text-align: center; - - - h2{ - font-size: clamp(40px, 7vw, 50px); - font-family: var(--font-family-main); - line-height: 1.5; - font-weight: bold; - color: #e89dff; - } - ul { list-style-type: none; padding-left: 0; } } -.workmanComponent{ - +.membersListContainer h2 { + font-size: clamp(40px, 7vw, 50px); + font-family: var(--font-family-main); + line-height: 1.5; + font-weight: bold; + color: #e89dff; +} +.workmanComponent { display: flex; justify-content: center; gap: 10px; - h3{ + h3 { font-size: clamp(20px, 5vw, 25px); line-height: var(--font-family-main); } @@ -68,19 +61,15 @@ padding-bottom: 10px; - - ul{ + ul { display: flex; align-items: center; gap: 10px; } - .clickableLogo{ - color: var(--secondary-color); - cursor: pointer; - @include link-scale-effect('icon'); - } - - + .clickableLogo { + color: var(--secondary-color); + cursor: pointer; + @include link-scale-effect('icon'); + } } - From ed2c5ca03f7cffd39804fe5803b2760c08bd7f8f Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Sun, 15 Sep 2024 15:39:26 +0300 Subject: [PATCH 04/74] - Added fetch functionality to retrieve team member data from the backend API. - Implemented grouping logic to organize members by role in the SectionMembers component. - Enhanced UI integration by displaying fetched data dynamically within the application. --- .../SectionMembers/ui/SectionMembers.tsx | 198 +++++++++--------- 1 file changed, 99 insertions(+), 99 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx index 271a82ea8..689978d08 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx @@ -1,117 +1,117 @@ -import cls from "./SectionMembers.module.scss"; -import Image from 'next/image' -import {groupsWithMembersLocally, GroupWithMember, Member} from "@/entities/Member"; -import {FC, memo, useMemo} from "react"; -import {ScrollBottomButton} from "@/features/ScrollBottom"; -import {classNames} from "@/shared/lib/classNames/classNames"; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import {faGithub} from "@fortawesome/free-brands-svg-icons"; -import {openLinkInNewTab} from "@/shared/lib/openLinkInNewTab/openLinkInNewTab"; -import {faGlobe} from "@fortawesome/free-solid-svg-icons"; -import { faLinkedin } from '@fortawesome/free-brands-svg-icons'; -import {Container} from "@/shared/ui/Container"; -import {useClientTranslation} from "@/shared/i18n"; -import {useParams} from "next/navigation"; - - - -interface WorkersSectionProps { - className?: string; +import cls from './SectionMembers.module.scss'; +import { ScrollBottomButton } from '@/features/ScrollBottom'; +import { classNames } from '@/shared/lib/classNames/classNames'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faGlobe, faEnvelope } from '@fortawesome/free-solid-svg-icons'; +import { Container } from '@/shared/ui/Container'; +import { openLinkInNewTab } from '@/shared/lib/openLinkInNewTab/openLinkInNewTab'; // Utility to open links +import { useClientTranslation } from '@/shared/i18n'; +import { useParams } from 'next/navigation'; +import { FC, memo, useEffect, useState } from 'react'; +import { TeamMember, fetchTeamMembers } from '../model/membersApi'; + +interface WorkersSectionProps { + className?: string; } +export const SectionMembers: FC = ({ className = '' }) => { + const [teamMembers, setTeamMembers] = useState([]); + const params = useParams(); + const lng = params.lng as string; + const { t } = useClientTranslation(lng, 'team'); + + useEffect(() => { + const fetchMembers = async () => { + try { + const data = await fetchTeamMembers(); + setTeamMembers(data); + } catch (error) { + console.error('Failed to fetch team members:', error); + } + }; + fetchMembers(); + }, []); + + const groupedMembers = groupByRole(teamMembers); + + return ( +
+ + + {Object.keys(groupedMembers).map((role) => ( +
+

{t(role)}

+ {groupedMembers[role].map((member) => ( + + ))} +
+ ))} +
+
+ ); +}; -export const SectionMembers = ({className = ''}: WorkersSectionProps) => { - - const memoizedGroupsWithWorkers = useMemo(() => groupsWithMembersLocally, []); - - const params = useParams(); - const lng = params.lng as string; - const {t} = useClientTranslation(lng, "team"); - - return ( -
- - - - - - { - memoizedGroupsWithWorkers.map(group=>( - - )) - } - - -
- ); +const groupByRole = (members: TeamMember[]): Record => { + return members.reduce((acc, member) => { + if (!acc[member.Role]) { + acc[member.Role] = []; + } + acc[member.Role].push(member); + return acc; + }, {} as Record); }; -interface GroupWithWorkmanProps{ - groupWithMember: GroupWithMember; +interface GroupWithMemberProps { + member: TeamMember; } -const GroupWithWorkmanComponent: FC = memo(({groupWithMember}) => { - - +const GroupWithMemberComponent: FC = memo( + ({ member }) => { const params = useParams(); const lng = params.lng as string; - const {t} = useClientTranslation(lng, "members"); + const { t } = useClientTranslation(lng, 'members'); return ( -
-

{t(`${groupWithMember.group}`)}

-
    - {groupWithMember.workers.map((member) => ( -
  • - -
  • - ))} -
-
+
+ +
); -}); -GroupWithWorkmanComponent.displayName = "GroupWithWorkmanComponent"; + }, +); +GroupWithMemberComponent.displayName = 'GroupWithMemberComponent'; -interface WorkmanProps { - member: Member; +interface MemberProps { + member: TeamMember; } - -const MemberComponent: FC = memo(({ member }) => { - return ( -
- {member.imgSrc && {member.name} -

{member.name}

-
    - {member.role &&
  • Rooli: {`${member.role}`}
  • } - - {member.site && -
  • - openLinkInNewTab(member?.site)} /> -
  • - } - {member.github && -
  • - openLinkInNewTab(`https://github.com/${member.github}`)} /> -
  • - } - - {member.linkedin && -
  • - openLinkInNewTab(member?.linkedin)} /> -
  • - } - - {member.status &&
  • Status: {`${member.status}`}
  • } - {member.workPeriod &&
  • Työjakso: {`${member.workPeriod}`}
  • } - {member.email &&
  • Email: {`${member.email}`}
  • } - {member.phone &&
  • Puhelinnumero: {`${member.phone}`}
  • } - {member.trello &&
  • Trello: {`${member.trello}`}
  • } - {member.discord &&
  • Discord: {`${member.discord}`}
  • } -
-
- ); +const MemberComponent: FC = memo(({ member }) => { + return ( +
+

{member.Name}

+
    + {member.website && ( +
  • + openLinkInNewTab(member.website)} + /> + +
  • + )} +
  • + {member.Email} +
  • +
+
+ ); }); -MemberComponent.displayName = "MemberComponent"; +MemberComponent.displayName = 'MemberComponent'; From 4301449e9c545cac91bf7388839d116dd0ef510f Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Wed, 18 Sep 2024 15:27:10 +0300 Subject: [PATCH 05/74] add more content for members to show --- .../SectionMembers/model/membersApi.ts | 5 +- .../SectionMembers/ui/SectionMembers.tsx | 64 ++++++++++++++----- 2 files changed, 52 insertions(+), 17 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts index a9893debc..c83ef4fa1 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts +++ b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts @@ -6,8 +6,9 @@ export interface TeamMember { Name: string; Email: string; Logo?: string; - website?: string; - github?: string; + Website?: string; + Github?: string; + Linkedin?: string; createdAt: string; updatedAt: string; publishedAt: string; diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx index 689978d08..4d4a17be3 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx @@ -1,4 +1,5 @@ import cls from './SectionMembers.module.scss'; +import Image from 'next/image'; import { ScrollBottomButton } from '@/features/ScrollBottom'; import { classNames } from '@/shared/lib/classNames/classNames'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; @@ -9,6 +10,7 @@ import { useClientTranslation } from '@/shared/i18n'; import { useParams } from 'next/navigation'; import { FC, memo, useEffect, useState } from 'react'; import { TeamMember, fetchTeamMembers } from '../model/membersApi'; +import { faGithub, faLinkedin } from '@fortawesome/free-brands-svg-icons'; interface WorkersSectionProps { className?: string; @@ -93,22 +95,54 @@ const MemberComponent: FC = memo(({ member }) => {

{member.Name}

    - {member.website && ( -
  • - openLinkInNewTab(member.website)} - /> - -
  • + {member.Website && ( + <> +
  • + openLinkInNewTab(member.Website)} + /> + +
  • +
  • + openLinkInNewTab(member.Github)} + /> + +
  • +
  • + openLinkInNewTab(member.Linkedin)} + /> + +
  • +
  • + openLinkInNewTab(`mailto:${member.Email}`)} + /> + +
  • + )} -
  • - {member.Email} -
); From 5e968b127ec8ece703cdf1aa2721b697ba71f38b Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Wed, 18 Sep 2024 15:29:15 +0300 Subject: [PATCH 06/74] Conditionally render clickable sections based on available backend data --- .../SectionMembers/ui/SectionMembers.tsx | 96 ++++++++++--------- 1 file changed, 50 insertions(+), 46 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx index 4d4a17be3..bdd6fe3ca 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx @@ -96,52 +96,56 @@ const MemberComponent: FC = memo(({ member }) => {

{member.Name}

    {member.Website && ( - <> -
  • - openLinkInNewTab(member.Website)} - /> - -
  • -
  • - openLinkInNewTab(member.Github)} - /> - -
  • -
  • - openLinkInNewTab(member.Linkedin)} - /> - -
  • -
  • - openLinkInNewTab(`mailto:${member.Email}`)} - /> - -
  • - +
  • + openLinkInNewTab(member.Website)} + /> + +
  • + )} + {member.Github && ( +
  • + openLinkInNewTab(member.Github)} + /> + +
  • + )} + {member.Linkedin && ( +
  • + openLinkInNewTab(member.Linkedin)} + /> + +
  • + )} + {member.Email && ( +
  • + openLinkInNewTab(`mailto:${member.Email}`)} + /> + +
  • )}
From f0b6df7ae2926f21552bc0f171e6087253c97678 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Wed, 18 Sep 2024 15:38:12 +0300 Subject: [PATCH 07/74] Disable text selection and cursor visibility --- .../src/widgets/SectionMembers/ui/SectionMembers.module.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss index f7c723b9c..49173def6 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss @@ -41,12 +41,14 @@ line-height: 1.5; font-weight: bold; color: #e89dff; + user-select: none; } .workmanComponent { display: flex; justify-content: center; gap: 10px; + user-select: none; h3 { font-size: clamp(20px, 5vw, 25px); From e122e120717274ac52c7f4f2efca6a8a47f91cc5 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Thu, 19 Sep 2024 12:30:10 +0300 Subject: [PATCH 08/74] documentation --- .../SectionMembers/ui/SectionMembers.tsx | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx index bdd6fe3ca..6db0a8644 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx @@ -1,3 +1,5 @@ +/* This code snippet is a TypeScript React component that displays a list of team members grouped by +their roles. Here's a breakdown of what the code is doing: */ import cls from './SectionMembers.module.scss'; import Image from 'next/image'; import { ScrollBottomButton } from '@/features/ScrollBottom'; @@ -5,7 +7,7 @@ import { classNames } from '@/shared/lib/classNames/classNames'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faGlobe, faEnvelope } from '@fortawesome/free-solid-svg-icons'; import { Container } from '@/shared/ui/Container'; -import { openLinkInNewTab } from '@/shared/lib/openLinkInNewTab/openLinkInNewTab'; // Utility to open links +import { openLinkInNewTab } from '@/shared/lib/openLinkInNewTab/openLinkInNewTab'; import { useClientTranslation } from '@/shared/i18n'; import { useParams } from 'next/navigation'; import { FC, memo, useEffect, useState } from 'react'; @@ -16,6 +18,10 @@ interface WorkersSectionProps { className?: string; } +/* This code snippet defines a React functional component named `SectionMembers` that takes in a prop +`className` of type string. Inside the component function, it initializes state using the `useState` +hook to store an array of `TeamMember` objects as `teamMembers`. It then retrieves parameters using +the `useParams` hook and extracts the language (`lng`) from the parameters. */ export const SectionMembers: FC = ({ className = '' }) => { const [teamMembers, setTeamMembers] = useState([]); const params = useParams(); @@ -56,6 +62,14 @@ export const SectionMembers: FC = ({ className = '' }) => { ); }; +/** + * The `groupByRole` function takes an array of `TeamMember` objects and groups them by their `Role` + * property into a Record where the keys are roles and the values are arrays of team members with that + * role. + * @param {TeamMember[]} members - An array of TeamMember objects. + * @returns The `groupByRole` function returns an object where each key represents a role and the + * corresponding value is an array of `TeamMember` objects with that role. + */ const groupByRole = (members: TeamMember[]): Record => { return members.reduce((acc, member) => { if (!acc[member.Role]) { @@ -70,6 +84,11 @@ interface GroupWithMemberProps { member: TeamMember; } +/* The `GroupWithMemberComponent` constant is defining a React functional component that takes in a +prop `member` of type `GroupWithMemberProps`. Inside the component function, it first retrieves +parameters using the `useParams` hook and extracts the language (`lng`) from the parameters. Then, +it uses the `useClientTranslation` hook to get the translation function `t` for the 'members' +namespace. */ const GroupWithMemberComponent: FC = memo( ({ member }) => { const params = useParams(); @@ -90,6 +109,10 @@ interface MemberProps { member: TeamMember; } +/* The `MemberComponent` constant is defining a React functional component that takes in a prop +`member` of type `MemberProps`. Inside the component function, it renders a `
` element with a +class name of `cls.workmanComponent`. Within this `
`, it displays the member's name +(`member.Name`) as an `

` element. */ const MemberComponent: FC = memo(({ member }) => { return (
From 76f995c338bb9190dca3d2e1d4b5ed37c8a7df50 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Thu, 19 Sep 2024 21:08:14 +0300 Subject: [PATCH 09/74] - Added TaskText as a separate element below the member's name and icons. - Updated the structure of MemberComponent to include a flex container for icons. - Adjusted CSS to ensure icons are aligned in a row while TaskText is displayed below. --- .../SectionMembers/model/membersApi.ts | 3 +- .../ui/SectionMembers.module.scss | 32 +++++++------ .../SectionMembers/ui/SectionMembers.tsx | 46 +++++++------------ 3 files changed, 35 insertions(+), 46 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts index c83ef4fa1..c6911db84 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts +++ b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts @@ -3,8 +3,9 @@ const BASE_URL = 'http://localhost:1337/api'; export interface TeamMember { id: number; Role: string; + Task?: string; Name: string; - Email: string; + Email?: string; Logo?: string; Website?: string; Github?: string; diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss index 49173def6..bb94c55d4 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss @@ -46,8 +46,8 @@ .workmanComponent { display: flex; - justify-content: center; - gap: 10px; + flex-direction: column; + align-items: center; user-select: none; h3 { @@ -55,23 +55,25 @@ line-height: var(--font-family-main); } - @media only screen and (min-width: 1921px) { - h3 { - font-size: inherit; - } + .iconContainer { + display: flex; /* Align icons in a row */ + align-items: center; /* Center icons vertically */ + gap: 10px; /* Space between icons */ } - padding-bottom: 10px; - - ul { + .taskText { display: flex; - align-items: center; - gap: 10px; + text-align: start; } - .clickableLogo { - color: var(--secondary-color); - cursor: pointer; - @include link-scale-effect('icon'); + @media only screen and (min-width: 1921px) { + h3 { + font-size: inherit; + } } } +.clickableLogo { + color: var(--secondary-color); + cursor: pointer; + @include link-scale-effect('icon'); +} diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx index 6db0a8644..775b9f73f 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx @@ -110,67 +110,53 @@ interface MemberProps { } /* The `MemberComponent` constant is defining a React functional component that takes in a prop -`member` of type `MemberProps`. Inside the component function, it renders a `
` element with a -class name of `cls.workmanComponent`. Within this `
`, it displays the member's name -(`member.Name`) as an `

` element. */ +`member` of type `MemberProps`. Inside the component function, it renders a section displaying +information about a team member. Here's a breakdown of what it's doing: */ const MemberComponent: FC = memo(({ member }) => { return (
-

{member.Name}

-
    +
    +

    {member.Name}

    {member.Website && ( -
  • + openLinkInNewTab(member.Website)} /> - -
  • + )} {member.Github && ( -
  • + openLinkInNewTab(member.Github)} /> - -
  • + )} {member.Linkedin && ( -
  • + openLinkInNewTab(member.Linkedin)} /> - -
  • + )} {member.Email && ( -
  • + openLinkInNewTab(`mailto:${member.Email}`)} /> - -
  • + )} -
+
+
+

{member.Task}

+

); }); From 502a95998e33acf52ade84aaf71daad96ba47490 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Thu, 19 Sep 2024 21:22:14 +0300 Subject: [PATCH 10/74] - Added bottom border to TaskText for separation. - Adjusted TaskText display. --- .../SectionMembers/ui/SectionMembers.module.scss | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss index bb94c55d4..7efbb2785 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss @@ -56,14 +56,14 @@ } .iconContainer { - display: flex; /* Align icons in a row */ - align-items: center; /* Center icons vertically */ - gap: 10px; /* Space between icons */ + display: flex; + align-items: center; + gap: 10px; + border-bottom: 1px solid var(--secondary-color); } .taskText { - display: flex; - text-align: start; + display: block; } @media only screen and (min-width: 1921px) { From 7346c43326b203cc7715257dae779ff1dc951939 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Sun, 22 Sep 2024 20:08:31 +0300 Subject: [PATCH 11/74] add different colours for sections --- .../src/widgets/SectionMembers/ui/SectionMembers.module.scss | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss index 7efbb2785..b38179a8e 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss @@ -40,7 +40,7 @@ font-family: var(--font-family-main); line-height: 1.5; font-weight: bold; - color: #e89dff; + color: var(--secondary-color); user-select: none; } @@ -59,10 +59,11 @@ display: flex; align-items: center; gap: 10px; - border-bottom: 1px solid var(--secondary-color); + border-bottom: 1px solid var(--inverted-primary-color); } .taskText { + padding-bottom: 15px; display: block; } From 613c10a28e7ae13d20133450b4e58c6ffeb4e2b2 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Mon, 23 Sep 2024 15:33:28 +0300 Subject: [PATCH 12/74] Add envHelper for strapi --- .../src/shared/const/envHelper.ts | 9 +++---- .../SectionMembers/model/membersApi.ts | 24 ++++++++++++++----- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/frontend-next-migration/src/shared/const/envHelper.ts b/frontend-next-migration/src/shared/const/envHelper.ts index c1782e6fa..d0b4276ad 100644 --- a/frontend-next-migration/src/shared/const/envHelper.ts +++ b/frontend-next-migration/src/shared/const/envHelper.ts @@ -7,7 +7,8 @@ * @property {string} appDomain - The public domain for the application. Defaults to an empty string if not provided. */ export const envHelper = { - isDevMode: process.env.NODE_ENV === 'development', - apiLink : process.env.NEXT_PUBLIC_API_LINK || '', - appDomain : process.env.NEXT_PUBLIC_APP_DOMAIN || '' -} as const; \ No newline at end of file + isDevMode: process.env.NODE_ENV === 'development', + apiLink: process.env.NEXT_PUBLIC_API_LINK || '', + appDomain: process.env.NEXT_PUBLIC_APP_DOMAIN || '', + strapiApiUrl: process.env.NEXT_PUBLIC_STRAPI_API_URL || '', +} as const; diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts index c6911db84..f06b2ea49 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts +++ b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts @@ -1,4 +1,4 @@ -const BASE_URL = 'http://localhost:1337/api'; +import { envHelper } from '@/shared/const/envHelper'; export interface TeamMember { id: number; @@ -16,18 +16,30 @@ export interface TeamMember { locale: string; } -export const fetchTeamMembers = async (): Promise => { +/** + * Fetch team members from Strapi based on the locale (language). + * @param locale - Language code ('en' or 'fi') + */ +export const fetchTeamMembers = async ( + locale: string = 'en', +): Promise => { try { - const response = await fetch(`${BASE_URL}/teams`); + // Convert short locale code to full Strapi locale code + const strapiLocale = locale === 'fi' ? 'fi-FI' : 'en'; + + // Fetch data from Strapi based on the detected locale using the environment variable for BASE_URL + const response = await fetch( + `${envHelper.strapiApiUrl}/teams?locale=${strapiLocale}`, + ); + if (!response.ok) { throw new Error(`Error fetching data: ${response.statusText}`); } const data = await response.json(); - const members = Array.isArray(data.data) ? data.data : [data.data]; - - return members.map((item: any) => ({ + // Map the response data to your TeamMember interface + return data.data.map((item: any) => ({ id: item.id, ...item.attributes, })) as TeamMember[]; From f349b3c2aeb8c7528a8a764576d127ce42497f6f Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Mon, 23 Sep 2024 15:33:57 +0300 Subject: [PATCH 13/74] Add Translate for playButton Cleaning & Documentation --- .../SectionMembers/ui/SectionMembers.tsx | 57 +++++++------------ 1 file changed, 22 insertions(+), 35 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx index 775b9f73f..7165db127 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx @@ -1,44 +1,37 @@ -/* This code snippet is a TypeScript React component that displays a list of team members grouped by -their roles. Here's a breakdown of what the code is doing: */ import cls from './SectionMembers.module.scss'; -import Image from 'next/image'; +import { FC, memo, useEffect, useState } from 'react'; +import { useParams } from 'next/navigation'; +import { fetchTeamMembers, TeamMember } from '../model/membersApi'; import { ScrollBottomButton } from '@/features/ScrollBottom'; import { classNames } from '@/shared/lib/classNames/classNames'; +import { Container } from '@/shared/ui/Container'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faGlobe, faEnvelope } from '@fortawesome/free-solid-svg-icons'; -import { Container } from '@/shared/ui/Container'; -import { openLinkInNewTab } from '@/shared/lib/openLinkInNewTab/openLinkInNewTab'; -import { useClientTranslation } from '@/shared/i18n'; -import { useParams } from 'next/navigation'; -import { FC, memo, useEffect, useState } from 'react'; -import { TeamMember, fetchTeamMembers } from '../model/membersApi'; import { faGithub, faLinkedin } from '@fortawesome/free-brands-svg-icons'; +import { openLinkInNewTab } from '@/shared/lib/openLinkInNewTab/openLinkInNewTab'; +import { useClientTranslation } from '@/shared/i18n'; // Import translation hook interface WorkersSectionProps { className?: string; } -/* This code snippet defines a React functional component named `SectionMembers` that takes in a prop -`className` of type string. Inside the component function, it initializes state using the `useState` -hook to store an array of `TeamMember` objects as `teamMembers`. It then retrieves parameters using -the `useParams` hook and extracts the language (`lng`) from the parameters. */ export const SectionMembers: FC = ({ className = '' }) => { const [teamMembers, setTeamMembers] = useState([]); const params = useParams(); const lng = params.lng as string; - const { t } = useClientTranslation(lng, 'team'); + const { t } = useClientTranslation(lng, 'team'); // Use translation hook for locale 'team' useEffect(() => { const fetchMembers = async () => { try { - const data = await fetchTeamMembers(); + const data = await fetchTeamMembers(lng); setTeamMembers(data); } catch (error) { console.error('Failed to fetch team members:', error); } }; fetchMembers(); - }, []); + }, [lng]); const groupedMembers = groupByRole(teamMembers); @@ -51,7 +44,8 @@ export const SectionMembers: FC = ({ className = '' }) => { {Object.keys(groupedMembers).map((role) => (
-

{t(role)}

+

{role}

{' '} + {/* No need to translate, role names are managed in Strapi */} {groupedMembers[role].map((member) => ( ))} @@ -63,12 +57,11 @@ export const SectionMembers: FC = ({ className = '' }) => { }; /** - * The `groupByRole` function takes an array of `TeamMember` objects and groups them by their `Role` - * property into a Record where the keys are roles and the values are arrays of team members with that - * role. + * The groupByRole function takes an array of TeamMember objects and groups them by their Role + * property into a Record where the keys are roles and the values are arrays of team members with that role. * @param {TeamMember[]} members - An array of TeamMember objects. - * @returns The `groupByRole` function returns an object where each key represents a role and the - * corresponding value is an array of `TeamMember` objects with that role. + * @returns The groupByRole function returns an object where each key represents a role and the + * corresponding value is an array of TeamMember objects with that role. */ const groupByRole = (members: TeamMember[]): Record => { return members.reduce((acc, member) => { @@ -84,17 +77,11 @@ interface GroupWithMemberProps { member: TeamMember; } -/* The `GroupWithMemberComponent` constant is defining a React functional component that takes in a -prop `member` of type `GroupWithMemberProps`. Inside the component function, it first retrieves -parameters using the `useParams` hook and extracts the language (`lng`) from the parameters. Then, -it uses the `useClientTranslation` hook to get the translation function `t` for the 'members' -namespace. */ +/* The GroupWithMemberComponent constant is defining a React functional component that takes in a +prop member of type GroupWithMemberProps. Inside the component function, it simply renders the +information passed in by the member prop. No local translation is needed as this is already handled by Strapi. */ const GroupWithMemberComponent: FC = memo( ({ member }) => { - const params = useParams(); - const lng = params.lng as string; - const { t } = useClientTranslation(lng, 'members'); - return (
@@ -109,9 +96,9 @@ interface MemberProps { member: TeamMember; } -/* The `MemberComponent` constant is defining a React functional component that takes in a prop -`member` of type `MemberProps`. Inside the component function, it renders a section displaying -information about a team member. Here's a breakdown of what it's doing: */ +/* The MemberComponent constant is defining a React functional component that takes in a prop +member of type MemberProps. Inside the component function, it renders a section displaying +information about a team member, including their website, GitHub, LinkedIn, and email. */ const MemberComponent: FC = memo(({ member }) => { return (
@@ -149,7 +136,7 @@ const MemberComponent: FC = memo(({ member }) => { openLinkInNewTab(`mailto:${member.Email}`)} + onClick={() => openLinkInNewTab(member.Email)} /> )} From ffcb6fc8e97c64c71b469b0ff864dcd4be3b4e27 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Tue, 24 Sep 2024 10:46:04 +0300 Subject: [PATCH 14/74] - Add reverse order display for groups (works better with strapi managing) -Add alphabetic sorting for members --- .../SectionMembers/ui/SectionMembers.tsx | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx index 7165db127..b4f1a5474 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx @@ -25,6 +25,9 @@ export const SectionMembers: FC = ({ className = '' }) => { const fetchMembers = async () => { try { const data = await fetchTeamMembers(lng); + const sortedMembers = data.sort((a: TeamMember, b: TeamMember) => + a.Name.localeCompare(b.Name), + ); setTeamMembers(data); } catch (error) { console.error('Failed to fetch team members:', error); @@ -42,15 +45,17 @@ export const SectionMembers: FC = ({ className = '' }) => { text={t('playButton')} /> - {Object.keys(groupedMembers).map((role) => ( -
-

{role}

{' '} - {/* No need to translate, role names are managed in Strapi */} - {groupedMembers[role].map((member) => ( - - ))} -
- ))} + {Object.keys(groupedMembers) + .reverse() + .map((role) => ( +
+

{role}

{' '} + {/* No need to translate, translation are managed in Strapi */} + {groupedMembers[role].map((member) => ( + + ))} +
+ ))}
); From 4a35487f0cc88b7477a0222b74436f8b6fcdf2da Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Tue, 24 Sep 2024 14:49:12 +0300 Subject: [PATCH 15/74] add envHelper for strapiHost --- frontend-next-migration/next.config.js | 46 +++++++++---------- .../src/shared/const/envHelper.ts | 1 + 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/frontend-next-migration/next.config.js b/frontend-next-migration/next.config.js index 409b6db39..6e1813629 100644 --- a/frontend-next-migration/next.config.js +++ b/frontend-next-migration/next.config.js @@ -39,31 +39,31 @@ // withBundleAnalyzer, // ], nextConfig); - // module.exports = nextConfig; const path = require('path'); /** @type {import('next').NextConfig} */ const nextConfig = { + images: { + remotePatterns: [ + { hostname: process.env.NEXT_PUBLIC_API_DOMAIN }, + { hostname: 'hips.hearstapps.com' }, + { hostname: 'www.thesprucepets.com' }, + { hostname: 'heroes.ts.unsplash.com' }, + { hostname: 'raw.githubusercontent.com' }, + { hostname: 'localhost' }, // Add localhost for development + { hostname: new URL(process.env.NEXT_PUBLIC_STRAPI_HOST).hostname }, + ], + }, + sassOptions: { + includePaths: [path.join(__dirname, 'styles')], + // prependData: `@import "src/app/styles/variables/_mixins.scss";`, + prependData: `@import "src/app/_styles/variables/_mixins.scss";`, + // prependData: `@import "src/preparedApp/styles/variables/_mixins.scss";`, + }, + output: 'standalone', + // experimental: { + // webpackBuildWorker: true + // }, +}; - images: { - remotePatterns: [ - { hostname: process.env.NEXT_PUBLIC_API_DOMAIN }, - { hostname: "hips.hearstapps.com" }, - { hostname: "www.thesprucepets.com" }, - { hostname: "heroes.ts.unsplash.com" }, - { hostname: "raw.githubusercontent.com" }, - ], - }, - sassOptions: { - includePaths: [path.join(__dirname, 'styles')], - // prependData: `@import "src/app/styles/variables/_mixins.scss";`, - prependData: `@import "src/app/_styles/variables/_mixins.scss";`, - // prependData: `@import "src/preparedApp/styles/variables/_mixins.scss";`, - }, - output: 'standalone', - // experimental: { - // webpackBuildWorker: true - // }, -} - -module.exports = nextConfig +module.exports = nextConfig; diff --git a/frontend-next-migration/src/shared/const/envHelper.ts b/frontend-next-migration/src/shared/const/envHelper.ts index d0b4276ad..aaf01616d 100644 --- a/frontend-next-migration/src/shared/const/envHelper.ts +++ b/frontend-next-migration/src/shared/const/envHelper.ts @@ -11,4 +11,5 @@ export const envHelper = { apiLink: process.env.NEXT_PUBLIC_API_LINK || '', appDomain: process.env.NEXT_PUBLIC_APP_DOMAIN || '', strapiApiUrl: process.env.NEXT_PUBLIC_STRAPI_API_URL || '', + strapiHost: process.env.NEXT_PUBLIC_STRAPI_HOST || '', } as const; From 32835088bee6dc53d2c0e9767d8c2ba9238d26c7 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Tue, 24 Sep 2024 14:51:59 +0300 Subject: [PATCH 16/74] Add data structure mapping (not just any) Add Logo paths via envHelper Add documentation --- .../SectionMembers/model/membersApi.ts | 40 +++++++++++++++---- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts index f06b2ea49..a00e85b98 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts +++ b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts @@ -1,3 +1,6 @@ +/* This TypeScript code defines an interface `TeamMember` representing the structure of a team member +object. It includes properties like id, Role, Task, Name, Email, Logo, Website, Github, Linkedin, +createdAt, updatedAt, publishedAt, and locale. */ import { envHelper } from '@/shared/const/envHelper'; export interface TeamMember { @@ -24,12 +27,10 @@ export const fetchTeamMembers = async ( locale: string = 'en', ): Promise => { try { - // Convert short locale code to full Strapi locale code const strapiLocale = locale === 'fi' ? 'fi-FI' : 'en'; - // Fetch data from Strapi based on the detected locale using the environment variable for BASE_URL const response = await fetch( - `${envHelper.strapiApiUrl}/teams?locale=${strapiLocale}`, + `${envHelper.strapiApiUrl}/teams?locale=${strapiLocale}&populate=*`, ); if (!response.ok) { @@ -38,11 +39,34 @@ export const fetchTeamMembers = async ( const data = await response.json(); - // Map the response data to your TeamMember interface - return data.data.map((item: any) => ({ - id: item.id, - ...item.attributes, - })) as TeamMember[]; + /* This part of the code is mapping over the array of team members fetched from the Strapi API and + transforming each item into a new object with specific properties. Here's a breakdown of what + it's doing: */ + return data.data.map((item: any) => { + const attributes = item.attributes; + const logoData = attributes.Logo?.data; + const logoUrl = logoData + ? `${envHelper.strapiHost.replace(/\/$/, '')}${ + logoData.attributes.formats?.thumbnail?.url + }` + : null; + + return { + id: item.id, + Role: attributes.Role, + Task: attributes.Task, + Name: attributes.Name, + Email: attributes.Email, + Logo: logoUrl, + Website: attributes.Website, + Github: attributes.Github, + Linkedin: attributes.Linkedin, + createdAt: attributes.createdAt, + updatedAt: attributes.updatedAt, + publishedAt: attributes.publishedAt, + locale: attributes.locale, + }; + }) as TeamMember[]; } catch (error) { throw new Error('Error fetching team members data'); } From aa470ea36bcf8d13d49aaaed137d49f67e16b77d Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Tue, 24 Sep 2024 14:52:19 +0300 Subject: [PATCH 17/74] Add logo --- .../SectionMembers/ui/SectionMembers.tsx | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx index b4f1a5474..f9d6b754e 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx @@ -1,3 +1,6 @@ +/* The above code snippet is a TypeScript React component that displays a list of team members with +their information such as name, role, website, GitHub, LinkedIn, and email. Here is a breakdown of +what the code is doing: */ import cls from './SectionMembers.module.scss'; import { FC, memo, useEffect, useState } from 'react'; import { useParams } from 'next/navigation'; @@ -9,7 +12,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faGlobe, faEnvelope } from '@fortawesome/free-solid-svg-icons'; import { faGithub, faLinkedin } from '@fortawesome/free-brands-svg-icons'; import { openLinkInNewTab } from '@/shared/lib/openLinkInNewTab/openLinkInNewTab'; -import { useClientTranslation } from '@/shared/i18n'; // Import translation hook +import { useClientTranslation } from '@/shared/i18n'; +import Image from 'next/image'; interface WorkersSectionProps { className?: string; @@ -19,7 +23,7 @@ export const SectionMembers: FC = ({ className = '' }) => { const [teamMembers, setTeamMembers] = useState([]); const params = useParams(); const lng = params.lng as string; - const { t } = useClientTranslation(lng, 'team'); // Use translation hook for locale 'team' + const { t } = useClientTranslation(lng, 'team'); useEffect(() => { const fetchMembers = async () => { @@ -108,6 +112,18 @@ const MemberComponent: FC = memo(({ member }) => { return (
+ {member.Logo ? ( + {`logo`} + ) : ( + <> + )}

{member.Name}

{member.Website && ( @@ -115,6 +131,7 @@ const MemberComponent: FC = memo(({ member }) => { icon={faGlobe} size='xl' onClick={() => openLinkInNewTab(member.Website)} + className={cls.Logo} /> )} From 8e759b4f4a351a5938a35675703dc10ba1244dda Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Tue, 24 Sep 2024 15:39:10 +0300 Subject: [PATCH 18/74] Adjust logo position and size --- .../src/widgets/SectionMembers/ui/SectionMembers.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx index f9d6b754e..58f77ab33 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx @@ -112,19 +112,18 @@ const MemberComponent: FC = memo(({ member }) => { return (
+

{member.Name}

{member.Logo ? ( {`logo`} ) : ( <> )} -

{member.Name}

{member.Website && ( Date: Tue, 24 Sep 2024 15:49:23 +0300 Subject: [PATCH 19/74] Redesign Role looking like alt logo --- .../widgets/SectionMembers/ui/SectionMembers.module.scss | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss index b38179a8e..763f880b2 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss @@ -40,8 +40,10 @@ font-family: var(--font-family-main); line-height: 1.5; font-weight: bold; - color: var(--secondary-color); user-select: none; + color: var(--secondary-color); + -webkit-text-stroke: 2px black; + text-shadow: 2px 2px 2px var(--inverted-primary-color); } .workmanComponent { @@ -78,3 +80,7 @@ cursor: pointer; @include link-scale-effect('icon'); } +.memberLogo { + @include link-scale-effect('icon'); + size: inherit; +} From 6f6404b90110b8708d2a8498d36d8f35dd9914c6 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Tue, 24 Sep 2024 22:07:14 +0300 Subject: [PATCH 20/74] Add Part (first title) from strapi --- .../src/widgets/SectionMembers/model/membersApi.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts index a00e85b98..4afba1fb5 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts +++ b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts @@ -17,6 +17,7 @@ export interface TeamMember { updatedAt: string; publishedAt: string; locale: string; + Part: string; } /** @@ -65,6 +66,7 @@ export const fetchTeamMembers = async ( updatedAt: attributes.updatedAt, publishedAt: attributes.publishedAt, locale: attributes.locale, + Part: attributes.Part || '', }; }) as TeamMember[]; } catch (error) { From b78324cc6cdfc1ffd301ba3bb45fd4304235b9a9 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Tue, 24 Sep 2024 22:07:52 +0300 Subject: [PATCH 21/74] Add Part from strapi Adjust Arrange for part and role --- .../SectionMembers/ui/SectionMembers.tsx | 52 ++++++++++++------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx index 58f77ab33..e89a91eae 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx @@ -29,9 +29,6 @@ export const SectionMembers: FC = ({ className = '' }) => { const fetchMembers = async () => { try { const data = await fetchTeamMembers(lng); - const sortedMembers = data.sort((a: TeamMember, b: TeamMember) => - a.Name.localeCompare(b.Name), - ); setTeamMembers(data); } catch (error) { console.error('Failed to fetch team members:', error); @@ -40,7 +37,7 @@ export const SectionMembers: FC = ({ className = '' }) => { fetchMembers(); }, [lng]); - const groupedMembers = groupByRole(teamMembers); + const groupedMembers = groupByPartAndRole(teamMembers); return (
@@ -49,22 +46,32 @@ export const SectionMembers: FC = ({ className = '' }) => { text={t('playButton')} /> - {Object.keys(groupedMembers) - .reverse() - .map((role) => ( -
-

{role}

{' '} - {/* No need to translate, translation are managed in Strapi */} - {groupedMembers[role].map((member) => ( - + {Object.keys(groupedMembers).map((part) => ( +
+

{part}

{' '} + {Object.keys(groupedMembers[part]) + .filter( + (role) => role !== null && role !== undefined && role !== '', + ) + .map((role) => ( +
+

{role}

+ {groupedMembers[part][role] + .sort((a, b) => a.Name.localeCompare(b.Name)) + .map((member) => ( + + ))} +
))} -
- ))} +
+ ))}
); }; - /** * The groupByRole function takes an array of TeamMember objects and groups them by their Role * property into a Record where the keys are roles and the values are arrays of team members with that role. @@ -72,14 +79,19 @@ export const SectionMembers: FC = ({ className = '' }) => { * @returns The groupByRole function returns an object where each key represents a role and the * corresponding value is an array of TeamMember objects with that role. */ -const groupByRole = (members: TeamMember[]): Record => { +const groupByPartAndRole = ( + members: TeamMember[], +): Record> => { return members.reduce((acc, member) => { - if (!acc[member.Role]) { - acc[member.Role] = []; + if (!acc[member.Part]) { + acc[member.Part] = {}; + } + if (!acc[member.Part][member.Role]) { + acc[member.Part][member.Role] = []; } - acc[member.Role].push(member); + acc[member.Part][member.Role].push(member); return acc; - }, {} as Record); + }, {} as Record>); }; interface GroupWithMemberProps { From a73b74c55eb71cfedc9d7e871d0b9b5ba9a6153b Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Tue, 24 Sep 2024 22:08:32 +0300 Subject: [PATCH 22/74] make part and role as nude as possible --- .../ui/SectionMembers.module.scss | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss index 763f880b2..6764e9dfc 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss @@ -4,6 +4,8 @@ text-align: center; display: grid; justify-items: center; + user-select: none; + //color: var(--red-dark); //height: 100%; @@ -36,21 +38,21 @@ } .membersListContainer h2 { - font-size: clamp(40px, 7vw, 50px); + font-size: clamp(20px, 3vw, 50px); font-family: var(--font-family-main); line-height: 1.5; - font-weight: bold; - user-select: none; - color: var(--secondary-color); - -webkit-text-stroke: 2px black; - text-shadow: 2px 2px 2px var(--inverted-primary-color); + color: blue; +} +.membersListContainer h1 { + font-size: clamp(40px, 7vw, 50px); + font-family: var(--font-family-main); + color: red; } .workmanComponent { display: flex; flex-direction: column; align-items: center; - user-select: none; h3 { font-size: clamp(20px, 5vw, 25px); @@ -61,7 +63,6 @@ display: flex; align-items: center; gap: 10px; - border-bottom: 1px solid var(--inverted-primary-color); } .taskText { From 127ecf0b5198bfba7885ede41f9acafabc11cac3 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Fri, 27 Sep 2024 13:27:46 +0300 Subject: [PATCH 23/74] starting point --- .../SectionMembers/model/membersApi.ts | 121 ++++++--- .../src/widgets/SectionMembers/model/types.ts | 33 +++ .../ui/SectionMembers.module.scss | 97 ++++---- .../SectionMembers/ui/SectionMembers.tsx | 231 +++++++----------- 4 files changed, 257 insertions(+), 225 deletions(-) create mode 100644 frontend-next-migration/src/widgets/SectionMembers/model/types.ts diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts index 4afba1fb5..56bd0605d 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts +++ b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts @@ -1,13 +1,9 @@ -/* This TypeScript code defines an interface `TeamMember` representing the structure of a team member -object. It includes properties like id, Role, Task, Name, Email, Logo, Website, Github, Linkedin, -createdAt, updatedAt, publishedAt, and locale. */ import { envHelper } from '@/shared/const/envHelper'; -export interface TeamMember { +export interface Member { id: number; - Role: string; - Task?: string; Name: string; + Task?: string; Email?: string; Logo?: string; Website?: string; @@ -17,59 +13,106 @@ export interface TeamMember { updatedAt: string; publishedAt: string; locale: string; - Part: string; +} + +export interface Department { + id: number; + Name: string; + members: Member[]; // Lisää jäsenet +} + +export interface Team { + members: any; + id: number; + Name: string; + createdAt: string; + updatedAt: string; + publishedAt: string; + locale: string; + departments: Department[]; // Lisää osastot } /** - * Fetch team members from Strapi based on the locale (language). + * Fetch teams from Strapi based on the locale (language). * @param locale - Language code ('en' or 'fi') */ -export const fetchTeamMembers = async ( - locale: string = 'en', -): Promise => { +export const fetchTeams = async (locale: string = 'en'): Promise => { try { const strapiLocale = locale === 'fi' ? 'fi-FI' : 'en'; const response = await fetch( - `${envHelper.strapiApiUrl}/teams?locale=${strapiLocale}&populate=*`, + `${envHelper.strapiApiUrl}/teams?locale=${strapiLocale}&populate=departments,members`, // Populate members directly from the team ); if (!response.ok) { throw new Error(`Error fetching data: ${response.statusText}`); } - const data = await response.json(); + const teamData = await response.json(); - /* This part of the code is mapping over the array of team members fetched from the Strapi API and - transforming each item into a new object with specific properties. Here's a breakdown of what - it's doing: */ - return data.data.map((item: any) => { - const attributes = item.attributes; - const logoData = attributes.Logo?.data; - const logoUrl = logoData - ? `${envHelper.strapiHost.replace(/\/$/, '')}${ - logoData.attributes.formats?.thumbnail?.url - }` - : null; + // Map teams + const teams: Team[] = teamData.data.map((item: any) => { + // Get members directly from the team object + const members = + item.attributes.members?.data.map((member: any) => { + return { + id: member.id, + Name: member.attributes.Name, + Task: member.attributes.Task, + Email: member.attributes.Email, + Linkedin: member.attributes.Linkedin, + Website: member.attributes.Website, + Github: member.attributes.Github, + Facebook: member.attributes.Facebook, + Instagram: member.attributes.Instagram, + createdAt: member.attributes.createdAt, + updatedAt: member.attributes.updatedAt, + locale: member.attributes.locale, + }; + }) || []; return { id: item.id, - Role: attributes.Role, - Task: attributes.Task, - Name: attributes.Name, - Email: attributes.Email, - Logo: logoUrl, - Website: attributes.Website, - Github: attributes.Github, - Linkedin: attributes.Linkedin, - createdAt: attributes.createdAt, - updatedAt: attributes.updatedAt, - publishedAt: attributes.publishedAt, - locale: attributes.locale, - Part: attributes.Part || '', + Name: item.attributes.Team, + createdAt: item.attributes.createdAt, + updatedAt: item.attributes.updatedAt, + publishedAt: item.attributes.publishedAt, + locale: item.attributes.locale, + members, + departments: + item.attributes.departments?.data.map((dept: any) => ({ + id: dept.id, + Name: dept.attributes.Department, + members: + members.filter( + (member: { department: { data: { id: any } } }) => + member.department?.data?.id === dept.id, + ) || [], + })) || [], }; - }) as TeamMember[]; + }); + + const order = [ + 'Game Design', + 'Mentoring', + 'Sounds', + 'Programming', + 'Graphics', + 'Comic book', + 'Production', + 'Analysis', + 'Art', + 'Game Art Education Package', + 'Other Participants', + 'Special Thanks', + ]; + + return teams.sort((a: Team, b: Team) => { + const indexA = order.indexOf(a.Name); + const indexB = order.indexOf(b.Name); + return indexA - indexB; + }); } catch (error) { - throw new Error('Error fetching team members data'); + throw new Error('Error fetching teams data'); } }; diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/types.ts b/frontend-next-migration/src/widgets/SectionMembers/model/types.ts new file mode 100644 index 000000000..87626f487 --- /dev/null +++ b/frontend-next-migration/src/widgets/SectionMembers/model/types.ts @@ -0,0 +1,33 @@ +export interface Member { + id: number; + name: string; // Changed from Name to name + task?: string; + email?: string; + website?: string; + github?: string; + linkedin?: string; + facebook?: string; + instagram?: string; + logo?: string; + createdAt: string; + updatedAt: string; + locale: string; +} + +export interface Department { + id: number; + name: string; // Changed from Name to name + members: Member[]; // Changed from Members to members + createdAt: string; + updatedAt: string; + locale: string; +} + +export interface Team { + id: number; + team?: string; // Changed from Team to team + departments?: Department[]; // Changed from Departments to departments + createdAt: string; + updatedAt: string; + locale: string; +} diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss index 6764e9dfc..bd7d1fa28 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss @@ -1,87 +1,98 @@ .MembersSection { font-family: var(--font-family-texts); - //min-height: 100% !important; - text-align: center; display: grid; justify-items: center; user-select: none; - - //color: var(--red-dark); - - //height: 100%; } .scrollBottomButton { - //align-self: start; margin-bottom: 10px; - @include link-scale-effect; } .membersListContainer { border-radius: var(--border-radius-custom); z-index: 2; - //background-color: var(--transparent-bg-dark); background-color: rgba(0, 0, 0, 0.55); } -.groupComponent { - display: flex; - flex-direction: column; - justify-content: center; - text-align: center; - - ul { - list-style-type: none; - padding-left: 0; - } -} - .membersListContainer h2 { font-size: clamp(20px, 3vw, 50px); font-family: var(--font-family-main); line-height: 1.5; color: blue; + text-align: center; } + .membersListContainer h1 { - font-size: clamp(40px, 7vw, 50px); + font-size: clamp(20px, 3vw, 30px); font-family: var(--font-family-main); color: red; + text-align: start; } .workmanComponent { display: flex; flex-direction: column; - align-items: center; + width: 100%; + margin-bottom: 15px; + padding-left: 20%; + padding-right: 20%; - h3 { - font-size: clamp(20px, 5vw, 25px); - line-height: var(--font-family-main); + .memberRow { + display: flex; + justify-content: space-between; + align-items: center; + gap: 10px; + width: 100%; + padding: 10px 0; } - .iconContainer { + .teamName { + text-align: left; + font-weight: bold; + font-size: 1.1rem; + flex: 1; + } + + .centerContainer { display: flex; + justify-content: center; align-items: center; - gap: 10px; + gap: 1rem; + flex: 2; + text-align: center; + } + + .memberName { + font-weight: bold; + font-size: 1rem; + text-align: center; } .taskText { - padding-bottom: 15px; - display: block; + font-size: 1rem; + color: white; + text-align: center; + flex: 1; } - @media only screen and (min-width: 1921px) { - h3 { - font-size: inherit; - } + .iconContainer { + display: flex; + gap: 1rem; + justify-content: flex-end; + align-items: center; + } + + .clickableLogo { + color: var(--secondary-color); + cursor: pointer; + @include link-scale-effect('icon'); + } + + .memberLogo { + @include link-scale-effect('icon'); + size: inherit; + margin-top: 10px; } -} -.clickableLogo { - color: var(--secondary-color); - cursor: pointer; - @include link-scale-effect('icon'); -} -.memberLogo { - @include link-scale-effect('icon'); - size: inherit; } diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx index e89a91eae..d1a798601 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx @@ -1,10 +1,7 @@ -/* The above code snippet is a TypeScript React component that displays a list of team members with -their information such as name, role, website, GitHub, LinkedIn, and email. Here is a breakdown of -what the code is doing: */ import cls from './SectionMembers.module.scss'; -import { FC, memo, useEffect, useState } from 'react'; +import { FC, useEffect, useState } from 'react'; import { useParams } from 'next/navigation'; -import { fetchTeamMembers, TeamMember } from '../model/membersApi'; +import { fetchTeams, Team, Member } from '../model/membersApi'; import { ScrollBottomButton } from '@/features/ScrollBottom'; import { classNames } from '@/shared/lib/classNames/classNames'; import { Container } from '@/shared/ui/Container'; @@ -15,30 +12,73 @@ import { openLinkInNewTab } from '@/shared/lib/openLinkInNewTab/openLinkInNewTab import { useClientTranslation } from '@/shared/i18n'; import Image from 'next/image'; +// MemberItem Component to Render a Single Member +const MemberItem: FC<{ member: Member }> = ({ member }) => ( +
  • +
    +
    + {member.Name} + {member.Task} +
    + {member.Website && ( + openLinkInNewTab(member.Website)} + className={cls.clickableLogo}> + + + )} + {member.Github && ( + openLinkInNewTab(member.Github)} + className={cls.clickableLogo}> + + + )} + {member.Linkedin && ( + openLinkInNewTab(member.Linkedin)} + className={cls.clickableLogo}> + + + )} + {member.Email && ( + openLinkInNewTab(`mailto:${member.Email}`)} + className={cls.clickableLogo}> + + + )} +
    +
    +
    + {member.Logo && ( + {member.Name} + )} +
  • +); + interface WorkersSectionProps { className?: string; } export const SectionMembers: FC = ({ className = '' }) => { - const [teamMembers, setTeamMembers] = useState([]); + const [teams, setTeams] = useState([]); const params = useParams(); const lng = params.lng as string; const { t } = useClientTranslation(lng, 'team'); useEffect(() => { - const fetchMembers = async () => { + const fetchTeamsData = async () => { try { - const data = await fetchTeamMembers(lng); - setTeamMembers(data); + const data = await fetchTeams(lng); + setTeams(data); } catch (error) { - console.error('Failed to fetch team members:', error); + console.error('Failed to fetch teams:', error); } }; - fetchMembers(); + fetchTeamsData(); }, [lng]); - const groupedMembers = groupByPartAndRole(teamMembers); - return (
    = ({ className = '' }) => { text={t('playButton')} /> - {Object.keys(groupedMembers).map((part) => ( -
    -

    {part}

    {' '} - {Object.keys(groupedMembers[part]) - .filter( - (role) => role !== null && role !== undefined && role !== '', - ) - .map((role) => ( -
    -

    {role}

    - {groupedMembers[part][role] - .sort((a, b) => a.Name.localeCompare(b.Name)) - .map((member) => ( - - ))} -
    - ))} + {teams.map((team) => ( +
    +

    {team.Name}

    + + {/* Check if team has departments */} + {team.departments.length > 0 ? ( + // Render departments and their members +
    + {team.departments.map((department) => ( +
    +

    {department.Name}

    + {department.members.length > 0 ? ( +
      + {department.members.map((member) => ( + + ))} +
    + ) : ( +

    {t('noMembers')}

    + )} +
    + ))} +
    + ) : ( + // If no departments, render team members directly +
      + {team.members.length > 0 ? ( + team.members.map((member) => ( + + )) + ) : ( +

      {t('noMembers')}

      + )} +
    + )}
    ))}
    ); }; -/** - * The groupByRole function takes an array of TeamMember objects and groups them by their Role - * property into a Record where the keys are roles and the values are arrays of team members with that role. - * @param {TeamMember[]} members - An array of TeamMember objects. - * @returns The groupByRole function returns an object where each key represents a role and the - * corresponding value is an array of TeamMember objects with that role. - */ -const groupByPartAndRole = ( - members: TeamMember[], -): Record> => { - return members.reduce((acc, member) => { - if (!acc[member.Part]) { - acc[member.Part] = {}; - } - if (!acc[member.Part][member.Role]) { - acc[member.Part][member.Role] = []; - } - acc[member.Part][member.Role].push(member); - return acc; - }, {} as Record>); -}; - -interface GroupWithMemberProps { - member: TeamMember; -} - -/* The GroupWithMemberComponent constant is defining a React functional component that takes in a -prop member of type GroupWithMemberProps. Inside the component function, it simply renders the -information passed in by the member prop. No local translation is needed as this is already handled by Strapi. */ -const GroupWithMemberComponent: FC = memo( - ({ member }) => { - return ( -
    - -
    - ); - }, -); - -GroupWithMemberComponent.displayName = 'GroupWithMemberComponent'; - -interface MemberProps { - member: TeamMember; -} - -/* The MemberComponent constant is defining a React functional component that takes in a prop -member of type MemberProps. Inside the component function, it renders a section displaying -information about a team member, including their website, GitHub, LinkedIn, and email. */ -const MemberComponent: FC = memo(({ member }) => { - return ( -
    -
    -

    {member.Name}

    - {member.Logo ? ( - {`logo`} - ) : ( - <> - )} - {member.Website && ( - - openLinkInNewTab(member.Website)} - className={cls.Logo} - /> - - )} - {member.Github && ( - - openLinkInNewTab(member.Github)} - /> - - )} - {member.Linkedin && ( - - openLinkInNewTab(member.Linkedin)} - /> - - )} - {member.Email && ( - - openLinkInNewTab(member.Email)} - /> - - )} -
    -
    -

    {member.Task}

    -
    -
    - ); -}); - -MemberComponent.displayName = 'MemberComponent'; From e3511a69adeb97d89ad46993147dce2d8732ee92 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Fri, 27 Sep 2024 14:31:57 +0300 Subject: [PATCH 24/74] add more attributes for member add right handling for department --- .../SectionMembers/model/membersApi.ts | 70 ++++++++++++------- 1 file changed, 45 insertions(+), 25 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts index 56bd0605d..fee608ec0 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts +++ b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts @@ -9,6 +9,8 @@ export interface Member { Website?: string; Github?: string; Linkedin?: string; + Facebook?: string; + Instagram?: string; createdAt: string; updatedAt: string; publishedAt: string; @@ -41,7 +43,7 @@ export const fetchTeams = async (locale: string = 'en'): Promise => { const strapiLocale = locale === 'fi' ? 'fi-FI' : 'en'; const response = await fetch( - `${envHelper.strapiApiUrl}/teams?locale=${strapiLocale}&populate=departments,members`, // Populate members directly from the team + `${envHelper.strapiApiUrl}/teams?locale=${strapiLocale}&populate=departments.members,members`, // Populate members directly from both team and departments ); if (!response.ok) { @@ -54,20 +56,46 @@ export const fetchTeams = async (locale: string = 'en'): Promise => { const teams: Team[] = teamData.data.map((item: any) => { // Get members directly from the team object const members = - item.attributes.members?.data.map((member: any) => { + item.attributes.members?.data.map((member: any) => ({ + id: member.id, + Name: member.attributes.Name, + Task: member.attributes.Task, + Email: member.attributes.Email, + Linkedin: member.attributes.Linkedin, + Website: member.attributes.Website, + Github: member.attributes.Github, + Logo: member.attributes.Logo, + Facebook: member.attributes.Facebook, + Instagram: member.attributes.Instagram, + createdAt: member.attributes.createdAt, + updatedAt: member.attributes.updatedAt, + locale: member.attributes.locale, + })) || []; + + // Map departments and assign members to their respective departments + const departments = + item.attributes.departments?.data.map((dept: any) => { + const departmentMembers = + dept.attributes.members?.data.map((member: any) => ({ + id: member.id, + Name: member.attributes.Name, + Task: member.attributes.Task, + Email: member.attributes.Email, + Linkedin: member.attributes.Linkedin, + Website: member.attributes.Website, + Github: member.attributes.Github, + Logo: member.attributes.Logo, + Facebook: member.attributes.Facebook, + Instagram: member.attributes.Instagram, + createdAt: member.attributes.createdAt, + updatedAt: member.attributes.updatedAt, + locale: member.attributes.locale, + })) || []; // Extract members for each department + return { - id: member.id, - Name: member.attributes.Name, - Task: member.attributes.Task, - Email: member.attributes.Email, - Linkedin: member.attributes.Linkedin, - Website: member.attributes.Website, - Github: member.attributes.Github, - Facebook: member.attributes.Facebook, - Instagram: member.attributes.Instagram, - createdAt: member.attributes.createdAt, - updatedAt: member.attributes.updatedAt, - locale: member.attributes.locale, + id: dept.id, + Name: dept.attributes.Department, + members: departmentMembers, // Assign members to department }; }) || []; @@ -78,20 +106,12 @@ export const fetchTeams = async (locale: string = 'en'): Promise => { updatedAt: item.attributes.updatedAt, publishedAt: item.attributes.publishedAt, locale: item.attributes.locale, - members, - departments: - item.attributes.departments?.data.map((dept: any) => ({ - id: dept.id, - Name: dept.attributes.Department, - members: - members.filter( - (member: { department: { data: { id: any } } }) => - member.department?.data?.id === dept.id, - ) || [], - })) || [], + members, // Team members (if no departments) + departments, // Departments and their members }; }); + // Custom ordering of teams const order = [ 'Game Design', 'Mentoring', From dbd3f6633af3f0bd45bd39131c91fadc1bbf076b Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Fri, 27 Sep 2024 14:32:21 +0300 Subject: [PATCH 25/74] add instagram and facebook icons for member --- .../SectionMembers/ui/SectionMembers.tsx | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx index d1a798601..e1b92d9c6 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx @@ -8,6 +8,7 @@ import { Container } from '@/shared/ui/Container'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faGlobe, faEnvelope } from '@fortawesome/free-solid-svg-icons'; import { faGithub, faLinkedin } from '@fortawesome/free-brands-svg-icons'; +import { faInstagram, faFacebook } from '@fortawesome/free-brands-svg-icons'; import { openLinkInNewTab } from '@/shared/lib/openLinkInNewTab/openLinkInNewTab'; import { useClientTranslation } from '@/shared/i18n'; import Image from 'next/image'; @@ -41,6 +42,20 @@ const MemberItem: FC<{ member: Member }> = ({ member }) => ( )} + {member.Facebook && ( + openLinkInNewTab(member.Facebook)} + className={cls.clickableLogo}> + + + )} + {member.Instagram && ( + openLinkInNewTab(member.Instagram)} + className={cls.clickableLogo}> + + + )} {member.Email && ( openLinkInNewTab(`mailto:${member.Email}`)} @@ -90,9 +105,8 @@ export const SectionMembers: FC = ({ className = '' }) => {

    {team.Name}

    - {/* Check if team has departments */} + {/* Check if the team has departments */} {team.departments.length > 0 ? ( - // Render departments and their members
    {team.departments.map((department) => (
    From 69c05544f358a854a2ab6738c015687ab4e8031e Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Fri, 27 Sep 2024 15:34:59 +0300 Subject: [PATCH 26/74] add localization add tittle order for fi language --- .../SectionMembers/model/membersApi.ts | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts index fee608ec0..d7b4f1be9 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts +++ b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts @@ -111,8 +111,8 @@ export const fetchTeams = async (locale: string = 'en'): Promise => { }; }); - // Custom ordering of teams - const order = [ + // Define custom ordering for both English and Finnish locales + const orderEn = [ 'Game Design', 'Mentoring', 'Sounds', @@ -127,6 +127,23 @@ export const fetchTeams = async (locale: string = 'en'): Promise => { 'Special Thanks', ]; + const orderFi = [ + 'Pelisuunnittelu', + 'Mentorointi', + 'Ohjelmointi', + 'Grafiikka', + 'Äänet', + 'Sarjakuva', + 'Tuotanto', + 'Analyysi', + 'Pelitaiteen opetuspaketti', + 'Muut mukana olleet', + 'Erityiskiitokset', + ]; + + // Select the correct order based on locale + const order = locale === 'fi' ? orderFi : orderEn; + return teams.sort((a: Team, b: Team) => { const indexA = order.indexOf(a.Name); const indexB = order.indexOf(b.Name); From 9ea9e194d04092d6a1356f4d3f49342b76d7a4fa Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Fri, 27 Sep 2024 15:35:27 +0300 Subject: [PATCH 27/74] delete unused css styling --- .../ui/SectionMembers.module.scss | 66 ++++++++++++------- 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss index bd7d1fa28..d623517ef 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss @@ -11,24 +11,31 @@ } .membersListContainer { - border-radius: var(--border-radius-custom); - z-index: 2; - background-color: rgba(0, 0, 0, 0.55); -} - -.membersListContainer h2 { - font-size: clamp(20px, 3vw, 50px); - font-family: var(--font-family-main); - line-height: 1.5; - color: blue; - text-align: center; -} - -.membersListContainer h1 { + padding: 1rem 2rem; font-size: clamp(20px, 3vw, 30px); font-family: var(--font-family-main); - color: red; text-align: start; + background-color: rgba(0, 0, 0, 0.55); + border-radius: var(--border-radius-custom); + + h1 { + text-transform: uppercase; + font-size: clamp( + 20px, + 3vw, + 30px + ); /* Yhdistetty kahden h1 tyylin fonttikoko */ + color: var(--secondary-color); + text-align: start; + background-color: transparent; /* Tausta poistettu */ + } + + h2 { + font-size: clamp(20px, 3vw, 50px); + line-height: 1.5; + color: var(--secondary-color); + text-align: center; + } } .workmanComponent { @@ -48,26 +55,18 @@ padding: 10px 0; } - .teamName { - text-align: left; - font-weight: bold; - font-size: 1.1rem; - flex: 1; - } - .centerContainer { display: flex; justify-content: center; - align-items: center; gap: 1rem; flex: 2; - text-align: center; } .memberName { font-weight: bold; font-size: 1rem; - text-align: center; + text-align: right; /* Aseta teksti oikealle */ + direction: rtl; /* Aseta teksti virtaamaan oikealta vasemmalle */ } .taskText { @@ -96,3 +95,20 @@ margin-top: 10px; } } + +.memberCard { + padding: 1rem; + margin-bottom: 1rem; + border-radius: var(--border-radius-custom); +} + +.departmentsSection { + margin-top: 1rem; + padding-left: 1rem; +} + +.departmentCard { + padding: 0.5rem; + margin-bottom: 1rem; + border-radius: var(--border-radius-custom); +} From 662a7e3fa9a1c925f6ccd1fc199d93ebb3b81771 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Fri, 27 Sep 2024 15:43:13 +0300 Subject: [PATCH 28/74] add height and widht to logo remove logs --- .../SectionMembers/ui/SectionMembers.tsx | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx index e1b92d9c6..fb4114a12 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx @@ -67,7 +67,13 @@ const MemberItem: FC<{ member: Member }> = ({ member }) => (
    {member.Logo && ( - {member.Name} + {member.Name} )} ); @@ -111,14 +117,12 @@ export const SectionMembers: FC = ({ className = '' }) => { {team.departments.map((department) => (

    {department.Name}

    - {department.members.length > 0 ? ( + {department.members.length > 0 && (
      {department.members.map((member) => ( ))}
    - ) : ( -

    {t('noMembers')}

    )}
    ))} @@ -126,13 +130,10 @@ export const SectionMembers: FC = ({ className = '' }) => { ) : ( // If no departments, render team members directly
      - {team.members.length > 0 ? ( - team.members.map((member) => ( + {team.members.length > 0 && + team.members.map((member: Member) => ( - )) - ) : ( -

      {t('noMembers')}

      - )} + ))}
    )}
    From 68e8123e3a134a87e78357fdf5847c438cace3ad Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Fri, 27 Sep 2024 21:14:33 +0300 Subject: [PATCH 29/74] fix translate routing --- .../SectionMembers/model/membersApi.ts | 179 ++++++++++-------- 1 file changed, 100 insertions(+), 79 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts index d7b4f1be9..c3d8d1891 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts +++ b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts @@ -1,117 +1,116 @@ import { envHelper } from '@/shared/const/envHelper'; +// Interfaces export interface Member { id: number; - Name: string; - Task?: string; - Email?: string; - Logo?: string; - Website?: string; - Github?: string; - Linkedin?: string; - Facebook?: string; - Instagram?: string; + name: string; + task?: string; + email?: string; + logo?: string; + website?: string; + github?: string; + linkedin?: string; + facebook?: string; + instagram?: string; createdAt: string; updatedAt: string; - publishedAt: string; locale: string; } export interface Department { id: number; - Name: string; - members: Member[]; // Lisää jäsenet + name: string; + members: Member[]; } export interface Team { - members: any; id: number; - Name: string; + name: string; createdAt: string; updatedAt: string; - publishedAt: string; locale: string; - departments: Department[]; // Lisää osastot + members: Member[]; + departments: Department[]; } -/** - * Fetch teams from Strapi based on the locale (language). - * @param locale - Language code ('en' or 'fi') - */ +// Function to map members +const mapMembers = (membersData: any[]): Member[] => { + return ( + membersData.map((member: any) => ({ + id: member.id, + name: member.attributes.Name, + task: member.attributes.Task, + email: member.attributes.Email, + linkedin: member.attributes.Linkedin, + website: member.attributes.Website, + github: member.attributes.Github, + logo: member.attributes.Logo, + facebook: member.attributes.Facebook, + instagram: member.attributes.Instagram, + createdAt: member.attributes.createdAt, + updatedAt: member.attributes.updatedAt, + locale: member.attributes.locale, + })) || [] + ); +}; + +// Function to map departments +const mapDepartments = ( + departmentsData: any[], + locale: string, +): Department[] => { + return ( + departmentsData.map((dept: any) => { + // Look for localized department name + const localizedDeptName = + dept.attributes.localizations?.data.find( + (loc: any) => loc.attributes.locale === locale, + )?.attributes.Department || dept.attributes.Department; + + const members = mapMembers(dept.attributes.members?.data || []); + + return { + id: dept.id, + name: localizedDeptName, + members, + }; + }) || [] + ); +}; + +// Fetch Teams export const fetchTeams = async (locale: string = 'en'): Promise => { try { const strapiLocale = locale === 'fi' ? 'fi-FI' : 'en'; const response = await fetch( - `${envHelper.strapiApiUrl}/teams?locale=${strapiLocale}&populate=departments.members,members`, // Populate members directly from both team and departments + `${envHelper.strapiApiUrl}/teams?locale=${strapiLocale}&populate=departments.members,members`, ); if (!response.ok) { - throw new Error(`Error fetching data: ${response.statusText}`); + throw new Error(`Error fetching teams: ${response.statusText}`); } const teamData = await response.json(); - // Map teams const teams: Team[] = teamData.data.map((item: any) => { - // Get members directly from the team object - const members = - item.attributes.members?.data.map((member: any) => ({ - id: member.id, - Name: member.attributes.Name, - Task: member.attributes.Task, - Email: member.attributes.Email, - Linkedin: member.attributes.Linkedin, - Website: member.attributes.Website, - Github: member.attributes.Github, - Logo: member.attributes.Logo, - Facebook: member.attributes.Facebook, - Instagram: member.attributes.Instagram, - createdAt: member.attributes.createdAt, - updatedAt: member.attributes.updatedAt, - locale: member.attributes.locale, - })) || []; - - // Map departments and assign members to their respective departments - const departments = - item.attributes.departments?.data.map((dept: any) => { - const departmentMembers = - dept.attributes.members?.data.map((member: any) => ({ - id: member.id, - Name: member.attributes.Name, - Task: member.attributes.Task, - Email: member.attributes.Email, - Linkedin: member.attributes.Linkedin, - Website: member.attributes.Website, - Github: member.attributes.Github, - Logo: member.attributes.Logo, - Facebook: member.attributes.Facebook, - Instagram: member.attributes.Instagram, - createdAt: member.attributes.createdAt, - updatedAt: member.attributes.updatedAt, - locale: member.attributes.locale, - })) || []; // Extract members for each department - - return { - id: dept.id, - Name: dept.attributes.Department, - members: departmentMembers, // Assign members to department - }; - }) || []; + const members = mapMembers(item.attributes.members?.data || []); + const departments = mapDepartments( + item.attributes.departments?.data || [], + strapiLocale, + ); return { id: item.id, - Name: item.attributes.Team, + name: item.attributes.Team || item.attributes.Name, createdAt: item.attributes.createdAt, updatedAt: item.attributes.updatedAt, - publishedAt: item.attributes.publishedAt, locale: item.attributes.locale, - members, // Team members (if no departments) - departments, // Departments and their members + members, + departments, }; }); - // Define custom ordering for both English and Finnish locales const orderEn = [ 'Game Design', 'Mentoring', @@ -141,15 +140,37 @@ export const fetchTeams = async (locale: string = 'en'): Promise => { 'Erityiskiitokset', ]; - // Select the correct order based on locale const order = locale === 'fi' ? orderFi : orderEn; - return teams.sort((a: Team, b: Team) => { - const indexA = order.indexOf(a.Name); - const indexB = order.indexOf(b.Name); - return indexA - indexB; - }); + return teams.sort( + (a: Team, b: Team) => order.indexOf(a.name) - order.indexOf(b.name), + ); + } catch (error) { + console.error('Error fetching teams data:', error); + return []; + } +}; + +// Fetch Departments independently if needed +export const fetchDepartments = async ( + locale: string = 'en', +): Promise => { + try { + const strapiLocale = locale === 'fi' ? 'fi-FI' : 'en'; + + const response = await fetch( + `${envHelper.strapiApiUrl}/departments?locale=${strapiLocale}&populate=*`, + ); + + if (!response.ok) { + throw new Error(`Error fetching departments: ${response.statusText}`); + } + + const departmentData = await response.json(); + + return mapDepartments(departmentData.data || [], strapiLocale); } catch (error) { - throw new Error('Error fetching teams data'); + console.error('Error fetching departments data:', error); + return []; } }; From b9402eb47befdd606b8898384e379cbebc2a8321 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Fri, 27 Sep 2024 22:21:55 +0300 Subject: [PATCH 30/74] fix translation --- .../SectionMembers/model/membersApi.ts | 41 ++++---------- .../SectionMembers/ui/SectionMembers.tsx | 56 ++++++++++--------- 2 files changed, 41 insertions(+), 56 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts index c3d8d1891..50573261c 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts +++ b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts @@ -54,6 +54,7 @@ const mapMembers = (membersData: any[]): Member[] => { ); }; +// Function to map departments // Function to map departments const mapDepartments = ( departmentsData: any[], @@ -61,11 +62,15 @@ const mapDepartments = ( ): Department[] => { return ( departmentsData.map((dept: any) => { - // Look for localized department name - const localizedDeptName = - dept.attributes.localizations?.data.find( - (loc: any) => loc.attributes.locale === locale, - )?.attributes.Department || dept.attributes.Department; + // Etsi lokalisoitu nimi 'Department'-kentästä + const localizedDept = dept.attributes.localizations?.data.find( + (loc: any) => loc.attributes.locale === locale, + ); + + // Käytä lokalisoitua nimeä, jos saatavilla, muuten oletus 'Department' + const localizedDeptName = localizedDept + ? localizedDept.attributes.Department // Tämä on lokalisoitu kenttä + : dept.attributes.Department; const members = mapMembers(dept.attributes.members?.data || []); @@ -84,7 +89,7 @@ export const fetchTeams = async (locale: string = 'en'): Promise => { const strapiLocale = locale === 'fi' ? 'fi-FI' : 'en'; const response = await fetch( - `${envHelper.strapiApiUrl}/teams?locale=${strapiLocale}&populate=departments.members,members`, + `${envHelper.strapiApiUrl}/teams?locale=${strapiLocale}&populate=departments.localizations,members`, ); if (!response.ok) { @@ -150,27 +155,3 @@ export const fetchTeams = async (locale: string = 'en'): Promise => { return []; } }; - -// Fetch Departments independently if needed -export const fetchDepartments = async ( - locale: string = 'en', -): Promise => { - try { - const strapiLocale = locale === 'fi' ? 'fi-FI' : 'en'; - - const response = await fetch( - `${envHelper.strapiApiUrl}/departments?locale=${strapiLocale}&populate=*`, - ); - - if (!response.ok) { - throw new Error(`Error fetching departments: ${response.statusText}`); - } - - const departmentData = await response.json(); - - return mapDepartments(departmentData.data || [], strapiLocale); - } catch (error) { - console.error('Error fetching departments data:', error); - return []; - } -}; diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx index fb4114a12..2f26d1f8a 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx @@ -7,8 +7,12 @@ import { classNames } from '@/shared/lib/classNames/classNames'; import { Container } from '@/shared/ui/Container'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faGlobe, faEnvelope } from '@fortawesome/free-solid-svg-icons'; -import { faGithub, faLinkedin } from '@fortawesome/free-brands-svg-icons'; -import { faInstagram, faFacebook } from '@fortawesome/free-brands-svg-icons'; +import { + faGithub, + faLinkedin, + faInstagram, + faFacebook, +} from '@fortawesome/free-brands-svg-icons'; import { openLinkInNewTab } from '@/shared/lib/openLinkInNewTab/openLinkInNewTab'; import { useClientTranslation } from '@/shared/i18n'; import Image from 'next/image'; @@ -18,47 +22,47 @@ const MemberItem: FC<{ member: Member }> = ({ member }) => (
  • - {member.Name} - {member.Task} + {member.name} + {member.task}
    - {member.Website && ( + {member.website && ( openLinkInNewTab(member.Website)} + onClick={() => openLinkInNewTab(member.website)} className={cls.clickableLogo}> )} - {member.Github && ( + {member.github && ( openLinkInNewTab(member.Github)} + onClick={() => openLinkInNewTab(member.github)} className={cls.clickableLogo}> )} - {member.Linkedin && ( + {member.linkedin && ( openLinkInNewTab(member.Linkedin)} + onClick={() => openLinkInNewTab(member.linkedin)} className={cls.clickableLogo}> )} - {member.Facebook && ( + {member.facebook && ( openLinkInNewTab(member.Facebook)} + onClick={() => openLinkInNewTab(member.facebook)} className={cls.clickableLogo}> )} - {member.Instagram && ( + {member.instagram && ( openLinkInNewTab(member.Instagram)} + onClick={() => openLinkInNewTab(member.instagram)} className={cls.clickableLogo}> )} - {member.Email && ( + {member.email && ( openLinkInNewTab(`mailto:${member.Email}`)} + onClick={() => openLinkInNewTab(`mailto:${member.email}`)} className={cls.clickableLogo}> @@ -66,10 +70,10 @@ const MemberItem: FC<{ member: Member }> = ({ member }) => (
    - {member.Logo && ( + {member.logo && ( {member.Name} = ({ className = '' }) => { const [teams, setTeams] = useState([]); const params = useParams(); - const lng = params.lng as string; + const lng = params.lng as string; // tämä on nyt lokaali, esim. 'fi-FI' const { t } = useClientTranslation(lng, 'team'); useEffect(() => { const fetchTeamsData = async () => { try { - const data = await fetchTeams(lng); + const data = await fetchTeams(lng); // Välitetään oikea lokaali setTeams(data); } catch (error) { console.error('Failed to fetch teams:', error); } }; fetchTeamsData(); - }, [lng]); + }, [lng]); // Locale varmistetaan, että päivitetään oikea lokaali return (
    @@ -109,14 +113,14 @@ export const SectionMembers: FC = ({ className = '' }) => { {teams.map((team) => (
    -

    {team.Name}

    +

    {team.name}

    - {/* Check if the team has departments */} + {/* Tarkista, onko osastoja */} {team.departments.length > 0 ? (
    {team.departments.map((department) => (
    -

    {department.Name}

    +

    {department.name}

    {/* Lokalisoitu osaston nimi */} {department.members.length > 0 && (
      {department.members.map((member) => ( @@ -128,7 +132,7 @@ export const SectionMembers: FC = ({ className = '' }) => { ))}
    ) : ( - // If no departments, render team members directly + // Jos ei osastoja, renderöi tiimin jäsenet suoraan
      {team.members.length > 0 && team.members.map((member: Member) => ( From cc7be3a9b48e05ab630f7f900583bc47d02db017 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Fri, 27 Sep 2024 23:23:12 +0300 Subject: [PATCH 31/74] fixing rendering problem --- .../SectionMembers/model/membersApi.ts | 22 +++++++++++-------- .../src/widgets/SectionMembers/model/types.ts | 10 +++++---- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts index 50573261c..0400e3b9c 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts +++ b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts @@ -54,7 +54,6 @@ const mapMembers = (membersData: any[]): Member[] => { ); }; -// Function to map departments // Function to map departments const mapDepartments = ( departmentsData: any[], @@ -62,21 +61,22 @@ const mapDepartments = ( ): Department[] => { return ( departmentsData.map((dept: any) => { - // Etsi lokalisoitu nimi 'Department'-kentästä + // Haetaan lokalisoitu osaston nimi 'localizations'-kentästä const localizedDept = dept.attributes.localizations?.data.find( - (loc: any) => loc.attributes.locale === locale, + (loc: any) => loc.attributes.locale === locale, // Tarkistetaan locale ); - // Käytä lokalisoitua nimeä, jos saatavilla, muuten oletus 'Department' + // Käytetään lokalisoitua nimeä, jos saatavilla, muuten oletus 'Department' const localizedDeptName = localizedDept - ? localizedDept.attributes.Department // Tämä on lokalisoitu kenttä - : dept.attributes.Department; + ? localizedDept.attributes.Name // Lokalisoidun nimen kenttä, tarkista että tämä kenttä on oikein + : dept.attributes.Name; // Oletuskenttä, jos ei lokalisaatiota + // Haetaan osaston jäsenet const members = mapMembers(dept.attributes.members?.data || []); return { id: dept.id, - name: localizedDeptName, + name: localizedDeptName, // Käytetään lokalisoitua nimeä members, }; }) || [] @@ -88,6 +88,7 @@ export const fetchTeams = async (locale: string = 'en'): Promise => { try { const strapiLocale = locale === 'fi' ? 'fi-FI' : 'en'; + // Hakee kaikki lokalisoidut tiedot osastoille ja jäsenille const response = await fetch( `${envHelper.strapiApiUrl}/teams?locale=${strapiLocale}&populate=departments.localizations,members`, ); @@ -98,16 +99,17 @@ export const fetchTeams = async (locale: string = 'en'): Promise => { const teamData = await response.json(); + // Kartoitus tiimit ja niiden osastot const teams: Team[] = teamData.data.map((item: any) => { const members = mapMembers(item.attributes.members?.data || []); const departments = mapDepartments( item.attributes.departments?.data || [], - strapiLocale, + strapiLocale, // Passataan locale tässä ); return { id: item.id, - name: item.attributes.Team || item.attributes.Name, + name: item.attributes.Team || item.attributes.Name, // Tarkistetaan tiimin nimi createdAt: item.attributes.createdAt, updatedAt: item.attributes.updatedAt, locale: item.attributes.locale, @@ -116,6 +118,7 @@ export const fetchTeams = async (locale: string = 'en'): Promise => { }; }); + // Järjestys osastoille englanniksi ja suomeksi const orderEn = [ 'Game Design', 'Mentoring', @@ -147,6 +150,7 @@ export const fetchTeams = async (locale: string = 'en'): Promise => { const order = locale === 'fi' ? orderFi : orderEn; + // Järjestetään tiimit ennalta määrätyssä järjestyksessä return teams.sort( (a: Team, b: Team) => order.indexOf(a.name) - order.indexOf(b.name), ); diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/types.ts b/frontend-next-migration/src/widgets/SectionMembers/model/types.ts index 87626f487..2aefaec55 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/model/types.ts +++ b/frontend-next-migration/src/widgets/SectionMembers/model/types.ts @@ -16,8 +16,8 @@ export interface Member { export interface Department { id: number; - name: string; // Changed from Name to name - members: Member[]; // Changed from Members to members + name: string; + members: Member[]; createdAt: string; updatedAt: string; locale: string; @@ -25,8 +25,10 @@ export interface Department { export interface Team { id: number; - team?: string; // Changed from Team to team - departments?: Department[]; // Changed from Departments to departments + name: string; // Pitää olla string, ei funktio + team?: string; // Voit jättää tämän optional-ominaisuudeksi, jos se ei ole pakollinen + departments?: Department[]; // Jos tiimillä on osastoja, tämä voi olla olemassa + members?: Member[]; // Lisää tämä, jos tiimillä voi olla jäseniä ilman osastoja createdAt: string; updatedAt: string; locale: string; From fdfa28834d338e39a390155869c1a6fcde153fff Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Fri, 27 Sep 2024 23:43:52 +0300 Subject: [PATCH 32/74] fix member location --- .../SectionMembers/ui/SectionMembers.tsx | 63 ++++++++++--------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx index 2f26d1f8a..75eabda93 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx @@ -17,7 +17,6 @@ import { openLinkInNewTab } from '@/shared/lib/openLinkInNewTab/openLinkInNewTab import { useClientTranslation } from '@/shared/i18n'; import Image from 'next/image'; -// MemberItem Component to Render a Single Member const MemberItem: FC<{ member: Member }> = ({ member }) => (
    • @@ -111,37 +110,43 @@ export const SectionMembers: FC = ({ className = '' }) => { text={t('playButton')} /> - {teams.map((team) => ( -
      -

      {team.name}

      + {teams.map((team) => { + // Käydään läpi tiimin jäsenet ja osastot + return ( +
      +

      {team.name}

      - {/* Tarkista, onko osastoja */} - {team.departments.length > 0 ? ( -
      - {team.departments.map((department) => ( -
      -

      {department.name}

      {/* Lokalisoitu osaston nimi */} - {department.members.length > 0 && ( -
        - {department.members.map((member) => ( - - ))} -
      - )} -
      - ))} -
      - ) : ( - // Jos ei osastoja, renderöi tiimin jäsenet suoraan -
        - {team.members.length > 0 && - team.members.map((member: Member) => ( + {/* Tarkistetaan, onko osastoja */} + {team.departments.length > 0 && ( +
        + {team.departments.map((department) => ( +
        +

        {department.name}

        {' '} + {/* Lokalisoitu osaston nimi */} + {/* Renderöidään osaston jäsenet */} + {department.members.length > 0 && ( +
          + {department.members.map((member: Member) => ( + + ))} +
        + )} +
        + ))} +
        + )} + + {/* Renderöidään tiimin jäsenet, jotka eivät kuulu osastoihin */} + {team.members.length > 0 && ( +
          + {team.members.map((member: Member) => ( ))} -
        - )} -
      - ))} +
    + )} +
    + ); + })}
    ); From b4e3a8b86b0a3b5a37ea7fa4d8b7eeb79bcb722a Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Sat, 28 Sep 2024 13:37:00 +0300 Subject: [PATCH 33/74] Fix incorrect rendering of members by ensuring proper assignment to departments - Modified `fetchTeams` to prevent members from being rendered both at the department and team levels. - Added logic to collect department member IDs and filter them out from team-level members. - Ensured that only department-less members are assigned to the team-level list. - Updated data mapping to correctly associate all members with their appropriate departments and prevent duplicates. --- .../SectionMembers/model/membersApi.ts | 48 ++++++++++++------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts index 0400e3b9c..9fc2d661a 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts +++ b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts @@ -54,30 +54,29 @@ const mapMembers = (membersData: any[]): Member[] => { ); }; -// Function to map departments +// Function to map departments and ensure the correct members are assigned const mapDepartments = ( departmentsData: any[], locale: string, ): Department[] => { return ( departmentsData.map((dept: any) => { - // Haetaan lokalisoitu osaston nimi 'localizations'-kentästä + // Find the localized name if available const localizedDept = dept.attributes.localizations?.data.find( - (loc: any) => loc.attributes.locale === locale, // Tarkistetaan locale + (loc: any) => loc.attributes.locale === locale, ); - // Käytetään lokalisoitua nimeä, jos saatavilla, muuten oletus 'Department' const localizedDeptName = localizedDept - ? localizedDept.attributes.Name // Lokalisoidun nimen kenttä, tarkista että tämä kenttä on oikein - : dept.attributes.Name; // Oletuskenttä, jos ei lokalisaatiota + ? localizedDept.attributes.Name + : dept.attributes.Name; - // Haetaan osaston jäsenet + // Map the members that are explicitly part of this department const members = mapMembers(dept.attributes.members?.data || []); return { id: dept.id, - name: localizedDeptName, // Käytetään lokalisoitua nimeä - members, + name: localizedDeptName, + members, // Explicitly assign members that belong to this department }; }) || [] ); @@ -88,9 +87,9 @@ export const fetchTeams = async (locale: string = 'en'): Promise => { try { const strapiLocale = locale === 'fi' ? 'fi-FI' : 'en'; - // Hakee kaikki lokalisoidut tiedot osastoille ja jäsenille + // Fetch data including localized departments and members const response = await fetch( - `${envHelper.strapiApiUrl}/teams?locale=${strapiLocale}&populate=departments.localizations,members`, + `${envHelper.strapiApiUrl}/teams?locale=${strapiLocale}&populate=departments.localizations,members,departments.members`, ); if (!response.ok) { @@ -99,17 +98,30 @@ export const fetchTeams = async (locale: string = 'en'): Promise => { const teamData = await response.json(); - // Kartoitus tiimit ja niiden osastot + // Map teams and assign their respective members and departments const teams: Team[] = teamData.data.map((item: any) => { - const members = mapMembers(item.attributes.members?.data || []); + // Map team-level members (members who are not part of any specific department) + let members = mapMembers(item.attributes.members?.data || []); + + // Map departments related to the team const departments = mapDepartments( item.attributes.departments?.data || [], - strapiLocale, // Passataan locale tässä + strapiLocale, + ); + + // Collect all member IDs that are assigned to departments + const departmentMemberIds = departments.flatMap((dept) => + dept.members.map((member) => member.id), + ); + + // Filter out members from team-level members that are already in a department + members = members.filter( + (member) => !departmentMemberIds.includes(member.id), ); return { id: item.id, - name: item.attributes.Team || item.attributes.Name, // Tarkistetaan tiimin nimi + name: item.attributes.Team || item.attributes.Name, createdAt: item.attributes.createdAt, updatedAt: item.attributes.updatedAt, locale: item.attributes.locale, @@ -118,13 +130,13 @@ export const fetchTeams = async (locale: string = 'en'): Promise => { }; }); - // Järjestys osastoille englanniksi ja suomeksi + // Order teams by predefined lists const orderEn = [ 'Game Design', 'Mentoring', - 'Sounds', 'Programming', 'Graphics', + 'Sounds', 'Comic book', 'Production', 'Analysis', @@ -150,7 +162,7 @@ export const fetchTeams = async (locale: string = 'en'): Promise => { const order = locale === 'fi' ? orderFi : orderEn; - // Järjestetään tiimit ennalta määrätyssä järjestyksessä + // Sort teams based on the order return teams.sort( (a: Team, b: Team) => order.indexOf(a.name) - order.indexOf(b.name), ); From 349538f67ab102f9e66fe2223ea2b82c81011c84 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Sat, 28 Sep 2024 13:43:21 +0300 Subject: [PATCH 34/74] refactor typing solution --- .../SectionMembers/model/membersApi.ts | 36 ++----------------- .../src/widgets/SectionMembers/model/types.ts | 16 ++++----- .../SectionMembers/ui/SectionMembers.tsx | 5 ++- 3 files changed, 13 insertions(+), 44 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts index 9fc2d661a..840806a6b 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts +++ b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts @@ -1,37 +1,5 @@ import { envHelper } from '@/shared/const/envHelper'; - -// Interfaces -export interface Member { - id: number; - name: string; - task?: string; - email?: string; - logo?: string; - website?: string; - github?: string; - linkedin?: string; - facebook?: string; - instagram?: string; - createdAt: string; - updatedAt: string; - locale: string; -} - -export interface Department { - id: number; - name: string; - members: Member[]; -} - -export interface Team { - id: number; - name: string; - createdAt: string; - updatedAt: string; - locale: string; - members: Member[]; - departments: Department[]; -} +import { Member, Department, Team } from '../model/types'; // Function to map members const mapMembers = (membersData: any[]): Member[] => { @@ -76,7 +44,7 @@ const mapDepartments = ( return { id: dept.id, name: localizedDeptName, - members, // Explicitly assign members that belong to this department + members, }; }) || [] ); diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/types.ts b/frontend-next-migration/src/widgets/SectionMembers/model/types.ts index 2aefaec55..1ee866aa2 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/model/types.ts +++ b/frontend-next-migration/src/widgets/SectionMembers/model/types.ts @@ -1,14 +1,16 @@ +// types.ts + export interface Member { id: number; - name: string; // Changed from Name to name + name: string; task?: string; email?: string; + logo?: string; website?: string; github?: string; linkedin?: string; facebook?: string; instagram?: string; - logo?: string; createdAt: string; updatedAt: string; locale: string; @@ -18,18 +20,14 @@ export interface Department { id: number; name: string; members: Member[]; - createdAt: string; - updatedAt: string; - locale: string; } export interface Team { id: number; - name: string; // Pitää olla string, ei funktio - team?: string; // Voit jättää tämän optional-ominaisuudeksi, jos se ei ole pakollinen - departments?: Department[]; // Jos tiimillä on osastoja, tämä voi olla olemassa - members?: Member[]; // Lisää tämä, jos tiimillä voi olla jäseniä ilman osastoja + name: string; createdAt: string; updatedAt: string; locale: string; + members: Member[]; + departments: Department[]; } diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx index 75eabda93..7755bbdd9 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx @@ -1,7 +1,8 @@ import cls from './SectionMembers.module.scss'; import { FC, useEffect, useState } from 'react'; import { useParams } from 'next/navigation'; -import { fetchTeams, Team, Member } from '../model/membersApi'; +import { fetchTeams } from '../model/membersApi'; +import { Team, Member } from '../model/types'; import { ScrollBottomButton } from '@/features/ScrollBottom'; import { classNames } from '@/shared/lib/classNames/classNames'; import { Container } from '@/shared/ui/Container'; @@ -17,6 +18,8 @@ import { openLinkInNewTab } from '@/shared/lib/openLinkInNewTab/openLinkInNewTab import { useClientTranslation } from '@/shared/i18n'; import Image from 'next/image'; +// Rest of the component code remains the same + const MemberItem: FC<{ member: Member }> = ({ member }) => (
  • From f938ff029b3e6d0ebe1b08b732cb3e3ed33fc9e1 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Sat, 28 Sep 2024 13:47:14 +0300 Subject: [PATCH 35/74] refactor api mapping and fetching functions --- .../widgets/SectionMembers/model/mappers.ts | 52 ++++++++++++++++++ .../SectionMembers/model/membersApi.ts | 54 ++----------------- 2 files changed, 56 insertions(+), 50 deletions(-) create mode 100644 frontend-next-migration/src/widgets/SectionMembers/model/mappers.ts diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/mappers.ts b/frontend-next-migration/src/widgets/SectionMembers/model/mappers.ts new file mode 100644 index 000000000..b6d2d2b47 --- /dev/null +++ b/frontend-next-migration/src/widgets/SectionMembers/model/mappers.ts @@ -0,0 +1,52 @@ +// mappers.ts + +import { Member, Department } from './types'; + +// Function to map members +export const mapMembers = (membersData: any[]): Member[] => { + return ( + membersData.map((member: any) => ({ + id: member.id, + name: member.attributes.Name, + task: member.attributes.Task, + email: member.attributes.Email, + linkedin: member.attributes.Linkedin, + website: member.attributes.Website, + github: member.attributes.Github, + logo: member.attributes.Logo, + facebook: member.attributes.Facebook, + instagram: member.attributes.Instagram, + createdAt: member.attributes.createdAt, + updatedAt: member.attributes.updatedAt, + locale: member.attributes.locale, + })) || [] + ); +}; + +// Function to map departments and ensure the correct members are assigned +export const mapDepartments = ( + departmentsData: any[], + locale: string, +): Department[] => { + return ( + departmentsData.map((dept: any) => { + // Find the localized name if available + const localizedDept = dept.attributes.localizations?.data.find( + (loc: any) => loc.attributes.locale === locale, + ); + + const localizedDeptName = localizedDept + ? localizedDept.attributes.Name + : dept.attributes.Name; + + // Map the members that are explicitly part of this department + const members = mapMembers(dept.attributes.members?.data || []); + + return { + id: dept.id, + name: localizedDeptName, + members, + }; + }) || [] + ); +}; diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts index 840806a6b..d8cdaa062 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts +++ b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts @@ -1,54 +1,8 @@ -import { envHelper } from '@/shared/const/envHelper'; -import { Member, Department, Team } from '../model/types'; - -// Function to map members -const mapMembers = (membersData: any[]): Member[] => { - return ( - membersData.map((member: any) => ({ - id: member.id, - name: member.attributes.Name, - task: member.attributes.Task, - email: member.attributes.Email, - linkedin: member.attributes.Linkedin, - website: member.attributes.Website, - github: member.attributes.Github, - logo: member.attributes.Logo, - facebook: member.attributes.Facebook, - instagram: member.attributes.Instagram, - createdAt: member.attributes.createdAt, - updatedAt: member.attributes.updatedAt, - locale: member.attributes.locale, - })) || [] - ); -}; - -// Function to map departments and ensure the correct members are assigned -const mapDepartments = ( - departmentsData: any[], - locale: string, -): Department[] => { - return ( - departmentsData.map((dept: any) => { - // Find the localized name if available - const localizedDept = dept.attributes.localizations?.data.find( - (loc: any) => loc.attributes.locale === locale, - ); - - const localizedDeptName = localizedDept - ? localizedDept.attributes.Name - : dept.attributes.Name; +// membersApi.ts - // Map the members that are explicitly part of this department - const members = mapMembers(dept.attributes.members?.data || []); - - return { - id: dept.id, - name: localizedDeptName, - members, - }; - }) || [] - ); -}; +import { envHelper } from '@/shared/const/envHelper'; +import { Member, Team } from '../model/types'; +import { mapMembers, mapDepartments } from '../model/mappers'; // Import mappers // Fetch Teams export const fetchTeams = async (locale: string = 'en'): Promise => { From b90d722ee5ccb69c2cadf592f911a426c535fe47 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Sat, 28 Sep 2024 13:50:37 +0300 Subject: [PATCH 36/74] refaactor memberItem and departmentItem for own files --- .../SectionMembers/ui/DepartmentItem.tsx | 23 +++ .../widgets/SectionMembers/ui/MemberItem.tsx | 81 ++++++++++ .../SectionMembers/ui/SectionMembers.tsx | 145 ++++-------------- 3 files changed, 131 insertions(+), 118 deletions(-) create mode 100644 frontend-next-migration/src/widgets/SectionMembers/ui/DepartmentItem.tsx create mode 100644 frontend-next-migration/src/widgets/SectionMembers/ui/MemberItem.tsx diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/DepartmentItem.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/DepartmentItem.tsx new file mode 100644 index 000000000..fd3a52e7c --- /dev/null +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/DepartmentItem.tsx @@ -0,0 +1,23 @@ +import { FC } from 'react'; +import { Department, Member } from '../model/types'; +import cls from './SectionMembers.module.scss'; +import MemberItem from './MemberItem'; + +interface DepartmentItemProps { + department: Department; +} + +const DepartmentItem: FC = ({ department }) => ( +
    +

    {department.name}

    + {department.members.length > 0 && ( +
      + {department.members.map((member: Member) => ( + + ))} +
    + )} +
    +); + +export default DepartmentItem; diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/MemberItem.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/MemberItem.tsx new file mode 100644 index 000000000..f5b144212 --- /dev/null +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/MemberItem.tsx @@ -0,0 +1,81 @@ +// MemberItem.tsx + +import { FC } from 'react'; +import { Member } from '../model/types'; +import cls from './SectionMembers.module.scss'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faGlobe, faEnvelope } from '@fortawesome/free-solid-svg-icons'; +import { + faGithub, + faLinkedin, + faInstagram, + faFacebook, +} from '@fortawesome/free-brands-svg-icons'; +import { openLinkInNewTab } from '@/shared/lib/openLinkInNewTab/openLinkInNewTab'; +import Image from 'next/image'; + +const MemberItem: FC<{ member: Member }> = ({ member }) => ( +
  • +
    +
    + {member.name} + {member.task} +
    + {member.website && ( + openLinkInNewTab(member.website)} + className={cls.clickableLogo}> + + + )} + {member.github && ( + openLinkInNewTab(member.github)} + className={cls.clickableLogo}> + + + )} + {member.linkedin && ( + openLinkInNewTab(member.linkedin)} + className={cls.clickableLogo}> + + + )} + {member.facebook && ( + openLinkInNewTab(member.facebook)} + className={cls.clickableLogo}> + + + )} + {member.instagram && ( + openLinkInNewTab(member.instagram)} + className={cls.clickableLogo}> + + + )} + {member.email && ( + openLinkInNewTab(`mailto:${member.email}`)} + className={cls.clickableLogo}> + + + )} +
    +
    +
    + {member.logo && ( + {member.name} + )} +
  • +); + +export default MemberItem; diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx index 7755bbdd9..96302e55c 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx @@ -1,89 +1,16 @@ +// SectionMembers.tsx + import cls from './SectionMembers.module.scss'; import { FC, useEffect, useState } from 'react'; import { useParams } from 'next/navigation'; import { fetchTeams } from '../model/membersApi'; -import { Team, Member } from '../model/types'; +import { Team } from '../model/types'; import { ScrollBottomButton } from '@/features/ScrollBottom'; import { classNames } from '@/shared/lib/classNames/classNames'; import { Container } from '@/shared/ui/Container'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { faGlobe, faEnvelope } from '@fortawesome/free-solid-svg-icons'; -import { - faGithub, - faLinkedin, - faInstagram, - faFacebook, -} from '@fortawesome/free-brands-svg-icons'; -import { openLinkInNewTab } from '@/shared/lib/openLinkInNewTab/openLinkInNewTab'; +import DepartmentItem from './DepartmentItem'; import { useClientTranslation } from '@/shared/i18n'; -import Image from 'next/image'; - -// Rest of the component code remains the same - -const MemberItem: FC<{ member: Member }> = ({ member }) => ( -
  • -
    -
    - {member.name} - {member.task} -
    - {member.website && ( - openLinkInNewTab(member.website)} - className={cls.clickableLogo}> - - - )} - {member.github && ( - openLinkInNewTab(member.github)} - className={cls.clickableLogo}> - - - )} - {member.linkedin && ( - openLinkInNewTab(member.linkedin)} - className={cls.clickableLogo}> - - - )} - {member.facebook && ( - openLinkInNewTab(member.facebook)} - className={cls.clickableLogo}> - - - )} - {member.instagram && ( - openLinkInNewTab(member.instagram)} - className={cls.clickableLogo}> - - - )} - {member.email && ( - openLinkInNewTab(`mailto:${member.email}`)} - className={cls.clickableLogo}> - - - )} -
    -
    -
    - {member.logo && ( - {member.name} - )} -
  • -); - +import MemberItem from './MemberItem'; interface WorkersSectionProps { className?: string; } @@ -91,20 +18,20 @@ interface WorkersSectionProps { export const SectionMembers: FC = ({ className = '' }) => { const [teams, setTeams] = useState([]); const params = useParams(); - const lng = params.lng as string; // tämä on nyt lokaali, esim. 'fi-FI' + const lng = params.lng as string; const { t } = useClientTranslation(lng, 'team'); useEffect(() => { const fetchTeamsData = async () => { try { - const data = await fetchTeams(lng); // Välitetään oikea lokaali + const data = await fetchTeams(lng); setTeams(data); } catch (error) { console.error('Failed to fetch teams:', error); } }; fetchTeamsData(); - }, [lng]); // Locale varmistetaan, että päivitetään oikea lokaali + }, [lng]); return (
    @@ -113,43 +40,25 @@ export const SectionMembers: FC = ({ className = '' }) => { text={t('playButton')} /> - {teams.map((team) => { - // Käydään läpi tiimin jäsenet ja osastot - return ( -
    -

    {team.name}

    - - {/* Tarkistetaan, onko osastoja */} - {team.departments.length > 0 && ( -
    - {team.departments.map((department) => ( -
    -

    {department.name}

    {' '} - {/* Lokalisoitu osaston nimi */} - {/* Renderöidään osaston jäsenet */} - {department.members.length > 0 && ( -
      - {department.members.map((member: Member) => ( - - ))} -
    - )} -
    - ))} -
    - )} - - {/* Renderöidään tiimin jäsenet, jotka eivät kuulu osastoihin */} - {team.members.length > 0 && ( -
      - {team.members.map((member: Member) => ( - - ))} -
    - )} -
    - ); - })} + {teams.map((team) => ( +
    +

    {team.name}

    + {team.departments.length > 0 && ( +
    + {team.departments.map((department) => ( + + ))} +
    + )} + {team.members.length > 0 && ( +
      + {team.members.map((member) => ( + + ))} +
    + )} +
    + ))}
    ); From 2eb04b1adfac29574931f3853512ab7c5dd4a13d Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Sat, 28 Sep 2024 21:41:26 +0300 Subject: [PATCH 37/74] Updated API call to include Logo for both department and team section members --- .../widgets/SectionMembers/model/mappers.ts | 41 ++++++++++--------- .../SectionMembers/model/membersApi.ts | 2 +- .../src/widgets/SectionMembers/model/types.ts | 11 +++-- 3 files changed, 31 insertions(+), 23 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/mappers.ts b/frontend-next-migration/src/widgets/SectionMembers/model/mappers.ts index b6d2d2b47..b8899f84a 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/model/mappers.ts +++ b/frontend-next-migration/src/widgets/SectionMembers/model/mappers.ts @@ -1,25 +1,28 @@ -// mappers.ts - import { Member, Department } from './types'; -// Function to map members export const mapMembers = (membersData: any[]): Member[] => { return ( - membersData.map((member: any) => ({ - id: member.id, - name: member.attributes.Name, - task: member.attributes.Task, - email: member.attributes.Email, - linkedin: member.attributes.Linkedin, - website: member.attributes.Website, - github: member.attributes.Github, - logo: member.attributes.Logo, - facebook: member.attributes.Facebook, - instagram: member.attributes.Instagram, - createdAt: member.attributes.createdAt, - updatedAt: member.attributes.updatedAt, - locale: member.attributes.locale, - })) || [] + membersData.map((member: any) => { + const logoUrl = member.attributes.Logo?.data?.attributes?.url + ? `${process.env.NEXT_PUBLIC_STRAPI_HOST}${member.attributes.Logo.data.attributes.url}` + : null; + + return { + id: member.id, + name: member.attributes.Name, + task: member.attributes.Task, + email: member.attributes.Email, + linkedin: member.attributes.Linkedin, + website: member.attributes.Website, + github: member.attributes.Github, + logo: logoUrl, + facebook: member.attributes.Facebook, + instagram: member.attributes.Instagram, + createdAt: member.attributes.createdAt, + updatedAt: member.attributes.updatedAt, + locale: member.attributes.locale, + }; + }) || [] ); }; @@ -39,7 +42,7 @@ export const mapDepartments = ( ? localizedDept.attributes.Name : dept.attributes.Name; - // Map the members that are explicitly part of this department + // Map the members that are explicitly part of this department, including logo information const members = mapMembers(dept.attributes.members?.data || []); return { diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts index d8cdaa062..c3c8b13d9 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts +++ b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts @@ -11,7 +11,7 @@ export const fetchTeams = async (locale: string = 'en'): Promise => { // Fetch data including localized departments and members const response = await fetch( - `${envHelper.strapiApiUrl}/teams?locale=${strapiLocale}&populate=departments.localizations,members,departments.members`, + `${envHelper.strapiApiUrl}/teams?locale=${strapiLocale}&populate=departments.localizations,members.Logo,departments.members.Logo`, ); if (!response.ok) { diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/types.ts b/frontend-next-migration/src/widgets/SectionMembers/model/types.ts index 1ee866aa2..ea4cb42fa 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/model/types.ts +++ b/frontend-next-migration/src/widgets/SectionMembers/model/types.ts @@ -1,11 +1,16 @@ -// types.ts - +export interface Logo { + data: { + attributes: { + url: string; + }; + } | null; +} export interface Member { id: number; name: string; task?: string; email?: string; - logo?: string; + logo?: string | null; website?: string; github?: string; linkedin?: string; From 7c22310b0695765bff5b9f2edcd7e909168bab42 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Sat, 28 Sep 2024 21:42:59 +0300 Subject: [PATCH 38/74] refactor move logo into icon container --- .../widgets/SectionMembers/ui/MemberItem.tsx | 129 +++++++++--------- 1 file changed, 66 insertions(+), 63 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/MemberItem.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/MemberItem.tsx index f5b144212..959e2244e 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/MemberItem.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/MemberItem.tsx @@ -1,5 +1,3 @@ -// MemberItem.tsx - import { FC } from 'react'; import { Member } from '../model/types'; import cls from './SectionMembers.module.scss'; @@ -14,68 +12,73 @@ import { import { openLinkInNewTab } from '@/shared/lib/openLinkInNewTab/openLinkInNewTab'; import Image from 'next/image'; -const MemberItem: FC<{ member: Member }> = ({ member }) => ( -
  • -
    -
    - {member.name} - {member.task} -
    - {member.website && ( - openLinkInNewTab(member.website)} - className={cls.clickableLogo}> - - - )} - {member.github && ( - openLinkInNewTab(member.github)} - className={cls.clickableLogo}> - - - )} - {member.linkedin && ( - openLinkInNewTab(member.linkedin)} - className={cls.clickableLogo}> - - - )} - {member.facebook && ( - openLinkInNewTab(member.facebook)} - className={cls.clickableLogo}> - - - )} - {member.instagram && ( - openLinkInNewTab(member.instagram)} - className={cls.clickableLogo}> - - - )} - {member.email && ( - openLinkInNewTab(`mailto:${member.email}`)} - className={cls.clickableLogo}> - - - )} +const MemberItem: FC<{ member: Member }> = ({ member }) => { + return ( +
  • +
    +
    + {member.name} + {member.task} +
    + {member.logo ? ( + {member.name} + ) : ( + // Renderoi paikkakuva, jos logoa ei ole +
    No Image
    + )} + {member.website && ( + openLinkInNewTab(member.website)} + className={cls.clickableLogo}> + + + )} + {member.github && ( + openLinkInNewTab(member.github)} + className={cls.clickableLogo}> + + + )} + {member.linkedin && ( + openLinkInNewTab(member.linkedin)} + className={cls.clickableLogo}> + + + )} + {member.facebook && ( + openLinkInNewTab(member.facebook)} + className={cls.clickableLogo}> + + + )} + {member.instagram && ( + openLinkInNewTab(member.instagram)} + className={cls.clickableLogo}> + + + )} + {member.email && ( + openLinkInNewTab(`mailto:${member.email}`)} + className={cls.clickableLogo}> + + + )} +
    -
  • - {member.logo && ( - {member.name} - )} - -); + + ); +}; export default MemberItem; From 14e19eb61fa56f780158e1ba2e1c97b926fe7506 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Sat, 28 Sep 2024 21:54:33 +0300 Subject: [PATCH 39/74] refactor: clean up and add detailed documentation for Strapi mapping, sorting, and fetching functions --- .../widgets/SectionMembers/model/mappers.ts | 32 +++++++++++-- .../SectionMembers/model/membersApi.ts | 48 +++++++++++++++---- .../src/widgets/SectionMembers/model/types.ts | 8 ++++ .../SectionMembers/ui/DepartmentItem.tsx | 7 +++ .../widgets/SectionMembers/ui/MemberItem.tsx | 9 ++-- .../SectionMembers/ui/SectionMembers.tsx | 18 ++++++- 6 files changed, 103 insertions(+), 19 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/mappers.ts b/frontend-next-migration/src/widgets/SectionMembers/model/mappers.ts index b8899f84a..97c234ed3 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/model/mappers.ts +++ b/frontend-next-migration/src/widgets/SectionMembers/model/mappers.ts @@ -1,8 +1,24 @@ +// mappers.ts + +/** + * This file contains mapping functions used to transform data from the API response + * into a format that matches the application's data models. + * It includes functions for mapping members and departments. + */ + import { Member, Department } from './types'; +/** + * Maps raw member data from the API response to the Member type used in the application. + * @param membersData An array of raw member data from the API. + * @returns An array of members mapped to the Member type. + */ export const mapMembers = (membersData: any[]): Member[] => { return ( membersData.map((member: any) => { + /** + * Construct the logo URL if logo data is available + */ const logoUrl = member.attributes.Logo?.data?.attributes?.url ? `${process.env.NEXT_PUBLIC_STRAPI_HOST}${member.attributes.Logo.data.attributes.url}` : null; @@ -26,14 +42,22 @@ export const mapMembers = (membersData: any[]): Member[] => { ); }; -// Function to map departments and ensure the correct members are assigned +/** + * Maps raw department data from the API response to the Department type used in the application. + * It ensures that the correct members are assigned to each department. + * @param departmentsData An array of raw department data from the API. + * @param locale The language locale used to find the localized department name. + * @returns An array of departments mapped to the Department type. + */ export const mapDepartments = ( departmentsData: any[], locale: string, ): Department[] => { return ( departmentsData.map((dept: any) => { - // Find the localized name if available + /** + * Find the localized name if available, otherwise use the default name + */ const localizedDept = dept.attributes.localizations?.data.find( (loc: any) => loc.attributes.locale === locale, ); @@ -42,7 +66,9 @@ export const mapDepartments = ( ? localizedDept.attributes.Name : dept.attributes.Name; - // Map the members that are explicitly part of this department, including logo information + /** + * Map the members that are explicitly part of this department, including logo information + */ const members = mapMembers(dept.attributes.members?.data || []); return { diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts index c3c8b13d9..df7264470 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts +++ b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts @@ -1,15 +1,29 @@ // membersApi.ts +/** + * This file provides API functions related to fetching team data, including members and departments. + * It handles fetching data from Strapi, mapping the data to the correct types, and sorting teams accordingly. + */ + import { envHelper } from '@/shared/const/envHelper'; import { Member, Team } from '../model/types'; -import { mapMembers, mapDepartments } from '../model/mappers'; // Import mappers +import { mapMembers, mapDepartments } from '../model/mappers'; -// Fetch Teams +/** + * Fetches a list of teams, including their members and departments, from the Strapi API. + * @param locale The language locale to be used for fetching data. Defaults to 'en'. + * @returns A Promise that resolves to an array of teams. + */ export const fetchTeams = async (locale: string = 'en'): Promise => { try { + /** + * Determine the Strapi locale based on the input locale + */ const strapiLocale = locale === 'fi' ? 'fi-FI' : 'en'; - // Fetch data including localized departments and members + /** + * Fetch data including localized departments and members with their logos + */ const response = await fetch( `${envHelper.strapiApiUrl}/teams?locale=${strapiLocale}&populate=departments.localizations,members.Logo,departments.members.Logo`, ); @@ -20,23 +34,33 @@ export const fetchTeams = async (locale: string = 'en'): Promise => { const teamData = await response.json(); - // Map teams and assign their respective members and departments + /** + * Map teams and assign their respective members and departments + */ const teams: Team[] = teamData.data.map((item: any) => { - // Map team-level members (members who are not part of any specific department) + /** + * Map team-level members (members who are not part of any specific department) + */ let members = mapMembers(item.attributes.members?.data || []); - // Map departments related to the team + /** + * Map departments related to the team + */ const departments = mapDepartments( item.attributes.departments?.data || [], strapiLocale, ); - // Collect all member IDs that are assigned to departments + /** + * Collect all member IDs that are assigned to departments + */ const departmentMemberIds = departments.flatMap((dept) => dept.members.map((member) => member.id), ); - // Filter out members from team-level members that are already in a department + /** + * Filter out members from team-level members that are already in a department + */ members = members.filter( (member) => !departmentMemberIds.includes(member.id), ); @@ -52,7 +76,9 @@ export const fetchTeams = async (locale: string = 'en'): Promise => { }; }); - // Order teams by predefined lists + /** + * Define the order for teams based on the locale + */ const orderEn = [ 'Game Design', 'Mentoring', @@ -84,7 +110,9 @@ export const fetchTeams = async (locale: string = 'en'): Promise => { const order = locale === 'fi' ? orderFi : orderEn; - // Sort teams based on the order + /** + * Sort teams based on the predefined order + */ return teams.sort( (a: Team, b: Team) => order.indexOf(a.name) - order.indexOf(b.name), ); diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/types.ts b/frontend-next-migration/src/widgets/SectionMembers/model/types.ts index ea4cb42fa..3e9d0e79f 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/model/types.ts +++ b/frontend-next-migration/src/widgets/SectionMembers/model/types.ts @@ -1,3 +1,10 @@ +// types.ts + +/** + * This file contains TypeScript interfaces that represent the structure of various entities + * used throughout the application, such as Member, Department, Team, and Logo. + */ + export interface Logo { data: { attributes: { @@ -5,6 +12,7 @@ export interface Logo { }; } | null; } + export interface Member { id: number; name: string; diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/DepartmentItem.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/DepartmentItem.tsx index fd3a52e7c..d22e9a49d 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/DepartmentItem.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/DepartmentItem.tsx @@ -3,10 +3,17 @@ import { Department, Member } from '../model/types'; import cls from './SectionMembers.module.scss'; import MemberItem from './MemberItem'; +/** + * Props for the DepartmentItem component. + */ interface DepartmentItemProps { department: Department; } +/** + * DepartmentItem component displays information about a specific department. + * It includes the department's name and a list of members in that department. + */ const DepartmentItem: FC = ({ department }) => (

    {department.name}

    diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/MemberItem.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/MemberItem.tsx index 959e2244e..db9e9e720 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/MemberItem.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/MemberItem.tsx @@ -12,6 +12,10 @@ import { import { openLinkInNewTab } from '@/shared/lib/openLinkInNewTab/openLinkInNewTab'; import Image from 'next/image'; +/** + * MemberItem component displays information about a specific member. + * It includes member's name, task, logo, and relevant links like website, GitHub, LinkedIn, etc. + */ const MemberItem: FC<{ member: Member }> = ({ member }) => { return (
  • @@ -20,7 +24,7 @@ const MemberItem: FC<{ member: Member }> = ({ member }) => { {member.name} {member.task}
    - {member.logo ? ( + {member.logo && ( {member.name} = ({ member }) => { width={35} height={35} /> - ) : ( - // Renderoi paikkakuva, jos logoa ei ole -
    No Image
    )} {member.website && ( = ({ className = '' }) => { const [teams, setTeams] = useState([]); const params = useParams(); const lng = params.lng as string; const { t } = useClientTranslation(lng, 'team'); + { + /*Fetch team data when the language changes*/ + } useEffect(() => { const fetchTeamsData = async () => { try { @@ -35,14 +44,18 @@ export const SectionMembers: FC = ({ className = '' }) => { return (
    + {/* Scroll button to go to the bottom of the page */} + {/* Container to hold the list of teams */} {teams.map((team) => (
    + {/* Render team name */}

    {team.name}

    + {/* Render departments within the team */} {team.departments.length > 0 && (
    {team.departments.map((department) => ( @@ -50,6 +63,7 @@ export const SectionMembers: FC = ({ className = '' }) => { ))}
    )} + {/* Render members that do not belong to any department */} {team.members.length > 0 && (
      {team.members.map((member) => ( From 6582c1b6068598764421961d9570e873ddf46f5a Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Sat, 28 Sep 2024 23:57:02 +0300 Subject: [PATCH 40/74] add styling for membersSection --- .../MembersPage/ui/MembersPage.module.scss | 15 +-- .../widgets/SectionMembers/ui/MemberItem.tsx | 23 ++-- .../ui/SectionMembers.module.scss | 109 +++++++++++------- 3 files changed, 86 insertions(+), 61 deletions(-) diff --git a/frontend-next-migration/src/preparedPages/MembersPage/ui/MembersPage.module.scss b/frontend-next-migration/src/preparedPages/MembersPage/ui/MembersPage.module.scss index 8911cd04d..d876c9b39 100644 --- a/frontend-next-migration/src/preparedPages/MembersPage/ui/MembersPage.module.scss +++ b/frontend-next-migration/src/preparedPages/MembersPage/ui/MembersPage.module.scss @@ -1,10 +1,7 @@ -.MembersPage{ - +.MembersPage { } - - -.backgroundOpacity{ +.backgroundOpacity { z-index: 1; position: fixed !important; width: 100%; @@ -12,22 +9,20 @@ pointer-events: none; } -.workersSection{ +.workersSection { padding-top: 200px; z-index: 2; @media only screen and (min-width: 1921px) { * { - font-size: xxx-large!important; + font-size: xxx-large !important; } //h1{ // font-size: xxx-large!important; //} } - } -.wholePageBG{ +.wholePageBG { filter: brightness(85%); } - diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/MemberItem.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/MemberItem.tsx index db9e9e720..7af1eef47 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/MemberItem.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/MemberItem.tsx @@ -24,15 +24,20 @@ const MemberItem: FC<{ member: Member }> = ({ member }) => { {member.name} {member.task}
      - {member.logo && ( - {member.name} - )} + {/* Render logo if available, otherwise render an empty placeholder */} +
      + {member.logo ? ( + {member.name} + ) : ( +
      + )} +
      {member.website && ( openLinkInNewTab(member.website)} diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss index d623517ef..51b6ac4de 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss @@ -11,8 +11,7 @@ } .membersListContainer { - padding: 1rem 2rem; - font-size: clamp(20px, 3vw, 30px); + font-size: clamp(10px, 3vw, 40px); font-family: var(--font-family-main); text-align: start; background-color: rgba(0, 0, 0, 0.55); @@ -20,18 +19,14 @@ h1 { text-transform: uppercase; - font-size: clamp( - 20px, - 3vw, - 30px - ); /* Yhdistetty kahden h1 tyylin fonttikoko */ + font-size: clamp(20px, 3vw, 30px); /* Muuntuva fonttikoko */ color: var(--secondary-color); text-align: start; background-color: transparent; /* Tausta poistettu */ } h2 { - font-size: clamp(20px, 3vw, 50px); + font-size: clamp(20px, 3vw, 30px); /* Muuntuva fonttikoko */ line-height: 1.5; color: var(--secondary-color); text-align: center; @@ -41,74 +36,104 @@ .workmanComponent { display: flex; flex-direction: column; - width: 100%; - margin-bottom: 15px; - padding-left: 20%; - padding-right: 20%; + margin: 5px; .memberRow { display: flex; - justify-content: space-between; - align-items: center; - gap: 10px; width: 100%; padding: 10px 0; - } + gap: 10px; - .centerContainer { - display: flex; - justify-content: center; - gap: 1rem; - flex: 2; - } + .memberName { + font-weight: bold; + font-size: clamp(0.8rem, 2.5vw, 3rem); /* Muuntuva fonttikoko */ + text-align: left; + flex-grow: 3; /* Yhdenmukainen arvo taskText:in kanssa */ + min-width: 0; /* Sallii kutistumisen */ + } - .memberName { - font-weight: bold; - font-size: 1rem; - text-align: right; /* Aseta teksti oikealle */ - direction: rtl; /* Aseta teksti virtaamaan oikealta vasemmalle */ - } + .taskText { + font-size: clamp(0.8rem, 2.5vw, 2rem); /* Muuntuva fonttikoko */ + text-align: left; + flex-grow: 2; + padding: 0 5px; /* Pienennä täytettä pienten näyttöjen osalta */ + min-width: 0; /* Sallii kutistumisen */ + justify-self: start; + } - .taskText { - font-size: 1rem; - color: white; - text-align: center; - flex: 1; + .iconContainer { + display: flex; + gap: 1rem; /* Pienennä gap-pienillä näytöillä */ + align-items: center; + flex-grow: 1; + min-width: 0; /* Sallii kutistumisen */ + } } - .iconContainer { + .centerContainer { display: flex; - gap: 1rem; - justify-content: flex-end; - align-items: center; + flex: 2; + align-items: start; } .clickableLogo { color: var(--secondary-color); cursor: pointer; + font-size: clamp(1rem, 3vw, 5rem); /* Muuntuva fonttikoko */ @include link-scale-effect('icon'); } - .memberLogo { + .LogoWrapper { + width: clamp( + 50px, + 5vw, + 40px + ); /* Leveys on vähintään 20px, enintään 50px, ja 5vw välillä */ + height: auto; + cursor: pointer; @include link-scale-effect('icon'); - size: inherit; - margin-top: 10px; + + .placeholderLogo { + width: 100%; + height: 100%; + background-color: rgba(200, 200, 200, 0.3); /* Placeholder väri */ + border-radius: 50%; /* Sama muoto kuin logo */ + } } } .memberCard { - padding: 1rem; + padding: 3rem; margin-bottom: 1rem; + font-size: clamp(1rem, 2vw, 1.5rem); /* Muuntuva fonttikoko */ border-radius: var(--border-radius-custom); } .departmentsSection { margin-top: 1rem; - padding-left: 1rem; + font-size: clamp(1rem, 2vw, 1.5rem); /* Muuntuva fonttikoko */ } .departmentCard { padding: 0.5rem; margin-bottom: 1rem; + font-size: clamp(0.8rem, 2vw, 1.2rem); /* Muuntuva fonttikoko */ border-radius: var(--border-radius-custom); } + +@media screen and (min-width: 1024px) { + .MembersSection { + padding-left: 5rem; + padding-right: 5rem; + } + + .membersListContainer { + padding-left: 2.5rem; + padding-right: 2.5rem; + } + + .workmanComponent { + padding-left: 2.5rem; + padding-right: 2.5rem; + } +} From 443ccfc440bde695de23925a895fe75291f82dc5 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Mon, 30 Sep 2024 13:39:59 +0300 Subject: [PATCH 41/74] Rename logowrapper and adjust measurements --- .../src/widgets/SectionMembers/ui/MemberItem.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/MemberItem.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/MemberItem.tsx index 7af1eef47..2652473c5 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/MemberItem.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/MemberItem.tsx @@ -11,6 +11,8 @@ import { } from '@fortawesome/free-brands-svg-icons'; import { openLinkInNewTab } from '@/shared/lib/openLinkInNewTab/openLinkInNewTab'; import Image from 'next/image'; +import { ClickableBorder } from '@/shared/ui/ClickableBorder'; +import { classNames } from '../../../shared/lib/classNames/classNames'; /** * MemberItem component displays information about a specific member. @@ -25,14 +27,14 @@ const MemberItem: FC<{ member: Member }> = ({ member }) => { {member.task}
      {/* Render logo if available, otherwise render an empty placeholder */} -
      +
      {member.logo ? ( {member.name} ) : (
      From 558a14d863866a0588edb1d59ff9a1021ee7a470 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Mon, 30 Sep 2024 13:43:21 +0300 Subject: [PATCH 42/74] Add new styling for team page --- .../ui/SectionMembers.module.scss | 138 ++++++++---------- 1 file changed, 61 insertions(+), 77 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss index 51b6ac4de..6324448ff 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss @@ -4,6 +4,9 @@ justify-items: center; user-select: none; } +.MembersSection li { + list-style-type: none; +} .scrollBottomButton { margin-bottom: 10px; @@ -11,129 +14,110 @@ } .membersListContainer { - font-size: clamp(10px, 3vw, 40px); + font-size: clamp(0.5rem, 3vw, 1.7rem); font-family: var(--font-family-main); - text-align: start; background-color: rgba(0, 0, 0, 0.55); border-radius: var(--border-radius-custom); + padding: 0.7rem; h1 { text-transform: uppercase; - font-size: clamp(20px, 3vw, 30px); /* Muuntuva fonttikoko */ color: var(--secondary-color); text-align: start; - background-color: transparent; /* Tausta poistettu */ + padding-left: 3rem; + padding-bottom: 1rem; + background-color: transparent; } h2 { - font-size: clamp(20px, 3vw, 30px); /* Muuntuva fonttikoko */ - line-height: 1.5; color: var(--secondary-color); text-align: center; + font-size: clamp(0.5rem, 3vw, 2rem); + padding-bottom: 0.8rem; + padding-right: 6rem; } } -.workmanComponent { +.memberRow { display: flex; - flex-direction: column; - margin: 5px; + width: 100%; + justify-content: space-between; + + .memberName { + font-weight: bold; + text-align: right; // Kohdistetaan nimi oikealle reunaan + flex: 2; // Antaa nimelle enemmän tilaa + min-width: 0; + padding-right: 2rem; // Poistettu ylimääräinen padding-top + align-self: center; // Keskitetään nimi pystysuunnassa + display: flex; + justify-content: flex-end; // Kohdistaa sisällön oikeaan reunaan + } + + .taskText { + text-align: left; + flex: 2; // Jättää tehtävälle vähemmän tilaa kuin nimelle + min-width: 0; + } - .memberRow { + .iconContainer { display: flex; - width: 100%; - padding: 10px 0; - gap: 10px; - - .memberName { - font-weight: bold; - font-size: clamp(0.8rem, 2.5vw, 3rem); /* Muuntuva fonttikoko */ - text-align: left; - flex-grow: 3; /* Yhdenmukainen arvo taskText:in kanssa */ - min-width: 0; /* Sallii kutistumisen */ - } - - .taskText { - font-size: clamp(0.8rem, 2.5vw, 2rem); /* Muuntuva fonttikoko */ - text-align: left; - flex-grow: 2; - padding: 0 5px; /* Pienennä täytettä pienten näyttöjen osalta */ - min-width: 0; /* Sallii kutistumisen */ - justify-self: start; - } - - .iconContainer { - display: flex; - gap: 1rem; /* Pienennä gap-pienillä näytöillä */ - align-items: center; - flex-grow: 1; - min-width: 0; /* Sallii kutistumisen */ - } + gap: 0.5rem; + align-items: center; // Kohdistaa ikonit keskelle pystysuunnassa + justify-content: center; + flex: 1; // Sama tila kuin taskText + min-width: 0; + align-self: center; // Keskitetään ikonit pystysuunnassa } .centerContainer { display: flex; flex: 2; - align-items: start; } .clickableLogo { color: var(--secondary-color); cursor: pointer; - font-size: clamp(1rem, 3vw, 5rem); /* Muuntuva fonttikoko */ @include link-scale-effect('icon'); } - .LogoWrapper { - width: clamp( - 50px, - 5vw, - 40px - ); /* Leveys on vähintään 20px, enintään 50px, ja 5vw välillä */ - height: auto; + .memberLogo { + width: clamp(0.5rem, 3vw, 2rem); // Kasvatetaan logon kokoa + height: clamp(0.5rem, 3vw, 2rem); + border-radius: 50%; // Varmistetaan pyöreys + overflow: hidden; // Varmistaa, että logo pysyy pyöreänä myös piilotettuna + @include link-scale-effect('icon'); + } + + .Logo { + width: 100%; + height: 100%; + object-fit: cover; // Täyttää säiliön sekä korkeuden että leveyden osalta + border-radius: 50%; // Pitää logon pyöreänä cursor: pointer; @include link-scale-effect('icon'); + background-color: var(--secondary-color); + } - .placeholderLogo { - width: 100%; - height: 100%; - background-color: rgba(200, 200, 200, 0.3); /* Placeholder väri */ - border-radius: 50%; /* Sama muoto kuin logo */ - } + .placeholderLogo { + width: 100%; + height: 100%; + opacity: 0; // Täysin läpinäkyvä + border-radius: 50%; + @include link-scale-effect('icon'); } } .memberCard { - padding: 3rem; - margin-bottom: 1rem; - font-size: clamp(1rem, 2vw, 1.5rem); /* Muuntuva fonttikoko */ + padding-bottom: 2rem; border-radius: var(--border-radius-custom); } .departmentsSection { margin-top: 1rem; - font-size: clamp(1rem, 2vw, 1.5rem); /* Muuntuva fonttikoko */ } .departmentCard { - padding: 0.5rem; - margin-bottom: 1rem; - font-size: clamp(0.8rem, 2vw, 1.2rem); /* Muuntuva fonttikoko */ + padding-bottom: 2rem; border-radius: var(--border-radius-custom); } - -@media screen and (min-width: 1024px) { - .MembersSection { - padding-left: 5rem; - padding-right: 5rem; - } - - .membersListContainer { - padding-left: 2.5rem; - padding-right: 2.5rem; - } - - .workmanComponent { - padding-left: 2.5rem; - padding-right: 2.5rem; - } -} From 3865aa604e0f63d790309ef9f413d1e48f98166e Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Tue, 1 Oct 2024 09:05:04 +0300 Subject: [PATCH 43/74] Add alphabetic arrange for members --- .../widgets/SectionMembers/model/mappers.ts | 84 +++++++++---------- 1 file changed, 40 insertions(+), 44 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/mappers.ts b/frontend-next-migration/src/widgets/SectionMembers/model/mappers.ts index 97c234ed3..8f8f40680 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/model/mappers.ts +++ b/frontend-next-migration/src/widgets/SectionMembers/model/mappers.ts @@ -10,41 +10,41 @@ import { Member, Department } from './types'; /** * Maps raw member data from the API response to the Member type used in the application. + * Sorts members alphabetically by name. * @param membersData An array of raw member data from the API. * @returns An array of members mapped to the Member type. */ export const mapMembers = (membersData: any[]): Member[] => { return ( - membersData.map((member: any) => { - /** - * Construct the logo URL if logo data is available - */ - const logoUrl = member.attributes.Logo?.data?.attributes?.url - ? `${process.env.NEXT_PUBLIC_STRAPI_HOST}${member.attributes.Logo.data.attributes.url}` - : null; + membersData + .map((member: any) => { + const logoUrl = member.attributes.Logo?.data?.attributes?.url + ? `${process.env.NEXT_PUBLIC_STRAPI_HOST}${member.attributes.Logo.data.attributes.url}` + : null; - return { - id: member.id, - name: member.attributes.Name, - task: member.attributes.Task, - email: member.attributes.Email, - linkedin: member.attributes.Linkedin, - website: member.attributes.Website, - github: member.attributes.Github, - logo: logoUrl, - facebook: member.attributes.Facebook, - instagram: member.attributes.Instagram, - createdAt: member.attributes.createdAt, - updatedAt: member.attributes.updatedAt, - locale: member.attributes.locale, - }; - }) || [] + return { + id: member.id, + name: member.attributes.Name, + task: member.attributes.Task, + email: member.attributes.Email, + linkedin: member.attributes.Linkedin, + website: member.attributes.Website, + github: member.attributes.Github, + logo: logoUrl, + facebook: member.attributes.Facebook, + instagram: member.attributes.Instagram, + createdAt: member.attributes.createdAt, + updatedAt: member.attributes.updatedAt, + locale: member.attributes.locale, + }; + }) + .sort((a, b) => a.name.localeCompare(b.name)) || [] ); }; /** * Maps raw department data from the API response to the Department type used in the application. - * It ensures that the correct members are assigned to each department. + * Ensures that departments are sorted alphabetically by their localized or default names. * @param departmentsData An array of raw department data from the API. * @param locale The language locale used to find the localized department name. * @returns An array of departments mapped to the Department type. @@ -54,28 +54,24 @@ export const mapDepartments = ( locale: string, ): Department[] => { return ( - departmentsData.map((dept: any) => { - /** - * Find the localized name if available, otherwise use the default name - */ - const localizedDept = dept.attributes.localizations?.data.find( - (loc: any) => loc.attributes.locale === locale, - ); + departmentsData + .map((dept: any) => { + const localizedDept = dept.attributes.localizations?.data.find( + (loc: any) => loc.attributes.locale === locale, + ); - const localizedDeptName = localizedDept - ? localizedDept.attributes.Name - : dept.attributes.Name; + const localizedDeptName = localizedDept + ? localizedDept.attributes.Name + : dept.attributes.Name; - /** - * Map the members that are explicitly part of this department, including logo information - */ - const members = mapMembers(dept.attributes.members?.data || []); + const members = mapMembers(dept.attributes.members?.data || []); - return { - id: dept.id, - name: localizedDeptName, - members, - }; - }) || [] + return { + id: dept.id, + name: localizedDeptName, + members, + }; + }) + .sort((a, b) => a.name.localeCompare(b.name)) || [] ); }; From 62709962d2fcf0230de89b07c7fce7921ebb29f6 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Tue, 1 Oct 2024 09:29:55 +0300 Subject: [PATCH 44/74] Add sorting for departments --- .../widgets/SectionMembers/model/mappers.ts | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/mappers.ts b/frontend-next-migration/src/widgets/SectionMembers/model/mappers.ts index 8f8f40680..216837caa 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/model/mappers.ts +++ b/frontend-next-migration/src/widgets/SectionMembers/model/mappers.ts @@ -53,6 +53,31 @@ export const mapDepartments = ( departmentsData: any[], locale: string, ): Department[] => { + // Määritä järjestys osastoille + const orderEn = [ + 'Lead Developers', + 'Game Developer', + 'Website Developer', + 'Developers', + 'Graphics', + 'Graphical Game Development', + 'Sound Design & Composition', + 'Sound Design-Oriented Game Development', + ]; + + const orderFi = [ + 'Vastaava Ohjelmistokehittäjä', + 'Pelikehittäjä', + 'Verkkosivukehittäjä', + 'Ohjelmistokehittäjät', + 'Grafiikka', + 'Graafinen pelikehitys', + 'Äänisuunnittelu ja Sävellys', + 'Äänisuunnittelullinen Pelikehitys', + ]; + + const order = locale === 'fi' ? orderFi : orderEn; + return ( departmentsData .map((dept: any) => { @@ -72,6 +97,6 @@ export const mapDepartments = ( members, }; }) - .sort((a, b) => a.name.localeCompare(b.name)) || [] + .sort((a, b) => order.indexOf(a.name) - order.indexOf(b.name)) || [] ); }; From ce667e0169f8f55559e0f8fc32bd09a99524f227 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Tue, 1 Oct 2024 09:32:31 +0300 Subject: [PATCH 45/74] department section documentation --- .../src/widgets/SectionMembers/model/mappers.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/mappers.ts b/frontend-next-migration/src/widgets/SectionMembers/model/mappers.ts index 216837caa..9fc87d3a1 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/model/mappers.ts +++ b/frontend-next-migration/src/widgets/SectionMembers/model/mappers.ts @@ -44,16 +44,16 @@ export const mapMembers = (membersData: any[]): Member[] => { /** * Maps raw department data from the API response to the Department type used in the application. - * Ensures that departments are sorted alphabetically by their localized or default names. + * Sorts departments based on a predefined order depending on the locale. * @param departmentsData An array of raw department data from the API. * @param locale The language locale used to find the localized department name. * @returns An array of departments mapped to the Department type. */ + export const mapDepartments = ( departmentsData: any[], locale: string, ): Department[] => { - // Määritä järjestys osastoille const orderEn = [ 'Lead Developers', 'Game Developer', From 2bddc5d30d6011b1737ab18c68a810703995dc85 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Thu, 3 Oct 2024 19:58:14 +0300 Subject: [PATCH 46/74] Remove unnecessery comments add padding Add icon aling to end --- .../ui/SectionMembers.module.scss | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss index 6324448ff..2ee58dafd 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss @@ -19,6 +19,8 @@ background-color: rgba(0, 0, 0, 0.55); border-radius: var(--border-radius-custom); padding: 0.7rem; + padding-left: 1rem; + padding-right: 1rem; h1 { text-transform: uppercase; @@ -45,29 +47,28 @@ .memberName { font-weight: bold; - text-align: right; // Kohdistetaan nimi oikealle reunaan - flex: 2; // Antaa nimelle enemmän tilaa + text-align: end; + flex: 2; min-width: 0; - padding-right: 2rem; // Poistettu ylimääräinen padding-top - align-self: center; // Keskitetään nimi pystysuunnassa + padding-right: 2rem; + align-self: center; display: flex; - justify-content: flex-end; // Kohdistaa sisällön oikeaan reunaan + justify-content: flex-end; } .taskText { text-align: left; - flex: 2; // Jättää tehtävälle vähemmän tilaa kuin nimelle + flex: 2; min-width: 0; } .iconContainer { display: flex; gap: 0.5rem; - align-items: center; // Kohdistaa ikonit keskelle pystysuunnassa - justify-content: center; - flex: 1; // Sama tila kuin taskText + align-items: center; + justify-content: end; + flex: 1; min-width: 0; - align-self: center; // Keskitetään ikonit pystysuunnassa } .centerContainer { @@ -82,18 +83,18 @@ } .memberLogo { - width: clamp(0.5rem, 3vw, 2rem); // Kasvatetaan logon kokoa + width: clamp(0.5rem, 3vw, 2rem); height: clamp(0.5rem, 3vw, 2rem); - border-radius: 50%; // Varmistetaan pyöreys - overflow: hidden; // Varmistaa, että logo pysyy pyöreänä myös piilotettuna + border-radius: 50%; + overflow: hidden; @include link-scale-effect('icon'); } .Logo { width: 100%; height: 100%; - object-fit: cover; // Täyttää säiliön sekä korkeuden että leveyden osalta - border-radius: 50%; // Pitää logon pyöreänä + object-fit: cover; + border-radius: 50%; cursor: pointer; @include link-scale-effect('icon'); background-color: var(--secondary-color); @@ -102,7 +103,7 @@ .placeholderLogo { width: 100%; height: 100%; - opacity: 0; // Täysin läpinäkyvä + opacity: 0; border-radius: 50%; @include link-scale-effect('icon'); } From dd73298d1553c52a72cc08154127f254d163e9d7 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Thu, 3 Oct 2024 20:05:04 +0300 Subject: [PATCH 47/74] refactor types file to entities --- .../Member/model/data/membersLocally.ts | 1546 ++++++++--------- .../src/entities/Member/model/types/types.ts | 125 +- .../src/widgets/SectionMembers/model/types.ts | 46 - .../widgets/SectionMembers/ui/MemberItem.tsx | 2 +- 4 files changed, 860 insertions(+), 859 deletions(-) delete mode 100644 frontend-next-migration/src/widgets/SectionMembers/model/types.ts diff --git a/frontend-next-migration/src/entities/Member/model/data/membersLocally.ts b/frontend-next-migration/src/entities/Member/model/data/membersLocally.ts index 219abb703..4ed7b0b56 100644 --- a/frontend-next-migration/src/entities/Member/model/data/membersLocally.ts +++ b/frontend-next-migration/src/entities/Member/model/data/membersLocally.ts @@ -1,773 +1,773 @@ -import { GroupType, GroupWithMember } from '../types/types'; -export const groupsWithMembersLocally: GroupWithMember[] = [ - { - group: GroupType.Concept, - workers: [ - { - id: 1, - name: 'Aapo Laurila', - }, - ], - }, - //-------------------------------------------------------------------- - - { - group: GroupType.ArtisticDirector, - workers: [ - { - id: 2, - name: 'Helena Pavloff-Pelkonen', - github: 'psykkis', - }, - ], - }, - //-------------------------------------------------------------------- - { - group: GroupType.EducationalDesigner, - workers: [ - { - id: 1002200, - name: 'Esa Pavloff-Pelkonen', - }, - ], - }, - //-------------------------------------------------------------------- - { - group: GroupType.Production, - workers: [ - { - id: 1002097098, - name: 'Eeva Pirttiaho', - }, - ], - }, - //-------------------------------------------------------------------- - { - group: GroupType.ProductionConsultant, - workers: [ - { - id: 11324234, - name: 'Tarja Porkka-Kontturi', - }, - ], - }, - //-------------------------------------------------------------------- - { - group: GroupType.TechnicalConsultant, - workers: [ - { - id: 1132344, - name: 'Sakari Lukkaroinen', - }, - ], - }, - //-------------------------------------------------------------------- - - { - group: GroupType.Graphic, - workers: [ - { - id: 4, - name: 'Emilio Mäkipää', - }, - { - id: 44444, - name: 'Milo Keronen', - site: 'https://mxmilo.wixsite.com/hiisikoloart', - // imgSrc: keronen - }, - { - id: 5, - name: 'Milja Sissonen', - // imgSrc: imgStub - }, - { - id: 6, - name: 'Emmi Pusa', - // imgSrc: pusa - }, - { - id: 7787, - name: 'Katri Tempakka', - // imgSrc: imgStub - }, - { - id: 7, - name: 'Anastasiia (Nasti) Skobkina', - // imgSrc: imgStub - }, - { - id: 8, - name: 'Iida Välimäki', - // imgSrc: valimaki - }, - { - id: 9, - name: 'Nova Kallio', - // imgSrc: imgStub - }, - { - id: 12, - name: 'Valeria Velichko', - site: 'https://linktr.ee/snowycrowart', - // imgSrc: velichko - }, - { - id: 44444234, - name: 'Markku Pyrrö', - // imgSrc: imgStub - }, - { - id: 5432424234, - name: 'Joanna Lindström', - // imgSrc: lindstrom - }, - { - id: 4366435325, - name: 'Krister Pohjanlehto', - site: 'https://krizzerart.artstation.com/', - }, - { - id: 543535345, - name: 'Juho Ollila', - site: 'https://www.artstation.com/juhoollila', - }, - { - id: 5435354545345, - name: 'Minna Niemi', - }, - { - id: 42342359, - name: 'Anna Raevskaia', - site: 'https://www.artstation.com/annarae', - }, - { - id: 423423553459, - name: 'Sonja Tähkänen', - site: 'https://www.artstation.com/annarae', - }, - { - id: 65435435, - name: 'Rasmus Toikka', - // imgSrc: toikka - }, - { - id: 98765432, - name: 'Ale Neppius', - site: 'https://aleneppius.artstation.com/', - }, - { - id: 87654321, - name: 'Elvi Suonperä', - site: 'https://www.kimeelvi.com/', - }, - { - id: 76543210, - name: 'Emma "Lilyawe"', - site: 'https://www.artstation.com/lilyawe', - }, - { - id: 65432109, - name: 'Katriina Ruotsalainen', - site: 'https://miaskyelord.wixsite.com/katriina-ruotsalaine', - }, - { - id: 54321098, - name: 'Luca Cannavò', - site: 'https://www.artstation.com/luca_cannavo', - }, - { - id: 43210987, - name: 'Mariia Lassila', - site: 'https://mariialassila2000.wixsite.com/mariialassila', - }, - { - id: 32109876, - name: 'S. M. K. Tähkänen', - }, - { - id: 21098765, - name: 'Sandesh Neupane', - site: 'https://www.linkedin.com/in/sandeshneupane2055/', - }, - { - id: 10987654, - name: 'Sirumilla Kotilainen', - site: 'https://sirumillakotilainen.webnode.fi/', - }, - { - id: 9876543, - name: 'Suvi Hokkanen', - site: 'https://exanthe.wixsite.com/exanthesuvi', - }, - { - id: 8765432, - name: 'Taru Teivonen', - }, - { - id: 7654321, - name: 'Tuuli Kauppinen', - }, - { - id: 6543210, - name: 'Stanislav Nefedov', - site: 'https://www.linkedin.com/in/stanislav-nefedov/', - }, - ], - }, - - //-------------------------------------------------------------------- - { - group: GroupType.GameCode, - workers: [ - { - id: 13, - name: 'Jari Petäys', - github: 'jpetays', - }, - { - id: 14, - name: 'Tomi Rämö', - github: 'TomiRam', - }, - { - id: 15, - name: 'Pasi Ylärinne', - github: 'Bashwyck', - }, - { - id: 16, - name: 'Elmeri Jatala', - github: 'Elmeri', - site: 'https://www.instagram.com/elkku045/', - }, - { - id: 17, - name: 'Otto Ikonen', - github: 'OttoIkonen', - }, - { - id: 18, - name: 'Lukas Järvelä', - github: 'ScrubMans', - }, - { - id: 19, - name: 'Lassi Salo', - }, - { - id: 9005, - name: 'Anna Hyttinen', - }, - { - id: 8948, - name: 'Benjamin Wallenius', - site: 'https://www.linkedin.com/in/benkkuwln/', - }, - { - id: 2414, - name: 'Haris Hussain', - }, - { - id: 6911, - name: 'Joona Klaar', - }, - { - id: 7673, - name: 'Marko Sulkunen', - }, - { - id: 2274, - name: 'Markus Nummi', - }, - { - id: 5330, - name: 'Niklas Bergström', - }, - { - id: 2390, - name: 'Roope Grimm-Pohjanpalo', - }, - { - id: 4598, - name: 'Samuli Salin', - }, - { - id: 8846, - name: 'Ville Leino', - }, - { - id: 7314, - name: 'William Rueter', - }, - { - id: 2730, - name: 'Mikko Härkönen', - // imgSrc: harkonen - }, - { - id: 3902, - name: 'Toni Peltonen', - site: 'www.linkedin.com/in/toni-peltonen-238a0b240', - }, - ], - }, - - //-------------------------------------------------------------------- - - { - group: GroupType.APICode, - workers: [ - { - id: 20, - name: 'Mikhail Deriabin', - github: 'MikhailDeriabin', - site: 'https://mikhail.hostaan.ac/', - }, - ], - }, - - //-------------------------------------------------------------------- - - { - group: GroupType.WebPagesCode, - workers: [ - { - id: 21, - name: 'Leo Hannolainen', - github: 'leolabdev', - site: 'https://leo-hannolainen.netlify.app/', - linkedin: 'https://www.linkedin.com/in/leo-hannolainen-860859205/', - }, - { - id: 5515151111, - name: 'Joni Roine', - github: 'Jonroi', - site: 'https://datanomit.fi/TVT2023/jonroi/', - linkedin: 'https://www.linkedin.com/in/joni-roine/', - }, - ], - }, - { - //-------------------------------------------------------------------- - group: GroupType.UserInterface, - workers: [ - { - id: 2291918, - name: 'Aleksi Mäkelä', - }, - { - id: 2423523452, - name: 'Amila Ranasinghe', - }, - { - id: 551615615, - name: 'Vilhelmiina Piira', - }, - { - id: 24235324, - name: 'Planks Wooden', - site: 'https://planksman.com/', - }, - { - id: 24235322, - name: 'Janne Mähönen', - linkedin: 'https://www.linkedin.com/in/janne-mahonen-803419231', - }, - ], - }, - //-------------------------------------------------------------------- - { - group: GroupType.Sound, - workers: [ - { - id: 22, - name: 'Otso Puhakka', - site: 'https://otsopuhakkasound.com/', - }, - { - id: 2423523452, - name: 'Mikko Rainio', - }, - { - id: 2423236858, - name: 'Jose Eronen', - }, - ], - }, - - //-------------------------------------------------------------------- - { - group: GroupType.Comics, - workers: [ - { - id: 24, - name: 'Christian Lindholm', - site: 'https://peliprojektini.webnode.fi/', - }, - { - id: 24346547, - name: 'Milo Keronen ', - site: 'https://mxmilo.wixsite.com/hiisikoloart', - }, - { - id: 25654674645, - name: 'Suvi Palviainen', - }, - { - id: 25654642374645, - name: 'Essi Tarvainen', - }, - ], - }, - - //-------------------------------------------------------------------- - { - group: GroupType.OthersComics, - workers: [ - { - id: 43254023545, - name: 'Suvi Palviainen', - }, - { - id: 424234, - name: 'Essi Tarvainen', - }, - - { - id: 42342413, - name: 'Milo Keronen', - }, - - { - id: 432425123, - name: 'Christian Lindholm', - }, - ], - }, - //-------------------------------------------------------------------- - { - group: GroupType.OthersGame, - workers: [ - { - id: 252431421, - name: 'Markku Pyrrö', - }, - - { - id: 25, - name: 'Esa Pavloff-Pelkonen', - }, - { - id: 26, - name: 'Suvi Palviainen', - }, - { - id: 27, - name: 'Mikko Härkönen', - }, - { - id: 29, - name: 'Sampo Rajala', - }, - { - id: 30, - name: 'Kristian Turkki', - }, - { - id: 31, - name: 'Sakari Pohjola', - }, - { - id: 32, - name: 'Ale Neppius', - }, - { - id: 33, - name: 'Oona Suikkanen', - }, - { - id: 34, - name: 'Stanislav Nefedov', - }, - { - id: 35, - name: 'Saku Remahl', - }, - { - id: 36, - name: 'Mikael Eskonen', - }, - { - id: 38, - name: 'Aleksi Saarinen', - }, - { - id: 39, - name: 'Jay Heikkilä', - }, - { - id: 40, - name: 'Sami Sobori', - }, - { - id: 41, - name: 'Alice Grönholm', - }, - { - id: 42, - name: 'Taru Hämäläinen', - }, - { - id: 43, - name: 'Joni Rokkanen', - }, - { - id: 44, - name: 'Jesse', - }, - { - id: 45, - name: 'Anna-Maija Hyttinen', - }, - { - id: 46, - name: 'Tiia Söderlund', - }, - { - id: 47, - name: 'Andreas Julkunen', - }, - { - id: 48, - name: 'Jarno Vartiainen', - }, - { - id: 49, - name: 'Janika Suhonen', - }, - { - id: 50, - name: 'Krista Puusti', - }, - { - id: 51, - name: 'Pauliina Holopainen', - }, - { - id: 52, - name: 'Ronnie Isomäki', - }, - { - id: 152, - name: 'Pyry Siikjärvi', - }, - { - id: 53, - name: 'Joni Miettinen', - }, - { - id: 54, - name: 'Samuel Lindström', - }, - { - id: 55, - name: 'Lauri Salmi', - }, - { - id: 56, - name: 'William Rueter', - }, - { - id: 57, - name: 'Samuel Käyhkö', - }, - { - id: 58, - name: 'Stella Crawford', - }, - { - id: 59, - name: 'Emilio Mäkipää', - }, - { - id: 60, - name: 'Sebastian Lindgren', - }, - { - id: 61, - name: 'Luca Cannavo', - }, - { - id: 62, - name: 'Rikhard Liikanen', - }, - { - id: 63, - name: 'Nana Siikava', - }, - { - id: 64, - name: 'Jupiter Pitkänen', - }, - { - id: 65, - name: 'Mille Rönkkö', - }, - { - id: 66, - name: 'Anna-Maija Ratilainen', - }, - { - id: 67, - name: 'Jere Koivisto', - }, - - { - id: 6743534524, - name: 'Elmeri Jatala', - }, - - { - id: 67435345, - name: 'Lucas Järvelä', - }, - - { - id: 6743534545, - name: 'Lassi Salo', - }, - - { - id: 6743574545, - name: 'Pasi Ylärinne', - }, - - { - id: 6743514545, - name: 'Aino Ulvi', - }, - - { - id: 6743514541, - name: 'Albert Rantala', - }, - - { - id: 6742514541, - name: 'Otto Ikonen', - }, - - { - id: 6742514543, - name: 'Nova Kallio', - }, - - { - id: 67425145434, - name: 'Anastasiia (Nasti) Skobkina', - }, - - { - id: 67425141434, - name: 'Janne Pyöriä', - }, - - { - id: 67425141438, - name: 'Katri Tempakka', - }, - - { - id: 674255435, - name: 'Milja Sissonen', - }, - - { - id: 3124124, - name: 'Valeria Velichko', - }, - - { - id: 32432563, - name: 'Iida Välimäki (Mehukatti)', - }, - - { - id: 3545353, - name: 'Santtu Syväsalmi', - }, - - { - id: 674535, - name: 'Ida (Rimppu)', - }, - { - id: 6745355435, - name: 'Tarja Porkka-Kontturi', - }, - ], - }, - //-------------------------------------------------------------------- - { - group: GroupType.Others, - workers: [ - { - id: 72, - name: 'Anssi Ahola', - }, - { - id: 73, - name: 'Olli Raudus', - }, - { - id: 74, - name: 'Vesa Raudasoja', - }, - { - id: 75, - name: 'Maria Kalliorinne', - }, - - { - id: 76, - name: 'Tuukka Lehkonen', - }, - - { - id: 77, - name: 'Susanna Viljanmaa', - }, - { - id: 78, - name: 'Milsa Malin', - }, - - { - id: 81, - name: 'Milla Pennanen', - }, - { - id: 82, - name: 'Henri Huttunen', - }, - { - id: 83, - name: 'Maria Jauhiainen', - }, - { - id: 84, - name: 'Tuuja Jänicke', - }, - { - id: 85, - name: 'Jarno Paunonen', - }, - - { - id: 86, - name: 'Juko Leino', - }, - ], - }, -]; +// import { GroupType, GroupWithMember } from '../types/types'; +// export const groupsWithMembersLocally: GroupWithMember[] = [ +// { +// group: GroupType.Concept, +// workers: [ +// { +// id: 1, +// name: 'Aapo Laurila', +// }, +// ], +// }, +// //-------------------------------------------------------------------- + +// { +// group: GroupType.ArtisticDirector, +// workers: [ +// { +// id: 2, +// name: 'Helena Pavloff-Pelkonen', +// github: 'psykkis', +// }, +// ], +// }, +// //-------------------------------------------------------------------- +// { +// group: GroupType.EducationalDesigner, +// workers: [ +// { +// id: 1002200, +// name: 'Esa Pavloff-Pelkonen', +// }, +// ], +// }, +// //-------------------------------------------------------------------- +// { +// group: GroupType.Production, +// workers: [ +// { +// id: 1002097098, +// name: 'Eeva Pirttiaho', +// }, +// ], +// }, +// //-------------------------------------------------------------------- +// { +// group: GroupType.ProductionConsultant, +// workers: [ +// { +// id: 11324234, +// name: 'Tarja Porkka-Kontturi', +// }, +// ], +// }, +// //-------------------------------------------------------------------- +// { +// group: GroupType.TechnicalConsultant, +// workers: [ +// { +// id: 1132344, +// name: 'Sakari Lukkaroinen', +// }, +// ], +// }, +// //-------------------------------------------------------------------- + +// { +// group: GroupType.Graphic, +// workers: [ +// { +// id: 4, +// name: 'Emilio Mäkipää', +// }, +// { +// id: 44444, +// name: 'Milo Keronen', +// site: 'https://mxmilo.wixsite.com/hiisikoloart', +// // imgSrc: keronen +// }, +// { +// id: 5, +// name: 'Milja Sissonen', +// // imgSrc: imgStub +// }, +// { +// id: 6, +// name: 'Emmi Pusa', +// // imgSrc: pusa +// }, +// { +// id: 7787, +// name: 'Katri Tempakka', +// // imgSrc: imgStub +// }, +// { +// id: 7, +// name: 'Anastasiia (Nasti) Skobkina', +// // imgSrc: imgStub +// }, +// { +// id: 8, +// name: 'Iida Välimäki', +// // imgSrc: valimaki +// }, +// { +// id: 9, +// name: 'Nova Kallio', +// // imgSrc: imgStub +// }, +// { +// id: 12, +// name: 'Valeria Velichko', +// site: 'https://linktr.ee/snowycrowart', +// // imgSrc: velichko +// }, +// { +// id: 44444234, +// name: 'Markku Pyrrö', +// // imgSrc: imgStub +// }, +// { +// id: 5432424234, +// name: 'Joanna Lindström', +// // imgSrc: lindstrom +// }, +// { +// id: 4366435325, +// name: 'Krister Pohjanlehto', +// site: 'https://krizzerart.artstation.com/', +// }, +// { +// id: 543535345, +// name: 'Juho Ollila', +// site: 'https://www.artstation.com/juhoollila', +// }, +// { +// id: 5435354545345, +// name: 'Minna Niemi', +// }, +// { +// id: 42342359, +// name: 'Anna Raevskaia', +// site: 'https://www.artstation.com/annarae', +// }, +// { +// id: 423423553459, +// name: 'Sonja Tähkänen', +// site: 'https://www.artstation.com/annarae', +// }, +// { +// id: 65435435, +// name: 'Rasmus Toikka', +// // imgSrc: toikka +// }, +// { +// id: 98765432, +// name: 'Ale Neppius', +// site: 'https://aleneppius.artstation.com/', +// }, +// { +// id: 87654321, +// name: 'Elvi Suonperä', +// site: 'https://www.kimeelvi.com/', +// }, +// { +// id: 76543210, +// name: 'Emma "Lilyawe"', +// site: 'https://www.artstation.com/lilyawe', +// }, +// { +// id: 65432109, +// name: 'Katriina Ruotsalainen', +// site: 'https://miaskyelord.wixsite.com/katriina-ruotsalaine', +// }, +// { +// id: 54321098, +// name: 'Luca Cannavò', +// site: 'https://www.artstation.com/luca_cannavo', +// }, +// { +// id: 43210987, +// name: 'Mariia Lassila', +// site: 'https://mariialassila2000.wixsite.com/mariialassila', +// }, +// { +// id: 32109876, +// name: 'S. M. K. Tähkänen', +// }, +// { +// id: 21098765, +// name: 'Sandesh Neupane', +// site: 'https://www.linkedin.com/in/sandeshneupane2055/', +// }, +// { +// id: 10987654, +// name: 'Sirumilla Kotilainen', +// site: 'https://sirumillakotilainen.webnode.fi/', +// }, +// { +// id: 9876543, +// name: 'Suvi Hokkanen', +// site: 'https://exanthe.wixsite.com/exanthesuvi', +// }, +// { +// id: 8765432, +// name: 'Taru Teivonen', +// }, +// { +// id: 7654321, +// name: 'Tuuli Kauppinen', +// }, +// { +// id: 6543210, +// name: 'Stanislav Nefedov', +// site: 'https://www.linkedin.com/in/stanislav-nefedov/', +// }, +// ], +// }, + +// //-------------------------------------------------------------------- +// { +// group: GroupType.GameCode, +// workers: [ +// { +// id: 13, +// name: 'Jari Petäys', +// github: 'jpetays', +// }, +// { +// id: 14, +// name: 'Tomi Rämö', +// github: 'TomiRam', +// }, +// { +// id: 15, +// name: 'Pasi Ylärinne', +// github: 'Bashwyck', +// }, +// { +// id: 16, +// name: 'Elmeri Jatala', +// github: 'Elmeri', +// site: 'https://www.instagram.com/elkku045/', +// }, +// { +// id: 17, +// name: 'Otto Ikonen', +// github: 'OttoIkonen', +// }, +// { +// id: 18, +// name: 'Lukas Järvelä', +// github: 'ScrubMans', +// }, +// { +// id: 19, +// name: 'Lassi Salo', +// }, +// { +// id: 9005, +// name: 'Anna Hyttinen', +// }, +// { +// id: 8948, +// name: 'Benjamin Wallenius', +// site: 'https://www.linkedin.com/in/benkkuwln/', +// }, +// { +// id: 2414, +// name: 'Haris Hussain', +// }, +// { +// id: 6911, +// name: 'Joona Klaar', +// }, +// { +// id: 7673, +// name: 'Marko Sulkunen', +// }, +// { +// id: 2274, +// name: 'Markus Nummi', +// }, +// { +// id: 5330, +// name: 'Niklas Bergström', +// }, +// { +// id: 2390, +// name: 'Roope Grimm-Pohjanpalo', +// }, +// { +// id: 4598, +// name: 'Samuli Salin', +// }, +// { +// id: 8846, +// name: 'Ville Leino', +// }, +// { +// id: 7314, +// name: 'William Rueter', +// }, +// { +// id: 2730, +// name: 'Mikko Härkönen', +// // imgSrc: harkonen +// }, +// { +// id: 3902, +// name: 'Toni Peltonen', +// site: 'www.linkedin.com/in/toni-peltonen-238a0b240', +// }, +// ], +// }, + +// //-------------------------------------------------------------------- + +// { +// group: GroupType.APICode, +// workers: [ +// { +// id: 20, +// name: 'Mikhail Deriabin', +// github: 'MikhailDeriabin', +// site: 'https://mikhail.hostaan.ac/', +// }, +// ], +// }, + +// //-------------------------------------------------------------------- + +// { +// group: GroupType.WebPagesCode, +// workers: [ +// { +// id: 21, +// name: 'Leo Hannolainen', +// github: 'leolabdev', +// site: 'https://leo-hannolainen.netlify.app/', +// linkedin: 'https://www.linkedin.com/in/leo-hannolainen-860859205/', +// }, +// { +// id: 5515151111, +// name: 'Joni Roine', +// github: 'Jonroi', +// site: 'https://datanomit.fi/TVT2023/jonroi/', +// linkedin: 'https://www.linkedin.com/in/joni-roine/', +// }, +// ], +// }, +// { +// //-------------------------------------------------------------------- +// group: GroupType.UserInterface, +// workers: [ +// { +// id: 2291918, +// name: 'Aleksi Mäkelä', +// }, +// { +// id: 2423523452, +// name: 'Amila Ranasinghe', +// }, +// { +// id: 551615615, +// name: 'Vilhelmiina Piira', +// }, +// { +// id: 24235324, +// name: 'Planks Wooden', +// site: 'https://planksman.com/', +// }, +// { +// id: 24235322, +// name: 'Janne Mähönen', +// linkedin: 'https://www.linkedin.com/in/janne-mahonen-803419231', +// }, +// ], +// }, +// //-------------------------------------------------------------------- +// { +// group: GroupType.Sound, +// workers: [ +// { +// id: 22, +// name: 'Otso Puhakka', +// site: 'https://otsopuhakkasound.com/', +// }, +// { +// id: 2423523452, +// name: 'Mikko Rainio', +// }, +// { +// id: 2423236858, +// name: 'Jose Eronen', +// }, +// ], +// }, + +// //-------------------------------------------------------------------- +// { +// group: GroupType.Comics, +// workers: [ +// { +// id: 24, +// name: 'Christian Lindholm', +// site: 'https://peliprojektini.webnode.fi/', +// }, +// { +// id: 24346547, +// name: 'Milo Keronen ', +// site: 'https://mxmilo.wixsite.com/hiisikoloart', +// }, +// { +// id: 25654674645, +// name: 'Suvi Palviainen', +// }, +// { +// id: 25654642374645, +// name: 'Essi Tarvainen', +// }, +// ], +// }, + +// //-------------------------------------------------------------------- +// { +// group: GroupType.OthersComics, +// workers: [ +// { +// id: 43254023545, +// name: 'Suvi Palviainen', +// }, +// { +// id: 424234, +// name: 'Essi Tarvainen', +// }, + +// { +// id: 42342413, +// name: 'Milo Keronen', +// }, + +// { +// id: 432425123, +// name: 'Christian Lindholm', +// }, +// ], +// }, +// //-------------------------------------------------------------------- +// { +// group: GroupType.OthersGame, +// workers: [ +// { +// id: 252431421, +// name: 'Markku Pyrrö', +// }, + +// { +// id: 25, +// name: 'Esa Pavloff-Pelkonen', +// }, +// { +// id: 26, +// name: 'Suvi Palviainen', +// }, +// { +// id: 27, +// name: 'Mikko Härkönen', +// }, +// { +// id: 29, +// name: 'Sampo Rajala', +// }, +// { +// id: 30, +// name: 'Kristian Turkki', +// }, +// { +// id: 31, +// name: 'Sakari Pohjola', +// }, +// { +// id: 32, +// name: 'Ale Neppius', +// }, +// { +// id: 33, +// name: 'Oona Suikkanen', +// }, +// { +// id: 34, +// name: 'Stanislav Nefedov', +// }, +// { +// id: 35, +// name: 'Saku Remahl', +// }, +// { +// id: 36, +// name: 'Mikael Eskonen', +// }, +// { +// id: 38, +// name: 'Aleksi Saarinen', +// }, +// { +// id: 39, +// name: 'Jay Heikkilä', +// }, +// { +// id: 40, +// name: 'Sami Sobori', +// }, +// { +// id: 41, +// name: 'Alice Grönholm', +// }, +// { +// id: 42, +// name: 'Taru Hämäläinen', +// }, +// { +// id: 43, +// name: 'Joni Rokkanen', +// }, +// { +// id: 44, +// name: 'Jesse', +// }, +// { +// id: 45, +// name: 'Anna-Maija Hyttinen', +// }, +// { +// id: 46, +// name: 'Tiia Söderlund', +// }, +// { +// id: 47, +// name: 'Andreas Julkunen', +// }, +// { +// id: 48, +// name: 'Jarno Vartiainen', +// }, +// { +// id: 49, +// name: 'Janika Suhonen', +// }, +// { +// id: 50, +// name: 'Krista Puusti', +// }, +// { +// id: 51, +// name: 'Pauliina Holopainen', +// }, +// { +// id: 52, +// name: 'Ronnie Isomäki', +// }, +// { +// id: 152, +// name: 'Pyry Siikjärvi', +// }, +// { +// id: 53, +// name: 'Joni Miettinen', +// }, +// { +// id: 54, +// name: 'Samuel Lindström', +// }, +// { +// id: 55, +// name: 'Lauri Salmi', +// }, +// { +// id: 56, +// name: 'William Rueter', +// }, +// { +// id: 57, +// name: 'Samuel Käyhkö', +// }, +// { +// id: 58, +// name: 'Stella Crawford', +// }, +// { +// id: 59, +// name: 'Emilio Mäkipää', +// }, +// { +// id: 60, +// name: 'Sebastian Lindgren', +// }, +// { +// id: 61, +// name: 'Luca Cannavo', +// }, +// { +// id: 62, +// name: 'Rikhard Liikanen', +// }, +// { +// id: 63, +// name: 'Nana Siikava', +// }, +// { +// id: 64, +// name: 'Jupiter Pitkänen', +// }, +// { +// id: 65, +// name: 'Mille Rönkkö', +// }, +// { +// id: 66, +// name: 'Anna-Maija Ratilainen', +// }, +// { +// id: 67, +// name: 'Jere Koivisto', +// }, + +// { +// id: 6743534524, +// name: 'Elmeri Jatala', +// }, + +// { +// id: 67435345, +// name: 'Lucas Järvelä', +// }, + +// { +// id: 6743534545, +// name: 'Lassi Salo', +// }, + +// { +// id: 6743574545, +// name: 'Pasi Ylärinne', +// }, + +// { +// id: 6743514545, +// name: 'Aino Ulvi', +// }, + +// { +// id: 6743514541, +// name: 'Albert Rantala', +// }, + +// { +// id: 6742514541, +// name: 'Otto Ikonen', +// }, + +// { +// id: 6742514543, +// name: 'Nova Kallio', +// }, + +// { +// id: 67425145434, +// name: 'Anastasiia (Nasti) Skobkina', +// }, + +// { +// id: 67425141434, +// name: 'Janne Pyöriä', +// }, + +// { +// id: 67425141438, +// name: 'Katri Tempakka', +// }, + +// { +// id: 674255435, +// name: 'Milja Sissonen', +// }, + +// { +// id: 3124124, +// name: 'Valeria Velichko', +// }, + +// { +// id: 32432563, +// name: 'Iida Välimäki (Mehukatti)', +// }, + +// { +// id: 3545353, +// name: 'Santtu Syväsalmi', +// }, + +// { +// id: 674535, +// name: 'Ida (Rimppu)', +// }, +// { +// id: 6745355435, +// name: 'Tarja Porkka-Kontturi', +// }, +// ], +// }, +// //-------------------------------------------------------------------- +// { +// group: GroupType.Others, +// workers: [ +// { +// id: 72, +// name: 'Anssi Ahola', +// }, +// { +// id: 73, +// name: 'Olli Raudus', +// }, +// { +// id: 74, +// name: 'Vesa Raudasoja', +// }, +// { +// id: 75, +// name: 'Maria Kalliorinne', +// }, + +// { +// id: 76, +// name: 'Tuukka Lehkonen', +// }, + +// { +// id: 77, +// name: 'Susanna Viljanmaa', +// }, +// { +// id: 78, +// name: 'Milsa Malin', +// }, + +// { +// id: 81, +// name: 'Milla Pennanen', +// }, +// { +// id: 82, +// name: 'Henri Huttunen', +// }, +// { +// id: 83, +// name: 'Maria Jauhiainen', +// }, +// { +// id: 84, +// name: 'Tuuja Jänicke', +// }, +// { +// id: 85, +// name: 'Jarno Paunonen', +// }, + +// { +// id: 86, +// name: 'Juko Leino', +// }, +// ], +// }, +// ]; diff --git a/frontend-next-migration/src/entities/Member/model/types/types.ts b/frontend-next-migration/src/entities/Member/model/types/types.ts index 372561448..eecacbe3e 100644 --- a/frontend-next-migration/src/entities/Member/model/types/types.ts +++ b/frontend-next-migration/src/entities/Member/model/types/types.ts @@ -1,50 +1,97 @@ -export enum GroupType { - APICode = 'APICode', - ArtisticDirector = 'ArtisticDirector', - Comics = 'Comics', - Concept = 'Concept', - EducationalDesigner = 'EducationalDesigner', - GameAnimation = 'GameAnimation', - GameCode = 'GameCode', - GameDesign = 'GameDesign', - GameGraphic = 'GameGraphic', - Graphic = 'Graphic', - LogoGraphic = 'LogoGraphic', - Others = 'Others', - OthersComics = 'OthersComics', - OthersGame = 'OthersGame', - Production = 'Production', - ProductionConsultant = 'ProductionConsultant', - SocialMedia = 'SocialMedia', - Sound = 'Sound', - TechnicalConsultant = 'TechnicalConsultant', - UserInterface = 'UserInterface', - WebPagesCode = 'WebPagesCode', -} +// export enum GroupType { +// APICode = 'APICode', +// ArtisticDirector = 'ArtisticDirector', +// Comics = 'Comics', +// Concept = 'Concept', +// EducationalDesigner = 'EducationalDesigner', +// GameAnimation = 'GameAnimation', +// GameCode = 'GameCode', +// GameDesign = 'GameDesign', +// GameGraphic = 'GameGraphic', +// Graphic = 'Graphic', +// LogoGraphic = 'LogoGraphic', +// Others = 'Others', +// OthersComics = 'OthersComics', +// OthersGame = 'OthersGame', +// Production = 'Production', +// ProductionConsultant = 'ProductionConsultant', +// SocialMedia = 'SocialMedia', +// Sound = 'Sound', +// TechnicalConsultant = 'TechnicalConsultant', +// UserInterface = 'UserInterface', +// WebPagesCode = 'WebPagesCode', +// } -export enum MemberStatus { - voluntary = 'vapaaehtoinen', - worker = 'työntekijä', - intern = 'työharjoittelija', -} +// export enum MemberStatus { +// voluntary = 'vapaaehtoinen', +// worker = 'työntekijä', +// intern = 'työharjoittelija', +// } + +// export interface GroupWithMember { +// group: GroupType; +// workers: Member[]; +// } + +// export interface Member { +// id: number; +// name: string; +// imgSrc?: string; +// role?: string; +// email?: string; +// phone?: string; +// github?: string; +// discord?: string; +// trello?: string; +// status?: MemberStatus; +// workPeriod?: string; +// site?: string; +// linkedin?: string; +// } -export interface GroupWithMember { - group: GroupType; - workers: Member[]; +// types.ts + +/** + * This file contains TypeScript interfaces that represent the structure of various entities + * used throughout the application, such as Member, Department, Team, and Logo. + */ + +export interface Logo { + data: { + attributes: { + url: string; + }; + } | null; } export interface Member { id: number; name: string; - imgSrc?: string; - role?: string; + task?: string; email?: string; - phone?: string; + logo?: string | null; + website?: string; github?: string; - discord?: string; - trello?: string; - status?: MemberStatus; - workPeriod?: string; - site?: string; linkedin?: string; + facebook?: string; + instagram?: string; + createdAt: string; + updatedAt: string; + locale: string; +} + +export interface Department { + id: number; + name: string; + members: Member[]; +} + +export interface Team { + id: number; + name: string; + createdAt: string; + updatedAt: string; + locale: string; + members: Member[]; + departments: Department[]; } diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/types.ts b/frontend-next-migration/src/widgets/SectionMembers/model/types.ts deleted file mode 100644 index 3e9d0e79f..000000000 --- a/frontend-next-migration/src/widgets/SectionMembers/model/types.ts +++ /dev/null @@ -1,46 +0,0 @@ -// types.ts - -/** - * This file contains TypeScript interfaces that represent the structure of various entities - * used throughout the application, such as Member, Department, Team, and Logo. - */ - -export interface Logo { - data: { - attributes: { - url: string; - }; - } | null; -} - -export interface Member { - id: number; - name: string; - task?: string; - email?: string; - logo?: string | null; - website?: string; - github?: string; - linkedin?: string; - facebook?: string; - instagram?: string; - createdAt: string; - updatedAt: string; - locale: string; -} - -export interface Department { - id: number; - name: string; - members: Member[]; -} - -export interface Team { - id: number; - name: string; - createdAt: string; - updatedAt: string; - locale: string; - members: Member[]; - departments: Department[]; -} diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/MemberItem.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/MemberItem.tsx index 2652473c5..d67844bee 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/MemberItem.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/MemberItem.tsx @@ -1,5 +1,5 @@ import { FC } from 'react'; -import { Member } from '../model/types'; +import { Member } from '@/entities/Member/model/types/types'; import cls from './SectionMembers.module.scss'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faGlobe, faEnvelope } from '@fortawesome/free-solid-svg-icons'; From bb6d2ab4ad0862b6cfb906de203ba1e1c8ebdda9 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Thu, 3 Oct 2024 20:47:31 +0300 Subject: [PATCH 48/74] Refactor mapping Add mapLinks --- .../Member/model/data}/mappers.ts | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) rename frontend-next-migration/src/{widgets/SectionMembers/model => entities/Member/model/data}/mappers.ts (85%) diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/mappers.ts b/frontend-next-migration/src/entities/Member/model/data/mappers.ts similarity index 85% rename from frontend-next-migration/src/widgets/SectionMembers/model/mappers.ts rename to frontend-next-migration/src/entities/Member/model/data/mappers.ts index 9fc87d3a1..f4a266900 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/model/mappers.ts +++ b/frontend-next-migration/src/entities/Member/model/data/mappers.ts @@ -1,12 +1,25 @@ -// mappers.ts - /** * This file contains mapping functions used to transform data from the API response * into a format that matches the application's data models. - * It includes functions for mapping members and departments. + * It includes functions for mapping members, departments, and icons. */ +import { Member, Department } from '@/entities/Member/model/types/types'; +import { faGlobe, faEnvelope } from '@fortawesome/free-solid-svg-icons'; +import { + faGithub, + faLinkedin, + faInstagram, + faFacebook, +} from '@fortawesome/free-brands-svg-icons'; -import { Member, Department } from './types'; +export const getLinksMap = () => ({ + website: faGlobe, + github: faGithub, + linkedin: faLinkedin, + facebook: faFacebook, + instagram: faInstagram, + email: faEnvelope, +}); /** * Maps raw member data from the API response to the Member type used in the application. @@ -49,7 +62,6 @@ export const mapMembers = (membersData: any[]): Member[] => { * @param locale The language locale used to find the localized department name. * @returns An array of departments mapped to the Department type. */ - export const mapDepartments = ( departmentsData: any[], locale: string, From b5f04e58576f3933a78c3c40487afc0540fc4f5d Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Thu, 3 Oct 2024 20:48:57 +0300 Subject: [PATCH 49/74] Correct types import --- .../src/widgets/SectionMembers/model/membersApi.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts index df7264470..fd94e2eb5 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts +++ b/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts @@ -6,8 +6,11 @@ */ import { envHelper } from '@/shared/const/envHelper'; -import { Member, Team } from '../model/types'; -import { mapMembers, mapDepartments } from '../model/mappers'; +import { Team } from '@/entities/Member/model/types/types'; +import { + mapMembers, + mapDepartments, +} from '../../../entities/Member/model/data/mappers'; /** * Fetches a list of teams, including their members and departments, from the Strapi API. From 2c16cc23b1f20edcd0c20f9a5fd4cc63a7d83923 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Thu, 3 Oct 2024 20:49:26 +0300 Subject: [PATCH 50/74] correct types import --- .../src/widgets/SectionMembers/ui/SectionMembers.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx index c87fa5ed0..1a65be315 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx @@ -2,7 +2,7 @@ import cls from './SectionMembers.module.scss'; import { FC, useEffect, useState } from 'react'; import { useParams } from 'next/navigation'; import { fetchTeams } from '../model/membersApi'; -import { Team } from '../model/types'; +import { Team } from '@/entities/Member/model/types/types'; import { ScrollBottomButton } from '@/features/ScrollBottom'; import { classNames } from '@/shared/lib/classNames/classNames'; import { Container } from '@/shared/ui/Container'; From 2c5cfcff93848e4a1b53bc6df3d756e1cd540f2f Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Thu, 3 Oct 2024 21:12:21 +0300 Subject: [PATCH 51/74] Refactor memberItem to use nextLink --- .../src/entities/Member/ui/MemberItem.tsx | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 frontend-next-migration/src/entities/Member/ui/MemberItem.tsx diff --git a/frontend-next-migration/src/entities/Member/ui/MemberItem.tsx b/frontend-next-migration/src/entities/Member/ui/MemberItem.tsx new file mode 100644 index 000000000..8410a1e4a --- /dev/null +++ b/frontend-next-migration/src/entities/Member/ui/MemberItem.tsx @@ -0,0 +1,57 @@ +import { FC } from 'react'; +import Link from 'next/link'; +import { Member } from '@/entities/Member/model/types/types'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import cls from '@/widgets/SectionMembers/ui/SectionMembers.module.scss'; +import Image from 'next/image'; +import { LinksMap } from '@/entities/Member/api/mappers'; + +const MemberItem: FC<{ member: Member }> = ({ member }) => { + const linksMap = LinksMap(); + + return ( +
    • +
      +
      + {member.name} + {member.task} +
      +
      + {member.logo ? ( + {member.name} + ) : ( +
      + )} +
      + {Object.entries(linksMap).map(([key, icon]) => { + const link = member[key as keyof Member]; + if (link) { + const href = key === 'email' ? `mailto:${link}` : link; + const target = key === 'email' ? '_self' : '_blank'; + return ( + + + + ); + } + return null; + })} +
      +
      +
      +
    • + ); +}; + +export default MemberItem; From b8e2aa494b42e62e0907522304adc826c9cab43a Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Thu, 3 Oct 2024 21:12:48 +0300 Subject: [PATCH 52/74] relocate mappers --- .../src/entities/Member/{model/data => api}/mappers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename frontend-next-migration/src/entities/Member/{model/data => api}/mappers.ts (98%) diff --git a/frontend-next-migration/src/entities/Member/model/data/mappers.ts b/frontend-next-migration/src/entities/Member/api/mappers.ts similarity index 98% rename from frontend-next-migration/src/entities/Member/model/data/mappers.ts rename to frontend-next-migration/src/entities/Member/api/mappers.ts index f4a266900..19636770b 100644 --- a/frontend-next-migration/src/entities/Member/model/data/mappers.ts +++ b/frontend-next-migration/src/entities/Member/api/mappers.ts @@ -12,7 +12,7 @@ import { faFacebook, } from '@fortawesome/free-brands-svg-icons'; -export const getLinksMap = () => ({ +export const LinksMap = () => ({ website: faGlobe, github: faGithub, linkedin: faLinkedin, From 7de7ce810921f0a0e8cd40e0fa84e8fc1893e330 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Thu, 3 Oct 2024 21:13:27 +0300 Subject: [PATCH 53/74] Relocate api,memberItem and DepartmentItem --- .../Member/api}/membersApi.ts | 5 +- .../Member}/ui/DepartmentItem.tsx | 4 +- .../widgets/SectionMembers/ui/MemberItem.tsx | 92 ------------------- .../SectionMembers/ui/SectionMembers.tsx | 16 +--- 4 files changed, 6 insertions(+), 111 deletions(-) rename frontend-next-migration/src/{widgets/SectionMembers/model => entities/Member/api}/membersApi.ts (97%) rename frontend-next-migration/src/{widgets/SectionMembers => entities/Member}/ui/DepartmentItem.tsx (84%) delete mode 100644 frontend-next-migration/src/widgets/SectionMembers/ui/MemberItem.tsx diff --git a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts b/frontend-next-migration/src/entities/Member/api/membersApi.ts similarity index 97% rename from frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts rename to frontend-next-migration/src/entities/Member/api/membersApi.ts index fd94e2eb5..c767e0887 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/model/membersApi.ts +++ b/frontend-next-migration/src/entities/Member/api/membersApi.ts @@ -7,10 +7,7 @@ import { envHelper } from '@/shared/const/envHelper'; import { Team } from '@/entities/Member/model/types/types'; -import { - mapMembers, - mapDepartments, -} from '../../../entities/Member/model/data/mappers'; +import { mapMembers, mapDepartments } from './mappers'; /** * Fetches a list of teams, including their members and departments, from the Strapi API. diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/DepartmentItem.tsx b/frontend-next-migration/src/entities/Member/ui/DepartmentItem.tsx similarity index 84% rename from frontend-next-migration/src/widgets/SectionMembers/ui/DepartmentItem.tsx rename to frontend-next-migration/src/entities/Member/ui/DepartmentItem.tsx index d22e9a49d..9583e5a0b 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/DepartmentItem.tsx +++ b/frontend-next-migration/src/entities/Member/ui/DepartmentItem.tsx @@ -1,6 +1,6 @@ import { FC } from 'react'; -import { Department, Member } from '../model/types'; -import cls from './SectionMembers.module.scss'; +import { Department, Member } from '@/entities/Member/model/types/types'; +import cls from '@/widgets/SectionMembers/ui/SectionMembers.module.scss'; import MemberItem from './MemberItem'; /** diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/MemberItem.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/MemberItem.tsx deleted file mode 100644 index d67844bee..000000000 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/MemberItem.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import { FC } from 'react'; -import { Member } from '@/entities/Member/model/types/types'; -import cls from './SectionMembers.module.scss'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { faGlobe, faEnvelope } from '@fortawesome/free-solid-svg-icons'; -import { - faGithub, - faLinkedin, - faInstagram, - faFacebook, -} from '@fortawesome/free-brands-svg-icons'; -import { openLinkInNewTab } from '@/shared/lib/openLinkInNewTab/openLinkInNewTab'; -import Image from 'next/image'; -import { ClickableBorder } from '@/shared/ui/ClickableBorder'; -import { classNames } from '../../../shared/lib/classNames/classNames'; - -/** - * MemberItem component displays information about a specific member. - * It includes member's name, task, logo, and relevant links like website, GitHub, LinkedIn, etc. - */ -const MemberItem: FC<{ member: Member }> = ({ member }) => { - return ( -
    • -
      -
      - {member.name} - {member.task} -
      - {/* Render logo if available, otherwise render an empty placeholder */} -
      - {member.logo ? ( - {member.name} - ) : ( -
      - )} -
      - {member.website && ( - openLinkInNewTab(member.website)} - className={cls.clickableLogo}> - - - )} - {member.github && ( - openLinkInNewTab(member.github)} - className={cls.clickableLogo}> - - - )} - {member.linkedin && ( - openLinkInNewTab(member.linkedin)} - className={cls.clickableLogo}> - - - )} - {member.facebook && ( - openLinkInNewTab(member.facebook)} - className={cls.clickableLogo}> - - - )} - {member.instagram && ( - openLinkInNewTab(member.instagram)} - className={cls.clickableLogo}> - - - )} - {member.email && ( - openLinkInNewTab(`mailto:${member.email}`)} - className={cls.clickableLogo}> - - - )} -
      -
      -
      -
    • - ); -}; - -export default MemberItem; diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx index 1a65be315..da66645c0 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx @@ -1,35 +1,25 @@ import cls from './SectionMembers.module.scss'; import { FC, useEffect, useState } from 'react'; import { useParams } from 'next/navigation'; -import { fetchTeams } from '../model/membersApi'; +import { fetchTeams } from '../../../entities/Member/api/membersApi'; import { Team } from '@/entities/Member/model/types/types'; import { ScrollBottomButton } from '@/features/ScrollBottom'; import { classNames } from '@/shared/lib/classNames/classNames'; import { Container } from '@/shared/ui/Container'; -import DepartmentItem from './DepartmentItem'; +import DepartmentItem from '../../../entities/Member/ui/DepartmentItem'; import { useClientTranslation } from '@/shared/i18n'; -import MemberItem from './MemberItem'; +import MemberItem from '@/entities/Member/ui/MemberItem'; -/** - * Props for the SectionMembers component. - */ interface WorkersSectionProps { className?: string; } -/** - * SectionMembers component displays a list of teams, including their departments and members. - * It fetches data from an API and renders the content dynamically based on the response. - */ export const SectionMembers: FC = ({ className = '' }) => { const [teams, setTeams] = useState([]); const params = useParams(); const lng = params.lng as string; const { t } = useClientTranslation(lng, 'team'); - { - /*Fetch team data when the language changes*/ - } useEffect(() => { const fetchTeamsData = async () => { try { From 5cee26b07fdefd6bef69356bbfaf7fe82088f7db Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Thu, 3 Oct 2024 21:57:47 +0300 Subject: [PATCH 54/74] Relocate department and member item --- .../Member/ui/DepartmentItem.module.scss | 3 + .../src/entities/Member/ui/DepartmentItem.tsx | 2 +- .../entities/Member/ui/MemberItem.module.scss | 67 +++++++++++++++++++ .../src/entities/Member/ui/MemberItem.tsx | 2 +- 4 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 frontend-next-migration/src/entities/Member/ui/DepartmentItem.module.scss create mode 100644 frontend-next-migration/src/entities/Member/ui/MemberItem.module.scss diff --git a/frontend-next-migration/src/entities/Member/ui/DepartmentItem.module.scss b/frontend-next-migration/src/entities/Member/ui/DepartmentItem.module.scss new file mode 100644 index 000000000..9c704b85e --- /dev/null +++ b/frontend-next-migration/src/entities/Member/ui/DepartmentItem.module.scss @@ -0,0 +1,3 @@ +.departmentCard { + margin-bottom: 2rem; +} diff --git a/frontend-next-migration/src/entities/Member/ui/DepartmentItem.tsx b/frontend-next-migration/src/entities/Member/ui/DepartmentItem.tsx index 9583e5a0b..5693e83d2 100644 --- a/frontend-next-migration/src/entities/Member/ui/DepartmentItem.tsx +++ b/frontend-next-migration/src/entities/Member/ui/DepartmentItem.tsx @@ -1,6 +1,6 @@ import { FC } from 'react'; import { Department, Member } from '@/entities/Member/model/types/types'; -import cls from '@/widgets/SectionMembers/ui/SectionMembers.module.scss'; +import cls from './DepartmentItem.module.scss'; import MemberItem from './MemberItem'; /** diff --git a/frontend-next-migration/src/entities/Member/ui/MemberItem.module.scss b/frontend-next-migration/src/entities/Member/ui/MemberItem.module.scss new file mode 100644 index 000000000..69ce5bf44 --- /dev/null +++ b/frontend-next-migration/src/entities/Member/ui/MemberItem.module.scss @@ -0,0 +1,67 @@ +.memberRow { + display: flex; + width: 100%; + justify-content: space-between; + + .memberName { + font-weight: bold; + text-align: end; + flex: 2; + min-width: 0; + padding-right: 2rem; + display: flex; + justify-content: flex-end; + } + + .taskText { + text-align: left; + flex: 2; + min-width: 0; + } + + .iconContainer { + display: flex; + gap: 0.5rem; + align-items: center; + justify-content: end; + flex: 1; + min-width: 0; + } + + .centerContainer { + display: flex; + flex: 2; + } + + .clickableLogo { + color: var(--secondary-color); + cursor: pointer; + @include link-scale-effect('icon'); + } + + .memberLogo { + width: clamp(0.5rem, 3vw, 2rem); + height: clamp(0.5rem, 3vw, 2rem); + border-radius: 50%; + overflow: hidden; + @include link-scale-effect('icon'); + } + + .Logo { + width: 100%; + height: 100%; + object-fit: cover; + border-radius: 50%; + cursor: pointer; + @include link-scale-effect('icon'); + background-color: var(--secondary-color); + } + + .placeholderLogo { + width: 100%; + height: 100%; + opacity: 0; + border-radius: 50%; + @include link-scale-effect('icon'); + } +} diff --git a/frontend-next-migration/src/entities/Member/ui/MemberItem.tsx b/frontend-next-migration/src/entities/Member/ui/MemberItem.tsx index 8410a1e4a..78e9c9974 100644 --- a/frontend-next-migration/src/entities/Member/ui/MemberItem.tsx +++ b/frontend-next-migration/src/entities/Member/ui/MemberItem.tsx @@ -2,7 +2,7 @@ import { FC } from 'react'; import Link from 'next/link'; import { Member } from '@/entities/Member/model/types/types'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import cls from '@/widgets/SectionMembers/ui/SectionMembers.module.scss'; +import cls from './MemberItem.module.scss'; import Image from 'next/image'; import { LinksMap } from '@/entities/Member/api/mappers'; From e7e3c50f543b12bf6847fd54838d5fce60043084 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Thu, 3 Oct 2024 21:58:11 +0300 Subject: [PATCH 55/74] clean usnecessery comments --- .../src/entities/Member/api/membersApi.ts | 34 +------------------ 1 file changed, 1 insertion(+), 33 deletions(-) diff --git a/frontend-next-migration/src/entities/Member/api/membersApi.ts b/frontend-next-migration/src/entities/Member/api/membersApi.ts index c767e0887..104e64c2a 100644 --- a/frontend-next-migration/src/entities/Member/api/membersApi.ts +++ b/frontend-next-migration/src/entities/Member/api/membersApi.ts @@ -1,7 +1,5 @@ -// membersApi.ts - /** - * This file provides API functions related to fetching team data, including members and departments. + * This file provides API functions related to fetching team data, including teams,members, logos and departments. * It handles fetching data from Strapi, mapping the data to the correct types, and sorting teams accordingly. */ @@ -16,14 +14,7 @@ import { mapMembers, mapDepartments } from './mappers'; */ export const fetchTeams = async (locale: string = 'en'): Promise => { try { - /** - * Determine the Strapi locale based on the input locale - */ const strapiLocale = locale === 'fi' ? 'fi-FI' : 'en'; - - /** - * Fetch data including localized departments and members with their logos - */ const response = await fetch( `${envHelper.strapiApiUrl}/teams?locale=${strapiLocale}&populate=departments.localizations,members.Logo,departments.members.Logo`, ); @@ -34,33 +25,16 @@ export const fetchTeams = async (locale: string = 'en'): Promise => { const teamData = await response.json(); - /** - * Map teams and assign their respective members and departments - */ const teams: Team[] = teamData.data.map((item: any) => { - /** - * Map team-level members (members who are not part of any specific department) - */ let members = mapMembers(item.attributes.members?.data || []); - - /** - * Map departments related to the team - */ const departments = mapDepartments( item.attributes.departments?.data || [], strapiLocale, ); - /** - * Collect all member IDs that are assigned to departments - */ const departmentMemberIds = departments.flatMap((dept) => dept.members.map((member) => member.id), ); - - /** - * Filter out members from team-level members that are already in a department - */ members = members.filter( (member) => !departmentMemberIds.includes(member.id), ); @@ -76,9 +50,6 @@ export const fetchTeams = async (locale: string = 'en'): Promise => { }; }); - /** - * Define the order for teams based on the locale - */ const orderEn = [ 'Game Design', 'Mentoring', @@ -110,9 +81,6 @@ export const fetchTeams = async (locale: string = 'en'): Promise => { const order = locale === 'fi' ? orderFi : orderEn; - /** - * Sort teams based on the predefined order - */ return teams.sort( (a: Team, b: Team) => order.indexOf(a.name) - order.indexOf(b.name), ); From 5b52c5bc3b9a5eabea41ea5404067acc177adc4c Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Thu, 3 Oct 2024 21:59:17 +0300 Subject: [PATCH 56/74] Clean comments & refactor css properties for member and department modules --- .../ui/SectionMembers.module.scss | 95 ++----------------- .../SectionMembers/ui/SectionMembers.tsx | 4 - 2 files changed, 9 insertions(+), 90 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss index 2ee58dafd..3d83ba50f 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.module.scss @@ -1,13 +1,14 @@ -.MembersSection { - font-family: var(--font-family-texts); - display: grid; - justify-items: center; - user-select: none; -} .MembersSection li { list-style-type: none; } +.MembersSection { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + .scrollBottomButton { margin-bottom: 10px; @include link-scale-effect; @@ -21,6 +22,7 @@ padding: 0.7rem; padding-left: 1rem; padding-right: 1rem; + align-items: start; h1 { text-transform: uppercase; @@ -39,86 +41,7 @@ padding-right: 6rem; } } - -.memberRow { - display: flex; - width: 100%; - justify-content: space-between; - - .memberName { - font-weight: bold; - text-align: end; - flex: 2; - min-width: 0; - padding-right: 2rem; - align-self: center; - display: flex; - justify-content: flex-end; - } - - .taskText { - text-align: left; - flex: 2; - min-width: 0; - } - - .iconContainer { - display: flex; - gap: 0.5rem; - align-items: center; - justify-content: end; - flex: 1; - min-width: 0; - } - - .centerContainer { - display: flex; - flex: 2; - } - - .clickableLogo { - color: var(--secondary-color); - cursor: pointer; - @include link-scale-effect('icon'); - } - - .memberLogo { - width: clamp(0.5rem, 3vw, 2rem); - height: clamp(0.5rem, 3vw, 2rem); - border-radius: 50%; - overflow: hidden; - @include link-scale-effect('icon'); - } - - .Logo { - width: 100%; - height: 100%; - object-fit: cover; - border-radius: 50%; - cursor: pointer; - @include link-scale-effect('icon'); - background-color: var(--secondary-color); - } - - .placeholderLogo { - width: 100%; - height: 100%; - opacity: 0; - border-radius: 50%; - @include link-scale-effect('icon'); - } -} - .memberCard { - padding-bottom: 2rem; - border-radius: var(--border-radius-custom); -} - -.departmentsSection { - margin-top: 1rem; -} - -.departmentCard { - padding-bottom: 2rem; + padding-bottom: 3rem; border-radius: var(--border-radius-custom); } diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx index da66645c0..e54579326 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx @@ -34,18 +34,14 @@ export const SectionMembers: FC = ({ className = '' }) => { return (
      - {/* Scroll button to go to the bottom of the page */} - {/* Container to hold the list of teams */} {teams.map((team) => (
      - {/* Render team name */}

      {team.name}

      - {/* Render departments within the team */} {team.departments.length > 0 && (
      {team.departments.map((department) => ( From 729611cb0af78b71084fbf6a240f3851d1a5ca7b Mon Sep 17 00:00:00 2001 From: leolab1337 <61798137+leolab1337@users.noreply.github.com> Date: Fri, 4 Oct 2024 20:00:36 +0300 Subject: [PATCH 57/74] Remove unnecessary language parameter The language parameter `lng` was redundant and has been removed from the `useClientTranslation` hook call. This change simplifies the code and eliminates potential confusion regarding language handling. --- .../src/widgets/SectionMembers/ui/SectionMembers.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx index e54579326..39580aba5 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx @@ -18,7 +18,7 @@ export const SectionMembers: FC = ({ className = '' }) => { const [teams, setTeams] = useState([]); const params = useParams(); const lng = params.lng as string; - const { t } = useClientTranslation(lng, 'team'); + const { t } = useClientTranslation('team'); useEffect(() => { const fetchTeamsData = async () => { From e3b958d4c699aec7bcc6f60790513be6fbc49828 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Fri, 4 Oct 2024 21:54:33 +0300 Subject: [PATCH 58/74] add links for member module --- frontend-next-migration/src/entities/Member/index.ts | 8 ++++---- frontend-next-migration/src/entities/Member/ui/index.ts | 2 ++ .../src/widgets/SectionMembers/ui/SectionMembers.tsx | 4 +--- 3 files changed, 7 insertions(+), 7 deletions(-) create mode 100644 frontend-next-migration/src/entities/Member/ui/index.ts diff --git a/frontend-next-migration/src/entities/Member/index.ts b/frontend-next-migration/src/entities/Member/index.ts index 125c49e5f..05896431d 100644 --- a/frontend-next-migration/src/entities/Member/index.ts +++ b/frontend-next-migration/src/entities/Member/index.ts @@ -1,4 +1,4 @@ -import {groupsWithMembersLocally} from './model/data/membersLocally' -export type {Member,GroupWithMember} from './model/types/types' - -export {groupsWithMembersLocally} from './model/data/membersLocally' \ No newline at end of file +export { default as fetchTeams } from './api/membersApi'; +export { MemberItem, DepartmentItem } from './ui'; +export * from './model/types/types'; +export * from './api/mappers'; diff --git a/frontend-next-migration/src/entities/Member/ui/index.ts b/frontend-next-migration/src/entities/Member/ui/index.ts new file mode 100644 index 000000000..002f98191 --- /dev/null +++ b/frontend-next-migration/src/entities/Member/ui/index.ts @@ -0,0 +1,2 @@ +export { default as MemberItem } from './MemberItem'; +export { default as DepartmentItem } from './DepartmentItem'; diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx index 39580aba5..a8f3a2fac 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx @@ -1,14 +1,12 @@ import cls from './SectionMembers.module.scss'; import { FC, useEffect, useState } from 'react'; import { useParams } from 'next/navigation'; -import { fetchTeams } from '../../../entities/Member/api/membersApi'; +import { fetchTeams, MemberItem, DepartmentItem } from '@/entities/Member'; import { Team } from '@/entities/Member/model/types/types'; import { ScrollBottomButton } from '@/features/ScrollBottom'; import { classNames } from '@/shared/lib/classNames/classNames'; import { Container } from '@/shared/ui/Container'; -import DepartmentItem from '../../../entities/Member/ui/DepartmentItem'; import { useClientTranslation } from '@/shared/i18n'; -import MemberItem from '@/entities/Member/ui/MemberItem'; interface WorkersSectionProps { className?: string; From 2bc752d6a53fda04eb676493f6b15e3c83f35ae4 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Fri, 4 Oct 2024 21:55:21 +0300 Subject: [PATCH 59/74] add better naming for member functions --- .../src/entities/Member/api/mappers.ts | 16 +++++++--------- .../src/entities/Member/api/membersApi.ts | 10 ++++++---- .../src/entities/Member/ui/MemberItem.tsx | 6 +++--- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/frontend-next-migration/src/entities/Member/api/mappers.ts b/frontend-next-migration/src/entities/Member/api/mappers.ts index 19636770b..b37276b2f 100644 --- a/frontend-next-migration/src/entities/Member/api/mappers.ts +++ b/frontend-next-migration/src/entities/Member/api/mappers.ts @@ -1,8 +1,3 @@ -/** - * This file contains mapping functions used to transform data from the API response - * into a format that matches the application's data models. - * It includes functions for mapping members, departments, and icons. - */ import { Member, Department } from '@/entities/Member/model/types/types'; import { faGlobe, faEnvelope } from '@fortawesome/free-solid-svg-icons'; import { @@ -12,7 +7,10 @@ import { faFacebook, } from '@fortawesome/free-brands-svg-icons'; -export const LinksMap = () => ({ +/** + * LinksMap provides a mapping of link types to FontAwesome icons. + */ +export const getLinksMap = () => ({ website: faGlobe, github: faGithub, linkedin: faLinkedin, @@ -27,7 +25,7 @@ export const LinksMap = () => ({ * @param membersData An array of raw member data from the API. * @returns An array of members mapped to the Member type. */ -export const mapMembers = (membersData: any[]): Member[] => { +export const getMappedMembers = (membersData: any[]): Member[] => { return ( membersData .map((member: any) => { @@ -62,7 +60,7 @@ export const mapMembers = (membersData: any[]): Member[] => { * @param locale The language locale used to find the localized department name. * @returns An array of departments mapped to the Department type. */ -export const mapDepartments = ( +export const getMappedDepartments = ( departmentsData: any[], locale: string, ): Department[] => { @@ -101,7 +99,7 @@ export const mapDepartments = ( ? localizedDept.attributes.Name : dept.attributes.Name; - const members = mapMembers(dept.attributes.members?.data || []); + const members = getMappedMembers(dept.attributes.members?.data || []); return { id: dept.id, diff --git a/frontend-next-migration/src/entities/Member/api/membersApi.ts b/frontend-next-migration/src/entities/Member/api/membersApi.ts index 104e64c2a..209cc1fce 100644 --- a/frontend-next-migration/src/entities/Member/api/membersApi.ts +++ b/frontend-next-migration/src/entities/Member/api/membersApi.ts @@ -1,11 +1,11 @@ /** - * This file provides API functions related to fetching team data, including teams,members, logos and departments. + * This file provides API functions related to fetching team data, including teams, members, logos, and departments. * It handles fetching data from Strapi, mapping the data to the correct types, and sorting teams accordingly. */ import { envHelper } from '@/shared/const/envHelper'; import { Team } from '@/entities/Member/model/types/types'; -import { mapMembers, mapDepartments } from './mappers'; +import { getMappedMembers, getMappedDepartments } from './mappers'; /** * Fetches a list of teams, including their members and departments, from the Strapi API. @@ -26,8 +26,8 @@ export const fetchTeams = async (locale: string = 'en'): Promise => { const teamData = await response.json(); const teams: Team[] = teamData.data.map((item: any) => { - let members = mapMembers(item.attributes.members?.data || []); - const departments = mapDepartments( + let members = getMappedMembers(item.attributes.members?.data || []); + const departments = getMappedDepartments( item.attributes.departments?.data || [], strapiLocale, ); @@ -89,3 +89,5 @@ export const fetchTeams = async (locale: string = 'en'): Promise => { return []; } }; + +export default fetchTeams; diff --git a/frontend-next-migration/src/entities/Member/ui/MemberItem.tsx b/frontend-next-migration/src/entities/Member/ui/MemberItem.tsx index 78e9c9974..eb4126197 100644 --- a/frontend-next-migration/src/entities/Member/ui/MemberItem.tsx +++ b/frontend-next-migration/src/entities/Member/ui/MemberItem.tsx @@ -4,13 +4,13 @@ import { Member } from '@/entities/Member/model/types/types'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import cls from './MemberItem.module.scss'; import Image from 'next/image'; -import { LinksMap } from '@/entities/Member/api/mappers'; +import { getLinksMap } from '@/entities/Member/api/mappers'; const MemberItem: FC<{ member: Member }> = ({ member }) => { - const linksMap = LinksMap(); + const linksMap = getLinksMap(); return ( -
    • +
    • {member.name} From 35e2d90fce1e86b5c57f7011bbf76a0e79560bbf Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Fri, 4 Oct 2024 22:16:51 +0300 Subject: [PATCH 60/74] refactor membersApi as redux add new rtk on sectionMembers add connection to storeProvider --- .../_providers/StoreProvider/config/store.ts | 137 ++++++++-------- .../src/entities/Member/api/membersApi.ts | 154 ++++++++---------- .../src/entities/Member/index.ts | 2 +- .../SectionMembers/ui/SectionMembers.tsx | 24 +-- 4 files changed, 149 insertions(+), 168 deletions(-) diff --git a/frontend-next-migration/src/app/_providers/StoreProvider/config/store.ts b/frontend-next-migration/src/app/_providers/StoreProvider/config/store.ts index a2a2bfc84..58e275974 100644 --- a/frontend-next-migration/src/app/_providers/StoreProvider/config/store.ts +++ b/frontend-next-migration/src/app/_providers/StoreProvider/config/store.ts @@ -1,79 +1,76 @@ -import {combineReducers, configureStore} from "@reduxjs/toolkit"; -import { persistStore, persistReducer } from 'redux-persist' +import { combineReducers, configureStore } from '@reduxjs/toolkit'; +import { persistStore, persistReducer } from 'redux-persist'; import createWebStorage from 'redux-persist/lib/storage/createWebStorage'; -import {envHelper} from "@/shared/const/envHelper"; -import {StateSchema} from "./StateSchema"; -import {authUserReducer, authMiddleware} from "@/entities/Auth"; -import {FLUSH, PAUSE, PERSIST, PURGE, REGISTER, REHYDRATE} from "redux-persist"; -import {setupListeners} from "@reduxjs/toolkit/query"; -import {gameApi} from "@/shared/api"; - - -const createNoopStorage= () => { - return { - getItem(_key: any){ - return Promise.resolve(null) - }, - setItem(_key: any, value: any){ - return Promise.resolve(value) - }, - removeItem(_key: any){ - return Promise.resolve() - } - - } -} +import { envHelper } from '@/shared/const/envHelper'; +import { StateSchema } from './StateSchema'; +import { authUserReducer, authMiddleware } from '@/entities/Auth'; +import { + FLUSH, + PAUSE, + PERSIST, + PURGE, + REGISTER, + REHYDRATE, +} from 'redux-persist'; +import { setupListeners } from '@reduxjs/toolkit/query'; +import { gameApi } from '@/shared/api'; +import { teamApi } from '@/entities/Member/api/membersApi'; + +const createNoopStorage = () => { + return { + getItem(_key: any) { + return Promise.resolve(null); + }, + setItem(_key: any, value: any) { + return Promise.resolve(value); + }, + removeItem(_key: any) { + return Promise.resolve(); + }, + }; +}; const storage = - typeof window !== "undefined" - ? createWebStorage("local") - : createNoopStorage(); - + typeof window !== 'undefined' + ? createWebStorage('local') + : createNoopStorage(); export function createReduxStore(initialState?: StateSchema) { + const rootReducer = combineReducers({ + authUser: authUserReducer, + [gameApi.reducerPath]: gameApi.reducer, + [teamApi.reducerPath]: teamApi.reducer, // Lisää teamApi.reducer + }); + + const persistConfig = { + key: 'root', + storage, + blacklist: [gameApi.reducerPath, teamApi.reducerPath], // Lisää teamApi.reducerPath mustalle listalle + }; + + const persistedReducer = persistReducer(persistConfig, rootReducer); + + const store = configureStore({ + // reducer: rootReducer, + reducer: persistedReducer, + //only in dev mode + devTools: envHelper.isDevMode, + preloadedState: initialState, + middleware: (getDefaultMiddleware) => + getDefaultMiddleware({ + serializableCheck: { + ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER], + }, + }).concat( + gameApi.middleware, + teamApi.middleware, // Lisää teamApi.middleware + authMiddleware, + ), + }); - const rootReducer = combineReducers({ - authUser: authUserReducer, - [gameApi.reducerPath]: gameApi.reducer, - // todo add here strapiApi - }); - - const persistConfig = { - key: 'root', - storage, - // todo add here strapiApi - blacklist: [gameApi.reducerPath] - }; - - - const persistedReducer = persistReducer(persistConfig, rootReducer); - - - const store = configureStore({ - // reducer: rootReducer, - reducer: persistedReducer, - //only in dev mode - devTools: envHelper.isDevMode, - - preloadedState: initialState, - - middleware: (getDefaultMiddleware) => - getDefaultMiddleware({ - serializableCheck: { - ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER], - }, - }).concat( - gameApi.middleware, - authMiddleware, - ), - - }); - - const persistor = persistStore(store); - - setupListeners(store.dispatch); + const persistor = persistStore(store); - return { store, persistor }; + setupListeners(store.dispatch); + return { store, persistor }; } - diff --git a/frontend-next-migration/src/entities/Member/api/membersApi.ts b/frontend-next-migration/src/entities/Member/api/membersApi.ts index 209cc1fce..6fb2fe235 100644 --- a/frontend-next-migration/src/entities/Member/api/membersApi.ts +++ b/frontend-next-migration/src/entities/Member/api/membersApi.ts @@ -1,93 +1,83 @@ -/** - * This file provides API functions related to fetching team data, including teams, members, logos, and departments. - * It handles fetching data from Strapi, mapping the data to the correct types, and sorting teams accordingly. - */ - -import { envHelper } from '@/shared/const/envHelper'; +import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; import { Team } from '@/entities/Member/model/types/types'; import { getMappedMembers, getMappedDepartments } from './mappers'; +import { envHelper } from '@/shared/const/envHelper'; -/** - * Fetches a list of teams, including their members and departments, from the Strapi API. - * @param locale The language locale to be used for fetching data. Defaults to 'en'. - * @returns A Promise that resolves to an array of teams. - */ -export const fetchTeams = async (locale: string = 'en'): Promise => { - try { - const strapiLocale = locale === 'fi' ? 'fi-FI' : 'en'; - const response = await fetch( - `${envHelper.strapiApiUrl}/teams?locale=${strapiLocale}&populate=departments.localizations,members.Logo,departments.members.Logo`, - ); - - if (!response.ok) { - throw new Error(`Error fetching teams: ${response.statusText}`); - } - - const teamData = await response.json(); +// Määritä API slice +export const teamApi = createApi({ + reducerPath: 'teamApi', + baseQuery: fetchBaseQuery({ baseUrl: envHelper.strapiApiUrl }), + endpoints: (builder) => ({ + fetchTeams: builder.query({ + query: (locale = 'en') => { + const strapiLocale = locale === 'fi' ? 'fi-FI' : 'en'; + return `/teams?locale=${strapiLocale}&populate=departments.localizations,members.Logo,departments.members.Logo`; + }, + transformResponse: (response: any, meta, arg) => { + const strapiLocale = arg === 'fi' ? 'fi-FI' : 'en'; - const teams: Team[] = teamData.data.map((item: any) => { - let members = getMappedMembers(item.attributes.members?.data || []); - const departments = getMappedDepartments( - item.attributes.departments?.data || [], - strapiLocale, - ); + const teams: Team[] = response.data.map((item: any) => { + let members = getMappedMembers(item.attributes.members?.data || []); + const departments = getMappedDepartments( + item.attributes.departments?.data || [], + strapiLocale, + ); - const departmentMemberIds = departments.flatMap((dept) => - dept.members.map((member) => member.id), - ); - members = members.filter( - (member) => !departmentMemberIds.includes(member.id), - ); + const departmentMemberIds = departments.flatMap((dept) => + dept.members.map((member) => member.id), + ); + members = members.filter( + (member) => !departmentMemberIds.includes(member.id), + ); - return { - id: item.id, - name: item.attributes.Team || item.attributes.Name, - createdAt: item.attributes.createdAt, - updatedAt: item.attributes.updatedAt, - locale: item.attributes.locale, - members, - departments, - }; - }); + return { + id: item.id, + name: item.attributes.Team || item.attributes.Name, + createdAt: item.attributes.createdAt, + updatedAt: item.attributes.updatedAt, + locale: item.attributes.locale, + members, + departments, + }; + }); - const orderEn = [ - 'Game Design', - 'Mentoring', - 'Programming', - 'Graphics', - 'Sounds', - 'Comic book', - 'Production', - 'Analysis', - 'Art', - 'Game Art Education Package', - 'Other Participants', - 'Special Thanks', - ]; + const orderEn = [ + 'Game Design', + 'Mentoring', + 'Programming', + 'Graphics', + 'Sounds', + 'Comic book', + 'Production', + 'Analysis', + 'Art', + 'Game Art Education Package', + 'Other Participants', + 'Special Thanks', + ]; - const orderFi = [ - 'Pelisuunnittelu', - 'Mentorointi', - 'Ohjelmointi', - 'Grafiikka', - 'Äänet', - 'Sarjakuva', - 'Tuotanto', - 'Analyysi', - 'Pelitaiteen opetuspaketti', - 'Muut mukana olleet', - 'Erityiskiitokset', - ]; + const orderFi = [ + 'Pelisuunnittelu', + 'Mentorointi', + 'Ohjelmointi', + 'Grafiikka', + 'Äänet', + 'Sarjakuva', + 'Tuotanto', + 'Analyysi', + 'Pelitaiteen opetuspaketti', + 'Muut mukana olleet', + 'Erityiskiitokset', + ]; - const order = locale === 'fi' ? orderFi : orderEn; + const order = arg === 'fi' ? orderFi : orderEn; - return teams.sort( - (a: Team, b: Team) => order.indexOf(a.name) - order.indexOf(b.name), - ); - } catch (error) { - console.error('Error fetching teams data:', error); - return []; - } -}; + return teams.sort( + (a, b) => order.indexOf(a.name) - order.indexOf(b.name), + ); + }, + }), + }), +}); -export default fetchTeams; +export const { useFetchTeamsQuery } = teamApi; diff --git a/frontend-next-migration/src/entities/Member/index.ts b/frontend-next-migration/src/entities/Member/index.ts index 05896431d..c9ad9f97f 100644 --- a/frontend-next-migration/src/entities/Member/index.ts +++ b/frontend-next-migration/src/entities/Member/index.ts @@ -1,4 +1,4 @@ -export { default as fetchTeams } from './api/membersApi'; +export { useFetchTeamsQuery } from './api/membersApi'; export { MemberItem, DepartmentItem } from './ui'; export * from './model/types/types'; export * from './api/mappers'; diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx index a8f3a2fac..adb812825 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx @@ -1,34 +1,28 @@ import cls from './SectionMembers.module.scss'; -import { FC, useEffect, useState } from 'react'; +import { FC } from 'react'; import { useParams } from 'next/navigation'; -import { fetchTeams, MemberItem, DepartmentItem } from '@/entities/Member'; -import { Team } from '@/entities/Member/model/types/types'; +import { useFetchTeamsQuery } from '@/entities/Member/api/membersApi'; import { ScrollBottomButton } from '@/features/ScrollBottom'; import { classNames } from '@/shared/lib/classNames/classNames'; import { Container } from '@/shared/ui/Container'; import { useClientTranslation } from '@/shared/i18n'; +import MemberItem from '@/entities/Member/ui/MemberItem'; +import DepartmentItem from '@/entities/Member/ui/DepartmentItem'; interface WorkersSectionProps { className?: string; } export const SectionMembers: FC = ({ className = '' }) => { - const [teams, setTeams] = useState([]); const params = useParams(); const lng = params.lng as string; const { t } = useClientTranslation('team'); - useEffect(() => { - const fetchTeamsData = async () => { - try { - const data = await fetchTeams(lng); - setTeams(data); - } catch (error) { - console.error('Failed to fetch teams:', error); - } - }; - fetchTeamsData(); - }, [lng]); + const { data: teams = [], isError } = useFetchTeamsQuery(lng); + + if (isError) { + return

      Error fetching teams data

      ; + } return (
      From b830a1df9ece94b92ce9dd5b4e34a6db3f8af008 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Sat, 5 Oct 2024 17:09:53 +0300 Subject: [PATCH 61/74] fix correct import and usage of useGetTeamsQuery hook from membersApi --- frontend-next-migration/src/entities/Member/api/index.ts | 1 + frontend-next-migration/src/entities/Member/api/membersApi.ts | 3 +-- frontend-next-migration/src/entities/Member/index.ts | 3 --- .../src/widgets/SectionMembers/ui/SectionMembers.tsx | 4 ++-- 4 files changed, 4 insertions(+), 7 deletions(-) create mode 100644 frontend-next-migration/src/entities/Member/api/index.ts diff --git a/frontend-next-migration/src/entities/Member/api/index.ts b/frontend-next-migration/src/entities/Member/api/index.ts new file mode 100644 index 000000000..1105004f6 --- /dev/null +++ b/frontend-next-migration/src/entities/Member/api/index.ts @@ -0,0 +1 @@ +export { useGetTeamsQuery } from './membersApi'; diff --git a/frontend-next-migration/src/entities/Member/api/membersApi.ts b/frontend-next-migration/src/entities/Member/api/membersApi.ts index 6fb2fe235..7217b7224 100644 --- a/frontend-next-migration/src/entities/Member/api/membersApi.ts +++ b/frontend-next-migration/src/entities/Member/api/membersApi.ts @@ -3,7 +3,6 @@ import { Team } from '@/entities/Member/model/types/types'; import { getMappedMembers, getMappedDepartments } from './mappers'; import { envHelper } from '@/shared/const/envHelper'; -// Määritä API slice export const teamApi = createApi({ reducerPath: 'teamApi', baseQuery: fetchBaseQuery({ baseUrl: envHelper.strapiApiUrl }), @@ -80,4 +79,4 @@ export const teamApi = createApi({ }), }); -export const { useFetchTeamsQuery } = teamApi; +export const { useFetchTeamsQuery: useGetTeamsQuery } = teamApi; diff --git a/frontend-next-migration/src/entities/Member/index.ts b/frontend-next-migration/src/entities/Member/index.ts index c9ad9f97f..772f74e8c 100644 --- a/frontend-next-migration/src/entities/Member/index.ts +++ b/frontend-next-migration/src/entities/Member/index.ts @@ -1,4 +1 @@ -export { useFetchTeamsQuery } from './api/membersApi'; export { MemberItem, DepartmentItem } from './ui'; -export * from './model/types/types'; -export * from './api/mappers'; diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx index adb812825..52439b57f 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx @@ -1,7 +1,7 @@ import cls from './SectionMembers.module.scss'; import { FC } from 'react'; import { useParams } from 'next/navigation'; -import { useFetchTeamsQuery } from '@/entities/Member/api/membersApi'; +import { useGetTeamsQuery } from '@/entities/Member/api'; import { ScrollBottomButton } from '@/features/ScrollBottom'; import { classNames } from '@/shared/lib/classNames/classNames'; import { Container } from '@/shared/ui/Container'; @@ -18,7 +18,7 @@ export const SectionMembers: FC = ({ className = '' }) => { const lng = params.lng as string; const { t } = useClientTranslation('team'); - const { data: teams = [], isError } = useFetchTeamsQuery(lng); + const { data: teams = [], isError } = useGetTeamsQuery(lng); if (isError) { return

      Error fetching teams data

      ; From 9928b312f153a23fffc566725ebac371a62a51b4 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Sat, 5 Oct 2024 17:20:08 +0300 Subject: [PATCH 62/74] delete comments --- .../src/app/_providers/StoreProvider/config/store.ts | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/frontend-next-migration/src/app/_providers/StoreProvider/config/store.ts b/frontend-next-migration/src/app/_providers/StoreProvider/config/store.ts index 58e275974..4d221f4b7 100644 --- a/frontend-next-migration/src/app/_providers/StoreProvider/config/store.ts +++ b/frontend-next-migration/src/app/_providers/StoreProvider/config/store.ts @@ -39,13 +39,13 @@ export function createReduxStore(initialState?: StateSchema) { const rootReducer = combineReducers({ authUser: authUserReducer, [gameApi.reducerPath]: gameApi.reducer, - [teamApi.reducerPath]: teamApi.reducer, // Lisää teamApi.reducer + [teamApi.reducerPath]: teamApi.reducer, }); const persistConfig = { key: 'root', storage, - blacklist: [gameApi.reducerPath, teamApi.reducerPath], // Lisää teamApi.reducerPath mustalle listalle + blacklist: [gameApi.reducerPath, teamApi.reducerPath], }; const persistedReducer = persistReducer(persistConfig, rootReducer); @@ -61,11 +61,7 @@ export function createReduxStore(initialState?: StateSchema) { serializableCheck: { ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER], }, - }).concat( - gameApi.middleware, - teamApi.middleware, // Lisää teamApi.middleware - authMiddleware, - ), + }).concat(gameApi.middleware, teamApi.middleware, authMiddleware), }); const persistor = persistStore(store); From 83dacc80d3c438b01a3c496c58910549aeeaa53e Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Sat, 5 Oct 2024 17:20:58 +0300 Subject: [PATCH 63/74] add teamApi for stateSchema --- .../_providers/StoreProvider/config/StateSchema.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/frontend-next-migration/src/app/_providers/StoreProvider/config/StateSchema.ts b/frontend-next-migration/src/app/_providers/StoreProvider/config/StateSchema.ts index de84a648b..fd912c19c 100644 --- a/frontend-next-migration/src/app/_providers/StoreProvider/config/StateSchema.ts +++ b/frontend-next-migration/src/app/_providers/StoreProvider/config/StateSchema.ts @@ -1,9 +1,9 @@ -import {AuthUserSchema} from "@/entities/Auth"; -import {gameApi} from "@/shared/api"; +import { AuthUserSchema } from '@/entities/Auth'; +import { gameApi } from '@/shared/api'; +import { teamApi } from '@/entities/Member/api/membersApi'; export interface StateSchema { - authUser: AuthUserSchema; - [gameApi.reducerPath]: ReturnType; - // todo add here strapiApi + authUser: AuthUserSchema; + [gameApi.reducerPath]: ReturnType; + [teamApi.reducerPath]: ReturnType; } - From ba1c0d5fc80d555988d6b6454e963cf5f8f447d5 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Sat, 5 Oct 2024 17:28:08 +0300 Subject: [PATCH 64/74] refactor: update function names for clarity and remove 'map' references --- .../src/entities/Member/api/mappers.ts | 8 ++++---- .../src/entities/Member/api/membersApi.ts | 6 +++--- .../src/entities/Member/ui/MemberItem.tsx | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/frontend-next-migration/src/entities/Member/api/mappers.ts b/frontend-next-migration/src/entities/Member/api/mappers.ts index b37276b2f..e159cb7d3 100644 --- a/frontend-next-migration/src/entities/Member/api/mappers.ts +++ b/frontend-next-migration/src/entities/Member/api/mappers.ts @@ -10,7 +10,7 @@ import { /** * LinksMap provides a mapping of link types to FontAwesome icons. */ -export const getLinksMap = () => ({ +export const getLinks = () => ({ website: faGlobe, github: faGithub, linkedin: faLinkedin, @@ -25,7 +25,7 @@ export const getLinksMap = () => ({ * @param membersData An array of raw member data from the API. * @returns An array of members mapped to the Member type. */ -export const getMappedMembers = (membersData: any[]): Member[] => { +export const getMembers = (membersData: any[]): Member[] => { return ( membersData .map((member: any) => { @@ -60,7 +60,7 @@ export const getMappedMembers = (membersData: any[]): Member[] => { * @param locale The language locale used to find the localized department name. * @returns An array of departments mapped to the Department type. */ -export const getMappedDepartments = ( +export const getDepartments = ( departmentsData: any[], locale: string, ): Department[] => { @@ -99,7 +99,7 @@ export const getMappedDepartments = ( ? localizedDept.attributes.Name : dept.attributes.Name; - const members = getMappedMembers(dept.attributes.members?.data || []); + const members = getMembers(dept.attributes.members?.data || []); return { id: dept.id, diff --git a/frontend-next-migration/src/entities/Member/api/membersApi.ts b/frontend-next-migration/src/entities/Member/api/membersApi.ts index 7217b7224..ade984000 100644 --- a/frontend-next-migration/src/entities/Member/api/membersApi.ts +++ b/frontend-next-migration/src/entities/Member/api/membersApi.ts @@ -1,6 +1,6 @@ import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; import { Team } from '@/entities/Member/model/types/types'; -import { getMappedMembers, getMappedDepartments } from './mappers'; +import { getMembers, getDepartments } from './mappers'; import { envHelper } from '@/shared/const/envHelper'; export const teamApi = createApi({ @@ -16,8 +16,8 @@ export const teamApi = createApi({ const strapiLocale = arg === 'fi' ? 'fi-FI' : 'en'; const teams: Team[] = response.data.map((item: any) => { - let members = getMappedMembers(item.attributes.members?.data || []); - const departments = getMappedDepartments( + let members = getMembers(item.attributes.members?.data || []); + const departments = getDepartments( item.attributes.departments?.data || [], strapiLocale, ); diff --git a/frontend-next-migration/src/entities/Member/ui/MemberItem.tsx b/frontend-next-migration/src/entities/Member/ui/MemberItem.tsx index eb4126197..7491bb62d 100644 --- a/frontend-next-migration/src/entities/Member/ui/MemberItem.tsx +++ b/frontend-next-migration/src/entities/Member/ui/MemberItem.tsx @@ -4,10 +4,10 @@ import { Member } from '@/entities/Member/model/types/types'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import cls from './MemberItem.module.scss'; import Image from 'next/image'; -import { getLinksMap } from '@/entities/Member/api/mappers'; +import { getLinks } from '@/entities/Member/api/mappers'; const MemberItem: FC<{ member: Member }> = ({ member }) => { - const linksMap = getLinksMap(); + const linksMap = getLinks(); return (
    • From bd638be5dbf7cf4e2fa14dcd545f694544c65047 Mon Sep 17 00:00:00 2001 From: Joni Roine Date: Sat, 5 Oct 2024 17:35:22 +0300 Subject: [PATCH 65/74] fix correct path via envHelper --- frontend-next-migration/src/entities/Member/api/mappers.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend-next-migration/src/entities/Member/api/mappers.ts b/frontend-next-migration/src/entities/Member/api/mappers.ts index e159cb7d3..74e6308c3 100644 --- a/frontend-next-migration/src/entities/Member/api/mappers.ts +++ b/frontend-next-migration/src/entities/Member/api/mappers.ts @@ -1,5 +1,6 @@ import { Member, Department } from '@/entities/Member/model/types/types'; import { faGlobe, faEnvelope } from '@fortawesome/free-solid-svg-icons'; +import { envHelper } from '@/shared/const/envHelper'; import { faGithub, faLinkedin, @@ -30,7 +31,7 @@ export const getMembers = (membersData: any[]): Member[] => { membersData .map((member: any) => { const logoUrl = member.attributes.Logo?.data?.attributes?.url - ? `${process.env.NEXT_PUBLIC_STRAPI_HOST}${member.attributes.Logo.data.attributes.url}` + ? `${envHelper.strapiHost}${member.attributes.Logo.data.attributes.url}` : null; return { From 0c77243629bb455d8fc04c2e2d280b2da844d97d Mon Sep 17 00:00:00 2001 From: leolab1337 <61798137+leolab1337@users.noreply.github.com> Date: Mon, 7 Oct 2024 12:58:50 +0300 Subject: [PATCH 66/74] Refactor import paths in membersApi.ts Reorganize import paths to use relative paths for `Team` and mappers functions. This aligns with the project's import conventions and improves maintainability. --- frontend-next-migration/src/entities/Member/api/membersApi.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend-next-migration/src/entities/Member/api/membersApi.ts b/frontend-next-migration/src/entities/Member/api/membersApi.ts index ade984000..b1822cd94 100644 --- a/frontend-next-migration/src/entities/Member/api/membersApi.ts +++ b/frontend-next-migration/src/entities/Member/api/membersApi.ts @@ -1,7 +1,7 @@ import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; -import { Team } from '@/entities/Member/model/types/types'; -import { getMembers, getDepartments } from './mappers'; import { envHelper } from '@/shared/const/envHelper'; +import { Team } from '../model/types/types'; +import { getMembers, getDepartments } from './mappers'; export const teamApi = createApi({ reducerPath: 'teamApi', From abba6d7c8e05474f5aea5307e1825be12b330cfa Mon Sep 17 00:00:00 2001 From: leolab1337 <61798137+leolab1337@users.noreply.github.com> Date: Mon, 7 Oct 2024 12:59:28 +0300 Subject: [PATCH 67/74] Fix relative import path in Member mappers module Updated the import statement to use relative path '../model/types/types' instead of absolute path '@/entities/Member/model/types/types'. This change ensures compatibility with the project's module resolution configuration. --- frontend-next-migration/src/entities/Member/api/mappers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend-next-migration/src/entities/Member/api/mappers.ts b/frontend-next-migration/src/entities/Member/api/mappers.ts index 74e6308c3..ddd91676d 100644 --- a/frontend-next-migration/src/entities/Member/api/mappers.ts +++ b/frontend-next-migration/src/entities/Member/api/mappers.ts @@ -1,4 +1,4 @@ -import { Member, Department } from '@/entities/Member/model/types/types'; +import { Member, Department } from '../model/types/types'; import { faGlobe, faEnvelope } from '@fortawesome/free-solid-svg-icons'; import { envHelper } from '@/shared/const/envHelper'; import { From 32bc12a089bfed8c8ede0e798fd781973bc6f19f Mon Sep 17 00:00:00 2001 From: leolab1337 <61798137+leolab1337@users.noreply.github.com> Date: Mon, 7 Oct 2024 13:01:50 +0300 Subject: [PATCH 68/74] Refactor import paths for Member and Department types Updated relative import paths for 'Member' and 'Department' types to ensure better module resolution. Adjusted import order for cleaner and more consistent code organization. --- .../src/entities/Member/ui/DepartmentItem.tsx | 2 +- .../src/entities/Member/ui/MemberItem.tsx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend-next-migration/src/entities/Member/ui/DepartmentItem.tsx b/frontend-next-migration/src/entities/Member/ui/DepartmentItem.tsx index 5693e83d2..4f3e73b5e 100644 --- a/frontend-next-migration/src/entities/Member/ui/DepartmentItem.tsx +++ b/frontend-next-migration/src/entities/Member/ui/DepartmentItem.tsx @@ -1,5 +1,5 @@ import { FC } from 'react'; -import { Department, Member } from '@/entities/Member/model/types/types'; +import { Department, Member } from '../model/types/types'; import cls from './DepartmentItem.module.scss'; import MemberItem from './MemberItem'; diff --git a/frontend-next-migration/src/entities/Member/ui/MemberItem.tsx b/frontend-next-migration/src/entities/Member/ui/MemberItem.tsx index 7491bb62d..9375e97a1 100644 --- a/frontend-next-migration/src/entities/Member/ui/MemberItem.tsx +++ b/frontend-next-migration/src/entities/Member/ui/MemberItem.tsx @@ -1,10 +1,10 @@ import { FC } from 'react'; +import Image from 'next/image'; import Link from 'next/link'; -import { Member } from '@/entities/Member/model/types/types'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { Member } from '../model/types/types'; import cls from './MemberItem.module.scss'; -import Image from 'next/image'; -import { getLinks } from '@/entities/Member/api/mappers'; +import { getLinks } from '../api/mappers'; const MemberItem: FC<{ member: Member }> = ({ member }) => { const linksMap = getLinks(); From 900d96d047e8132ff6d3ec6b6bc42d223b5621bc Mon Sep 17 00:00:00 2001 From: leolab1337 <61798137+leolab1337@users.noreply.github.com> Date: Mon, 7 Oct 2024 13:07:23 +0300 Subject: [PATCH 69/74] Refactor member link type handling Update the MemberItem component to use a more accurate type for the member links by excluding the "id" property. This change ensures type safety and prevents potential runtime errors when accessing link properties. --- frontend-next-migration/src/entities/Member/ui/MemberItem.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend-next-migration/src/entities/Member/ui/MemberItem.tsx b/frontend-next-migration/src/entities/Member/ui/MemberItem.tsx index 9375e97a1..d1e34e1f4 100644 --- a/frontend-next-migration/src/entities/Member/ui/MemberItem.tsx +++ b/frontend-next-migration/src/entities/Member/ui/MemberItem.tsx @@ -30,7 +30,7 @@ const MemberItem: FC<{ member: Member }> = ({ member }) => { )}
    • {Object.entries(linksMap).map(([key, icon]) => { - const link = member[key as keyof Member]; + const link = member[key as keyof Omit]; if (link) { const href = key === 'email' ? `mailto:${link}` : link; const target = key === 'email' ? '_self' : '_blank'; From 15a20cf3a99823d6f36fa8ea2f012a2e5c9503a5 Mon Sep 17 00:00:00 2001 From: leolab1337 <61798137+leolab1337@users.noreply.github.com> Date: Mon, 7 Oct 2024 13:56:01 +0300 Subject: [PATCH 70/74] Add Strapi API integration Introduce Strapi API to the project by creating `strapiApi` in `strapiApi.ts` and updating state schema and store configuration. This ensures the Strapi API can now be utilized alongside the existing game API to manage different data interactions. --- .../StoreProvider/config/StateSchema.ts | 5 ++--- .../app/_providers/StoreProvider/config/store.ts | 16 +++++++++++----- frontend-next-migration/src/shared/api/index.ts | 7 ++++++- .../src/shared/api/strapiApi.ts | 8 ++++++++ 4 files changed, 27 insertions(+), 9 deletions(-) create mode 100644 frontend-next-migration/src/shared/api/strapiApi.ts diff --git a/frontend-next-migration/src/app/_providers/StoreProvider/config/StateSchema.ts b/frontend-next-migration/src/app/_providers/StoreProvider/config/StateSchema.ts index fd912c19c..cde03e5a7 100644 --- a/frontend-next-migration/src/app/_providers/StoreProvider/config/StateSchema.ts +++ b/frontend-next-migration/src/app/_providers/StoreProvider/config/StateSchema.ts @@ -1,9 +1,8 @@ import { AuthUserSchema } from '@/entities/Auth'; -import { gameApi } from '@/shared/api'; -import { teamApi } from '@/entities/Member/api/membersApi'; +import {gameApi, strapiApi} from '@/shared/api'; export interface StateSchema { authUser: AuthUserSchema; [gameApi.reducerPath]: ReturnType; - [teamApi.reducerPath]: ReturnType; + [strapiApi.reducerPath]: ReturnType; } diff --git a/frontend-next-migration/src/app/_providers/StoreProvider/config/store.ts b/frontend-next-migration/src/app/_providers/StoreProvider/config/store.ts index 4d221f4b7..33f6d80a5 100644 --- a/frontend-next-migration/src/app/_providers/StoreProvider/config/store.ts +++ b/frontend-next-migration/src/app/_providers/StoreProvider/config/store.ts @@ -13,8 +13,7 @@ import { REHYDRATE, } from 'redux-persist'; import { setupListeners } from '@reduxjs/toolkit/query'; -import { gameApi } from '@/shared/api'; -import { teamApi } from '@/entities/Member/api/membersApi'; +import {gameApi, strapiApi} from '@/shared/api'; const createNoopStorage = () => { return { @@ -39,13 +38,16 @@ export function createReduxStore(initialState?: StateSchema) { const rootReducer = combineReducers({ authUser: authUserReducer, [gameApi.reducerPath]: gameApi.reducer, - [teamApi.reducerPath]: teamApi.reducer, + [strapiApi.reducerPath]: strapiApi.reducer, }); const persistConfig = { key: 'root', storage, - blacklist: [gameApi.reducerPath, teamApi.reducerPath], + blacklist: [ + gameApi.reducerPath, + strapiApi.reducerPath + ], }; const persistedReducer = persistReducer(persistConfig, rootReducer); @@ -61,7 +63,11 @@ export function createReduxStore(initialState?: StateSchema) { serializableCheck: { ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER], }, - }).concat(gameApi.middleware, teamApi.middleware, authMiddleware), + }).concat( + gameApi.middleware, + strapiApi.middleware, + authMiddleware + ), }); const persistor = persistStore(store); diff --git a/frontend-next-migration/src/shared/api/index.ts b/frontend-next-migration/src/shared/api/index.ts index c932afa59..f29b7d7fc 100644 --- a/frontend-next-migration/src/shared/api/index.ts +++ b/frontend-next-migration/src/shared/api/index.ts @@ -1,4 +1,9 @@ export { gameApi, GameApiCacheTags -} from "./gameApi"; \ No newline at end of file +} from "./gameApi"; + + +export { + strapiApi +} from "./strapiApi"; \ No newline at end of file diff --git a/frontend-next-migration/src/shared/api/strapiApi.ts b/frontend-next-migration/src/shared/api/strapiApi.ts new file mode 100644 index 000000000..8aa9d645b --- /dev/null +++ b/frontend-next-migration/src/shared/api/strapiApi.ts @@ -0,0 +1,8 @@ +import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; +import { envHelper } from '@/shared/const/envHelper'; + +export const strapiApi = createApi({ + reducerPath: 'strapiApi', + baseQuery: fetchBaseQuery({ baseUrl: envHelper.strapiApiUrl }), + endpoints: () => ({}), +}); From 027725fdaa65b64d34d8b3c1bf01be420497584d Mon Sep 17 00:00:00 2001 From: leolab1337 <61798137+leolab1337@users.noreply.github.com> Date: Mon, 7 Oct 2024 13:58:12 +0300 Subject: [PATCH 71/74] Refactor teamApi to use strapiApi for endpoint injection Replaced `createApi` with `strapiApi.injectEndpoints` to streamline API handling. This change reduces redundancy by utilizing the shared `strapiApi` configuration, simplifying the codebase and ensuring consistency in endpoint management. --- .../src/entities/Member/api/membersApi.ts | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/frontend-next-migration/src/entities/Member/api/membersApi.ts b/frontend-next-migration/src/entities/Member/api/membersApi.ts index b1822cd94..9813b84eb 100644 --- a/frontend-next-migration/src/entities/Member/api/membersApi.ts +++ b/frontend-next-migration/src/entities/Member/api/membersApi.ts @@ -1,11 +1,8 @@ -import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; -import { envHelper } from '@/shared/const/envHelper'; +import { strapiApi } from '@/shared/api/strapiApi'; import { Team } from '../model/types/types'; import { getMembers, getDepartments } from './mappers'; -export const teamApi = createApi({ - reducerPath: 'teamApi', - baseQuery: fetchBaseQuery({ baseUrl: envHelper.strapiApiUrl }), +const teamApi = strapiApi.injectEndpoints({ endpoints: (builder) => ({ fetchTeams: builder.query({ query: (locale = 'en') => { @@ -18,15 +15,15 @@ export const teamApi = createApi({ const teams: Team[] = response.data.map((item: any) => { let members = getMembers(item.attributes.members?.data || []); const departments = getDepartments( - item.attributes.departments?.data || [], - strapiLocale, + item.attributes.departments?.data || [], + strapiLocale, ); const departmentMemberIds = departments.flatMap((dept) => - dept.members.map((member) => member.id), + dept.members.map((member) => member.id), ); members = members.filter( - (member) => !departmentMemberIds.includes(member.id), + (member) => !departmentMemberIds.includes(member.id), ); return { @@ -72,11 +69,11 @@ export const teamApi = createApi({ const order = arg === 'fi' ? orderFi : orderEn; return teams.sort( - (a, b) => order.indexOf(a.name) - order.indexOf(b.name), + (a, b) => order.indexOf(a.name) - order.indexOf(b.name), ); }, }), }), }); -export const { useFetchTeamsQuery: useGetTeamsQuery } = teamApi; +export const { useFetchTeamsQuery: useGetTeamsQuery } = teamApi; \ No newline at end of file From 7a6e640202fb49c06faa8e41a20657a5c1a0ce9c Mon Sep 17 00:00:00 2001 From: leolab1337 <61798137+leolab1337@users.noreply.github.com> Date: Mon, 7 Oct 2024 13:58:20 +0300 Subject: [PATCH 72/74] Add useGetTeamsQuery export to Member entity Exporting useGetTeamsQuery enables team data fetching in components utilizing the Member entity. This change simplifies importing necessary hooks directly from the member module. --- frontend-next-migration/src/entities/Member/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend-next-migration/src/entities/Member/index.ts b/frontend-next-migration/src/entities/Member/index.ts index 772f74e8c..a30477143 100644 --- a/frontend-next-migration/src/entities/Member/index.ts +++ b/frontend-next-migration/src/entities/Member/index.ts @@ -1 +1,2 @@ export { MemberItem, DepartmentItem } from './ui'; +export {useGetTeamsQuery} from "./api/membersApi"; \ No newline at end of file From 7247955eb07f97f9b22d063ef796dc8d88b7c094 Mon Sep 17 00:00:00 2001 From: leolab1337 <61798137+leolab1337@users.noreply.github.com> Date: Mon, 7 Oct 2024 14:03:58 +0300 Subject: [PATCH 73/74] Refactor imports in SectionMembers.tsx Consolidate imports from '@/entities/Member' to enhance readability and maintainability. This change groups related imports together, reducing redundancy and improving code organization. --- .../src/widgets/SectionMembers/ui/SectionMembers.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx index 52439b57f..795571788 100644 --- a/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx +++ b/frontend-next-migration/src/widgets/SectionMembers/ui/SectionMembers.tsx @@ -1,13 +1,15 @@ import cls from './SectionMembers.module.scss'; import { FC } from 'react'; import { useParams } from 'next/navigation'; -import { useGetTeamsQuery } from '@/entities/Member/api'; import { ScrollBottomButton } from '@/features/ScrollBottom'; import { classNames } from '@/shared/lib/classNames/classNames'; import { Container } from '@/shared/ui/Container'; import { useClientTranslation } from '@/shared/i18n'; -import MemberItem from '@/entities/Member/ui/MemberItem'; -import DepartmentItem from '@/entities/Member/ui/DepartmentItem'; +import { + DepartmentItem, + MemberItem, + useGetTeamsQuery +} from '@/entities/Member'; interface WorkersSectionProps { className?: string; From ac51dbf8c6195e0fc361598f9ca0ec73e5e4ad34 Mon Sep 17 00:00:00 2001 From: leolab1337 <61798137+leolab1337@users.noreply.github.com> Date: Mon, 7 Oct 2024 14:12:21 +0300 Subject: [PATCH 74/74] Add Strapi environment variables to CI workflow This commit introduces NEXT_PUBLIC_STRAPI_API_URL and NEXT_PUBLIC_STRAPI_HOST to the CI workflow. These additional environment variables are necessary for testing and building Strapi-dependent features. --- .github/workflows/ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4d29d9da9..90caf7cf5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,6 +36,9 @@ jobs: NEXT_PUBLIC_API_LINK: ${{ secrets.NEXT_PUBLIC_API_LINK }} NEXT_PUBLIC_API_DOMAIN: ${{ secrets.NEXT_PUBLIC_API_DOMAIN }} NEXT_PUBLIC_LOCAL_HOST: ${{ secrets.NEXT_PUBLIC_LOCAL_HOST }} + NEXT_PUBLIC_STRAPI_API_URL: ${{ secrets.NEXT_PUBLIC_STRAPI_API_URL }} + NEXT_PUBLIC_STRAPI_HOST: ${{ secrets.NEXT_PUBLIC_STRAPI_HOST }} + - name: Run tests run: npm test @@ -44,6 +47,8 @@ jobs: NEXT_PUBLIC_API_LINK: ${{ secrets.NEXT_PUBLIC_API_LINK }} NEXT_PUBLIC_API_DOMAIN: ${{ secrets.NEXT_PUBLIC_API_DOMAIN }} NEXT_PUBLIC_LOCAL_HOST: ${{ secrets.NEXT_PUBLIC_LOCAL_HOST }} + NEXT_PUBLIC_STRAPI_API_URL: ${{ secrets.NEXT_PUBLIC_STRAPI_API_URL }} + NEXT_PUBLIC_STRAPI_HOST: ${{ secrets.NEXT_PUBLIC_STRAPI_HOST }} # - name: Run Cypress tests # run: npm run cypress:run