From 2642a10e3df39284b9811529c16e5cabca615f67 Mon Sep 17 00:00:00 2001 From: Bogdan Date: Wed, 13 Nov 2024 09:31:45 +0200 Subject: [PATCH] 560-refactor: Widget principles (#636) * refactor: 560 - principles scss to modules * refactor: 560 - principle card to scss modules * refactor: 560 - move principles to separate folder * refactor: 560 - replace divs with semantic tags * fix: 560 - test issue * refactor: 560 - replace interface with type * refactor: 560 - move data to dev-data folder * refactor: 560 - remove unnecessary z-indexes * refactor: 560 - remove file extensions from import statements * fix: 560 - test case --- dev-data/index.ts | 1 + .../principle-cards.data.tsx | 15 +-- src/shared/icons/index.tsx | 3 - .../icons/open-source-philosophy-icon.tsx | 6 -- src/shared/icons/open-to-everyone-icon.tsx | 6 -- src/shared/icons/teach-It-forward-icon.tsx | 6 -- src/widgets/principles/index.ts | 3 +- src/widgets/principles/types.ts | 7 ++ ...e-card.scss => principle-card.module.scss} | 91 +++++++++---------- .../ui/principle-card/principle-card.tsx | 31 +++---- .../ui/principle-card/principles.tsx | 18 ---- .../principles.module.scss} | 14 +-- .../{ => ui/principles}/principles.test.tsx | 11 ++- .../principles/ui/principles/principles.tsx | 23 +++++ 14 files changed, 104 insertions(+), 131 deletions(-) rename src/widgets/principles/constants.tsx => dev-data/principle-cards.data.tsx (50%) delete mode 100644 src/shared/icons/open-source-philosophy-icon.tsx delete mode 100644 src/shared/icons/open-to-everyone-icon.tsx delete mode 100644 src/shared/icons/teach-It-forward-icon.tsx create mode 100644 src/widgets/principles/types.ts rename src/widgets/principles/ui/principle-card/{principle-card.scss => principle-card.module.scss} (60%) delete mode 100644 src/widgets/principles/ui/principle-card/principles.tsx rename src/widgets/principles/ui/{principle-card/principles.scss => principles/principles.module.scss} (51%) rename src/widgets/principles/{ => ui/principles}/principles.test.tsx (71%) create mode 100644 src/widgets/principles/ui/principles/principles.tsx diff --git a/dev-data/index.ts b/dev-data/index.ts index 3b0fc03f1..dbea3caf8 100644 --- a/dev-data/index.ts +++ b/dev-data/index.ts @@ -55,6 +55,7 @@ export { mentorshipCourses, mentorshipCoursesDefault } from './mentorship.data'; export { nodejs } from './nodejs.data'; export { picturesSocialMediaLinks } from './pictures.data'; export { preSchoolEn, preSchoolRu } from './preSchool.data'; +export { principleCards } from './principle-cards.data'; export { reactEn } from './react-en.data'; export { reactRu } from './react-ru.data'; export { requirementsData } from './requirements.data'; diff --git a/src/widgets/principles/constants.tsx b/dev-data/principle-cards.data.tsx similarity index 50% rename from src/widgets/principles/constants.tsx rename to dev-data/principle-cards.data.tsx index 0a0f9be1c..b94416c33 100644 --- a/src/widgets/principles/constants.tsx +++ b/dev-data/principle-cards.data.tsx @@ -1,23 +1,26 @@ -import { PrincipleCardProps } from './ui/principle-card/principle-card'; -import { OpenSourcePhilosophyIcon, OpenToEveryoneIcon, TeachItForwardIcon } from '@/shared/icons'; +import Image from 'next/image'; +import openSourcePhilosophyIcon from '@/shared/assets/svg/openSourcePhilosophyIcon.svg'; +import openToEveryoneIcon from '@/shared/assets/svg/openToEveryoneIcon.svg'; +import teachItForwardIcon from '@/shared/assets/svg/teachItForwardIcon.svg'; +import { PrincipleCard } from '@/widgets/principles'; -export const cards: PrincipleCardProps[] = [ +export const principleCards: PrincipleCard[] = [ { title: 'Open to everyone', description: 'Free courses, no obligations, and no contracts. No age limit. Only students’ time and dedication are required. Students can repeatedly attend courses.', - icon: , + icon: , }, { title: 'Open source philosophy', description: 'Our Learning Management System platform and educational materials are publicly available on GitHub and YouTube.', - icon: , + icon: , }, { title: '"Teach it forward"', description: 'Students study at school for free, but we request that they return as mentors to pass on their knowledge to the next generation of students.', - icon: , + icon: , }, ]; diff --git a/src/shared/icons/index.tsx b/src/shared/icons/index.tsx index 3c7badb6b..f5e4138af 100644 --- a/src/shared/icons/index.tsx +++ b/src/shared/icons/index.tsx @@ -12,10 +12,7 @@ export { JavascriptIcon } from './javascript-icon'; export { JetBrainsLogo } from './jetbrains'; export { LinkedInIcon } from './linkedIn'; export { NodeJsIcon } from './nodejs-icon'; -export { OpenSourcePhilosophyIcon } from './open-source-philosophy-icon'; -export { OpenToEveryoneIcon } from './open-to-everyone-icon'; export { ReactIcon } from './react-icon'; -export { TeachItForwardIcon } from './teach-It-forward-icon'; export { TelegramIcon } from './telegram'; export { TextLinkIcon } from './text-link-icon'; export { YouTubeIcon } from './youtube'; diff --git a/src/shared/icons/open-source-philosophy-icon.tsx b/src/shared/icons/open-source-philosophy-icon.tsx deleted file mode 100644 index 4845e4fa8..000000000 --- a/src/shared/icons/open-source-philosophy-icon.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import Image from 'next/image'; -import openSourcePhilosophyIcon from '@/shared/assets/svg/openSourcePhilosophyIcon.svg'; - -export const OpenSourcePhilosophyIcon = () => { - return Open Source Philosophy Icon; -}; diff --git a/src/shared/icons/open-to-everyone-icon.tsx b/src/shared/icons/open-to-everyone-icon.tsx deleted file mode 100644 index 8feed3403..000000000 --- a/src/shared/icons/open-to-everyone-icon.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import Image from 'next/image'; -import openToEveryoneIcon from '@/shared/assets/svg/openToEveryoneIcon.svg'; - -export const OpenToEveryoneIcon = () => { - return Open To Everyone Icon; -}; diff --git a/src/shared/icons/teach-It-forward-icon.tsx b/src/shared/icons/teach-It-forward-icon.tsx deleted file mode 100644 index 2de2bd40c..000000000 --- a/src/shared/icons/teach-It-forward-icon.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import Image from 'next/image'; -import teachItForwardIcon from '@/shared/assets/svg/teachItForwardIcon.svg'; - -export const TeachItForwardIcon = () => { - return Teach It Forward Icon; -}; diff --git a/src/widgets/principles/index.ts b/src/widgets/principles/index.ts index 24b4a7c05..c766eb1a1 100644 --- a/src/widgets/principles/index.ts +++ b/src/widgets/principles/index.ts @@ -1 +1,2 @@ -export { Principles } from './ui/principle-card/principles'; +export type { PrincipleCard } from './types'; +export { Principles } from './ui/principles/principles'; diff --git a/src/widgets/principles/types.ts b/src/widgets/principles/types.ts new file mode 100644 index 000000000..80ce896e8 --- /dev/null +++ b/src/widgets/principles/types.ts @@ -0,0 +1,7 @@ +import { ReactNode } from 'react'; + +export type PrincipleCard = { + title: string; + description: string; + icon: ReactNode; +}; diff --git a/src/widgets/principles/ui/principle-card/principle-card.scss b/src/widgets/principles/ui/principle-card/principle-card.module.scss similarity index 60% rename from src/widgets/principles/ui/principle-card/principle-card.scss rename to src/widgets/principles/ui/principle-card/principle-card.module.scss index 095a01082..c9ef78360 100644 --- a/src/widgets/principles/ui/principle-card/principle-card.scss +++ b/src/widgets/principles/ui/principle-card/principle-card.module.scss @@ -1,15 +1,12 @@ .principle-card { @extend %transition-all; - cursor: default; - position: relative; overflow: hidden; - display: flex; - flex-flow: column nowrap; - place-content: center flex-start; - align-items: flex-start; + display: grid; + grid-template-columns: max-content 1fr; + column-gap: 16px; width: 100%; padding: 24px; @@ -20,7 +17,22 @@ border: 1px solid rgb(255 219 32 / 8%); border-radius: 12px; - & .card-header { + &::after { + content: ''; + + position: absolute; + right: -160px; + bottom: -150px; + + width: 310px; + height: 300px; + + background-color: rgb(255 219 32 / 20%); + filter: blur(32px); + border-radius: 100%; + } + + .card-header { display: flex; gap: 16px; align-items: center; @@ -33,14 +45,11 @@ } } - & .icon-wrapper { - position: relative; - display: flex; - align-items: center; - justify-content: center; - } + .card-description { + z-index: 1; + + grid-column: span 2; - & .card-description { font-size: 18px; font-weight: $font-weight-regular; line-height: 1.4; @@ -48,28 +57,31 @@ letter-spacing: 0; } - span > img { - width: 44px; - height: 44px; - } + .icon { + display: flex; + justify-content: center; - & .accent { - position: absolute; - z-index: 1; + img { + position: relative; + width: 44px; + height: 44px; + } - display: block; - flex-shrink: 0; - align-self: flex-start; + &::before { + content: ''; - width: 20px; - height: 19px; + position: absolute; - background-color: rgba($color-yellow, $opacity-80); - filter: blur(8px); - border-radius: 100%; + width: 20px; + height: 20px; + + background-color: rgba($color-yellow, $opacity-80); + filter: blur(8px); + border-radius: 100%; + } } - & .card-title { + .card-title { align-self: flex-start; max-width: 265px; @@ -96,26 +108,9 @@ width: 100%; padding: 32px 24px; - & .card-description { + .card-description { font-size: 16px; line-height: 24px; } } } - -.accent-corner { - position: absolute; - z-index: 1; - right: -160px; - bottom: -150px; - - display: block; - flex-shrink: 0; - - width: 310px; - height: 300px; - - background-color: rgb(255 219 32 / 20%); - filter: blur(32px); - border-radius: 100%; -} diff --git a/src/widgets/principles/ui/principle-card/principle-card.tsx b/src/widgets/principles/ui/principle-card/principle-card.tsx index fdabe084b..06576e8b1 100644 --- a/src/widgets/principles/ui/principle-card/principle-card.tsx +++ b/src/widgets/principles/ui/principle-card/principle-card.tsx @@ -1,23 +1,16 @@ -import { ReactNode } from 'react'; +import classnames from 'classnames/bind'; +import { Paragraph } from '@/shared/ui/paragraph'; +import { WidgetTitle } from '@/shared/ui/widget-title'; +import type { PrincipleCard as TPrincipleCard } from '@/widgets/principles'; -import './principle-card.scss'; +import styles from './principle-card.module.scss'; -export interface PrincipleCardProps { - title: string; - description: string; - icon: ReactNode; -} +const cx = classnames.bind(styles); -export const PrincipleCard = ({ title, description, icon }: PrincipleCardProps) => ( -
-
-
-
- {icon} -
-
{title}
-
-
{description}
-
-
+export const PrincipleCard = ({ title, description, icon }: TPrincipleCard) => ( +
+ {icon} + {title} + {description} +
); diff --git a/src/widgets/principles/ui/principle-card/principles.tsx b/src/widgets/principles/ui/principle-card/principles.tsx deleted file mode 100644 index 4cfec2fc1..000000000 --- a/src/widgets/principles/ui/principle-card/principles.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { PrincipleCard } from './principle-card'; -import { cards } from '../../constants'; -import { WidgetTitle } from '@/shared/ui/widget-title'; - -import './principles.scss'; - -export const Principles = () => ( -
-
- RS School Principles are an ability to complete our mission -
- {cards.map(({ title, description, icon }) => ( - - ))} -
-
-
-); diff --git a/src/widgets/principles/ui/principle-card/principles.scss b/src/widgets/principles/ui/principles/principles.module.scss similarity index 51% rename from src/widgets/principles/ui/principle-card/principles.scss rename to src/widgets/principles/ui/principles/principles.module.scss index c8e7ba174..4de4dff73 100644 --- a/src/widgets/principles/ui/principle-card/principles.scss +++ b/src/widgets/principles/ui/principles/principles.module.scss @@ -1,17 +1,5 @@ .principles { - &.content { - padding: 20px 120px 40px; - - @include media-laptop { - padding: 20px 40px 40px; - } - - @include media-tablet { - padding: 20px 16px 40px; - } - } - - & .cards { + .cards { gap: 32px; align-items: stretch; margin-top: 24px; diff --git a/src/widgets/principles/principles.test.tsx b/src/widgets/principles/ui/principles/principles.test.tsx similarity index 71% rename from src/widgets/principles/principles.test.tsx rename to src/widgets/principles/ui/principles/principles.test.tsx index 3599d7274..a6e465605 100644 --- a/src/widgets/principles/principles.test.tsx +++ b/src/widgets/principles/ui/principles/principles.test.tsx @@ -1,8 +1,9 @@ import { render, screen } from '@testing-library/react'; import { beforeEach, describe, expect, it } from 'vitest'; -import { cards } from './constants'; +import { Principles } from '@/widgets/principles'; +import { principleCards } from 'data'; -import { Principles } from './ui/principle-card/principles'; +const principleItemsNum = 3; describe('Principles', () => { beforeEach(() => { @@ -18,7 +19,7 @@ describe('Principles', () => { }); it('renders PrincipleCards correctly', () => { - cards.forEach(({ title, description }) => { + principleCards.forEach(({ title, description }) => { const titleElement = screen.getByText(title); const descriptionElement = screen.getByText(description); @@ -28,8 +29,8 @@ describe('Principles', () => { }); it('renders the correct number of PrincipleCards', () => { - const principleCards = document.getElementsByClassName('principle-card'); + const principleCards = screen.getAllByTestId('principle-card'); - expect(principleCards).toHaveLength(cards.length); + expect(principleCards).toHaveLength(principleItemsNum); }); }); diff --git a/src/widgets/principles/ui/principles/principles.tsx b/src/widgets/principles/ui/principles/principles.tsx new file mode 100644 index 000000000..cd46e78af --- /dev/null +++ b/src/widgets/principles/ui/principles/principles.tsx @@ -0,0 +1,23 @@ +import classnames from 'classnames/bind'; +import { WidgetTitle } from '@/shared/ui/widget-title'; +import { PrincipleCard } from '@/widgets/principles/ui/principle-card/principle-card.tsx'; +import { principleCards } from 'data'; + +import styles from './principles.module.scss'; + +const cx = classnames.bind(styles); + +export const Principles = () => ( +
+
+ + RS School Principles are an ability to complete our mission + +
+ {principleCards.map(({ title, description, icon }) => ( + + ))} +
+
+
+);