From 0dc5a48f8da43f47f0b2aa6f7744871cd0f7ccaa Mon Sep 17 00:00:00 2001 From: jamessspanggg Date: Sat, 24 Apr 2021 00:19:56 +0800 Subject: [PATCH 01/58] Create custom Button component --- src/components/Button/Button.scss | 36 +++++++++++++++++++ src/components/Button/index.tsx | 24 +++++++++++++ .../FormElements/Button/Button.scss | 2 +- src/components/FormElements/Button/index.tsx | 4 +-- 4 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 src/components/Button/Button.scss create mode 100644 src/components/Button/index.tsx diff --git a/src/components/Button/Button.scss b/src/components/Button/Button.scss new file mode 100644 index 000000000..fbeaa984c --- /dev/null +++ b/src/components/Button/Button.scss @@ -0,0 +1,36 @@ +.Button { + align-items: center; + display: inline-flex; + height: 40px; + + &__empty { + background-color: var(--color-white); + border: none; + color: var(--color-primary); + + &:hover { + background-color: var(--color-blue-50); + border: 1px solid var(--color-gray-200); + } + } + + &__icon-right { + width: 16px; + } + + &__outlined { + background-color: var(--color-white); + border: 1px solid var(--color-gray-200); + color: var(--color-primary); + } + + &__primary { + background-color: var(--color-primary); + border: none; + color: var(--color-white); + } + + &--rounded { + border-radius: 100px; + } +} diff --git a/src/components/Button/index.tsx b/src/components/Button/index.tsx new file mode 100644 index 000000000..f546b712b --- /dev/null +++ b/src/components/Button/index.tsx @@ -0,0 +1,24 @@ +import React, {FC} from 'react'; + +import clsx from 'clsx'; + +import './Button.scss'; + +type Props = { + className?: string; + iconRight?: React.ReactNode; + onClick: (event: React.SyntheticEvent) => void; + rounded?: boolean; + type?: 'primary' | 'outlined' | 'empty'; +}; + +const Button: FC = ({children, className, iconRight, onClick, rounded = false, type = 'primary'}) => { + return ( + + ); +}; + +export default Button; diff --git a/src/components/FormElements/Button/Button.scss b/src/components/FormElements/Button/Button.scss index 1a3821110..d25baf203 100644 --- a/src/components/FormElements/Button/Button.scss +++ b/src/components/FormElements/Button/Button.scss @@ -1,4 +1,4 @@ -.Button { +.FormButton { $self: &; border-radius: 3px; border-style: solid; diff --git a/src/components/FormElements/Button/index.tsx b/src/components/FormElements/Button/index.tsx index 236f503e5..a46671d48 100644 --- a/src/components/FormElements/Button/index.tsx +++ b/src/components/FormElements/Button/index.tsx @@ -34,8 +34,8 @@ const Button: FC = ({ return ( + + + + +
+ +
+ + + ); +}; + +export default ProjectsHero; diff --git a/src/containers/Projects/index.tsx b/src/containers/Projects/index.tsx index 62ab9264a..8da05d9b6 100644 --- a/src/containers/Projects/index.tsx +++ b/src/containers/Projects/index.tsx @@ -1,53 +1,9 @@ -import React, {FC, useMemo} from 'react'; -import {Redirect, useParams} from 'react-router-dom'; +import React, {FC} from 'react'; -import {DashboardLayout, ProjectsMenuItems, Pagination} from 'components'; -import {projectsNavigationData} from 'components/ProjectsMenuItems'; -import {PageData, PageDataObject} from 'types/page-data'; - -import ProjectsMilestones from './ProjectsMilestones'; -import ProjectsOverview from './ProjectsOverview'; -import ProjectsProposalSubmissionProcess from './ProjectsProposalSubmissionProcess'; -import ProjectsRules from './ProjectsRules'; - -const defaultPageData: PageData = { - content: , - name: '', -}; - -const pageData: PageDataObject = { - milestones: { - content: , - name: 'Milestones & Payouts', - }, - overview: { - content: , - name: 'Overview', - }, - proposals: { - content: , - name: 'Proposal Submission Process', - }, - rules: { - content: , - name: 'Rules & Guidelines', - }, -}; - -const getPageData = (chapter: string): PageData => { - return pageData[chapter] || defaultPageData; -}; +import ProjectsHero from './ProjectsHero'; const Projects: FC = () => { - const {chapter} = useParams<{chapter: string}>(); - const {content, name} = useMemo(() => getPageData(chapter), [chapter]); - - return ( - } pageName={name} sectionName="Projects"> - {content} - - - ); + return ; }; export default Projects; diff --git a/src/containers/TopNav/TopNavDesktopItems/index.tsx b/src/containers/TopNav/TopNavDesktopItems/index.tsx index f4f2f1940..35a9c2486 100644 --- a/src/containers/TopNav/TopNavDesktopItems/index.tsx +++ b/src/containers/TopNav/TopNavDesktopItems/index.tsx @@ -59,7 +59,7 @@ const morePopoverItems: TopNavPopoverItemType[] = [ description: 'Propose ideas you want built', iconType: IconType.hammerWrench, title: 'Projects', - to: '/projects/overview', + to: '/projects', }, { description: 'Download thenewboston assets', diff --git a/src/styles/_colors.scss b/src/styles/_colors.scss index c3e98502c..64376ceab 100644 --- a/src/styles/_colors.scss +++ b/src/styles/_colors.scss @@ -2,6 +2,7 @@ --color-alert: #ed5f74; --color-bg: #fff; --color-black: black; + --color-blue-50: #f5fbff; --color-blue-gray-1000: #212d63; --color-blue-gray-100: #cfd8dc; --color-blue-gray-200: #b0bec5; @@ -19,6 +20,7 @@ --color-gray-100: #e3e8ee; --color-gray-1: #333333; --color-gray-2: #4f4f4f; + --color-gray-200: #c1c9d2; --color-gray-300: #a3acb9; --color-gray-3: #828282; --color-gray-4: #e0e0e0; From 9031f0e2a37404401dc22a586e9010beaf840182 Mon Sep 17 00:00:00 2001 From: jamessspanggg Date: Sat, 24 Apr 2021 11:20:54 +0800 Subject: [PATCH 03/58] Add button animation when hover --- src/components/Button/Button.scss | 7 ++----- src/components/Button/index.tsx | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/components/Button/Button.scss b/src/components/Button/Button.scss index fbeaa984c..ff7a4f472 100644 --- a/src/components/Button/Button.scss +++ b/src/components/Button/Button.scss @@ -5,8 +5,9 @@ &__empty { background-color: var(--color-white); - border: none; + border: 1px solid var(--color-white); color: var(--color-primary); + transition: 0.2s; &:hover { background-color: var(--color-blue-50); @@ -14,10 +15,6 @@ } } - &__icon-right { - width: 16px; - } - &__outlined { background-color: var(--color-white); border: 1px solid var(--color-gray-200); diff --git a/src/components/Button/index.tsx b/src/components/Button/index.tsx index f546b712b..11c7f730a 100644 --- a/src/components/Button/index.tsx +++ b/src/components/Button/index.tsx @@ -16,7 +16,7 @@ const Button: FC = ({children, className, iconRight, onClick, rounded = f return ( ); }; From b4086dd87f89c63e1045c1ba11ac5578bcbed1b8 Mon Sep 17 00:00:00 2001 From: jamessspanggg Date: Sat, 24 Apr 2021 11:21:38 +0800 Subject: [PATCH 04/58] Add responsive Project Card and list of projects --- .../ListOfProjects/ListOfProjects.scss | 29 +++++ .../Projects/ListOfProjects/index.tsx | 30 ++++++ .../Projects/ProjectCard/ProjectCard.scss | 100 ++++++++++++++++++ src/containers/Projects/ProjectCard/index.tsx | 43 ++++++++ src/containers/Projects/index.tsx | 8 +- src/styles/_colors.scss | 1 + 6 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 src/containers/Projects/ListOfProjects/ListOfProjects.scss create mode 100644 src/containers/Projects/ListOfProjects/index.tsx create mode 100644 src/containers/Projects/ProjectCard/ProjectCard.scss create mode 100644 src/containers/Projects/ProjectCard/index.tsx diff --git a/src/containers/Projects/ListOfProjects/ListOfProjects.scss b/src/containers/Projects/ListOfProjects/ListOfProjects.scss new file mode 100644 index 000000000..982708244 --- /dev/null +++ b/src/containers/Projects/ListOfProjects/ListOfProjects.scss @@ -0,0 +1,29 @@ +$card-width-original: 512px; +$card-width-992: 376px; +$card-width-768: 328px; +$card-width-480: 376px; + +.ListOfProjects { + column-gap: 32px; + display: grid; + grid-template-columns: $card-width-original $card-width-original; + justify-content: center; + margin-bottom: 32px; + row-gap: 32px; + + @media (max-width: 992px) { + grid-template-columns: $card-width-992 $card-width-992; + } + + @media (max-width: 768px) { + grid-template-columns: $card-width-768 $card-width-768; + } + + @media (max-width: 480px) { + grid-template-columns: $card-width-480; + } + + @media (max-width: 376px) { + grid-template-columns: max-content; + } +} diff --git a/src/containers/Projects/ListOfProjects/index.tsx b/src/containers/Projects/ListOfProjects/index.tsx new file mode 100644 index 000000000..a1817d462 --- /dev/null +++ b/src/containers/Projects/ListOfProjects/index.tsx @@ -0,0 +1,30 @@ +import React, {FC} from 'react'; + +import ProjectCard from '../ProjectCard'; + +import './ListOfProjects.scss'; + +const sampleProject = { + description: + 'Lorem ipsum dolor sit amet, consecteturadia adipiscing elit, sed do eiusmod tempor incididunt ut.ed do eiusmod tempor incididunt ut.', + logoUrl: 'https://yt3.ggpht.com/ytc/AAUvwnglVjQeNSAVO9GgKkrjIbCO_y0rOx7Yxx-2bv9r_A=s176-c-k-c0x00ffffff-no-rj', + projectLead: 'Skylar', + title: 'Keysign', +}; + +const projects = [sampleProject, sampleProject, sampleProject, sampleProject, sampleProject, sampleProject]; + +const ListOfProjects: FC = () => { + return ( +
+ {projects.map((project, i) => { + const {description, logoUrl, projectLead, title} = project; + return ( + + ); + })} +
+ ); +}; + +export default ListOfProjects; diff --git a/src/containers/Projects/ProjectCard/ProjectCard.scss b/src/containers/Projects/ProjectCard/ProjectCard.scss new file mode 100644 index 000000000..4d01b0442 --- /dev/null +++ b/src/containers/Projects/ProjectCard/ProjectCard.scss @@ -0,0 +1,100 @@ +$card-width-original: 512px; +$card-height-original: 324px; + +$card-width-992: 376px; + +$card-width-768: 328px; +$card-height-768: 262px; + +$card-height-480: 324px; +$card-width-480: 376px; + +$padding: 40px; +$padding-768: 24px; + +.ProjectCard { + border-radius: 12px; + box-shadow: 0px 0px 30px 0px #e5eaf47a; + height: $card-height-original; + padding: $padding; + position: relative; + width: $card-width-original; + + @media (max-width: 992px) { + width: $card-width-992; + } + + @media (max-width: 768px) { + height: $card-height-768; + padding: $padding-768; + width: $card-width-768; + } + + @media (max-width: 480px) { + height: $card-height-480; + width: $card-width-480; + } + + @media (max-width: 376px) { + width: 100vw; + } + + &__title-container { + display: flex; + flex-direction: column; + gap: 10px; + } + + &__top-container { + align-items: center; + display: flex; + flex-direction: row; + gap: 20px; + margin-bottom: 35px; + } + + &__details-button { + bottom: $padding; + position: absolute; + right: $padding; + + @media (max-width: 768px) { + bottom: $padding-768; + right: $padding-768; + } + } + + &__description { + -webkit-box-orient: vertical; + color: var(--color-sail-gray-400); + display: -webkit-box; + -webkit-line-clamp: 5; /* max number of lines to show */ + overflow: hidden; + text-overflow: ellipsis; + + @media (max-width: 768px) { + -webkit-line-clamp: 3; /* max number of lines to show */ + } + + @media (max-width: 480px) { + -webkit-line-clamp: 6; /* max number of lines to show */ + } + } + + &__project-lead { + color: var(--color-sail-gray-300); + } + + &__project-lead-container { + display: flex; + gap: 5px; + } + + &__project-lead-name { + color: var(--color-sail-gray-700); + } + + &__project-title { + color: var(--color-blue-900); + } +} diff --git a/src/containers/Projects/ProjectCard/index.tsx b/src/containers/Projects/ProjectCard/index.tsx new file mode 100644 index 000000000..ab500c266 --- /dev/null +++ b/src/containers/Projects/ProjectCard/index.tsx @@ -0,0 +1,43 @@ +import React, {FC} from 'react'; + +import {Avatar} from 'components'; +import Button from 'components/Button'; +import {Icon, IconType} from '@thenewboston/ui'; + +import './ProjectCard.scss'; + +type Props = { + description: string; + logoUrl: string; + projectLead: string; + title: string; +}; + +const ProjectCard: FC = ({description, logoUrl, projectLead, title}) => { + return ( +
+
+ +
+

{title}

+
+

Project Lead:

+

{projectLead}

+
+
+
+
{description}
+ +
+ ); +}; + +export default ProjectCard; diff --git a/src/containers/Projects/index.tsx b/src/containers/Projects/index.tsx index 8da05d9b6..27fc2903a 100644 --- a/src/containers/Projects/index.tsx +++ b/src/containers/Projects/index.tsx @@ -1,9 +1,15 @@ import React, {FC} from 'react'; +import ListOfProjects from './ListOfProjects'; import ProjectsHero from './ProjectsHero'; const Projects: FC = () => { - return ; + return ( +
+ + +
+ ); }; export default Projects; diff --git a/src/styles/_colors.scss b/src/styles/_colors.scss index 64376ceab..058311ff5 100644 --- a/src/styles/_colors.scss +++ b/src/styles/_colors.scss @@ -3,6 +3,7 @@ --color-bg: #fff; --color-black: black; --color-blue-50: #f5fbff; + --color-blue-900: #131f41; --color-blue-gray-1000: #212d63; --color-blue-gray-100: #cfd8dc; --color-blue-gray-200: #b0bec5; From 451f6790c21969efa9985b3e091e0f978cb13b71 Mon Sep 17 00:00:00 2001 From: jamessspanggg Date: Sat, 24 Apr 2021 12:15:49 +0800 Subject: [PATCH 05/58] Define Project and Milestone apis and types --- src/apis/projects/api.ts | 31 +++++++++++++++++++++++++++++++ src/apis/projects/index.ts | 1 + src/types/api.ts | 4 ++++ src/types/projects.ts | 25 +++++++++++++++++++++++++ 4 files changed, 61 insertions(+) create mode 100644 src/apis/projects/api.ts create mode 100644 src/apis/projects/index.ts create mode 100644 src/types/projects.ts diff --git a/src/apis/projects/api.ts b/src/apis/projects/api.ts new file mode 100644 index 000000000..5d6aaa2f1 --- /dev/null +++ b/src/apis/projects/api.ts @@ -0,0 +1,31 @@ +import axios from 'axios'; + +import {APIArrayResponse} from 'types/api'; +import {Project, Milestone} from 'types/projects'; + +export async function getProjects(): Promise { + const response = await axios.get>(`${process.env.REACT_APP_BACKEND_API}/projects`); + + if (!response.data) { + throw new Error('Error while fetching projects, please try again.'); + } + return response.data.results; +} + +export async function getMilestones(): Promise { + const response = await axios.get>(`${process.env.REACT_APP_BACKEND_API}/milestones`); + if (!response.data) { + throw new Error('Error while fetching milestones, please try again.'); + } + return response.data.results; +} + +export async function getMilestonesByProject(id: string): Promise { + const response = await axios.get>( + `${process.env.REACT_APP_BACKEND_API}/milestones?project=${id}`, + ); + if (!response.data) { + throw new Error('Error while fetching milestones, please try again.'); + } + return response.data.results; +} diff --git a/src/apis/projects/index.ts b/src/apis/projects/index.ts new file mode 100644 index 000000000..1a615d19f --- /dev/null +++ b/src/apis/projects/index.ts @@ -0,0 +1 @@ +export * as api from './api'; diff --git a/src/types/api.ts b/src/types/api.ts index 83b608d6f..071e9e99d 100644 --- a/src/types/api.ts +++ b/src/types/api.ts @@ -11,3 +11,7 @@ export interface AuthResponse { export interface Token { token: string; } + +export interface APIArrayResponse { + results: T[]; +} diff --git a/src/types/projects.ts b/src/types/projects.ts new file mode 100644 index 000000000..75b1834e9 --- /dev/null +++ b/src/types/projects.ts @@ -0,0 +1,25 @@ +export type Project = { + uuid: string; + created_date: string; + modified_date: string; + title: string; + description: string; + logo: string; + github_url: string; + overview: string; + problem: string; + target_market: string; + benefits: string; + centered_around_tnb: string; + estimated_completion_date: string; + project_lead: string; +}; + +export type Milestone = { + uuid: string; + created_date: string; + modified_date: string; + number: number; + description: string; + project: string; +}; From 551cb08605a21f2646379ddbb5c7869582a6ee63 Mon Sep 17 00:00:00 2001 From: jamessspanggg Date: Sat, 24 Apr 2021 12:47:24 +0800 Subject: [PATCH 06/58] Change endpoint for project rules to accomodate project details page --- src/components/ProjectsMenuItems/index.tsx | 10 +++++----- src/containers/App.tsx | 3 ++- src/containers/ProjectRulesAndGuide/index.tsx | 2 +- src/containers/Projects/ProjectsHero/index.tsx | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/components/ProjectsMenuItems/index.tsx b/src/components/ProjectsMenuItems/index.tsx index cd2ec09f2..5a7b055d4 100644 --- a/src/components/ProjectsMenuItems/index.tsx +++ b/src/components/ProjectsMenuItems/index.tsx @@ -7,19 +7,19 @@ import {NavigationItem} from 'types/navigation'; export const projectsNavigationData = [ { name: 'Overview', - url: '/projects/overview', + url: '/project-rules/overview', }, { name: 'Rules & Guidelines', - url: '/projects/rules', + url: '/project-rules/rules', }, { name: 'Proposal Submission Process', - url: '/projects/proposals', + url: '/project-rules/proposals', }, { name: 'Milestones & Payouts', - url: '/projects/milestones', + url: '/project-rules/milestones', }, ]; @@ -33,7 +33,7 @@ const ProjectsMenuItems: FC = () => { }; return ( - + {renderNavLinks(projectsNavigationData)} ); diff --git a/src/containers/App.tsx b/src/containers/App.tsx index 16ea731d4..aeef8a7bd 100644 --- a/src/containers/App.tsx +++ b/src/containers/App.tsx @@ -83,7 +83,8 @@ const App: FC = () => { - + + diff --git a/src/containers/ProjectRulesAndGuide/index.tsx b/src/containers/ProjectRulesAndGuide/index.tsx index 62ab9264a..bcf123672 100644 --- a/src/containers/ProjectRulesAndGuide/index.tsx +++ b/src/containers/ProjectRulesAndGuide/index.tsx @@ -11,7 +11,7 @@ import ProjectsProposalSubmissionProcess from './ProjectsProposalSubmissionProce import ProjectsRules from './ProjectsRules'; const defaultPageData: PageData = { - content: , + content: , name: '', }; diff --git a/src/containers/Projects/ProjectsHero/index.tsx b/src/containers/Projects/ProjectsHero/index.tsx index eba3f9a39..6d9c83579 100644 --- a/src/containers/Projects/ProjectsHero/index.tsx +++ b/src/containers/Projects/ProjectsHero/index.tsx @@ -26,7 +26,7 @@ const ProjectsHero: FC = () => { > Propose a Project - From 3ea72d14b14e41212ebb91b0fd2e72504a11f47d Mon Sep 17 00:00:00 2001 From: jamessspanggg Date: Sat, 24 Apr 2021 13:08:16 +0800 Subject: [PATCH 07/58] Add ProjectCard hovered box shadow --- src/containers/Projects/ProjectCard/ProjectCard.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/containers/Projects/ProjectCard/ProjectCard.scss b/src/containers/Projects/ProjectCard/ProjectCard.scss index 4d01b0442..16f75c2ea 100644 --- a/src/containers/Projects/ProjectCard/ProjectCard.scss +++ b/src/containers/Projects/ProjectCard/ProjectCard.scss @@ -20,6 +20,11 @@ $padding-768: 24px; position: relative; width: $card-width-original; + &:hover { + box-shadow: 0px 0px 30px 0px #e5eaf47a; + box-shadow: 0px 7px 40px 0px #e9effd; + } + @media (max-width: 992px) { width: $card-width-992; } From 1408c45bab157e14915b98b15dd91e740bc8aa33 Mon Sep 17 00:00:00 2001 From: jamessspanggg Date: Sat, 24 Apr 2021 23:27:38 +0800 Subject: [PATCH 08/58] Add iconLeft support in Button component --- src/components/Button/index.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/Button/index.tsx b/src/components/Button/index.tsx index 11c7f730a..a4b0cbea4 100644 --- a/src/components/Button/index.tsx +++ b/src/components/Button/index.tsx @@ -6,15 +6,17 @@ import './Button.scss'; type Props = { className?: string; + iconLeft?: React.ReactNode; iconRight?: React.ReactNode; onClick: (event: React.SyntheticEvent) => void; rounded?: boolean; type?: 'primary' | 'outlined' | 'empty'; }; -const Button: FC = ({children, className, iconRight, onClick, rounded = false, type = 'primary'}) => { +const Button: FC = ({children, className, iconLeft, iconRight, onClick, rounded = false, type = 'primary'}) => { return ( From 74d1351b6ba72cb0abc5a2b016b74bc883c48b95 Mon Sep 17 00:00:00 2001 From: jamessspanggg Date: Sat, 24 Apr 2021 23:40:27 +0800 Subject: [PATCH 09/58] Implement project details page with temporary dummy data --- .../Projects/ListOfProjects/index.tsx | 9 +- src/containers/Projects/ProjectCard/index.tsx | 7 +- .../ProjectDetails/ProjectDetails.scss | 9 ++ .../ProjectDetailsContent.scss | 19 ++++ .../ProjectDetailsContent/index.tsx | 72 ++++++++++++++ .../ProjectDetailsHeader.scss | 52 ++++++++++ .../ProjectDetailsHeader/index.tsx | 44 +++++++++ .../ProjectDetailsSideMenu.scss | 51 ++++++++++ .../ProjectDetailsSideMenu/index.tsx | 50 ++++++++++ .../ProjectDetailsTopic.scss | 30 ++++++ .../ProjectDetailsTopic/index.tsx | 27 ++++++ .../Projects/ProjectDetails/constants.ts | 94 +++++++++++++++++++ .../Projects/ProjectDetails/index.tsx | 27 ++++++ src/containers/Projects/index.tsx | 49 +++++++++- src/styles/_colors.scss | 1 + 15 files changed, 535 insertions(+), 6 deletions(-) create mode 100644 src/containers/Projects/ProjectDetails/ProjectDetails.scss create mode 100644 src/containers/Projects/ProjectDetails/ProjectDetailsContent/ProjectDetailsContent.scss create mode 100644 src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx create mode 100644 src/containers/Projects/ProjectDetails/ProjectDetailsHeader/ProjectDetailsHeader.scss create mode 100644 src/containers/Projects/ProjectDetails/ProjectDetailsHeader/index.tsx create mode 100644 src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/ProjectDetailsSideMenu.scss create mode 100644 src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx create mode 100644 src/containers/Projects/ProjectDetails/ProjectDetailsTopic/ProjectDetailsTopic.scss create mode 100644 src/containers/Projects/ProjectDetails/ProjectDetailsTopic/index.tsx create mode 100644 src/containers/Projects/ProjectDetails/constants.ts create mode 100644 src/containers/Projects/ProjectDetails/index.tsx diff --git a/src/containers/Projects/ListOfProjects/index.tsx b/src/containers/Projects/ListOfProjects/index.tsx index a1817d462..c16969543 100644 --- a/src/containers/Projects/ListOfProjects/index.tsx +++ b/src/containers/Projects/ListOfProjects/index.tsx @@ -20,7 +20,14 @@ const ListOfProjects: FC = () => { {projects.map((project, i) => { const {description, logoUrl, projectLead, title} = project; return ( - + ); })} diff --git a/src/containers/Projects/ProjectCard/index.tsx b/src/containers/Projects/ProjectCard/index.tsx index ab500c266..b5895d07f 100644 --- a/src/containers/Projects/ProjectCard/index.tsx +++ b/src/containers/Projects/ProjectCard/index.tsx @@ -1,5 +1,6 @@ import React, {FC} from 'react'; +import {useHistory} from 'react-router'; import {Avatar} from 'components'; import Button from 'components/Button'; import {Icon, IconType} from '@thenewboston/ui'; @@ -8,12 +9,14 @@ import './ProjectCard.scss'; type Props = { description: string; + id: string; logoUrl: string; projectLead: string; title: string; }; -const ProjectCard: FC = ({description, logoUrl, projectLead, title}) => { +const ProjectCard: FC = ({description, id, logoUrl, projectLead, title}) => { + const history = useHistory(); return (
@@ -29,7 +32,7 @@ const ProjectCard: FC = ({description, logoUrl, projectLead, title}) => {
{description}
+
+
+ + ); +}; + +export default ProjectDetailsHeader; diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/ProjectDetailsSideMenu.scss b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/ProjectDetailsSideMenu.scss new file mode 100644 index 000000000..4dcc8e7c7 --- /dev/null +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/ProjectDetailsSideMenu.scss @@ -0,0 +1,51 @@ +.ProjectDetailsSideMenu { + background-color: var(--color-white); + border-radius: 0px 0px 0px 12px; + box-shadow: 0px 8px 88px rgba(0, 0, 0, 0.05); + height: fit-content; + padding: 32px; + width: 438px; + + @media (max-width: 1200px) { + width: 376px; + } + + @media (max-width: 992px) { + width: 320px; + } + + @media (max-width: 768px) { + width: 112px; + } + + @media (max-width: 480px) { + width: 88px; + } + + &__topic { + align-items: center; + color: var(--color-gray-500); + cursor: pointer; + display: flex; + flex-direction: row; + font-weight: 400; + gap: 18px; + margin-bottom: 32px; + outline: none; + + &:hover { + color: var(--color-cyan-800); + font-weight: 700; + } + + &--active { + color: var(--color-cyan-800); + font-weight: 700; + } + + &--hovered { + color: var(--color-cyan-800); + font-weight: 700; + } + } +} diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx new file mode 100644 index 000000000..0b1ff2f67 --- /dev/null +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx @@ -0,0 +1,50 @@ +import React, {FC, useState} from 'react'; + +import clsx from 'clsx'; + +import {Icon} from '@thenewboston/ui'; +import {useWindowDimensions} from 'hooks'; +import {projectDetailsTopic} from '../constants'; + +import './ProjectDetailsSideMenu.scss'; + +const ProjectDetailsSideMenu: FC = () => { + const [selectedTopicTitle, setSelectedTopicTitle] = useState(projectDetailsTopic.overview.title); + const [hoveredTopicTitle, setHoveredTopicTitle] = useState(''); + + const {width} = useWindowDimensions(); + const handleMouseEnter = (title: string) => { + setHoveredTopicTitle(title); + }; + + const handleMouseLeave = () => { + setHoveredTopicTitle(''); + }; + const shouldShowTopicTitle = width > 768; + return ( +
+ {Object.values(projectDetailsTopic).map((topic) => { + const {iconType, title} = topic; + return ( +
setSelectedTopicTitle(title)} + onMouseEnter={() => handleMouseEnter(title)} + onMouseLeave={handleMouseLeave} + tabIndex={0} + > + + {shouldShowTopicTitle && title} +
+ ); + })} +
+ ); +}; + +export default ProjectDetailsSideMenu; diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/ProjectDetailsTopic.scss b/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/ProjectDetailsTopic.scss new file mode 100644 index 000000000..b77db7c9d --- /dev/null +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/ProjectDetailsTopic.scss @@ -0,0 +1,30 @@ +.ProjectDetailsTopic { + align-items: flex-start; + display: flex; + flex-direction: row; + gap: 32px; + margin-bottom: 120px; + + @media (max-width: 480px) { + flex-direction: column; + } + + &__content { + display: flex; + flex-direction: column; + } + + &__content-overview { + // body1 + color: var(--color-sail-gray-500); + font-size: 14px; + font-weight: 400; + margin-bottom: 40px; + } + + &__content-title { + color: var(--color-sail-blue-900); + font-weight: 700; + margin-bottom: 8px; + } +} diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/index.tsx new file mode 100644 index 000000000..c78d36e82 --- /dev/null +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/index.tsx @@ -0,0 +1,27 @@ +import React, {FC} from 'react'; + +import {Icon, IconType} from '@thenewboston/ui'; + +import './ProjectDetailsTopic.scss'; + +type Props = { + content: React.ReactNode; + iconType: IconType; + title: string; + overview: string; +}; + +const ProjectDetailsTopic: FC = ({content, iconType, title, overview}) => { + return ( +
+ +
+

{title}

+

{overview}

+ {content} +
+
+ ); +}; + +export default ProjectDetailsTopic; diff --git a/src/containers/Projects/ProjectDetails/constants.ts b/src/containers/Projects/ProjectDetails/constants.ts new file mode 100644 index 000000000..a158f128e --- /dev/null +++ b/src/containers/Projects/ProjectDetails/constants.ts @@ -0,0 +1,94 @@ +import {IconType} from '@thenewboston/ui'; + +/* eslint-disable */ +export const projectDetailsTopic = { + overview: { + iconType: IconType.accountGroup, + overview: + 'A brief summary, situation, plan, and outline about the project, bigger picture, functionality and the possible outcome from this project', + title: 'Overview', + }, + problem: { + iconType: IconType.accountGroup, + overview: 'A precise information about the problem that this project is going to solve.', + title: 'Problem', + }, + target_market: { + iconType: IconType.accountGroup, + overview: 'A description of the group of users to whom TNB wants to provide the service.', + title: 'Target Market', + }, + benefits: { + iconType: IconType.accountGroup, + overview: + 'A brief description, how this service would bring the people together and providing opportunities of interaction', + title: 'Benefit to Network & Community', + }, + centered_around_tnb: { + iconType: IconType.accountGroup, + overview: 'A brief description how this service would blend into the TNB services.', + title: 'Centered around TNB', + }, + estimated_completion_date: { + iconType: IconType.accountGroup, + overview: 'A specific date of project completion.', + title: 'Estimated completion date', + }, + roadmap: { + iconType: IconType.accountGroup, + overview: 'A schedule of a lengthy project by breaking into realistic achiveable milestones.', + title: 'Roadmap', + }, +}; + +// temporary dummy data. TODO: remove when hooked up with api +export const dummyProject = { + benefits: + "This platform can be a bridge between buyers and sellers. There will be a spike in the number of people wanting to buy TNBC before it's officially released and this platform can work as an exchange for that period of time.", + centered_around_tnb: 'This service is, particularly for thenewboston.', + created_date: '2021-04-24T04:02:24.121458Z', + description: + 'An escrow web-application for thenewboston. This application will act as a bridge between the escrow providers, the buyers, and the sellers.', + estimated_completion_date: '2021-06-17T00:00:00Z', + github_url: 'https://github.com/tnbCrow', + logo: 'https://avatars.githubusercontent.com/u/79237675?s=200&v=4', + modified_date: '2021-04-24T04:02:24.121481Z', + overview: + 'An escrow web-application for thenewboston. This application will act as a bridge between the escrow providers, the buyers, and the sellers.', + problem: 'The problem is to get trusted escrow and avoid the scams that may happen in the near future.', + project_lead: 'cb5f1d92-40b5-4d39-ab78-12fef19adbd0', + target_market: + 'Anyone who wants to buy/sell TNBC in exchange with other (crypto or international) currencies or products before the coin is in exchange.', + title: 'tnbCrow', + uuid: '3415a73f-6d23-4530-88df-fe28c10413a3', +}; + +export const dummyMilestones = [ + { + created_date: '2021-04-24T03:42:45.721914Z', + description: + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt', + modified_date: '2021-04-24T03:42:45.721939Z', + number: 1, + project: '53b3f15c-262a-45f2-b3b7-86d82378ba64', + uuid: 'f771e59b-46a4-40a7-97cb-967aa60c55a1', + }, + { + created_date: '2021-04-24T03:42:54.187805Z', + description: + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt', + modified_date: '2021-04-24T03:42:54.187831Z', + number: 2, + project: '53b3f15c-262a-45f2-b3b7-86d82378ba64', + uuid: '1b5771b0-5613-434d-97ed-5e9a7f0194cf', + }, + { + created_date: '2021-04-24T03:43:02.728203Z', + description: + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt', + modified_date: '2021-04-24T03:43:02.728231Z', + number: 3, + project: '53b3f15c-262a-45f2-b3b7-86d82378ba64', + uuid: 'c0ea44d1-bd07-46c8-b3fb-02d7968292ec', + }, +]; diff --git a/src/containers/Projects/ProjectDetails/index.tsx b/src/containers/Projects/ProjectDetails/index.tsx new file mode 100644 index 000000000..2a960b5a3 --- /dev/null +++ b/src/containers/Projects/ProjectDetails/index.tsx @@ -0,0 +1,27 @@ +import React, {FC} from 'react'; + +import {Milestone, Project} from 'types/projects'; +import ProjectDetailsContent from './ProjectDetailsContent'; +import ProjectDetailsHeader from './ProjectDetailsHeader'; +import ProjectDetailsSideMenu from './ProjectDetailsSideMenu'; +import './ProjectDetails.scss'; + +type Props = { + milestones: Milestone[]; + project: Project; +}; + +const ProjectDetails: FC = ({milestones, project}) => { + const {title, logo, github_url: github, project_lead: projectLead} = project; + return ( +
+ +
+ + +
+
+ ); +}; + +export default ProjectDetails; diff --git a/src/containers/Projects/index.tsx b/src/containers/Projects/index.tsx index 27fc2903a..d532265ed 100644 --- a/src/containers/Projects/index.tsx +++ b/src/containers/Projects/index.tsx @@ -1,14 +1,57 @@ -import React, {FC} from 'react'; +import React, {FC, useEffect, useState} from 'react'; +import {useParams} from 'react-router-dom'; +import {api as projectsApi} from 'apis/projects'; +import {Project, Milestone} from 'types/projects'; +import {dummyMilestones, dummyProject} from './ProjectDetails/constants'; import ListOfProjects from './ListOfProjects'; import ProjectsHero from './ProjectsHero'; +import ProjectDetails from './ProjectDetails'; const Projects: FC = () => { + const {projectId} = useParams<{projectId: string}>(); + const [projects, setProjects] = useState([]); + const [milestones, setMilestones] = useState([]); + const isValidProjectId = projects.length && projects.some((project) => project.uuid === projectId); + + useEffect(() => { + (async function getProjects() { + try { + const projectsResponse = await projectsApi.getProjects(); + setProjects(projectsResponse); + } catch (err) { + // handle error + } + })(); + }, []); + + useEffect(() => { + (async function getMilestones() { + try { + if (isValidProjectId) { + const milestonesResponse = await projectsApi.getMilestonesByProject(projectId); + setMilestones(milestonesResponse); + } + } catch (err) { + // handle error + } + })(); + }, [isValidProjectId, projectId]); + + // TODO: remove when hooked up with api, currently testing the project details page by + // uncommenting the following line + // return ; + + if (isValidProjectId) { + const selectedProject = projects.find((project) => project.uuid === projectId) as Project; + return ; + } + return ( -
+ <> -
+ ); }; diff --git a/src/styles/_colors.scss b/src/styles/_colors.scss index 058311ff5..252d6a3b5 100644 --- a/src/styles/_colors.scss +++ b/src/styles/_colors.scss @@ -15,6 +15,7 @@ --color-blue-gray-700: #455a64; --color-blue-gray-800: #37474f; --color-blue-gray-900: #263238; + --color-cyan-800: #093353; --color-danger: #d30c15; --color-github-blue: #0366d6; --color-gray-050: #f7fafc; From 2051dcfe44ab76faaa491ca86df9fca82b4d29f4 Mon Sep 17 00:00:00 2001 From: jamessspanggg Date: Sun, 25 Apr 2021 14:38:00 +0800 Subject: [PATCH 10/58] Hook up apis and implement scroll behavior of project details --- src/apis/projects/api.ts | 8 ++ src/apis/users/index.ts | 9 +++ .../Projects/ListOfProjects/index.tsx | 23 +++--- src/containers/Projects/ProjectCard/index.tsx | 19 ++++- .../ProjectDetailsContent/index.tsx | 29 ++++++- .../ProjectDetailsHeader.scss | 8 +- .../ProjectDetailsHeader/index.tsx | 19 ++++- .../ProjectDetailsSideMenu.scss | 1 + .../ProjectDetailsSideMenu/index.tsx | 13 +++- .../ProjectDetailsTopic.scss | 8 +- .../ProjectDetailsTopic/index.tsx | 7 +- .../Projects/ProjectDetails/constants.ts | 77 ++++--------------- .../Projects/ProjectDetails/index.tsx | 15 +++- src/containers/Projects/Projects.scss | 9 +++ src/containers/Projects/index.tsx | 19 +++-- src/styles/_colors.scss | 1 + src/types/projects.ts | 33 ++++++++ 17 files changed, 193 insertions(+), 105 deletions(-) create mode 100644 src/containers/Projects/Projects.scss diff --git a/src/apis/projects/api.ts b/src/apis/projects/api.ts index 5d6aaa2f1..40635d1ff 100644 --- a/src/apis/projects/api.ts +++ b/src/apis/projects/api.ts @@ -29,3 +29,11 @@ export async function getMilestonesByProject(id: string): Promise { } return response.data.results; } + +export async function getProjectMemberById(id: string) { + const response = await axios.get(`${process.env.REACT_APP_BACKEND_API}/project_members/${id}`); + if (!response.data) { + throw new Error('Error while fetching project member, please try again.'); + } + return response.data; +} diff --git a/src/apis/users/index.ts b/src/apis/users/index.ts index aca82e2d9..8ec4b2c66 100644 --- a/src/apis/users/index.ts +++ b/src/apis/users/index.ts @@ -1,6 +1,7 @@ import axios from 'axios'; import {standardHeaders} from 'utils/requests'; +import {User} from 'types/app/User'; export async function createUser({ display_name, @@ -13,3 +14,11 @@ export async function createUser({ }) { return axios.post(`${process.env.REACT_APP_BACKEND_API}/users`, {display_name, email, password}, standardHeaders()); } + +export async function getUser({uuid}: {uuid: string}): Promise { + const response = await axios.get(`${process.env.REACT_APP_BACKEND_API}/users/${uuid}`); + if (!response.data) { + throw new Error('Error while fetching user. Please try again.'); + } + return response.data; +} diff --git a/src/containers/Projects/ListOfProjects/index.tsx b/src/containers/Projects/ListOfProjects/index.tsx index c16969543..717ba0e18 100644 --- a/src/containers/Projects/ListOfProjects/index.tsx +++ b/src/containers/Projects/ListOfProjects/index.tsx @@ -1,32 +1,27 @@ import React, {FC} from 'react'; +import {Project} from 'types/projects'; import ProjectCard from '../ProjectCard'; import './ListOfProjects.scss'; -const sampleProject = { - description: - 'Lorem ipsum dolor sit amet, consecteturadia adipiscing elit, sed do eiusmod tempor incididunt ut.ed do eiusmod tempor incididunt ut.', - logoUrl: 'https://yt3.ggpht.com/ytc/AAUvwnglVjQeNSAVO9GgKkrjIbCO_y0rOx7Yxx-2bv9r_A=s176-c-k-c0x00ffffff-no-rj', - projectLead: 'Skylar', - title: 'Keysign', +type Props = { + projects: Project[]; }; -const projects = [sampleProject, sampleProject, sampleProject, sampleProject, sampleProject, sampleProject]; - -const ListOfProjects: FC = () => { +const ListOfProjects: FC = ({projects}) => { return (
- {projects.map((project, i) => { - const {description, logoUrl, projectLead, title} = project; + {projects.map((project) => { + const {description, logo, project_lead: projectLead, title, uuid} = project; return ( ); })} diff --git a/src/containers/Projects/ProjectCard/index.tsx b/src/containers/Projects/ProjectCard/index.tsx index b5895d07f..f113fd598 100644 --- a/src/containers/Projects/ProjectCard/index.tsx +++ b/src/containers/Projects/ProjectCard/index.tsx @@ -1,8 +1,11 @@ -import React, {FC} from 'react'; +import React, {FC, useEffect, useState} from 'react'; +import {getUser} from 'apis/users'; +import {api as projectApi} from 'apis/projects'; import {useHistory} from 'react-router'; import {Avatar} from 'components'; import Button from 'components/Button'; +import {User} from 'types/app/User'; import {Icon, IconType} from '@thenewboston/ui'; import './ProjectCard.scss'; @@ -16,6 +19,18 @@ type Props = { }; const ProjectCard: FC = ({description, id, logoUrl, projectLead, title}) => { + const [projectLeadUser, setProjectLeadUser] = useState(null); + + useEffect(() => { + (async function () { + // We require to call two extra APIs just to get the project lead's name, perhaps we + // should adopt a BFF design + const projectMemberResponse = await projectApi.getProjectMemberById(projectLead); + const userResponse = await getUser({uuid: projectMemberResponse.user}); + setProjectLeadUser(userResponse); + })(); + }, [projectLead]); + const history = useHistory(); return (
@@ -25,7 +40,7 @@ const ProjectCard: FC = ({description, id, logoUrl, projectLead, title})

{title}

Project Lead:

-

{projectLead}

+

{projectLeadUser?.display_name}

diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx index 32cf79ad2..8df6c88a3 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx @@ -1,6 +1,6 @@ -import React, {FC} from 'react'; +import React, {FC, useEffect} from 'react'; -import {Milestone, Project} from 'types/projects'; +import {Milestone, Project, ProjectTopic, ProjectTopicTitle} from 'types/projects'; import ProjectDetailsTopic from '../ProjectDetailsTopic'; import {projectDetailsTopic} from '../constants'; import './ProjectDetailsContent.scss'; @@ -8,9 +8,25 @@ import './ProjectDetailsContent.scss'; type Props = { milestones: Milestone[]; project: Project; + currentTopic: ProjectTopic; }; -const ProjectDetailsContent: FC = ({milestones, project}) => { +const TOP_NAV_HEIGHT = 60; + +const ProjectDetailsContent: FC = ({milestones, project, currentTopic}) => { + useEffect(() => { + const element = document.getElementById(currentTopic.anchor); + const scrollBehavior = element ? 'smooth' : 'auto'; + + // scroll to top if it is the first topic, else scroll directly to the topic + const top = currentTopic.title === ProjectTopicTitle.Overview || !element ? 0 : element.offsetTop - TOP_NAV_HEIGHT; + + window.scrollTo({ + behavior: scrollBehavior, + top, + }); + }, [currentTopic]); + const renderMilestones = () => { return milestones.map((milestone) => { return ( @@ -24,42 +40,49 @@ const ProjectDetailsContent: FC = ({milestones, project}) => { return (
= ({github, logoUrl, projectLead, title}) => { + const [projectLeadUser, setProjectLeadUser] = useState(null); + useEffect(() => { + (async function () { + // We require to call two extra APIs just to get the project lead's name, perhaps we + // should adopt a BFF design + const projectMemberResponse = await projectApi.getProjectMemberById(projectLead); + const userResponse = await getUser({uuid: projectMemberResponse.user}); + setProjectLeadUser(userResponse); + })(); + }, [projectLead]); return (
@@ -21,8 +34,8 @@ const ProjectDetailsHeader: FC = ({github, logoUrl, projectLead, title})

{title}

-

Project Lead:

-

{projectLead}

+ Project Lead: + {projectLeadUser?.display_name}
diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/ProjectDetailsSideMenu.scss b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/ProjectDetailsSideMenu.scss index 4dcc8e7c7..b0fcdf5b3 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/ProjectDetailsSideMenu.scss +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/ProjectDetailsSideMenu.scss @@ -2,6 +2,7 @@ background-color: var(--color-white); border-radius: 0px 0px 0px 12px; box-shadow: 0px 8px 88px rgba(0, 0, 0, 0.05); + flex-shrink: 0; height: fit-content; padding: 32px; width: 438px; diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx index 0b1ff2f67..063c045f7 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx @@ -2,14 +2,19 @@ import React, {FC, useState} from 'react'; import clsx from 'clsx'; +import {ProjectTopic} from 'types/projects'; import {Icon} from '@thenewboston/ui'; import {useWindowDimensions} from 'hooks'; import {projectDetailsTopic} from '../constants'; import './ProjectDetailsSideMenu.scss'; -const ProjectDetailsSideMenu: FC = () => { - const [selectedTopicTitle, setSelectedTopicTitle] = useState(projectDetailsTopic.overview.title); +type Props = { + currentTopic: ProjectTopic; + onClick: (topic: ProjectTopic) => void; +}; + +const ProjectDetailsSideMenu: FC = ({currentTopic, onClick}) => { const [hoveredTopicTitle, setHoveredTopicTitle] = useState(''); const {width} = useWindowDimensions(); @@ -28,12 +33,12 @@ const ProjectDetailsSideMenu: FC = () => { return (
setSelectedTopicTitle(title)} + onClick={() => onClick(topic)} onMouseEnter={() => handleMouseEnter(title)} onMouseLeave={handleMouseLeave} tabIndex={0} diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/ProjectDetailsTopic.scss b/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/ProjectDetailsTopic.scss index b77db7c9d..78a99f97c 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/ProjectDetailsTopic.scss +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/ProjectDetailsTopic.scss @@ -19,7 +19,7 @@ color: var(--color-sail-gray-500); font-size: 14px; font-weight: 400; - margin-bottom: 40px; + margin-bottom: 32px; } &__content-title { @@ -27,4 +27,10 @@ font-weight: 700; margin-bottom: 8px; } + + &__content-main { + color: var(--color-sail-gray-600); + // h3 regular + font-weight: 400; + } } diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/index.tsx index c78d36e82..27c2fda99 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/index.tsx +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/index.tsx @@ -7,18 +7,19 @@ import './ProjectDetailsTopic.scss'; type Props = { content: React.ReactNode; iconType: IconType; + id: string; title: string; overview: string; }; -const ProjectDetailsTopic: FC = ({content, iconType, title, overview}) => { +const ProjectDetailsTopic: FC = ({content, iconType, id, title, overview}) => { return ( -
+

{title}

{overview}

- {content} + {typeof content === 'string' ?

{content}

: content}
); diff --git a/src/containers/Projects/ProjectDetails/constants.ts b/src/containers/Projects/ProjectDetails/constants.ts index a158f128e..6cb838b7a 100644 --- a/src/containers/Projects/ProjectDetails/constants.ts +++ b/src/containers/Projects/ProjectDetails/constants.ts @@ -1,94 +1,51 @@ import {IconType} from '@thenewboston/ui'; +import {ProjectTopicAnchor, ProjectTopicMap, ProjectTopicTitle} from 'types/projects'; + /* eslint-disable */ -export const projectDetailsTopic = { +export const projectDetailsTopic: ProjectTopicMap = { overview: { + anchor: ProjectTopicAnchor.Overview, iconType: IconType.accountGroup, overview: 'A brief summary, situation, plan, and outline about the project, bigger picture, functionality and the possible outcome from this project', - title: 'Overview', + title: ProjectTopicTitle.Overview, }, problem: { + anchor: ProjectTopicAnchor.Problem, iconType: IconType.accountGroup, overview: 'A precise information about the problem that this project is going to solve.', - title: 'Problem', + title: ProjectTopicTitle.Problem, }, target_market: { + anchor: ProjectTopicAnchor.TargetMarket, iconType: IconType.accountGroup, overview: 'A description of the group of users to whom TNB wants to provide the service.', - title: 'Target Market', + title: ProjectTopicTitle.TargetMarket, }, benefits: { + anchor: ProjectTopicAnchor.Benefits, iconType: IconType.accountGroup, overview: 'A brief description, how this service would bring the people together and providing opportunities of interaction', - title: 'Benefit to Network & Community', + title: ProjectTopicTitle.Benefits, }, centered_around_tnb: { + anchor: ProjectTopicAnchor.CenteredAroundTNB, iconType: IconType.accountGroup, overview: 'A brief description how this service would blend into the TNB services.', - title: 'Centered around TNB', + title: ProjectTopicTitle.CenteredAroundTNB, }, estimated_completion_date: { + anchor: ProjectTopicAnchor.EstimatedCompletionDate, iconType: IconType.accountGroup, overview: 'A specific date of project completion.', - title: 'Estimated completion date', + title: ProjectTopicTitle.EstimatedCompletionDate, }, roadmap: { + anchor: ProjectTopicAnchor.Roadmap, iconType: IconType.accountGroup, overview: 'A schedule of a lengthy project by breaking into realistic achiveable milestones.', - title: 'Roadmap', + title: ProjectTopicTitle.Roadmap, }, }; - -// temporary dummy data. TODO: remove when hooked up with api -export const dummyProject = { - benefits: - "This platform can be a bridge between buyers and sellers. There will be a spike in the number of people wanting to buy TNBC before it's officially released and this platform can work as an exchange for that period of time.", - centered_around_tnb: 'This service is, particularly for thenewboston.', - created_date: '2021-04-24T04:02:24.121458Z', - description: - 'An escrow web-application for thenewboston. This application will act as a bridge between the escrow providers, the buyers, and the sellers.', - estimated_completion_date: '2021-06-17T00:00:00Z', - github_url: 'https://github.com/tnbCrow', - logo: 'https://avatars.githubusercontent.com/u/79237675?s=200&v=4', - modified_date: '2021-04-24T04:02:24.121481Z', - overview: - 'An escrow web-application for thenewboston. This application will act as a bridge between the escrow providers, the buyers, and the sellers.', - problem: 'The problem is to get trusted escrow and avoid the scams that may happen in the near future.', - project_lead: 'cb5f1d92-40b5-4d39-ab78-12fef19adbd0', - target_market: - 'Anyone who wants to buy/sell TNBC in exchange with other (crypto or international) currencies or products before the coin is in exchange.', - title: 'tnbCrow', - uuid: '3415a73f-6d23-4530-88df-fe28c10413a3', -}; - -export const dummyMilestones = [ - { - created_date: '2021-04-24T03:42:45.721914Z', - description: - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt', - modified_date: '2021-04-24T03:42:45.721939Z', - number: 1, - project: '53b3f15c-262a-45f2-b3b7-86d82378ba64', - uuid: 'f771e59b-46a4-40a7-97cb-967aa60c55a1', - }, - { - created_date: '2021-04-24T03:42:54.187805Z', - description: - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt', - modified_date: '2021-04-24T03:42:54.187831Z', - number: 2, - project: '53b3f15c-262a-45f2-b3b7-86d82378ba64', - uuid: '1b5771b0-5613-434d-97ed-5e9a7f0194cf', - }, - { - created_date: '2021-04-24T03:43:02.728203Z', - description: - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt', - modified_date: '2021-04-24T03:43:02.728231Z', - number: 3, - project: '53b3f15c-262a-45f2-b3b7-86d82378ba64', - uuid: 'c0ea44d1-bd07-46c8-b3fb-02d7968292ec', - }, -]; diff --git a/src/containers/Projects/ProjectDetails/index.tsx b/src/containers/Projects/ProjectDetails/index.tsx index 2a960b5a3..124aea05c 100644 --- a/src/containers/Projects/ProjectDetails/index.tsx +++ b/src/containers/Projects/ProjectDetails/index.tsx @@ -1,9 +1,10 @@ -import React, {FC} from 'react'; +import React, {FC, useState} from 'react'; -import {Milestone, Project} from 'types/projects'; +import {Milestone, Project, ProjectTopic} from 'types/projects'; import ProjectDetailsContent from './ProjectDetailsContent'; import ProjectDetailsHeader from './ProjectDetailsHeader'; import ProjectDetailsSideMenu from './ProjectDetailsSideMenu'; +import {projectDetailsTopic} from './constants'; import './ProjectDetails.scss'; type Props = { @@ -12,13 +13,19 @@ type Props = { }; const ProjectDetails: FC = ({milestones, project}) => { + const [currentTopic, setCurrentTopic] = useState(projectDetailsTopic.overview); const {title, logo, github_url: github, project_lead: projectLead} = project; + + const handleSideMenuClick = (topic: ProjectTopic) => { + setCurrentTopic(topic); + }; + return (
- - + +
); diff --git a/src/containers/Projects/Projects.scss b/src/containers/Projects/Projects.scss new file mode 100644 index 000000000..cc4e2ef10 --- /dev/null +++ b/src/containers/Projects/Projects.scss @@ -0,0 +1,9 @@ +.Projects { + &__loading-container { + align-items: center; + display: flex; + height: 80vh; + justify-content: center; + width: 100%; + } +} diff --git a/src/containers/Projects/index.tsx b/src/containers/Projects/index.tsx index d532265ed..fa7f4084b 100644 --- a/src/containers/Projects/index.tsx +++ b/src/containers/Projects/index.tsx @@ -3,16 +3,19 @@ import {useParams} from 'react-router-dom'; import {api as projectsApi} from 'apis/projects'; import {Project, Milestone} from 'types/projects'; -import {dummyMilestones, dummyProject} from './ProjectDetails/constants'; +import {Loader} from 'components'; import ListOfProjects from './ListOfProjects'; import ProjectsHero from './ProjectsHero'; import ProjectDetails from './ProjectDetails'; +import './Projects.scss'; + const Projects: FC = () => { const {projectId} = useParams<{projectId: string}>(); const [projects, setProjects] = useState([]); const [milestones, setMilestones] = useState([]); const isValidProjectId = projects.length && projects.some((project) => project.uuid === projectId); + const [isLoading, setIsLoading] = useState(true); useEffect(() => { (async function getProjects() { @@ -21,6 +24,8 @@ const Projects: FC = () => { setProjects(projectsResponse); } catch (err) { // handle error + } finally { + setIsLoading(false); } })(); }, []); @@ -38,9 +43,13 @@ const Projects: FC = () => { })(); }, [isValidProjectId, projectId]); - // TODO: remove when hooked up with api, currently testing the project details page by - // uncommenting the following line - // return ; + if (isLoading) { + return ( +
+ +
+ ); + } if (isValidProjectId) { const selectedProject = projects.find((project) => project.uuid === projectId) as Project; @@ -50,7 +59,7 @@ const Projects: FC = () => { return ( <> - + ); }; diff --git a/src/styles/_colors.scss b/src/styles/_colors.scss index 252d6a3b5..9c9686c84 100644 --- a/src/styles/_colors.scss +++ b/src/styles/_colors.scss @@ -55,6 +55,7 @@ --color-sail-gray-400: #8792a2; --color-sail-gray-500: #697386; --color-sail-gray-50: #f7fafc; + --color-sail-gray-600: #4f566b; --color-sail-gray-700: #3c4257; --color-sail-gray-900: #042235; --color-sail-green-500: #09825d; diff --git a/src/types/projects.ts b/src/types/projects.ts index 75b1834e9..16c1ad7f8 100644 --- a/src/types/projects.ts +++ b/src/types/projects.ts @@ -1,3 +1,5 @@ +import {IconType} from '@thenewboston/ui'; + export type Project = { uuid: string; created_date: string; @@ -23,3 +25,34 @@ export type Milestone = { description: string; project: string; }; + +export type ProjectTopicMap = { + [key: string]: ProjectTopic; +}; + +export type ProjectTopic = { + anchor: ProjectTopicAnchor; + iconType: IconType; + overview: string; + title: ProjectTopicTitle; +}; + +export enum ProjectTopicTitle { + Overview = 'Overview', + Problem = 'Problem', + TargetMarket = 'Target Market', + Benefits = 'Benefit to Network & Community', + CenteredAroundTNB = 'Centered around TNB', + EstimatedCompletionDate = 'Estimated completion date', + Roadmap = 'Roadmap', +} + +export enum ProjectTopicAnchor { + Overview = 'topic-overview', + Problem = 'topic-problem', + TargetMarket = 'topic-target-market', + Benefits = 'topic-benefits', + CenteredAroundTNB = 'topic-centered-around-tnb', + EstimatedCompletionDate = 'topic-completion-date', + Roadmap = 'topic-roadmap', +} From 855413293a8665ad91c6ff292b8ec319d3ca0efb Mon Sep 17 00:00:00 2001 From: jamessspanggg Date: Sun, 25 Apr 2021 14:58:38 +0800 Subject: [PATCH 11/58] Improve scrolling behavior of project details based on figma design --- .../ProjectDetailsContent.scss | 10 +++++++++ .../ProjectDetailsContent/index.tsx | 22 ++++++++++++------- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsContent/ProjectDetailsContent.scss b/src/containers/Projects/ProjectDetails/ProjectDetailsContent/ProjectDetailsContent.scss index bd1c9620d..48e6bb9ba 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsContent/ProjectDetailsContent.scss +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsContent/ProjectDetailsContent.scss @@ -1,6 +1,12 @@ +$top-nav-height: 60px; +$details-header-height: 158px; +$details-header-height-480: 177px; + .ProjectDetailsContent { background-color: var(--color-white); box-shadow: 0px 8px 88px 0px #0000000d; + max-height: calc(100vh - #{$top-nav-height} - #{$details-header-height}); + overflow-y: scroll; padding: 32px; &__milestone { @@ -16,4 +22,8 @@ font-weight: 700; margin-bottom: 8px; } + + @media (max-width: 480px) { + max-height: calc(100vh - #{$top-nav-height} - #{$details-header-height-480}); + } } diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx index 8df6c88a3..c8c31c64a 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx @@ -1,5 +1,6 @@ -import React, {FC, useEffect} from 'react'; +import React, {FC, useEffect, useRef} from 'react'; +import {useWindowDimensions} from 'hooks'; import {Milestone, Project, ProjectTopic, ProjectTopicTitle} from 'types/projects'; import ProjectDetailsTopic from '../ProjectDetailsTopic'; import {projectDetailsTopic} from '../constants'; @@ -14,18 +15,23 @@ type Props = { const TOP_NAV_HEIGHT = 60; const ProjectDetailsContent: FC = ({milestones, project, currentTopic}) => { + const containerRef = useRef(null); + const {width} = useWindowDimensions(); + const detailsHeaderHeight = width >= 480 ? 158 : 177; useEffect(() => { const element = document.getElementById(currentTopic.anchor); const scrollBehavior = element ? 'smooth' : 'auto'; // scroll to top if it is the first topic, else scroll directly to the topic - const top = currentTopic.title === ProjectTopicTitle.Overview || !element ? 0 : element.offsetTop - TOP_NAV_HEIGHT; + const top = + currentTopic.title === ProjectTopicTitle.Overview || !element + ? 0 + : element.offsetTop - TOP_NAV_HEIGHT - detailsHeaderHeight; - window.scrollTo({ - behavior: scrollBehavior, - top, - }); - }, [currentTopic]); + if (containerRef.current) { + containerRef.current.scrollTo({behavior: scrollBehavior, top}); + } + }, [currentTopic, detailsHeaderHeight]); const renderMilestones = () => { return milestones.map((milestone) => { @@ -38,7 +44,7 @@ const ProjectDetailsContent: FC = ({milestones, project, currentTopic}) = }); }; return ( -
+
Date: Sun, 25 Apr 2021 18:12:29 +0800 Subject: [PATCH 12/58] Update mobile nav projects link --- src/containers/TopNav/TopNavMobileMenu/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/containers/TopNav/TopNavMobileMenu/index.tsx b/src/containers/TopNav/TopNavMobileMenu/index.tsx index c48a365e1..a2cee7360 100644 --- a/src/containers/TopNav/TopNavMobileMenu/index.tsx +++ b/src/containers/TopNav/TopNavMobileMenu/index.tsx @@ -103,7 +103,7 @@ const TopNavMobileMenu: FC = ({closeMenu, menuOpen, smallDevice, 'more', 'More', <> - {renderMobileLink('Projects', '/projects/overview')} + {renderMobileLink('Projects', '/projects')} {renderMobileLink('Blog', 'https://thenewboston.blog/', true)} {renderMobileLink('Assets', '/assets')} {renderMobileLink('FAQ', '/faq')} From e3a36bdfc55f388eb8604387e472fcb45760bc0d Mon Sep 17 00:00:00 2001 From: jamessspanggg Date: Sat, 1 May 2021 12:50:24 +0800 Subject: [PATCH 13/58] ! Use new project icons --- src/components/ProjectIcons/BenefitsIcon.tsx | 331 ++++++++++++++++++ .../ProjectIcons/IntegrationIcon.tsx | 63 ++++ .../ProjectIcons/MilestonesIcon.tsx | 88 +++++ src/components/ProjectIcons/OverviewIcon.tsx | 246 +++++++++++++ src/components/ProjectIcons/ProblemIcon.tsx | 120 +++++++ src/components/ProjectIcons/RoadmapIcon.tsx | 75 ++++ src/components/ProjectIcons/TargetIcon.tsx | 144 ++++++++ src/components/ProjectIcons/TimelineIcon.tsx | 282 +++++++++++++++ src/components/ProjectIcons/index.tsx | 140 ++++++++ src/components/ProjectIcons/types.ts | 7 + .../ProjectDetailsContent.scss | 9 + .../ProjectDetailsSideMenu/index.tsx | 12 +- .../ProjectDetailsTopic/index.tsx | 6 +- .../Projects/ProjectDetails/constants.ts | 16 +- src/types/projects.ts | 4 +- 15 files changed, 1526 insertions(+), 17 deletions(-) create mode 100644 src/components/ProjectIcons/BenefitsIcon.tsx create mode 100644 src/components/ProjectIcons/IntegrationIcon.tsx create mode 100644 src/components/ProjectIcons/MilestonesIcon.tsx create mode 100644 src/components/ProjectIcons/OverviewIcon.tsx create mode 100644 src/components/ProjectIcons/ProblemIcon.tsx create mode 100644 src/components/ProjectIcons/RoadmapIcon.tsx create mode 100644 src/components/ProjectIcons/TargetIcon.tsx create mode 100644 src/components/ProjectIcons/TimelineIcon.tsx create mode 100644 src/components/ProjectIcons/index.tsx create mode 100644 src/components/ProjectIcons/types.ts diff --git a/src/components/ProjectIcons/BenefitsIcon.tsx b/src/components/ProjectIcons/BenefitsIcon.tsx new file mode 100644 index 000000000..320efdc79 --- /dev/null +++ b/src/components/ProjectIcons/BenefitsIcon.tsx @@ -0,0 +1,331 @@ +import React, {FC} from 'react'; + +import {CustomIconProps} from './types'; + +const BenefitsIcon: FC = ({ + className, + color = 'currentColor', + onClick, + size = 24, + state = 'default', +}) => { + console.log(state); + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {state === 'default' && ( + + + + )} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default BenefitsIcon; diff --git a/src/components/ProjectIcons/IntegrationIcon.tsx b/src/components/ProjectIcons/IntegrationIcon.tsx new file mode 100644 index 000000000..6b8f8c052 --- /dev/null +++ b/src/components/ProjectIcons/IntegrationIcon.tsx @@ -0,0 +1,63 @@ +import React, {FC} from 'react'; + +import {CustomIconProps} from './types'; + +const IntegrationIcon: FC = ({ + className, + color = 'currentColor', + onClick, + size = 24, + state = 'default', +}) => { + return ( + + + + + + + + + + {state === 'default' && ( + + + + )} + + + + + + + + + + + + ); +}; + +export default IntegrationIcon; diff --git a/src/components/ProjectIcons/MilestonesIcon.tsx b/src/components/ProjectIcons/MilestonesIcon.tsx new file mode 100644 index 000000000..6786e94e1 --- /dev/null +++ b/src/components/ProjectIcons/MilestonesIcon.tsx @@ -0,0 +1,88 @@ +import React, {FC} from 'react'; + +import {CustomIconProps} from './types'; + +const MilestonesIcon: FC = ({ + className, + color = 'currentColor', + onClick, + size = 24, + state = 'default', +}) => { + return ( + + + + + + + + + + + + + + + + + {state === 'default' && ( + + + + )} + + + + + + + + + + + + + + + ); +}; + +export default MilestonesIcon; diff --git a/src/components/ProjectIcons/OverviewIcon.tsx b/src/components/ProjectIcons/OverviewIcon.tsx new file mode 100644 index 000000000..2a961136f --- /dev/null +++ b/src/components/ProjectIcons/OverviewIcon.tsx @@ -0,0 +1,246 @@ +import React, {FC} from 'react'; + +import {CustomIconProps} from './types'; + +const OverviewIcon: FC = ({ + className, + color = 'currentColor', + onClick, + size = 24, + state = 'default', +}) => { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {state === 'default' && ( + + + + )} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default OverviewIcon; diff --git a/src/components/ProjectIcons/ProblemIcon.tsx b/src/components/ProjectIcons/ProblemIcon.tsx new file mode 100644 index 000000000..3cc042520 --- /dev/null +++ b/src/components/ProjectIcons/ProblemIcon.tsx @@ -0,0 +1,120 @@ +import React, {FC} from 'react'; + +import {CustomIconProps} from './types'; + +const ProblemIcon: FC = ({ + className, + color = 'currentColor', + onClick, + size = 24, + state = 'default', +}) => { + return ( + + + + + + + + + + + {state === 'default' && ( + + + + )} + + + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default ProblemIcon; diff --git a/src/components/ProjectIcons/RoadmapIcon.tsx b/src/components/ProjectIcons/RoadmapIcon.tsx new file mode 100644 index 000000000..bafa2d997 --- /dev/null +++ b/src/components/ProjectIcons/RoadmapIcon.tsx @@ -0,0 +1,75 @@ +import React, {FC} from 'react'; + +import {CustomIconProps} from './types'; + +const RoadmapIcon: FC = ({ + className, + color = 'currentColor', + onClick, + size = 24, + state = 'default', +}) => { + return ( + + + + + + + + + + + + + + + + {state === 'default' && ( + + + + )} + + + + + + + + + + + + + + + ); +}; + +export default RoadmapIcon; diff --git a/src/components/ProjectIcons/TargetIcon.tsx b/src/components/ProjectIcons/TargetIcon.tsx new file mode 100644 index 000000000..837db2fa8 --- /dev/null +++ b/src/components/ProjectIcons/TargetIcon.tsx @@ -0,0 +1,144 @@ +import React, {FC} from 'react'; + +import {CustomIconProps} from './types'; + +const TargetIcon: FC = ({ + className, + color = 'currentColor', + onClick, + size = 24, + state = 'default', +}) => { + return ( + + + + + + + + + + + + + + + {state === 'default' && ( + + + + )} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default TargetIcon; diff --git a/src/components/ProjectIcons/TimelineIcon.tsx b/src/components/ProjectIcons/TimelineIcon.tsx new file mode 100644 index 000000000..e067e4b7e --- /dev/null +++ b/src/components/ProjectIcons/TimelineIcon.tsx @@ -0,0 +1,282 @@ +import React, {FC} from 'react'; + +import {CustomIconProps} from './types'; + +const TimelineIcon: FC = ({ + className, + color = 'currentColor', + onClick, + size = 24, + state = 'default', +}) => { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {state === 'default' && ( + + + + )} + + + + + + + + ); +}; + +export default TimelineIcon; diff --git a/src/components/ProjectIcons/index.tsx b/src/components/ProjectIcons/index.tsx new file mode 100644 index 000000000..4a71686c2 --- /dev/null +++ b/src/components/ProjectIcons/index.tsx @@ -0,0 +1,140 @@ +import React, {forwardRef, HTMLAttributes, ReactNode, useCallback, useMemo} from 'react'; + +import {bemify} from '@thenewboston/utils'; +import clsx from 'clsx'; +import BenefitsIcon from './BenefitsIcon'; +import IntegrationIcon from './IntegrationIcon'; +import MilestonesIcon from './MilestonesIcon'; +import OverviewIcon from './OverviewIcon'; +import ProblemIcon from './ProblemIcon'; +import RoadmapIcon from './RoadmapIcon'; +import TargetIcon from './TargetIcon'; +import TimelineIcon from './TimelineIcon'; +import {CustomIconProps} from './types'; + +export enum ProjectIconType { + Benefits = 'Benefits', + Integration = 'Integration', + Milestone = 'Milestone', + Overview = 'Overview', + Problem = 'Problem', + Roadmap = 'Roadmap', + Target = 'Target', + Timeline = 'Timeline', +} + +export interface IconProps extends HTMLAttributes { + /** Optional. Extra classNames you can pass. Storybook options: black, white, primary, secondary, tertiary, alert. */ + className?: string; + /** Optional. identifies a DOM node for testing purposes. */ + dataTestId?: string; + /** Optional. disabled onClick event if onClick is passed. */ + disabled?: boolean; + /** Required. pass in the icon type, using the ProjectIconType enum. */ + icon: ProjectIconType; + /** Optional. add an onClick event handler. */ + onClick?(e?: React.MouseEvent): void; + /** Optional. add an onKeyDown event handler. */ + onKeyDown?(e?: React.KeyboardEvent): void; + /** Optional. size of the actual icon. */ + size?: number; + /** Optional. size of the icon + paddings. Ignored if value is smaller than size. */ + totalSize?: number | 'unset'; + /** Optional. disables focus. Only works if there is also an onClick handler. */ + unfocusable?: boolean; +} + +/* eslint-disable */ +const ProjectIcon = forwardRef( + ( + { + className, + dataTestId, + disabled = false, + icon, + onClick, + onKeyDown, + size, + totalSize = 30, + unfocusable = false, + state, + }, + ref, + ) => { + const divStyle = useMemo(() => { + if (totalSize === 'unset') return {}; + const divSize = Math.max(size || 0, totalSize); + return {height: divSize, width: divSize}; + }, [size, totalSize]); + + const tabIndex = useMemo(() => (unfocusable || disabled || !onClick ? undefined : 0), [ + disabled, + onClick, + unfocusable, + ]); + + const handleClick = (e?: React.MouseEvent): void => { + if (disabled || !onClick) return; + + onClick(e); + }; + + const handleKeyDown = (e: React.KeyboardEvent): void => { + if (!onClick) return; + + if (e.key === 'Enter' && !disabled) { + handleClick(); + } + + onKeyDown?.(e); + }; + + const renderIcon = useCallback((): ReactNode => { + const iconBaseProps = { + 'data-testid': 'Icon__svg', + }; + + switch (icon) { + case ProjectIconType.Benefits: + return ; + case ProjectIconType.Integration: + return ; + case ProjectIconType.Milestone: + return ; + case ProjectIconType.Overview: + return ; + case ProjectIconType.Problem: + return ; + case ProjectIconType.Roadmap: + return ; + case ProjectIconType.Target: + return ; + case ProjectIconType.Timeline: + return ; + default: + return null; + } + }, [icon, size, state]); + + return ( +
+ {renderIcon()} +
+ ); + }, +); + +export {ProjectIcon}; diff --git a/src/components/ProjectIcons/types.ts b/src/components/ProjectIcons/types.ts new file mode 100644 index 000000000..6adfcdf74 --- /dev/null +++ b/src/components/ProjectIcons/types.ts @@ -0,0 +1,7 @@ +export interface CustomIconProps { + className?: string; + color?: string; + onClick?(e: React.MouseEvent): void; + size?: number | string; + state?: 'default' | 'hover' | 'active'; +} diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsContent/ProjectDetailsContent.scss b/src/containers/Projects/ProjectDetails/ProjectDetailsContent/ProjectDetailsContent.scss index 48e6bb9ba..a93dba9b3 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsContent/ProjectDetailsContent.scss +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsContent/ProjectDetailsContent.scss @@ -6,8 +6,17 @@ $details-header-height-480: 177px; background-color: var(--color-white); box-shadow: 0px 8px 88px 0px #0000000d; max-height: calc(100vh - #{$top-nav-height} - #{$details-header-height}); + + /* Hide scrollbar for IE, Edge and Firefox */ + -ms-overflow-style: none; /* IE and Edge */ overflow-y: scroll; padding: 32px; + scrollbar-width: none; /* Firefox */ + + /* Hide scrollbar for Chrome, Safari and Opera */ + &::-webkit-scrollbar { + display: none; + } &__milestone { color: var(--color-sail-gray-600); diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx index 063c045f7..87eda9e00 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx @@ -3,7 +3,7 @@ import React, {FC, useState} from 'react'; import clsx from 'clsx'; import {ProjectTopic} from 'types/projects'; -import {Icon} from '@thenewboston/ui'; +import {ProjectIcon} from 'components/ProjectIcons'; import {useWindowDimensions} from 'hooks'; import {projectDetailsTopic} from '../constants'; @@ -30,11 +30,15 @@ const ProjectDetailsSideMenu: FC = ({currentTopic, onClick}) => {
{Object.values(projectDetailsTopic).map((topic) => { const {iconType, title} = topic; + const isActive = currentTopic.title === title; + const isHovered = hoveredTopicTitle === title; + /* eslint-disable-next-line no-nested-ternary */ + const iconState = isActive ? 'active' : isHovered ? 'hover' : 'default'; return (
= ({currentTopic, onClick}) => { onMouseLeave={handleMouseLeave} tabIndex={0} > - + {shouldShowTopicTitle && title}
); diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/index.tsx index 27c2fda99..a79faea2e 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/index.tsx +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/index.tsx @@ -1,12 +1,12 @@ import React, {FC} from 'react'; -import {Icon, IconType} from '@thenewboston/ui'; +import {ProjectIcon, ProjectIconType} from 'components/ProjectIcons'; import './ProjectDetailsTopic.scss'; type Props = { content: React.ReactNode; - iconType: IconType; + iconType: ProjectIconType; id: string; title: string; overview: string; @@ -15,7 +15,7 @@ type Props = { const ProjectDetailsTopic: FC = ({content, iconType, id, title, overview}) => { return (
- +

{title}

{overview}

diff --git a/src/containers/Projects/ProjectDetails/constants.ts b/src/containers/Projects/ProjectDetails/constants.ts index 6cb838b7a..235b431f7 100644 --- a/src/containers/Projects/ProjectDetails/constants.ts +++ b/src/containers/Projects/ProjectDetails/constants.ts @@ -1,4 +1,4 @@ -import {IconType} from '@thenewboston/ui'; +import {ProjectIconType} from 'components/ProjectIcons'; import {ProjectTopicAnchor, ProjectTopicMap, ProjectTopicTitle} from 'types/projects'; @@ -6,45 +6,45 @@ import {ProjectTopicAnchor, ProjectTopicMap, ProjectTopicTitle} from 'types/proj export const projectDetailsTopic: ProjectTopicMap = { overview: { anchor: ProjectTopicAnchor.Overview, - iconType: IconType.accountGroup, + iconType: ProjectIconType.Overview, overview: 'A brief summary, situation, plan, and outline about the project, bigger picture, functionality and the possible outcome from this project', title: ProjectTopicTitle.Overview, }, problem: { anchor: ProjectTopicAnchor.Problem, - iconType: IconType.accountGroup, + iconType: ProjectIconType.Problem, overview: 'A precise information about the problem that this project is going to solve.', title: ProjectTopicTitle.Problem, }, target_market: { anchor: ProjectTopicAnchor.TargetMarket, - iconType: IconType.accountGroup, + iconType: ProjectIconType.Target, overview: 'A description of the group of users to whom TNB wants to provide the service.', title: ProjectTopicTitle.TargetMarket, }, benefits: { anchor: ProjectTopicAnchor.Benefits, - iconType: IconType.accountGroup, + iconType: ProjectIconType.Benefits, overview: 'A brief description, how this service would bring the people together and providing opportunities of interaction', title: ProjectTopicTitle.Benefits, }, centered_around_tnb: { anchor: ProjectTopicAnchor.CenteredAroundTNB, - iconType: IconType.accountGroup, + iconType: ProjectIconType.Integration, overview: 'A brief description how this service would blend into the TNB services.', title: ProjectTopicTitle.CenteredAroundTNB, }, estimated_completion_date: { anchor: ProjectTopicAnchor.EstimatedCompletionDate, - iconType: IconType.accountGroup, + iconType: ProjectIconType.Timeline, overview: 'A specific date of project completion.', title: ProjectTopicTitle.EstimatedCompletionDate, }, roadmap: { anchor: ProjectTopicAnchor.Roadmap, - iconType: IconType.accountGroup, + iconType: ProjectIconType.Roadmap, overview: 'A schedule of a lengthy project by breaking into realistic achiveable milestones.', title: ProjectTopicTitle.Roadmap, }, diff --git a/src/types/projects.ts b/src/types/projects.ts index 16c1ad7f8..e9dc4a593 100644 --- a/src/types/projects.ts +++ b/src/types/projects.ts @@ -1,4 +1,4 @@ -import {IconType} from '@thenewboston/ui'; +import {ProjectIconType} from 'components/ProjectIcons'; export type Project = { uuid: string; @@ -32,7 +32,7 @@ export type ProjectTopicMap = { export type ProjectTopic = { anchor: ProjectTopicAnchor; - iconType: IconType; + iconType: ProjectIconType; overview: string; title: ProjectTopicTitle; }; From efb9a6756baed5bc19a47e1d19f4614d12de497e Mon Sep 17 00:00:00 2001 From: jamessspanggg Date: Sat, 1 May 2021 16:08:45 +0800 Subject: [PATCH 14/58] ! Fix project icons overwritting colors of one another --- src/components/ProjectIcons/BenefitsIcon.tsx | 47 ++++++++----------- .../ProjectIcons/IntegrationIcon.tsx | 18 +++---- .../ProjectIcons/MilestonesIcon.tsx | 22 ++++----- src/components/ProjectIcons/OverviewIcon.tsx | 42 +++++++---------- src/components/ProjectIcons/ProblemIcon.tsx | 30 +++++------- src/components/ProjectIcons/RoadmapIcon.tsx | 22 ++++----- src/components/ProjectIcons/TargetIcon.tsx | 38 +++++++-------- src/components/ProjectIcons/TimelineIcon.tsx | 14 ++---- src/components/ProjectIcons/index.tsx | 10 ++-- src/components/ProjectIcons/types.ts | 2 - 10 files changed, 97 insertions(+), 148 deletions(-) diff --git a/src/components/ProjectIcons/BenefitsIcon.tsx b/src/components/ProjectIcons/BenefitsIcon.tsx index 320efdc79..742a35d28 100644 --- a/src/components/ProjectIcons/BenefitsIcon.tsx +++ b/src/components/ProjectIcons/BenefitsIcon.tsx @@ -2,25 +2,18 @@ import React, {FC} from 'react'; import {CustomIconProps} from './types'; -const BenefitsIcon: FC = ({ - className, - color = 'currentColor', - onClick, - size = 24, - state = 'default', -}) => { - console.log(state); +const BenefitsIcon: FC = ({onClick, size = 24, state = 'default'}) => { return ( - + = ({ = ({ = ({ = ({ = ({ = ({ {state === 'default' && ( @@ -222,7 +215,7 @@ const BenefitsIcon: FC = ({ = ({ = ({ = ({ = ({ = ({ = ({ = ({ = ({ = ({ - className, - color = 'currentColor', - onClick, - size = 24, - state = 'default', -}) => { +const IntegrationIcon: FC = ({onClick, size = 24, state = 'default'}) => { return ( - - + + = ({ = ({ - + diff --git a/src/components/ProjectIcons/MilestonesIcon.tsx b/src/components/ProjectIcons/MilestonesIcon.tsx index 6786e94e1..15b6ae1ab 100644 --- a/src/components/ProjectIcons/MilestonesIcon.tsx +++ b/src/components/ProjectIcons/MilestonesIcon.tsx @@ -2,23 +2,17 @@ import React, {FC} from 'react'; import {CustomIconProps} from './types'; -const MilestonesIcon: FC = ({ - className, - color = 'currentColor', - onClick, - size = 24, - state = 'default', -}) => { +const MilestonesIcon: FC = ({onClick, size = 24, state = 'default'}) => { return ( - - + + - + = ({ = ({ - + - + diff --git a/src/components/ProjectIcons/OverviewIcon.tsx b/src/components/ProjectIcons/OverviewIcon.tsx index 2a961136f..b042d9695 100644 --- a/src/components/ProjectIcons/OverviewIcon.tsx +++ b/src/components/ProjectIcons/OverviewIcon.tsx @@ -2,24 +2,18 @@ import React, {FC} from 'react'; import {CustomIconProps} from './types'; -const OverviewIcon: FC = ({ - className, - color = 'currentColor', - onClick, - size = 24, - state = 'default', -}) => { +const OverviewIcon: FC = ({onClick, size = 24, state = 'default'}) => { return ( - - + + = ({ /> = ({ /> = ({ = ({ = ({ /> {state === 'default' && ( @@ -159,7 +153,7 @@ const OverviewIcon: FC = ({ = ({ = ({ = ({ = ({ = ({ = ({ = ({ - + diff --git a/src/components/ProjectIcons/ProblemIcon.tsx b/src/components/ProjectIcons/ProblemIcon.tsx index 3cc042520..702c691e5 100644 --- a/src/components/ProjectIcons/ProblemIcon.tsx +++ b/src/components/ProjectIcons/ProblemIcon.tsx @@ -2,34 +2,28 @@ import React, {FC} from 'react'; import {CustomIconProps} from './types'; -const ProblemIcon: FC = ({ - className, - color = 'currentColor', - onClick, - size = 24, - state = 'default', -}) => { +const ProblemIcon: FC = ({onClick, size = 24, state = 'default'}) => { return ( - + = ({ )} = ({ = ({ = ({ = ({ = ({ - className, - color = 'currentColor', - onClick, - size = 24, - state = 'default', -}) => { +const RoadmapIcon: FC = ({onClick, size = 24, state = 'default'}) => { return ( - - + + = ({ d="M23.2615 8.27905H8.2373V28.0541H23.7708V27.2836L24.0255 25.7427L25.0441 24.4586L26.3173 23.945V11.3609L23.2615 8.27905Z" fill="#91B3FA" /> - + = ({ = ({ - + - + diff --git a/src/components/ProjectIcons/TargetIcon.tsx b/src/components/ProjectIcons/TargetIcon.tsx index 837db2fa8..1c9a62654 100644 --- a/src/components/ProjectIcons/TargetIcon.tsx +++ b/src/components/ProjectIcons/TargetIcon.tsx @@ -2,19 +2,13 @@ import React, {FC} from 'react'; import {CustomIconProps} from './types'; -const TargetIcon: FC = ({ - className, - color = 'currentColor', - onClick, - size = 24, - state = 'default', -}) => { +const TargetIcon: FC = ({onClick, size = 24, state = 'default'}) => { return ( - - + + = ({ /> = ({ /> {state === 'default' && ( @@ -68,7 +62,7 @@ const TargetIcon: FC = ({ = ({ = ({ = ({ = ({ = ({ = ({ - + diff --git a/src/components/ProjectIcons/TimelineIcon.tsx b/src/components/ProjectIcons/TimelineIcon.tsx index e067e4b7e..1f16b811e 100644 --- a/src/components/ProjectIcons/TimelineIcon.tsx +++ b/src/components/ProjectIcons/TimelineIcon.tsx @@ -2,16 +2,10 @@ import React, {FC} from 'react'; import {CustomIconProps} from './types'; -const TimelineIcon: FC = ({ - className, - color = 'currentColor', - onClick, - size = 24, - state = 'default', -}) => { +const TimelineIcon: FC = ({onClick, size = 24, state = 'default'}) => { return ( - - + + = ({ )} - + diff --git a/src/components/ProjectIcons/index.tsx b/src/components/ProjectIcons/index.tsx index 4a71686c2..7293263fd 100644 --- a/src/components/ProjectIcons/index.tsx +++ b/src/components/ProjectIcons/index.tsx @@ -91,7 +91,7 @@ const ProjectIcon = forwardRef( const renderIcon = useCallback((): ReactNode => { const iconBaseProps = { - 'data-testid': 'Icon__svg', + 'data-testid': 'ProjectIcon__svg', }; switch (icon) { @@ -118,12 +118,12 @@ const ProjectIcon = forwardRef( return (
): void; size?: number | string; state?: 'default' | 'hover' | 'active'; From 1f0de4db9503148afa25bc62c28d4e2d04d2fc3c Mon Sep 17 00:00:00 2001 From: jamessspanggg Date: Sat, 1 May 2021 16:15:07 +0800 Subject: [PATCH 15/58] ! Modify projects page to use latest font system --- .../ProjectsMilestones/ProjectsMilestones.scss | 6 ++++-- .../Projects/ProjectCard/ProjectCard.scss | 12 ++++++++++++ .../ProjectDetailsContent.scss | 5 +++-- .../ProjectDetailsSideMenu.scss | 13 ++++++++----- .../ProjectDetailsSideMenu/index.tsx | 16 +++++++++++----- .../ProjectDetailsTopic/ProjectDetailsTopic.scss | 13 +++++++------ .../Projects/ProjectsHero/ProjectsHero.scss | 10 ++++++---- 7 files changed, 51 insertions(+), 24 deletions(-) diff --git a/src/containers/ProjectRulesAndGuide/ProjectsMilestones/ProjectsMilestones.scss b/src/containers/ProjectRulesAndGuide/ProjectsMilestones/ProjectsMilestones.scss index a85a9355e..4064f1f01 100644 --- a/src/containers/ProjectRulesAndGuide/ProjectsMilestones/ProjectsMilestones.scss +++ b/src/containers/ProjectRulesAndGuide/ProjectsMilestones/ProjectsMilestones.scss @@ -1,3 +1,5 @@ +@import 'styles/font-mixins'; + .ProjectsMilestones { &__caption { margin: 12px 0; @@ -28,8 +30,8 @@ &__text { color: var(--color-primary); - font-size: var(--font-size-h3); - font-weight: normal; + font-weight: var(--font-weight-regular); + @extend %h3; } } diff --git a/src/containers/Projects/ProjectCard/ProjectCard.scss b/src/containers/Projects/ProjectCard/ProjectCard.scss index 16f75c2ea..145f0d04c 100644 --- a/src/containers/Projects/ProjectCard/ProjectCard.scss +++ b/src/containers/Projects/ProjectCard/ProjectCard.scss @@ -1,3 +1,5 @@ +@import 'styles/font-mixins'; + $card-width-original: 512px; $card-height-original: 324px; @@ -59,7 +61,9 @@ $padding-768: 24px; } &__details-button { + @extend %body1; bottom: $padding; + font-weight: var(--font-weight-regular); position: absolute; right: $padding; @@ -70,9 +74,11 @@ $padding-768: 24px; } &__description { + @extend %h3; -webkit-box-orient: vertical; color: var(--color-sail-gray-400); display: -webkit-box; + font-weight: var(--font-weight-regular); -webkit-line-clamp: 5; /* max number of lines to show */ overflow: hidden; text-overflow: ellipsis; @@ -87,7 +93,9 @@ $padding-768: 24px; } &__project-lead { + @extend %h4; color: var(--color-sail-gray-300); + font-weight: var(--font-weight-medium); } &__project-lead-container { @@ -96,10 +104,14 @@ $padding-768: 24px; } &__project-lead-name { + @extend %h4; color: var(--color-sail-gray-700); + font-weight: var(--font-weight-medium); } &__project-title { + @extend %h1; color: var(--color-blue-900); + font-weight: var(--font-weight-bold); } } diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsContent/ProjectDetailsContent.scss b/src/containers/Projects/ProjectDetails/ProjectDetailsContent/ProjectDetailsContent.scss index a93dba9b3..9e7f97013 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsContent/ProjectDetailsContent.scss +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsContent/ProjectDetailsContent.scss @@ -21,14 +21,15 @@ $details-header-height-480: 177px; &__milestone { color: var(--color-sail-gray-600); } + &__milestone-description { color: var(--color-sail-gray-600); - font-weight: 400; + font-weight: var(--font-weight-regular); margin-bottom: 40px; } &__milestone-number { - font-weight: 700; + font-weight: var(--font-weight-bold); margin-bottom: 8px; } diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/ProjectDetailsSideMenu.scss b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/ProjectDetailsSideMenu.scss index b0fcdf5b3..2abd0800e 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/ProjectDetailsSideMenu.scss +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/ProjectDetailsSideMenu.scss @@ -25,28 +25,31 @@ &__topic { align-items: center; - color: var(--color-gray-500); cursor: pointer; display: flex; flex-direction: row; - font-weight: 400; gap: 18px; margin-bottom: 32px; outline: none; + } + + &__topic-title { + color: var(--color-gray-500); + font-weight: var(--font-weight-regular); &:hover { color: var(--color-cyan-800); - font-weight: 700; + font-weight: var(--font-weight-bold); } &--active { color: var(--color-cyan-800); - font-weight: 700; + font-weight: var(--font-weight-bold); } &--hovered { color: var(--color-cyan-800); - font-weight: 700; + font-weight: var(--font-weight-bold); } } } diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx index 87eda9e00..a6faa90ad 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx @@ -36,10 +36,7 @@ const ProjectDetailsSideMenu: FC = ({currentTopic, onClick}) => { const iconState = isActive ? 'active' : isHovered ? 'hover' : 'default'; return (
onClick(topic)} @@ -48,7 +45,16 @@ const ProjectDetailsSideMenu: FC = ({currentTopic, onClick}) => { tabIndex={0} > - {shouldShowTopicTitle && title} + {shouldShowTopicTitle && ( +
+ {title} +
+ )}
); })} diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/ProjectDetailsTopic.scss b/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/ProjectDetailsTopic.scss index 78a99f97c..7d89a7711 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/ProjectDetailsTopic.scss +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/ProjectDetailsTopic.scss @@ -1,3 +1,5 @@ +@import 'styles/font-mixins'; + .ProjectDetailsTopic { align-items: flex-start; display: flex; @@ -15,22 +17,21 @@ } &__content-overview { - // body1 color: var(--color-sail-gray-500); - font-size: 14px; - font-weight: 400; + font-weight: var(--font-weight-regular); margin-bottom: 32px; + @extend %body1; } &__content-title { color: var(--color-sail-blue-900); - font-weight: 700; + font-weight: var(--font-weight-bold); margin-bottom: 8px; } &__content-main { color: var(--color-sail-gray-600); - // h3 regular - font-weight: 400; + font-weight: var(--font-weight-regular); + @extend %h3; } } diff --git a/src/containers/Projects/ProjectsHero/ProjectsHero.scss b/src/containers/Projects/ProjectsHero/ProjectsHero.scss index d423b869e..8c0f366a6 100644 --- a/src/containers/Projects/ProjectsHero/ProjectsHero.scss +++ b/src/containers/Projects/ProjectsHero/ProjectsHero.scss @@ -1,3 +1,5 @@ +@import 'styles/font-mixins'; + $gap-width: 50px; $left-pl: 64px; $right-width: 714px; @@ -81,16 +83,16 @@ $title-width: 480px; &__subtitle { color: var(--color-gray-500); - font-size: var(--font-size-regular); - font-weight: normal; + font-weight: var(--font-weight-regular); line-height: 1.5; margin-bottom: 40px; margin-top: 30px; + @extend %h3; } &__title { - font-size: 42px; - font-weight: 800; + @extend %display1; + font-weight: var(--font-weight-bold); line-height: 1.25; } From c2476206175034cdac5f2d9d69ee2d803bee70cf Mon Sep 17 00:00:00 2001 From: jamessspanggg Date: Sat, 1 May 2021 22:55:05 +0800 Subject: [PATCH 16/58] ! Fix colouring of integration icon --- .../ProjectIcons/IntegrationIcon.tsx | 77 +++++++++++-------- 1 file changed, 46 insertions(+), 31 deletions(-) diff --git a/src/components/ProjectIcons/IntegrationIcon.tsx b/src/components/ProjectIcons/IntegrationIcon.tsx index 8e5bee96f..f444f76c7 100644 --- a/src/components/ProjectIcons/IntegrationIcon.tsx +++ b/src/components/ProjectIcons/IntegrationIcon.tsx @@ -5,50 +5,65 @@ import {CustomIconProps} from './types'; const IntegrationIcon: FC = ({onClick, size = 24, state = 'default'}) => { return ( - + + + + + + + + + + + - - - - - - - {state === 'default' && ( - - - - )} + {state === 'default' && ( + + + + )} - - - + + + + ); From 76926d52c031ca7318e67ff0cc1dab289b9a4b3a Mon Sep 17 00:00:00 2001 From: jamessspanggg Date: Sat, 1 May 2021 23:19:22 +0800 Subject: [PATCH 17/58] ! Fix project icons not being masked properly --- src/components/ProjectIcons/BenefitsIcon.tsx | 2 +- src/components/ProjectIcons/IntegrationIcon.tsx | 2 +- src/components/ProjectIcons/MilestonesIcon.tsx | 2 +- src/components/ProjectIcons/OverviewIcon.tsx | 2 +- src/components/ProjectIcons/ProblemIcon.tsx | 2 +- src/components/ProjectIcons/RoadmapIcon.tsx | 2 +- src/components/ProjectIcons/TargetIcon.tsx | 2 +- src/components/ProjectIcons/TimelineIcon.tsx | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/components/ProjectIcons/BenefitsIcon.tsx b/src/components/ProjectIcons/BenefitsIcon.tsx index 742a35d28..d35594fbd 100644 --- a/src/components/ProjectIcons/BenefitsIcon.tsx +++ b/src/components/ProjectIcons/BenefitsIcon.tsx @@ -209,7 +209,7 @@ const BenefitsIcon: FC = ({onClick, size = 24, state = 'default {state === 'default' && ( - + )} diff --git a/src/components/ProjectIcons/IntegrationIcon.tsx b/src/components/ProjectIcons/IntegrationIcon.tsx index f444f76c7..15c12cdc0 100644 --- a/src/components/ProjectIcons/IntegrationIcon.tsx +++ b/src/components/ProjectIcons/IntegrationIcon.tsx @@ -38,7 +38,7 @@ const IntegrationIcon: FC = ({onClick, size = 24, state = 'defa {state === 'default' && ( - + )} diff --git a/src/components/ProjectIcons/MilestonesIcon.tsx b/src/components/ProjectIcons/MilestonesIcon.tsx index 15b6ae1ab..4a4f6c085 100644 --- a/src/components/ProjectIcons/MilestonesIcon.tsx +++ b/src/components/ProjectIcons/MilestonesIcon.tsx @@ -52,7 +52,7 @@ const MilestonesIcon: FC = ({onClick, size = 24, state = 'defau /> {state === 'default' && ( - + )} diff --git a/src/components/ProjectIcons/OverviewIcon.tsx b/src/components/ProjectIcons/OverviewIcon.tsx index b042d9695..f5dd27643 100644 --- a/src/components/ProjectIcons/OverviewIcon.tsx +++ b/src/components/ProjectIcons/OverviewIcon.tsx @@ -147,7 +147,7 @@ const OverviewIcon: FC = ({onClick, size = 24, state = 'default /> {state === 'default' && ( - + )} diff --git a/src/components/ProjectIcons/ProblemIcon.tsx b/src/components/ProjectIcons/ProblemIcon.tsx index 702c691e5..1d1a8478a 100644 --- a/src/components/ProjectIcons/ProblemIcon.tsx +++ b/src/components/ProjectIcons/ProblemIcon.tsx @@ -47,7 +47,7 @@ const ProblemIcon: FC = ({onClick, size = 24, state = 'default' /> {state === 'default' && ( - + )} diff --git a/src/components/ProjectIcons/RoadmapIcon.tsx b/src/components/ProjectIcons/RoadmapIcon.tsx index fb190f385..075cfdcba 100644 --- a/src/components/ProjectIcons/RoadmapIcon.tsx +++ b/src/components/ProjectIcons/RoadmapIcon.tsx @@ -39,7 +39,7 @@ const RoadmapIcon: FC = ({onClick, size = 24, state = 'default' {state === 'default' && ( - + )} diff --git a/src/components/ProjectIcons/TargetIcon.tsx b/src/components/ProjectIcons/TargetIcon.tsx index 1c9a62654..9ed0e342a 100644 --- a/src/components/ProjectIcons/TargetIcon.tsx +++ b/src/components/ProjectIcons/TargetIcon.tsx @@ -56,7 +56,7 @@ const TargetIcon: FC = ({onClick, size = 24, state = 'default'} /> {state === 'default' && ( - + )} diff --git a/src/components/ProjectIcons/TimelineIcon.tsx b/src/components/ProjectIcons/TimelineIcon.tsx index 1f16b811e..290288b81 100644 --- a/src/components/ProjectIcons/TimelineIcon.tsx +++ b/src/components/ProjectIcons/TimelineIcon.tsx @@ -260,7 +260,7 @@ const TimelineIcon: FC = ({onClick, size = 24, state = 'default /> {state === 'default' && ( - + )} From 1f492eb53692bb9d16014344516c1dec060603b2 Mon Sep 17 00:00:00 2001 From: jamessspanggg Date: Sun, 2 May 2021 00:07:16 +0800 Subject: [PATCH 18/58] ! Update projects hifi page based on latest updated design --- src/components/Button/Button.scss | 1 + .../ListOfProjects/ListOfProjects.scss | 10 +++---- .../Projects/ProjectCard/ProjectCard.scss | 20 ++++++++++--- src/containers/Projects/ProjectCard/index.tsx | 8 ++--- .../ProjectDetails/ProjectDetails.scss | 2 +- .../ProjectDetailsContent.scss | 20 ++----------- .../ProjectDetailsContent/index.tsx | 13 ++++---- .../ProjectDetailsHeader.scss | 30 ++++++++++++++++++- .../ProjectDetailsHeader/index.tsx | 2 +- .../ProjectDetailsSideMenu.scss | 22 +++++++------- .../ProjectDetailsSideMenu/index.tsx | 7 ++--- src/containers/Projects/_shared.scss | 5 ++++ src/containers/Projects/index.tsx | 3 +- 13 files changed, 85 insertions(+), 58 deletions(-) create mode 100644 src/containers/Projects/_shared.scss diff --git a/src/components/Button/Button.scss b/src/components/Button/Button.scss index ff7a4f472..e8f616614 100644 --- a/src/components/Button/Button.scss +++ b/src/components/Button/Button.scss @@ -2,6 +2,7 @@ align-items: center; display: inline-flex; height: 40px; + outline: none; &__empty { background-color: var(--color-white); diff --git a/src/containers/Projects/ListOfProjects/ListOfProjects.scss b/src/containers/Projects/ListOfProjects/ListOfProjects.scss index 982708244..76530f7c6 100644 --- a/src/containers/Projects/ListOfProjects/ListOfProjects.scss +++ b/src/containers/Projects/ListOfProjects/ListOfProjects.scss @@ -1,12 +1,12 @@ -$card-width-original: 512px; -$card-width-992: 376px; -$card-width-768: 328px; -$card-width-480: 376px; +$card-width-original: 384px; +$card-width-992: 432px; +$card-width-768: 320px; +$card-width-480: 360px; .ListOfProjects { column-gap: 32px; display: grid; - grid-template-columns: $card-width-original $card-width-original; + grid-template-columns: $card-width-original $card-width-original $card-width-original; justify-content: center; margin-bottom: 32px; row-gap: 32px; diff --git a/src/containers/Projects/ProjectCard/ProjectCard.scss b/src/containers/Projects/ProjectCard/ProjectCard.scss index 145f0d04c..4b27764e4 100644 --- a/src/containers/Projects/ProjectCard/ProjectCard.scss +++ b/src/containers/Projects/ProjectCard/ProjectCard.scss @@ -1,11 +1,11 @@ @import 'styles/font-mixins'; -$card-width-original: 512px; +$card-width-original: 384px; $card-height-original: 324px; -$card-width-992: 376px; +$card-width-992: 432px; -$card-width-768: 328px; +$card-width-768: 320px; $card-height-768: 262px; $card-height-480: 324px; @@ -50,6 +50,10 @@ $padding-768: 24px; display: flex; flex-direction: column; gap: 10px; + + @media (max-width: 768px) { + gap: 2px; + } } &__top-container { @@ -58,6 +62,12 @@ $padding-768: 24px; flex-direction: row; gap: 20px; margin-bottom: 35px; + + @media (max-width: 768px) { + flex-direction: column; + gap: 2px; + text-align: center; + } } &__details-button { @@ -69,7 +79,8 @@ $padding-768: 24px; @media (max-width: 768px) { bottom: $padding-768; - right: $padding-768; + left: 50%; + transform: translateX(-50%); } } @@ -85,6 +96,7 @@ $padding-768: 24px; @media (max-width: 768px) { -webkit-line-clamp: 3; /* max number of lines to show */ + text-align: center; } @media (max-width: 480px) { diff --git a/src/containers/Projects/ProjectCard/index.tsx b/src/containers/Projects/ProjectCard/index.tsx index f113fd598..45b1a1071 100644 --- a/src/containers/Projects/ProjectCard/index.tsx +++ b/src/containers/Projects/ProjectCard/index.tsx @@ -2,9 +2,9 @@ import React, {FC, useEffect, useState} from 'react'; import {getUser} from 'apis/users'; import {api as projectApi} from 'apis/projects'; -import {useHistory} from 'react-router'; import {Avatar} from 'components'; import Button from 'components/Button'; +import {useWindowDimensions} from 'hooks'; import {User} from 'types/app/User'; import {Icon, IconType} from '@thenewboston/ui'; @@ -20,6 +20,7 @@ type Props = { const ProjectCard: FC = ({description, id, logoUrl, projectLead, title}) => { const [projectLeadUser, setProjectLeadUser] = useState(null); + const {width} = useWindowDimensions(); useEffect(() => { (async function () { @@ -31,11 +32,10 @@ const ProjectCard: FC = ({description, id, logoUrl, projectLead, title}) })(); }, [projectLead]); - const history = useHistory(); return (
- + 768 ? 64 : 20} />

{title}

@@ -47,7 +47,7 @@ const ProjectCard: FC = ({description, id, logoUrl, projectLead, title})
{description}
-
{getMultiLineDivFromString(description)}
+
{description}
From a87f3b9946bb9e4cba810e2483bed752c8f806dd Mon Sep 17 00:00:00 2001 From: Justin Kim Date: Sun, 2 May 2021 13:18:32 -0500 Subject: [PATCH 26/58] remove strings.tsx --- package-lock.json | 40 ++++++++++--------- package.json | 2 +- src/containers/Projects/ProjectCard/index.tsx | 6 ++- .../ProjectDetailsContent.scss | 3 +- .../ProjectDetailsContent/index.tsx | 6 +-- .../ProjectDetailsHeader/index.tsx | 8 +++- .../ProjectDetailsTopic.scss | 1 + .../ProjectDetailsTopic/index.tsx | 17 +++----- src/utils/strings.tsx | 5 --- 9 files changed, 41 insertions(+), 47 deletions(-) delete mode 100644 src/utils/strings.tsx diff --git a/package-lock.json b/package-lock.json index 7976f1300..74f5d368f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@testing-library/jest-dom": "^5.11.9", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.6.3", - "@thenewboston/ui": "^0.1.7", + "@thenewboston/ui": "^0.1.8", "@thenewboston/utils": "^1.0.0", "@types/jest": "^26.0.20", "@types/node": "^12.0.0", @@ -2782,9 +2782,9 @@ } }, "node_modules/@thenewboston/ui": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/@thenewboston/ui/-/ui-0.1.7.tgz", - "integrity": "sha512-b8YFMaiD+b0X4OxT/ES+FgxxJsXCR/V9k14BUjT3mJDMrSFm24wu+JIcjZnCd46keMNlmYYQwUyWxBypHnWe4A==", + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@thenewboston/ui/-/ui-0.1.8.tgz", + "integrity": "sha512-Yra3XcirrqYmhYtdFkbBgSqhVugRlQ2Ggc/U9PWTTzP0fx7P7lQ7lx2F3My4f4TGodPMyyKsDQBi63+1FBJxYA==", "dependencies": { "@thenewboston/utils": "^1.0.0", "mdi-react": "^7.4.0" @@ -19650,9 +19650,9 @@ } }, "node_modules/ssri": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.0.tgz", - "integrity": "sha512-aq/pz989nxVYwn16Tsbj1TqFpD5LLrQxHf5zaHuieFV+R0Bbr4y8qUsOA45hXT/N4/9UNXTarBjnjVmjSOVaAA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", "dependencies": { "minipass": "^3.1.1" }, @@ -21936,6 +21936,7 @@ "version": "1.2.13", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "hasInstallScript": true, "optional": true, "os": [ "darwin" @@ -22301,6 +22302,7 @@ "version": "1.2.13", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "hasInstallScript": true, "optional": true, "os": [ "darwin" @@ -22786,9 +22788,9 @@ } }, "node_modules/webpack/node_modules/ssri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", "dependencies": { "figgy-pudding": "^3.5.1" } @@ -25729,9 +25731,9 @@ } }, "@thenewboston/ui": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/@thenewboston/ui/-/ui-0.1.7.tgz", - "integrity": "sha512-b8YFMaiD+b0X4OxT/ES+FgxxJsXCR/V9k14BUjT3mJDMrSFm24wu+JIcjZnCd46keMNlmYYQwUyWxBypHnWe4A==", + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@thenewboston/ui/-/ui-0.1.8.tgz", + "integrity": "sha512-Yra3XcirrqYmhYtdFkbBgSqhVugRlQ2Ggc/U9PWTTzP0fx7P7lQ7lx2F3My4f4TGodPMyyKsDQBi63+1FBJxYA==", "requires": { "@thenewboston/utils": "^1.0.0", "mdi-react": "^7.4.0" @@ -39642,9 +39644,9 @@ } }, "ssri": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.0.tgz", - "integrity": "sha512-aq/pz989nxVYwn16Tsbj1TqFpD5LLrQxHf5zaHuieFV+R0Bbr4y8qUsOA45hXT/N4/9UNXTarBjnjVmjSOVaAA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", "requires": { "minipass": "^3.1.1" } @@ -41842,9 +41844,9 @@ } }, "ssri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", "requires": { "figgy-pudding": "^3.5.1" } diff --git a/package.json b/package.json index e677ccbfd..9f5922a32 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "@testing-library/jest-dom": "^5.11.9", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.6.3", - "@thenewboston/ui": "^0.1.7", + "@thenewboston/ui": "^0.1.8", "@thenewboston/utils": "^1.0.0", "@types/jest": "^26.0.20", "@types/node": "^12.0.0", diff --git a/src/containers/Projects/ProjectCard/index.tsx b/src/containers/Projects/ProjectCard/index.tsx index 2f3f575ac..687878a0c 100644 --- a/src/containers/Projects/ProjectCard/index.tsx +++ b/src/containers/Projects/ProjectCard/index.tsx @@ -23,13 +23,15 @@ const ProjectCard: FC = ({description, id, logoUrl, projectLead, title}) const {width} = useWindowDimensions(); useEffect(() => { - (async function () { + const fetchData = async () => { // We require to call two extra APIs just to get the project lead's name, perhaps we // should adopt a BFF design const projectMemberResponse = await projectApi.getProjectMemberById(projectLead); const userResponse = await getUser({uuid: projectMemberResponse.user}); setProjectLeadUser(userResponse); - })(); + }; + + fetchData(); }, [projectLead]); return ( diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsContent/ProjectDetailsContent.scss b/src/containers/Projects/ProjectDetails/ProjectDetailsContent/ProjectDetailsContent.scss index 836264362..f93c438e7 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsContent/ProjectDetailsContent.scss +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsContent/ProjectDetailsContent.scss @@ -3,7 +3,7 @@ .ProjectDetailsContent { background-color: var(--color-white); - box-shadow: 0px 8px 88px 0px #0000000d; + box-shadow: 0 8px 88px 0 #0000000d; margin-bottom: 120px; padding: 32px; @@ -16,6 +16,7 @@ color: var(--color-sail-gray-600); font-weight: var(--font-weight-regular); margin-bottom: 40px; + white-space: pre-line; } &__milestone-number { diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx index 168d4a594..6725a27d4 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx @@ -1,10 +1,8 @@ import React, {FC, useEffect} from 'react'; import {format} from 'fecha'; -import Linkify from 'linkifyjs/react'; import {useWindowDimensions} from 'hooks'; import {Milestone, Project, ProjectTopic, ProjectTopicTitle} from 'types/projects'; -import {getMultiLineDivFromString} from 'utils/strings'; import ProjectDetailsTopic from '../ProjectDetailsTopic'; import {projectDetailsTopic} from '../constants'; import './ProjectDetailsContent.scss'; @@ -40,9 +38,7 @@ const ProjectDetailsContent: FC = ({milestones, project, currentTopic}) = return (

Milestone {milestone.number}

-
- {getMultiLineDivFromString(milestone.description)} -
+
{milestone.description}
); }); diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsHeader/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsHeader/index.tsx index 373ed5c0e..4bfebcd5c 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsHeader/index.tsx +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsHeader/index.tsx @@ -17,15 +17,19 @@ type Props = { const ProjectDetailsHeader: FC = ({github, logoUrl, projectLead, title}) => { const [projectLeadUser, setProjectLeadUser] = useState(null); + useEffect(() => { - (async function () { + const fetchData = async () => { // We require to call two extra APIs just to get the project lead's name, perhaps we // should adopt a BFF design const projectMemberResponse = await projectApi.getProjectMemberById(projectLead); const userResponse = await getUser({uuid: projectMemberResponse.user}); setProjectLeadUser(userResponse); - })(); + }; + + fetchData(); }, [projectLead]); + return (
diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/ProjectDetailsTopic.scss b/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/ProjectDetailsTopic.scss index a62713964..ea3cd7544 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/ProjectDetailsTopic.scss +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/ProjectDetailsTopic.scss @@ -25,6 +25,7 @@ &__content-main { @extend %h3; + white-space: pre-line; } &__content-overview { diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/index.tsx index 2ae1b06f7..19225914b 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/index.tsx +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/index.tsx @@ -1,31 +1,24 @@ import React, {FC} from 'react'; import {ProjectIcon, ProjectIconType} from 'components/ProjectIcons'; -import Linkify from 'linkifyjs/react'; -import {getMultiLineDivFromString} from 'utils/strings'; - import './ProjectDetailsTopic.scss'; -type Props = { +interface ComponentProps { content: React.ReactNode; iconType: ProjectIconType; id: string; - title: string; overview: string; -}; - -const ProjectDetailsTopic: FC = ({content, iconType, id, title, overview}) => { - const processedContent = typeof content === 'string' ? getMultiLineDivFromString(content) : content; + title: string; +} +const ProjectDetailsTopic: FC = ({content, iconType, id, title, overview}) => { return (

{title}

{overview}

-
- {processedContent} -
+
{content}
); diff --git a/src/utils/strings.tsx b/src/utils/strings.tsx deleted file mode 100644 index 7476e7868..000000000 --- a/src/utils/strings.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import React from 'react'; - -export const getMultiLineDivFromString = (content: string) => { - return content.split('\n').map((line, i) =>
{line}
); -}; From 5f15547048a9f64d0569bf7d4e6520a0c0af7887 Mon Sep 17 00:00:00 2001 From: Justin Kim Date: Sun, 2 May 2021 13:20:46 -0500 Subject: [PATCH 27/58] remove linkifyjs --- package-lock.json | 48 ----------------------------------------------- package.json | 2 -- 2 files changed, 50 deletions(-) diff --git a/package-lock.json b/package-lock.json index 74f5d368f..dcbf02570 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,7 +29,6 @@ "fecha": "^4.2.1", "formik": "^2.2.2", "leaflet": "^1.7.1", - "linkifyjs": "^2.1.9", "lodash-es": "^4.17.15", "mdi-react": "^7.3.0", "normalize.css": "^8.0.1", @@ -55,7 +54,6 @@ }, "devDependencies": { "@types/leaflet": "^1.5.19", - "@types/linkifyjs": "^2.1.3", "@types/lodash-es": "^4.17.3", "@types/qrcode": "^1.3.5", "@types/react-copy-to-clipboard": "^4.3.0", @@ -2965,15 +2963,6 @@ "@types/geojson": "*" } }, - "node_modules/@types/linkifyjs": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@types/linkifyjs/-/linkifyjs-2.1.3.tgz", - "integrity": "sha512-V3Xt9wgaOvDPXcpOy3dC8qXCxy3cs0Lr/Hqgd9Bi6m3sf/vpbpTtfmVR0LJklrqYEjaAmc7e3Xh/INT2rCAKjQ==", - "dev": true, - "dependencies": { - "@types/react": "*" - } - }, "node_modules/@types/lodash": { "version": "4.14.165", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.165.tgz", @@ -13367,12 +13356,6 @@ "node": ">=6" } }, - "node_modules/jquery": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz", - "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==", - "peer": true - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -13634,16 +13617,6 @@ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=" }, - "node_modules/linkifyjs": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/linkifyjs/-/linkifyjs-2.1.9.tgz", - "integrity": "sha512-74ivurkK6WHvHFozVaGtQWV38FzBwSTGNmJolEgFp7QgR2bl6ArUWlvT4GcHKbPe1z3nWYi+VUdDZk16zDOVug==", - "peerDependencies": { - "jquery": ">= 1.11.0", - "react": ">= 0.14.0", - "react-dom": ">= 0.14.0" - } - }, "node_modules/lint-staged": { "version": "10.5.1", "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.5.1.tgz", @@ -25905,15 +25878,6 @@ "@types/geojson": "*" } }, - "@types/linkifyjs": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@types/linkifyjs/-/linkifyjs-2.1.3.tgz", - "integrity": "sha512-V3Xt9wgaOvDPXcpOy3dC8qXCxy3cs0Lr/Hqgd9Bi6m3sf/vpbpTtfmVR0LJklrqYEjaAmc7e3Xh/INT2rCAKjQ==", - "dev": true, - "requires": { - "@types/react": "*" - } - }, "@types/lodash": { "version": "4.14.165", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.165.tgz", @@ -34389,12 +34353,6 @@ } } }, - "jquery": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz", - "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==", - "peer": true - }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -34615,12 +34573,6 @@ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=" }, - "linkifyjs": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/linkifyjs/-/linkifyjs-2.1.9.tgz", - "integrity": "sha512-74ivurkK6WHvHFozVaGtQWV38FzBwSTGNmJolEgFp7QgR2bl6ArUWlvT4GcHKbPe1z3nWYi+VUdDZk16zDOVug==", - "requires": {} - }, "lint-staged": { "version": "10.5.1", "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.5.1.tgz", diff --git a/package.json b/package.json index 9f5922a32..7bdcddeb3 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,6 @@ "fecha": "^4.2.1", "formik": "^2.2.2", "leaflet": "^1.7.1", - "linkifyjs": "^2.1.9", "lodash-es": "^4.17.15", "mdi-react": "^7.3.0", "normalize.css": "^8.0.1", @@ -74,7 +73,6 @@ }, "devDependencies": { "@types/leaflet": "^1.5.19", - "@types/linkifyjs": "^2.1.3", "@types/lodash-es": "^4.17.3", "@types/qrcode": "^1.3.5", "@types/react-copy-to-clipboard": "^4.3.0", From 4d74e0715befe961c814d74a36e8916df3e00f38 Mon Sep 17 00:00:00 2001 From: Justin Kim Date: Sun, 2 May 2021 13:29:21 -0500 Subject: [PATCH 28/58] remove fecha --- package-lock.json | 11 ----------- package.json | 1 - .../ProjectDetails/ProjectDetailsContent/index.tsx | 5 +++-- 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index dcbf02570..1a0bf18c0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,7 +26,6 @@ "axios": "^0.21.1", "clsx": "^1.1.1", "date-fns": "^2.16.1", - "fecha": "^4.2.1", "formik": "^2.2.2", "leaflet": "^1.7.1", "lodash-es": "^4.17.15", @@ -8709,11 +8708,6 @@ "bser": "2.1.1" } }, - "node_modules/fecha": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.1.tgz", - "integrity": "sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q==" - }, "node_modules/figgy-pudding": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", @@ -30690,11 +30684,6 @@ "bser": "2.1.1" } }, - "fecha": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.1.tgz", - "integrity": "sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q==" - }, "figgy-pudding": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", diff --git a/package.json b/package.json index 7bdcddeb3..94a608058 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,6 @@ "axios": "^0.21.1", "clsx": "^1.1.1", "date-fns": "^2.16.1", - "fecha": "^4.2.1", "formik": "^2.2.2", "leaflet": "^1.7.1", "lodash-es": "^4.17.15", diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx index 6725a27d4..ea4b7aa29 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx @@ -1,6 +1,7 @@ import React, {FC, useEffect} from 'react'; +import format from 'date-fns/format'; +import parseISO from 'date-fns/parseISO'; -import {format} from 'fecha'; import {useWindowDimensions} from 'hooks'; import {Milestone, Project, ProjectTopic, ProjectTopicTitle} from 'types/projects'; import ProjectDetailsTopic from '../ProjectDetailsTopic'; @@ -82,7 +83,7 @@ const ProjectDetailsContent: FC = ({milestones, project, currentTopic}) = /> Date: Sun, 2 May 2021 19:08:25 -0500 Subject: [PATCH 29/58] PaginatedResponse --- src/apis/projects/api.ts | 8 ++++---- src/apis/tutorials/index.ts | 9 ++++----- src/apis/tutorials/types.ts | 15 --------------- src/types/api.ts | 5 ++++- 4 files changed, 12 insertions(+), 25 deletions(-) delete mode 100644 src/apis/tutorials/types.ts diff --git a/src/apis/projects/api.ts b/src/apis/projects/api.ts index 40635d1ff..ef6c5578f 100644 --- a/src/apis/projects/api.ts +++ b/src/apis/projects/api.ts @@ -1,10 +1,10 @@ import axios from 'axios'; -import {APIArrayResponse} from 'types/api'; +import {PaginatedResponse} from 'types/api'; import {Project, Milestone} from 'types/projects'; export async function getProjects(): Promise { - const response = await axios.get>(`${process.env.REACT_APP_BACKEND_API}/projects`); + const response = await axios.get>(`${process.env.REACT_APP_BACKEND_API}/projects`); if (!response.data) { throw new Error('Error while fetching projects, please try again.'); @@ -13,7 +13,7 @@ export async function getProjects(): Promise { } export async function getMilestones(): Promise { - const response = await axios.get>(`${process.env.REACT_APP_BACKEND_API}/milestones`); + const response = await axios.get>(`${process.env.REACT_APP_BACKEND_API}/milestones`); if (!response.data) { throw new Error('Error while fetching milestones, please try again.'); } @@ -21,7 +21,7 @@ export async function getMilestones(): Promise { } export async function getMilestonesByProject(id: string): Promise { - const response = await axios.get>( + const response = await axios.get>( `${process.env.REACT_APP_BACKEND_API}/milestones?project=${id}`, ); if (!response.data) { diff --git a/src/apis/tutorials/index.ts b/src/apis/tutorials/index.ts index 1798c2fbf..5554bf5b1 100644 --- a/src/apis/tutorials/index.ts +++ b/src/apis/tutorials/index.ts @@ -1,12 +1,11 @@ import axios from 'axios'; import {allTutorialsFilter} from 'constants/tutorials'; +import {PaginatedResponse} from 'types/api'; import {Category, Playlist} from 'types/tutorials'; import {standardHeaders} from 'utils/requests'; -import {CategoriesResponse, PlaylistsResponse} from './types'; - export async function getCategories(): Promise { - const response = await axios.get( + const response = await axios.get>( `${process.env.REACT_APP_BACKEND_API}/categories`, standardHeaders(), ); @@ -16,7 +15,7 @@ export async function getCategories(): Promise { export async function getPlaylists(category: string): Promise { if (category !== allTutorialsFilter.title) { - const response = await axios.get( + const response = await axios.get>( `${process.env.REACT_APP_BACKEND_API}/playlists?category=${category}`, standardHeaders(), ); @@ -24,7 +23,7 @@ export async function getPlaylists(category: string): Promise { return response.data.results; } - const response = await axios.get( + const response = await axios.get>( `${process.env.REACT_APP_BACKEND_API}/playlists`, standardHeaders(), ); diff --git a/src/apis/tutorials/types.ts b/src/apis/tutorials/types.ts deleted file mode 100644 index 785e5ba60..000000000 --- a/src/apis/tutorials/types.ts +++ /dev/null @@ -1,15 +0,0 @@ -import {Category, Playlist} from 'types/tutorials'; - -export interface CategoriesResponse { - count: number; - next: number | null; - previous: number | null; - results: Category[]; -} - -export interface PlaylistsResponse { - count: number; - next: number | null; - previous: number | null; - results: Playlist[]; -} diff --git a/src/types/api.ts b/src/types/api.ts index 071e9e99d..a0707202e 100644 --- a/src/types/api.ts +++ b/src/types/api.ts @@ -12,6 +12,9 @@ export interface Token { token: string; } -export interface APIArrayResponse { +export interface PaginatedResponse { + count: number; + next: number | null; + previous: number | null; results: T[]; } From e3596315cb1d258756e3dc23fc146b00bf643d2d Mon Sep 17 00:00:00 2001 From: jamessspanggg Date: Mon, 3 May 2021 21:50:12 +0800 Subject: [PATCH 30/58] Remove milestone related api as milestone is nested within the projects model --- src/apis/projects/api.ts | 18 ------------------ .../ProjectDetailsContent/index.tsx | 5 ++--- .../Projects/ProjectDetails/index.tsx | 5 ++--- src/containers/Projects/index.tsx | 18 ++---------------- src/types/projects.ts | 1 + 5 files changed, 7 insertions(+), 40 deletions(-) diff --git a/src/apis/projects/api.ts b/src/apis/projects/api.ts index ef6c5578f..36a0c8688 100644 --- a/src/apis/projects/api.ts +++ b/src/apis/projects/api.ts @@ -12,24 +12,6 @@ export async function getProjects(): Promise { return response.data.results; } -export async function getMilestones(): Promise { - const response = await axios.get>(`${process.env.REACT_APP_BACKEND_API}/milestones`); - if (!response.data) { - throw new Error('Error while fetching milestones, please try again.'); - } - return response.data.results; -} - -export async function getMilestonesByProject(id: string): Promise { - const response = await axios.get>( - `${process.env.REACT_APP_BACKEND_API}/milestones?project=${id}`, - ); - if (!response.data) { - throw new Error('Error while fetching milestones, please try again.'); - } - return response.data.results; -} - export async function getProjectMemberById(id: string) { const response = await axios.get(`${process.env.REACT_APP_BACKEND_API}/project_members/${id}`); if (!response.data) { diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx index ea4b7aa29..6ccdec7f0 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx @@ -9,7 +9,6 @@ import {projectDetailsTopic} from '../constants'; import './ProjectDetailsContent.scss'; type Props = { - milestones: Milestone[]; project: Project; currentTopic: ProjectTopic; }; @@ -18,7 +17,7 @@ const TOP_NAV_HEIGHT = 60; const DETAILS_CONTAINER_HEIGHT = 158; const DETAILS_CONTAINER_HEIGHT_480 = 241; -const ProjectDetailsContent: FC = ({milestones, project, currentTopic}) => { +const ProjectDetailsContent: FC = ({project, currentTopic}) => { const {width} = useWindowDimensions(); const detailsHeaderHeight = width >= 480 ? DETAILS_CONTAINER_HEIGHT : DETAILS_CONTAINER_HEIGHT_480; useEffect(() => { @@ -35,7 +34,7 @@ const ProjectDetailsContent: FC = ({milestones, project, currentTopic}) = }, [currentTopic, detailsHeaderHeight]); const renderMilestones = () => { - return milestones.map((milestone) => { + return project.milestones.map((milestone) => { return (

Milestone {milestone.number}

diff --git a/src/containers/Projects/ProjectDetails/index.tsx b/src/containers/Projects/ProjectDetails/index.tsx index 124aea05c..3bdcbc61f 100644 --- a/src/containers/Projects/ProjectDetails/index.tsx +++ b/src/containers/Projects/ProjectDetails/index.tsx @@ -8,11 +8,10 @@ import {projectDetailsTopic} from './constants'; import './ProjectDetails.scss'; type Props = { - milestones: Milestone[]; project: Project; }; -const ProjectDetails: FC = ({milestones, project}) => { +const ProjectDetails: FC = ({project}) => { const [currentTopic, setCurrentTopic] = useState(projectDetailsTopic.overview); const {title, logo, github_url: github, project_lead: projectLead} = project; @@ -25,7 +24,7 @@ const ProjectDetails: FC = ({milestones, project}) => {
- +
); diff --git a/src/containers/Projects/index.tsx b/src/containers/Projects/index.tsx index b36bd2b0e..86a062c92 100644 --- a/src/containers/Projects/index.tsx +++ b/src/containers/Projects/index.tsx @@ -2,7 +2,7 @@ import React, {FC, useEffect, useState} from 'react'; import {useParams} from 'react-router-dom'; import {api as projectsApi} from 'apis/projects'; -import {Project, Milestone} from 'types/projects'; +import {Project} from 'types/projects'; import {Loader} from 'components'; import ListOfProjects from './ListOfProjects'; import ProjectsHero from './ProjectsHero'; @@ -13,7 +13,6 @@ import './Projects.scss'; const Projects: FC = () => { const {projectId} = useParams<{projectId: string}>(); const [projects, setProjects] = useState([]); - const [milestones, setMilestones] = useState([]); const isValidProjectId = projects.length && projects.some((project) => project.uuid === projectId); const [isLoading, setIsLoading] = useState(true); @@ -31,19 +30,6 @@ const Projects: FC = () => { })(); }, []); - useEffect(() => { - (async function getMilestones() { - try { - if (isValidProjectId) { - const milestonesResponse = await projectsApi.getMilestonesByProject(projectId); - setMilestones(milestonesResponse); - } - } catch (err) { - // handle error - } - })(); - }, [isValidProjectId, projectId]); - if (isLoading) { return (
@@ -54,7 +40,7 @@ const Projects: FC = () => { if (isValidProjectId) { const selectedProject = projects.find((project) => project.uuid === projectId) as Project; - return ; + return ; } return ( diff --git a/src/types/projects.ts b/src/types/projects.ts index e9dc4a593..55c0fdba8 100644 --- a/src/types/projects.ts +++ b/src/types/projects.ts @@ -15,6 +15,7 @@ export type Project = { centered_around_tnb: string; estimated_completion_date: string; project_lead: string; + milestones: Milestone[]; }; export type Milestone = { From b6b6deb4162326afd9cce49824621deb0c81dac9 Mon Sep 17 00:00:00 2001 From: Justin Kim Date: Mon, 3 May 2021 19:55:19 -0500 Subject: [PATCH 31/58] lint errors --- src/apis/projects/api.ts | 2 +- .../Projects/ProjectDetails/ProjectDetailsContent/index.tsx | 2 +- src/containers/Projects/ProjectDetails/index.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/apis/projects/api.ts b/src/apis/projects/api.ts index 36a0c8688..0902f62a2 100644 --- a/src/apis/projects/api.ts +++ b/src/apis/projects/api.ts @@ -1,7 +1,7 @@ import axios from 'axios'; import {PaginatedResponse} from 'types/api'; -import {Project, Milestone} from 'types/projects'; +import {Project} from 'types/projects'; export async function getProjects(): Promise { const response = await axios.get>(`${process.env.REACT_APP_BACKEND_API}/projects`); diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx index 6ccdec7f0..4f7d993f4 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx @@ -3,7 +3,7 @@ import format from 'date-fns/format'; import parseISO from 'date-fns/parseISO'; import {useWindowDimensions} from 'hooks'; -import {Milestone, Project, ProjectTopic, ProjectTopicTitle} from 'types/projects'; +import {Project, ProjectTopic, ProjectTopicTitle} from 'types/projects'; import ProjectDetailsTopic from '../ProjectDetailsTopic'; import {projectDetailsTopic} from '../constants'; import './ProjectDetailsContent.scss'; diff --git a/src/containers/Projects/ProjectDetails/index.tsx b/src/containers/Projects/ProjectDetails/index.tsx index 3bdcbc61f..3a010be41 100644 --- a/src/containers/Projects/ProjectDetails/index.tsx +++ b/src/containers/Projects/ProjectDetails/index.tsx @@ -1,6 +1,6 @@ import React, {FC, useState} from 'react'; -import {Milestone, Project, ProjectTopic} from 'types/projects'; +import {Project, ProjectTopic} from 'types/projects'; import ProjectDetailsContent from './ProjectDetailsContent'; import ProjectDetailsHeader from './ProjectDetailsHeader'; import ProjectDetailsSideMenu from './ProjectDetailsSideMenu'; From 000771cc5cb54d571559deb03adc9cd103bcbbc0 Mon Sep 17 00:00:00 2001 From: Justin Kim Date: Mon, 3 May 2021 20:16:05 -0500 Subject: [PATCH 32/58] transparent project details header --- .../ProjectDetailsHeader/ProjectDetailsHeader.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsHeader/ProjectDetailsHeader.scss b/src/containers/Projects/ProjectDetails/ProjectDetailsHeader/ProjectDetailsHeader.scss index 5cf9e60b7..b3b5d117a 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsHeader/ProjectDetailsHeader.scss +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsHeader/ProjectDetailsHeader.scss @@ -3,7 +3,7 @@ .ProjectDetailsHeader { align-items: center; - background-color: var(--color-white); + background: rgba(255, 255, 255, 0.9); display: flex; flex-direction: row; height: $details-header-height; @@ -38,7 +38,7 @@ @media (max-width: 480px) { align-items: center; flex-direction: column; - margin-left: 0px; + margin-left: 0; } } From 3e2dc0e9ca65e1f03b6fddb29c5461ee898f6946 Mon Sep 17 00:00:00 2001 From: jamessspanggg Date: Sun, 9 May 2021 14:39:32 +0800 Subject: [PATCH 33/58] Make list of project cards more responsive --- .../ListOfProjects/ListOfProjects.scss | 12 +++++----- .../Projects/ProjectCard/ProjectCard.scss | 22 +++++-------------- src/containers/Projects/_shared.scss | 15 +++++++++++++ 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/src/containers/Projects/ListOfProjects/ListOfProjects.scss b/src/containers/Projects/ListOfProjects/ListOfProjects.scss index d10e779b0..12c2479a7 100644 --- a/src/containers/Projects/ListOfProjects/ListOfProjects.scss +++ b/src/containers/Projects/ListOfProjects/ListOfProjects.scss @@ -1,23 +1,21 @@ -$card-width-original: 384px; -$card-width-992: 432px; -$card-width-768: 320px; -$card-width-480: 360px; +@import '../shared'; .ListOfProjects { column-gap: 32px; display: grid; - grid-template-columns: $card-width-original $card-width-original $card-width-original; + grid-template-columns: minmax($card-min-width-original, $card-width-original) minmax($card-min-width-original, $card-width-original) + minmax($card-min-width-original, $card-width-original); justify-content: center; justify-items: center; margin-bottom: 32px; row-gap: 32px; @media (max-width: 992px) { - grid-template-columns: $card-width-992 $card-width-992; + grid-template-columns: minmax($card-min-width-992, $card-width-992) minmax($card-min-width-992, $card-width-992); } @media (max-width: 768px) { - grid-template-columns: $card-width-768 $card-width-768; + grid-template-columns: minmax($card-min-width-768, $card-width-768) minmax($card-min-width-768, $card-width-768); } @media (max-width: 480px) { diff --git a/src/containers/Projects/ProjectCard/ProjectCard.scss b/src/containers/Projects/ProjectCard/ProjectCard.scss index 1beffaa64..986825804 100644 --- a/src/containers/Projects/ProjectCard/ProjectCard.scss +++ b/src/containers/Projects/ProjectCard/ProjectCard.scss @@ -1,15 +1,5 @@ @import 'styles/font-mixins'; - -$card-width-original: 384px; -$card-height-original: 324px; - -$card-width-992: 432px; - -$card-width-768: 320px; -$card-height-768: 262px; - -$card-height-480: 324px; -$card-width-480: 376px; +@import '../shared'; $padding: 40px; $padding-768: 24px; @@ -18,9 +8,9 @@ $padding-768: 24px; border-radius: 12px; box-shadow: 0px 0px 30px 0px #e5eaf47a; height: $card-height-original; + max-width: $card-width-original; padding: $padding; position: relative; - width: $card-width-original; &:hover { box-shadow: 0px 0px 30px 0px #e5eaf47a; @@ -28,22 +18,22 @@ $padding-768: 24px; } @media (max-width: 992px) { - width: $card-width-992; + max-width: $card-width-992; } @media (max-width: 768px) { height: $card-height-768; + max-width: $card-width-768; padding: $padding-768; - width: $card-width-768; } @media (max-width: 480px) { height: $card-height-480; - width: $card-width-480; + max-width: $card-width-480; } @media (max-width: 376px) { - width: 100vw; + max-width: 100vw; } &__title-container { diff --git a/src/containers/Projects/_shared.scss b/src/containers/Projects/_shared.scss index 0a55a23bf..8f0945765 100644 --- a/src/containers/Projects/_shared.scss +++ b/src/containers/Projects/_shared.scss @@ -3,3 +3,18 @@ $details-header-height: 158px; $details-header-height-480: 241px; $top-content-height: calc(#{$top-nav-height} + #{$details-header-height}); $top-content-height-480: calc(#{$top-nav-height} + #{$details-header-height-480}); + +// cards +$card-width-original: 384px; +$card-min-width-original: 300px; +$card-height-original: 324px; + +$card-width-992: 432px; +$card-min-width-992: 330px; + +$card-width-768: 320px; +$card-min-width-768: 220px; +$card-height-768: 262px; + +$card-height-480: 324px; +$card-width-480: 376px; From 836a5834c307eb97341b8f37cb869c67bc90380f Mon Sep 17 00:00:00 2001 From: Justin Kim Date: Wed, 19 May 2021 19:23:21 -0500 Subject: [PATCH 34/58] fix merge conflicts --- src/apis/tutorials/index.ts | 3 +-- src/apis/tutorials/types.ts | 15 --------------- src/containers/App.tsx | 1 + 3 files changed, 2 insertions(+), 17 deletions(-) delete mode 100644 src/apis/tutorials/types.ts diff --git a/src/apis/tutorials/index.ts b/src/apis/tutorials/index.ts index 7b13ba0b6..5f3e2e45b 100644 --- a/src/apis/tutorials/index.ts +++ b/src/apis/tutorials/index.ts @@ -1,10 +1,9 @@ import axios from 'axios'; import {allTutorialsFilter} from 'constants/tutorials'; +import {PaginatedResponse} from 'types/api'; import {Playlist, PlaylistCategory, Instructor} from 'types/tutorials'; import {standardHeaders} from 'utils/requests'; -import {PlaylistCategoriesResponse, PlaylistsResponse} from './types'; - export async function getPlaylistCategories(): Promise { const response = await axios.get>( `${process.env.REACT_APP_BACKEND_API}/playlist_categories`, diff --git a/src/apis/tutorials/types.ts b/src/apis/tutorials/types.ts deleted file mode 100644 index eae182424..000000000 --- a/src/apis/tutorials/types.ts +++ /dev/null @@ -1,15 +0,0 @@ -import {Playlist, PlaylistCategory} from 'types/tutorials'; - -export interface PlaylistCategoriesResponse { - count: number; - next: number | null; - previous: number | null; - results: PlaylistCategory[]; -} - -export interface PlaylistsResponse { - count: number; - next: number | null; - previous: number | null; - results: Playlist[]; -} diff --git a/src/containers/App.tsx b/src/containers/App.tsx index 966d39544..66b5f2086 100644 --- a/src/containers/App.tsx +++ b/src/containers/App.tsx @@ -84,6 +84,7 @@ const App: FC = () => { + From cfa604abe0ed459d0ab75849d67a58e3e60ef26d Mon Sep 17 00:00:00 2001 From: Justin Kim Date: Wed, 19 May 2021 19:49:23 -0500 Subject: [PATCH 35/58] z-index --- src/containers/Webmap/Webmap.scss | 4 +++- src/styles/_core.scss | 6 ++++-- src/styles/_z-index.scss | 15 ++++++++++++--- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/containers/Webmap/Webmap.scss b/src/containers/Webmap/Webmap.scss index 4b8829073..9c67650e2 100644 --- a/src/containers/Webmap/Webmap.scss +++ b/src/containers/Webmap/Webmap.scss @@ -1,11 +1,13 @@ @import '~leaflet/dist/leaflet.css'; +@import 'styles/z-index'; + $map-bottom-offset: 200px; .Map { height: calc(100vh - #{$map-bottom-offset}); margin-top: 10px; width: 100%; - z-index: 0; + z-index: $z-index-webmap; &__Popup { &-heading { diff --git a/src/styles/_core.scss b/src/styles/_core.scss index ea320f132..580ae3a0f 100644 --- a/src/styles/_core.scss +++ b/src/styles/_core.scss @@ -1,3 +1,5 @@ +@import 'styles/z-index'; + * { box-sizing: border-box; } @@ -17,13 +19,13 @@ body { #popover-root { position: fixed; top: 0; - z-index: 200; + z-index: $z-index-popover-root; } #slide-up-root { bottom: 0; position: fixed; - z-index: 150; + z-index: $z-index-slideup-root; } b, diff --git a/src/styles/_z-index.scss b/src/styles/_z-index.scss index 0e2d0d447..a355d2d8a 100644 --- a/src/styles/_z-index.scss +++ b/src/styles/_z-index.scss @@ -1,11 +1,20 @@ +$z-index-webmap: 0; + +$z-index-project-header: 1; + $z-index-breadcrumb: 2; $z-index-go-to-top: 2; $z-index-layout: 2; $z-index-modal: 2; -$z-index-slideup: 2; $z-index-slideup-overlay: 2; -$z-index-project-header: 1; -$z-index-top-nav: 4; +$z-index-slideup: 2; $z-index-top-nav-mobile-overlay: 2; + $z-index-top-nav-mobile-dropdown: 3; + +$z-index-top-nav: 4; $z-index-top-nav-mobile-button: 4; + +$z-index-slideup-root: 150; + +$z-index-popover-root: 200; From 4757e7e9e3b0c52a5fec0741f75ee83408f52619 Mon Sep 17 00:00:00 2001 From: Justin Kim Date: Wed, 19 May 2021 20:51:45 -0500 Subject: [PATCH 36/58] ProjectIcons --- src/components/ProjectIcons/BenefitsIcon.tsx | 6 +- .../ProjectIcons/IntegrationIcon.tsx | 6 +- .../ProjectIcons/MilestonesIcon.tsx | 4 +- src/components/ProjectIcons/OverviewIcon.tsx | 4 +- src/components/ProjectIcons/ProblemIcon.tsx | 4 +- src/components/ProjectIcons/RoadmapIcon.tsx | 4 +- src/components/ProjectIcons/TargetIcon.tsx | 4 +- src/components/ProjectIcons/TimelineIcon.tsx | 4 +- src/components/ProjectIcons/index.tsx | 161 ++++++------------ src/components/ProjectIcons/types.ts | 5 +- .../ProjectDetailsSideMenu/index.tsx | 9 +- .../ProjectDetailsTopic/index.tsx | 4 +- 12 files changed, 79 insertions(+), 136 deletions(-) diff --git a/src/components/ProjectIcons/BenefitsIcon.tsx b/src/components/ProjectIcons/BenefitsIcon.tsx index d35594fbd..6b18b7538 100644 --- a/src/components/ProjectIcons/BenefitsIcon.tsx +++ b/src/components/ProjectIcons/BenefitsIcon.tsx @@ -2,9 +2,9 @@ import React, {FC} from 'react'; import {CustomIconProps} from './types'; -const BenefitsIcon: FC = ({onClick, size = 24, state = 'default'}) => { +const BenefitsIcon: FC = ({size, state}) => { return ( - + = ({onClick, size = 24, state = 'default d="M17.0132 8.9209H16.6719L17.2977 9.54667L16.6719 10.1724H17.0132L17.639 9.54667L17.0132 8.9209Z" fill="white" /> - + diff --git a/src/components/ProjectIcons/IntegrationIcon.tsx b/src/components/ProjectIcons/IntegrationIcon.tsx index 15c12cdc0..8901b6e83 100644 --- a/src/components/ProjectIcons/IntegrationIcon.tsx +++ b/src/components/ProjectIcons/IntegrationIcon.tsx @@ -2,9 +2,9 @@ import React, {FC} from 'react'; import {CustomIconProps} from './types'; -const IntegrationIcon: FC = ({onClick, size = 24, state = 'default'}) => { +const IntegrationIcon: FC = ({size, state}) => { return ( - + = ({onClick, size = 24, state = 'defa d="M8.6614 9.8999H5.60449L11.2088 15.5042L5.60449 21.1086H8.6614L14.2657 15.5042L8.6614 9.8999Z" fill="white" /> - + diff --git a/src/components/ProjectIcons/MilestonesIcon.tsx b/src/components/ProjectIcons/MilestonesIcon.tsx index 4a4f6c085..8a01c55dc 100644 --- a/src/components/ProjectIcons/MilestonesIcon.tsx +++ b/src/components/ProjectIcons/MilestonesIcon.tsx @@ -2,9 +2,9 @@ import React, {FC} from 'react'; import {CustomIconProps} from './types'; -const MilestonesIcon: FC = ({onClick, size = 24, state = 'default'}) => { +const MilestonesIcon: FC = ({size, state}) => { return ( - + = ({onClick, size = 24, state = 'default'}) => { +const OverviewIcon: FC = ({size, state}) => { return ( - + = ({onClick, size = 24, state = 'default'}) => { +const ProblemIcon: FC = ({size, state}) => { return ( - + = ({onClick, size = 24, state = 'default'}) => { +const RoadmapIcon: FC = ({size, state}) => { return ( - + = ({onClick, size = 24, state = 'default'}) => { +const TargetIcon: FC = ({size, state}) => { return ( - + = ({onClick, size = 24, state = 'default'}) => { +const TimelineIcon: FC = ({size, state}) => { return ( - + { - /** Optional. Extra classNames you can pass. Storybook options: black, white, primary, secondary, tertiary, alert. */ +export enum ProjectIconSize { + small = 'small', + medium = 'medium', + large = 'large', +} + +export interface ComponentProps extends CustomIconProps { className?: string; - /** Optional. identifies a DOM node for testing purposes. */ dataTestId?: string; - /** Optional. disabled onClick event if onClick is passed. */ - disabled?: boolean; - /** Required. pass in the icon type, using the ProjectIconType enum. */ icon: ProjectIconType; - /** Optional. add an onClick event handler. */ - onClick?(e?: React.MouseEvent): void; - /** Optional. add an onKeyDown event handler. */ - onKeyDown?(e?: React.KeyboardEvent): void; - /** Optional. size of the actual icon. */ - size?: number; - /** Optional. size of the icon + paddings. Ignored if value is smaller than size. */ - totalSize?: number | 'unset'; - /** Optional. disables focus. Only works if there is also an onClick handler. */ - unfocusable?: boolean; + size: ProjectIconSize; } -/* eslint-disable */ -const ProjectIcon = forwardRef( - ( - { - className, - dataTestId, - disabled = false, - icon, - onClick, - onKeyDown, - size, - totalSize = 30, - unfocusable = false, - state, - }, - ref, - ) => { - const divStyle = useMemo(() => { - if (totalSize === 'unset') return {}; - const divSize = Math.max(size || 0, totalSize); - return {height: divSize, width: divSize}; - }, [size, totalSize]); - - const tabIndex = useMemo(() => (unfocusable || disabled || !onClick ? undefined : 0), [ - disabled, - onClick, - unfocusable, - ]); - - const handleClick = (e?: React.MouseEvent): void => { - if (disabled || !onClick) return; +const ProjectIcon: FC = ({className, dataTestId, icon, size, state}) => { + const renderIcon = useCallback((): ReactNode => { + let sizeNumber: number; + if (size === ProjectIconSize.small) { + sizeNumber = 24; + } else if (size === ProjectIconSize.medium) { + sizeNumber = 32; + } else { + sizeNumber = 96; + } - onClick(e); - }; - - const handleKeyDown = (e: React.KeyboardEvent): void => { - if (!onClick) return; - - if (e.key === 'Enter' && !disabled) { - handleClick(); - } - - onKeyDown?.(e); + const iconProps = { + 'data-testid': 'ProjectIcon__svg', + size: sizeNumber, + state, }; - const renderIcon = useCallback((): ReactNode => { - const iconBaseProps = { - 'data-testid': 'ProjectIcon__svg', - }; - - switch (icon) { - case ProjectIconType.Benefits: - return ; - case ProjectIconType.Integration: - return ; - case ProjectIconType.Milestone: - return ; - case ProjectIconType.Overview: - return ; - case ProjectIconType.Problem: - return ; - case ProjectIconType.Roadmap: - return ; - case ProjectIconType.Target: - return ; - case ProjectIconType.Timeline: - return ; - default: - return null; - } - }, [icon, size, state]); + switch (icon) { + case ProjectIconType.Benefits: + return ; + case ProjectIconType.Integration: + return ; + case ProjectIconType.Milestone: + return ; + case ProjectIconType.Overview: + return ; + case ProjectIconType.Problem: + return ; + case ProjectIconType.Roadmap: + return ; + case ProjectIconType.Target: + return ; + case ProjectIconType.Timeline: + return ; + default: + return null; + } + }, [icon, size, state]); - return ( -
- {renderIcon()} -
- ); - }, -); + return ( +
+ {renderIcon()} +
+ ); +}; -export {ProjectIcon}; +export default ProjectIcon; diff --git a/src/components/ProjectIcons/types.ts b/src/components/ProjectIcons/types.ts index 1023c5b36..2948246d1 100644 --- a/src/components/ProjectIcons/types.ts +++ b/src/components/ProjectIcons/types.ts @@ -1,5 +1,4 @@ export interface CustomIconProps { - onClick?(e: React.MouseEvent): void; - size?: number | string; - state?: 'default' | 'hover' | 'active'; + size: number | string; + state: 'default' | 'hover' | 'active'; } diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx index 442bd4898..6458b64a1 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx @@ -1,12 +1,11 @@ import React, {FC, useState} from 'react'; - import clsx from 'clsx'; -import {ProjectTopic} from 'types/projects'; -import {ProjectIcon} from 'components/ProjectIcons'; +import ProjectIcon, {ProjectIconSize} from 'components/ProjectIcons'; import {useWindowDimensions} from 'hooks'; -import {projectDetailsTopic} from '../constants'; +import {ProjectTopic} from 'types/projects'; +import {projectDetailsTopic} from '../constants'; import './ProjectDetailsSideMenu.scss'; type Props = { @@ -47,7 +46,7 @@ const ProjectDetailsSideMenu: FC = ({currentTopic, onClick}) => { {shouldShowDetails && ( diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/index.tsx index 19225914b..2e702eb4d 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/index.tsx +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/index.tsx @@ -1,6 +1,6 @@ import React, {FC} from 'react'; -import {ProjectIcon, ProjectIconType} from 'components/ProjectIcons'; +import ProjectIcon, {ProjectIconSize, ProjectIconType} from 'components/ProjectIcons'; import './ProjectDetailsTopic.scss'; interface ComponentProps { @@ -14,7 +14,7 @@ interface ComponentProps { const ProjectDetailsTopic: FC = ({content, iconType, id, title, overview}) => { return (
- +

{title}

{overview}

From 3eafb4071ba2b6418d027c2a4ab5cf169b2ff9ae Mon Sep 17 00:00:00 2001 From: Justin Kim Date: Wed, 19 May 2021 21:36:44 -0500 Subject: [PATCH 37/58] update annoying caniuse error --- package-lock.json | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1a0bf18c0..daa6a5c6d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5157,9 +5157,13 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001159", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001159.tgz", - "integrity": "sha512-w9Ph56jOsS8RL20K9cLND3u/+5WASWdhC/PPrf+V3/HsM3uHOavWOR1Xzakbv4Puo/srmPHudkmCRWM7Aq+/UA==" + "version": "1.0.30001228", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001228.tgz", + "integrity": "sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + } }, "node_modules/capture-exit": { "version": "2.0.0", @@ -27808,9 +27812,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001159", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001159.tgz", - "integrity": "sha512-w9Ph56jOsS8RL20K9cLND3u/+5WASWdhC/PPrf+V3/HsM3uHOavWOR1Xzakbv4Puo/srmPHudkmCRWM7Aq+/UA==" + "version": "1.0.30001228", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001228.tgz", + "integrity": "sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A==" }, "capture-exit": { "version": "2.0.0", From 3971b0ce241d260e89ecd345af0b6e16afa84478 Mon Sep 17 00:00:00 2001 From: Justin Kim Date: Sat, 22 May 2021 20:12:41 -0500 Subject: [PATCH 38/58] a couple changes --- src/containers/App.tsx | 3 +- .../Projects/ListOfProjects/index.tsx | 6 ++-- src/containers/Projects/ProjectCard/index.tsx | 16 +++++---- .../Projects/ProjectsHero/index.tsx | 7 +++- src/containers/Projects/index.tsx | 34 +++++++++++++------ src/containers/Teams/TeamTabs/index.tsx | 2 +- src/containers/TopNav/TopNavPopover/index.tsx | 2 +- src/containers/Tutorials/index.tsx | 2 +- src/types/projects.ts | 2 +- 9 files changed, 47 insertions(+), 27 deletions(-) diff --git a/src/containers/App.tsx b/src/containers/App.tsx index 66b5f2086..fa60eb424 100644 --- a/src/containers/App.tsx +++ b/src/containers/App.tsx @@ -85,8 +85,7 @@ const App: FC = () => { - - + diff --git a/src/containers/Projects/ListOfProjects/index.tsx b/src/containers/Projects/ListOfProjects/index.tsx index 717ba0e18..98aa161b1 100644 --- a/src/containers/Projects/ListOfProjects/index.tsx +++ b/src/containers/Projects/ListOfProjects/index.tsx @@ -13,15 +13,15 @@ const ListOfProjects: FC = ({projects}) => { return (
{projects.map((project) => { - const {description, logo, project_lead: projectLead, title, uuid} = project; + const {description, logo, project_lead: projectLead, title, pk} = project; return ( ); })} diff --git a/src/containers/Projects/ProjectCard/index.tsx b/src/containers/Projects/ProjectCard/index.tsx index 687878a0c..0a27f74f3 100644 --- a/src/containers/Projects/ProjectCard/index.tsx +++ b/src/containers/Projects/ProjectCard/index.tsx @@ -1,4 +1,5 @@ import React, {FC, useEffect, useState} from 'react'; +import {useHistory} from 'react-router-dom'; import {getUser} from 'apis/users'; import {api as projectApi} from 'apis/projects'; @@ -19,21 +20,24 @@ type Props = { }; const ProjectCard: FC = ({description, id, logoUrl, projectLead, title}) => { + const history = useHistory(); const [projectLeadUser, setProjectLeadUser] = useState(null); const {width} = useWindowDimensions(); useEffect(() => { - const fetchData = async () => { + (async () => { // We require to call two extra APIs just to get the project lead's name, perhaps we // should adopt a BFF design const projectMemberResponse = await projectApi.getProjectMemberById(projectLead); const userResponse = await getUser({uuid: projectMemberResponse.user}); setProjectLeadUser(userResponse); - }; - - fetchData(); + })(); }, [projectLead]); + const handleButtonClick = (): void => { + history.push(`/projects/${id}`); + }; + return (
@@ -42,14 +46,14 @@ const ProjectCard: FC = ({description, id, logoUrl, projectLead, title})

{title}

Project Lead: - {projectLeadUser?.display_name} + {projectLeadUser?.display_name || ''}
{description}
- ); -}; - -export default Button; diff --git a/src/components/FormElements/Button/Button.scss b/src/components/FormElements/Button/Button.scss index b5d83299f..300a93d56 100644 --- a/src/components/FormElements/Button/Button.scss +++ b/src/components/FormElements/Button/Button.scss @@ -1,9 +1,8 @@ -.FormButton { +.Button { $self: &; border-radius: 100px; border-style: solid; border-width: 1px; - box-shadow: 0 4px 4px rgba(4, 34, 53, 0.25); cursor: pointer; padding: 11px 12px; transition: all 0.1s; @@ -57,11 +56,11 @@ background: transparent; &#{$self}--primary { - border-color: var(--color-primary); + border-color: var(--color-gray-200); color: var(--color-primary); &:hover { - background: var(--color-primary); + background: var(--color-gray-100); } &#{$self}--disabled, diff --git a/src/components/FormElements/Button/index.tsx b/src/components/FormElements/Button/index.tsx index a46671d48..236f503e5 100644 --- a/src/components/FormElements/Button/index.tsx +++ b/src/components/FormElements/Button/index.tsx @@ -34,8 +34,8 @@ const Button: FC = ({ return (
{description}
-
); diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsHeader/ProjectDetailsHeader.scss b/src/containers/Projects/ProjectDetails/ProjectDetailsHeader/ProjectDetailsHeader.scss index b3b5d117a..f5becc4b0 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsHeader/ProjectDetailsHeader.scss +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsHeader/ProjectDetailsHeader.scss @@ -19,6 +19,15 @@ padding: 24px; } + &__github-button { + align-items: center; + display: flex; + } + + &__github-icon { + margin-right: 6px; + } + &__left-container { align-items: center; display: flex; diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsHeader/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsHeader/index.tsx index 4bfebcd5c..86810b426 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsHeader/index.tsx +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsHeader/index.tsx @@ -2,8 +2,7 @@ import React, {FC, useEffect, useState} from 'react'; import {getUser} from 'apis/users'; import {api as projectApi} from 'apis/projects'; -import {Avatar} from 'components'; -import Button from 'components/Button'; +import {Avatar, Button} from 'components'; import {Icon, IconType} from '@thenewboston/ui'; import {User} from 'types/app/User'; import './ProjectDetailsHeader.scss'; @@ -45,11 +44,11 @@ const ProjectDetailsHeader: FC = ({github, logoUrl, projectLead, title})
diff --git a/src/containers/Projects/ProjectsHero/index.tsx b/src/containers/Projects/ProjectsHero/index.tsx index 3f38c0981..e92b914fa 100644 --- a/src/containers/Projects/ProjectsHero/index.tsx +++ b/src/containers/Projects/ProjectsHero/index.tsx @@ -1,7 +1,7 @@ import React, {FC} from 'react'; import {useHistory} from 'react-router-dom'; -import Button from 'components/Button'; +import {Button} from 'components'; import ProjectsHeroImage from './ProjectsHeroImage'; import './ProjectsHero.scss'; @@ -26,12 +26,11 @@ const ProjectsHero: FC = () => { '_blank', ) } - rounded - type="primary" + variant="contained" > Propose a Project -
From 5175904bf18a4be3d5cbf849169c3cf4f97e1464 Mon Sep 17 00:00:00 2001 From: Justin Kim Date: Mon, 24 May 2021 20:22:26 -0500 Subject: [PATCH 41/58] minor change to ProjectMilestones.scss --- .../ProjectsMilestones/ProjectsMilestones.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/containers/ProjectRulesAndGuide/ProjectsMilestones/ProjectsMilestones.scss b/src/containers/ProjectRulesAndGuide/ProjectsMilestones/ProjectsMilestones.scss index 4064f1f01..5166da032 100644 --- a/src/containers/ProjectRulesAndGuide/ProjectsMilestones/ProjectsMilestones.scss +++ b/src/containers/ProjectRulesAndGuide/ProjectsMilestones/ProjectsMilestones.scss @@ -29,9 +29,9 @@ } &__text { + @extend %h3; color: var(--color-primary); font-weight: var(--font-weight-regular); - @extend %h3; } } From 2fa96afdb308c6759de959c59cec8b194c98f652 Mon Sep 17 00:00:00 2001 From: Justin Kim Date: Mon, 24 May 2021 20:27:46 -0500 Subject: [PATCH 42/58] override css for button --- src/components/FormElements/Button/Button.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/FormElements/Button/Button.scss b/src/components/FormElements/Button/Button.scss index 300a93d56..bfed388ab 100644 --- a/src/components/FormElements/Button/Button.scss +++ b/src/components/FormElements/Button/Button.scss @@ -3,6 +3,7 @@ border-radius: 100px; border-style: solid; border-width: 1px; + box-shadow: none; // currently needed to override @thenewboston/ui 's css cursor: pointer; padding: 11px 12px; transition: all 0.1s; From 18e1f9b3364c7b01f181869c0fb9d8a7cac2693c Mon Sep 17 00:00:00 2001 From: Justin Kim Date: Mon, 24 May 2021 20:40:05 -0500 Subject: [PATCH 43/58] minor css changes --- src/containers/Projects/Projects.scss | 1 + src/containers/Projects/ProjectsHero/ProjectsHero.scss | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/containers/Projects/Projects.scss b/src/containers/Projects/Projects.scss index 954a0ea66..2dcfc349d 100644 --- a/src/containers/Projects/Projects.scss +++ b/src/containers/Projects/Projects.scss @@ -1,5 +1,6 @@ .Projects { overflow-x: hidden; + &__loading-container { align-items: center; display: flex; diff --git a/src/containers/Projects/ProjectsHero/ProjectsHero.scss b/src/containers/Projects/ProjectsHero/ProjectsHero.scss index 8c0f366a6..7b7590ca5 100644 --- a/src/containers/Projects/ProjectsHero/ProjectsHero.scss +++ b/src/containers/Projects/ProjectsHero/ProjectsHero.scss @@ -82,12 +82,12 @@ $title-width: 480px; } &__subtitle { + @extend %h3; color: var(--color-gray-500); font-weight: var(--font-weight-regular); line-height: 1.5; margin-bottom: 40px; margin-top: 30px; - @extend %h3; } &__title { From e432472878698e5842efe9a50209cbcd7c3f870a Mon Sep 17 00:00:00 2001 From: Justin Kim Date: Mon, 24 May 2021 20:49:08 -0500 Subject: [PATCH 44/58] ProjectDetailsHeader --- .../ProjectDetailsHeader/ProjectDetailsHeader.scss | 13 +++++++++---- .../ProjectDetails/ProjectDetailsHeader/index.tsx | 10 ++++------ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsHeader/ProjectDetailsHeader.scss b/src/containers/Projects/ProjectDetails/ProjectDetailsHeader/ProjectDetailsHeader.scss index f5becc4b0..ef004f04a 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsHeader/ProjectDetailsHeader.scss +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsHeader/ProjectDetailsHeader.scss @@ -67,12 +67,17 @@ } &__project-lead-container { - -webkit-box-orient: vertical; - // max one line to prevent it from affecting height of header - display: -webkit-box; - -webkit-line-clamp: 1; /* max number of lines to show */ + max-width: 500px; overflow: hidden; text-overflow: ellipsis; + + @media (max-width: 992px) { + max-width: 350px; + } + + @media (max-width: 578px) { + max-width: 250px; + } } &__project-lead { diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsHeader/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsHeader/index.tsx index 86810b426..2b1c0eeb4 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsHeader/index.tsx +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsHeader/index.tsx @@ -1,9 +1,9 @@ import React, {FC, useEffect, useState} from 'react'; +import {Icon, IconType} from '@thenewboston/ui'; import {getUser} from 'apis/users'; import {api as projectApi} from 'apis/projects'; import {Avatar, Button} from 'components'; -import {Icon, IconType} from '@thenewboston/ui'; import {User} from 'types/app/User'; import './ProjectDetailsHeader.scss'; @@ -18,15 +18,13 @@ const ProjectDetailsHeader: FC = ({github, logoUrl, projectLead, title}) const [projectLeadUser, setProjectLeadUser] = useState(null); useEffect(() => { - const fetchData = async () => { + (async () => { // We require to call two extra APIs just to get the project lead's name, perhaps we // should adopt a BFF design const projectMemberResponse = await projectApi.getProjectMemberById(projectLead); const userResponse = await getUser({uuid: projectMemberResponse.user}); setProjectLeadUser(userResponse); - }; - - fetchData(); + })(); }, [projectLead]); return ( @@ -38,7 +36,7 @@ const ProjectDetailsHeader: FC = ({github, logoUrl, projectLead, title})

{title}

Project Lead: - {projectLeadUser?.display_name} + {projectLeadUser?.display_name || ''}
From b18aecb45981b4c61428ac19373f37c8c37d84f8 Mon Sep 17 00:00:00 2001 From: Justin Kim Date: Mon, 24 May 2021 21:05:37 -0500 Subject: [PATCH 45/58] some directory changes --- src/components/index.ts | 2 -- src/containers/App.tsx | 2 +- .../ProjectDetails/ProjectDetailsSideMenu/index.tsx | 2 +- .../ProjectDetails/ProjectDetailsTopic/index.tsx | 2 +- src/containers/Projects/ProjectDetails/constants.ts | 3 +-- .../Projects}/ProjectIcons/BenefitsIcon.tsx | 0 .../Projects}/ProjectIcons/IntegrationIcon.tsx | 0 .../Projects}/ProjectIcons/MilestonesIcon.tsx | 0 .../Projects}/ProjectIcons/OverviewIcon.tsx | 0 .../Projects}/ProjectIcons/ProblemIcon.tsx | 0 .../Projects}/ProjectIcons/RoadmapIcon.tsx | 0 .../Projects}/ProjectIcons/TargetIcon.tsx | 0 .../Projects}/ProjectIcons/TimelineIcon.tsx | 0 .../Projects}/ProjectIcons/index.tsx | 0 .../Projects}/ProjectIcons/types.ts | 0 .../ProjectsMilestones/ProjectsMilestones.scss | 0 .../ProjectsMilestones/index.tsx | 0 .../ProjectsOverview/RoadmapMilestoneOverview.png | Bin .../ProjectRulesAndGuide/ProjectsOverview/index.tsx | 0 .../ProjectsProposalSubmissionProcess.scss | 0 .../ProjectsProposalSubmissionProcess/index.tsx | 0 .../ProjectsRules/ProjectsRules.scss | 0 .../ProjectRulesAndGuide/ProjectsRules/index.tsx | 0 .../{ => Projects}/ProjectRulesAndGuide/index.tsx | 4 ++-- .../ProjectsMenuItems/ProjectsMenuItems.test.tsx | 0 .../Projects}/ProjectsMenuItems/index.tsx | 0 src/types/projects.ts | 2 +- 27 files changed, 7 insertions(+), 10 deletions(-) rename src/{components => containers/Projects}/ProjectIcons/BenefitsIcon.tsx (100%) rename src/{components => containers/Projects}/ProjectIcons/IntegrationIcon.tsx (100%) rename src/{components => containers/Projects}/ProjectIcons/MilestonesIcon.tsx (100%) rename src/{components => containers/Projects}/ProjectIcons/OverviewIcon.tsx (100%) rename src/{components => containers/Projects}/ProjectIcons/ProblemIcon.tsx (100%) rename src/{components => containers/Projects}/ProjectIcons/RoadmapIcon.tsx (100%) rename src/{components => containers/Projects}/ProjectIcons/TargetIcon.tsx (100%) rename src/{components => containers/Projects}/ProjectIcons/TimelineIcon.tsx (100%) rename src/{components => containers/Projects}/ProjectIcons/index.tsx (100%) rename src/{components => containers/Projects}/ProjectIcons/types.ts (100%) rename src/containers/{ => Projects}/ProjectRulesAndGuide/ProjectsMilestones/ProjectsMilestones.scss (100%) rename src/containers/{ => Projects}/ProjectRulesAndGuide/ProjectsMilestones/index.tsx (100%) rename src/containers/{ => Projects}/ProjectRulesAndGuide/ProjectsOverview/RoadmapMilestoneOverview.png (100%) rename src/containers/{ => Projects}/ProjectRulesAndGuide/ProjectsOverview/index.tsx (100%) rename src/containers/{ => Projects}/ProjectRulesAndGuide/ProjectsProposalSubmissionProcess/ProjectsProposalSubmissionProcess.scss (100%) rename src/containers/{ => Projects}/ProjectRulesAndGuide/ProjectsProposalSubmissionProcess/index.tsx (100%) rename src/containers/{ => Projects}/ProjectRulesAndGuide/ProjectsRules/ProjectsRules.scss (100%) rename src/containers/{ => Projects}/ProjectRulesAndGuide/ProjectsRules/index.tsx (100%) rename src/containers/{ => Projects}/ProjectRulesAndGuide/index.tsx (90%) rename src/{components => containers/Projects}/ProjectsMenuItems/ProjectsMenuItems.test.tsx (100%) rename src/{components => containers/Projects}/ProjectsMenuItems/index.tsx (100%) diff --git a/src/components/index.ts b/src/components/index.ts index 1b06707dc..670d6fb2c 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -35,7 +35,6 @@ import Loader from './Loader'; import PageTitle from './PageTitle'; import Pagination from './Pagination'; import Popover from './Popover'; -import ProjectsMenuItems from './ProjectsMenuItems'; import Qr from './Qr'; import {QueryParamsOffsetAndLimit} from './QueryParams'; import Shadow from './Shadow'; @@ -84,7 +83,6 @@ export { PageTitle, Pagination, Popover, - ProjectsMenuItems, Qr, QueryParamsOffsetAndLimit, RequestResponseSnippet, diff --git a/src/containers/App.tsx b/src/containers/App.tsx index fa60eb424..4f1d629b6 100644 --- a/src/containers/App.tsx +++ b/src/containers/App.tsx @@ -21,7 +21,7 @@ import PrimaryValidatorApi from './PrimaryValidatorApi'; import Profile from './Profile'; import Progress from './Progress'; import Projects from './Projects'; -import ProjectRulesAndGuide from './ProjectRulesAndGuide'; +import ProjectRulesAndGuide from './Projects/ProjectRulesAndGuide'; import SignIn from './SignIn'; import SignOut from './SignOut'; import Social from './Social'; diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx index 6458b64a1..e075d411d 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx @@ -1,10 +1,10 @@ import React, {FC, useState} from 'react'; import clsx from 'clsx'; -import ProjectIcon, {ProjectIconSize} from 'components/ProjectIcons'; import {useWindowDimensions} from 'hooks'; import {ProjectTopic} from 'types/projects'; +import ProjectIcon, {ProjectIconSize} from '../../ProjectIcons'; import {projectDetailsTopic} from '../constants'; import './ProjectDetailsSideMenu.scss'; diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/index.tsx index 2e702eb4d..e0f681439 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/index.tsx +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/index.tsx @@ -1,6 +1,6 @@ import React, {FC} from 'react'; -import ProjectIcon, {ProjectIconSize, ProjectIconType} from 'components/ProjectIcons'; +import ProjectIcon, {ProjectIconSize, ProjectIconType} from '../../ProjectIcons'; import './ProjectDetailsTopic.scss'; interface ComponentProps { diff --git a/src/containers/Projects/ProjectDetails/constants.ts b/src/containers/Projects/ProjectDetails/constants.ts index 235b431f7..372dee27e 100644 --- a/src/containers/Projects/ProjectDetails/constants.ts +++ b/src/containers/Projects/ProjectDetails/constants.ts @@ -1,6 +1,5 @@ -import {ProjectIconType} from 'components/ProjectIcons'; - import {ProjectTopicAnchor, ProjectTopicMap, ProjectTopicTitle} from 'types/projects'; +import {ProjectIconType} from '../ProjectIcons'; /* eslint-disable */ export const projectDetailsTopic: ProjectTopicMap = { diff --git a/src/components/ProjectIcons/BenefitsIcon.tsx b/src/containers/Projects/ProjectIcons/BenefitsIcon.tsx similarity index 100% rename from src/components/ProjectIcons/BenefitsIcon.tsx rename to src/containers/Projects/ProjectIcons/BenefitsIcon.tsx diff --git a/src/components/ProjectIcons/IntegrationIcon.tsx b/src/containers/Projects/ProjectIcons/IntegrationIcon.tsx similarity index 100% rename from src/components/ProjectIcons/IntegrationIcon.tsx rename to src/containers/Projects/ProjectIcons/IntegrationIcon.tsx diff --git a/src/components/ProjectIcons/MilestonesIcon.tsx b/src/containers/Projects/ProjectIcons/MilestonesIcon.tsx similarity index 100% rename from src/components/ProjectIcons/MilestonesIcon.tsx rename to src/containers/Projects/ProjectIcons/MilestonesIcon.tsx diff --git a/src/components/ProjectIcons/OverviewIcon.tsx b/src/containers/Projects/ProjectIcons/OverviewIcon.tsx similarity index 100% rename from src/components/ProjectIcons/OverviewIcon.tsx rename to src/containers/Projects/ProjectIcons/OverviewIcon.tsx diff --git a/src/components/ProjectIcons/ProblemIcon.tsx b/src/containers/Projects/ProjectIcons/ProblemIcon.tsx similarity index 100% rename from src/components/ProjectIcons/ProblemIcon.tsx rename to src/containers/Projects/ProjectIcons/ProblemIcon.tsx diff --git a/src/components/ProjectIcons/RoadmapIcon.tsx b/src/containers/Projects/ProjectIcons/RoadmapIcon.tsx similarity index 100% rename from src/components/ProjectIcons/RoadmapIcon.tsx rename to src/containers/Projects/ProjectIcons/RoadmapIcon.tsx diff --git a/src/components/ProjectIcons/TargetIcon.tsx b/src/containers/Projects/ProjectIcons/TargetIcon.tsx similarity index 100% rename from src/components/ProjectIcons/TargetIcon.tsx rename to src/containers/Projects/ProjectIcons/TargetIcon.tsx diff --git a/src/components/ProjectIcons/TimelineIcon.tsx b/src/containers/Projects/ProjectIcons/TimelineIcon.tsx similarity index 100% rename from src/components/ProjectIcons/TimelineIcon.tsx rename to src/containers/Projects/ProjectIcons/TimelineIcon.tsx diff --git a/src/components/ProjectIcons/index.tsx b/src/containers/Projects/ProjectIcons/index.tsx similarity index 100% rename from src/components/ProjectIcons/index.tsx rename to src/containers/Projects/ProjectIcons/index.tsx diff --git a/src/components/ProjectIcons/types.ts b/src/containers/Projects/ProjectIcons/types.ts similarity index 100% rename from src/components/ProjectIcons/types.ts rename to src/containers/Projects/ProjectIcons/types.ts diff --git a/src/containers/ProjectRulesAndGuide/ProjectsMilestones/ProjectsMilestones.scss b/src/containers/Projects/ProjectRulesAndGuide/ProjectsMilestones/ProjectsMilestones.scss similarity index 100% rename from src/containers/ProjectRulesAndGuide/ProjectsMilestones/ProjectsMilestones.scss rename to src/containers/Projects/ProjectRulesAndGuide/ProjectsMilestones/ProjectsMilestones.scss diff --git a/src/containers/ProjectRulesAndGuide/ProjectsMilestones/index.tsx b/src/containers/Projects/ProjectRulesAndGuide/ProjectsMilestones/index.tsx similarity index 100% rename from src/containers/ProjectRulesAndGuide/ProjectsMilestones/index.tsx rename to src/containers/Projects/ProjectRulesAndGuide/ProjectsMilestones/index.tsx diff --git a/src/containers/ProjectRulesAndGuide/ProjectsOverview/RoadmapMilestoneOverview.png b/src/containers/Projects/ProjectRulesAndGuide/ProjectsOverview/RoadmapMilestoneOverview.png similarity index 100% rename from src/containers/ProjectRulesAndGuide/ProjectsOverview/RoadmapMilestoneOverview.png rename to src/containers/Projects/ProjectRulesAndGuide/ProjectsOverview/RoadmapMilestoneOverview.png diff --git a/src/containers/ProjectRulesAndGuide/ProjectsOverview/index.tsx b/src/containers/Projects/ProjectRulesAndGuide/ProjectsOverview/index.tsx similarity index 100% rename from src/containers/ProjectRulesAndGuide/ProjectsOverview/index.tsx rename to src/containers/Projects/ProjectRulesAndGuide/ProjectsOverview/index.tsx diff --git a/src/containers/ProjectRulesAndGuide/ProjectsProposalSubmissionProcess/ProjectsProposalSubmissionProcess.scss b/src/containers/Projects/ProjectRulesAndGuide/ProjectsProposalSubmissionProcess/ProjectsProposalSubmissionProcess.scss similarity index 100% rename from src/containers/ProjectRulesAndGuide/ProjectsProposalSubmissionProcess/ProjectsProposalSubmissionProcess.scss rename to src/containers/Projects/ProjectRulesAndGuide/ProjectsProposalSubmissionProcess/ProjectsProposalSubmissionProcess.scss diff --git a/src/containers/ProjectRulesAndGuide/ProjectsProposalSubmissionProcess/index.tsx b/src/containers/Projects/ProjectRulesAndGuide/ProjectsProposalSubmissionProcess/index.tsx similarity index 100% rename from src/containers/ProjectRulesAndGuide/ProjectsProposalSubmissionProcess/index.tsx rename to src/containers/Projects/ProjectRulesAndGuide/ProjectsProposalSubmissionProcess/index.tsx diff --git a/src/containers/ProjectRulesAndGuide/ProjectsRules/ProjectsRules.scss b/src/containers/Projects/ProjectRulesAndGuide/ProjectsRules/ProjectsRules.scss similarity index 100% rename from src/containers/ProjectRulesAndGuide/ProjectsRules/ProjectsRules.scss rename to src/containers/Projects/ProjectRulesAndGuide/ProjectsRules/ProjectsRules.scss diff --git a/src/containers/ProjectRulesAndGuide/ProjectsRules/index.tsx b/src/containers/Projects/ProjectRulesAndGuide/ProjectsRules/index.tsx similarity index 100% rename from src/containers/ProjectRulesAndGuide/ProjectsRules/index.tsx rename to src/containers/Projects/ProjectRulesAndGuide/ProjectsRules/index.tsx diff --git a/src/containers/ProjectRulesAndGuide/index.tsx b/src/containers/Projects/ProjectRulesAndGuide/index.tsx similarity index 90% rename from src/containers/ProjectRulesAndGuide/index.tsx rename to src/containers/Projects/ProjectRulesAndGuide/index.tsx index bcf123672..738d1ef37 100644 --- a/src/containers/ProjectRulesAndGuide/index.tsx +++ b/src/containers/Projects/ProjectRulesAndGuide/index.tsx @@ -1,10 +1,10 @@ import React, {FC, useMemo} from 'react'; import {Redirect, useParams} from 'react-router-dom'; -import {DashboardLayout, ProjectsMenuItems, Pagination} from 'components'; -import {projectsNavigationData} from 'components/ProjectsMenuItems'; +import {DashboardLayout, Pagination} from 'components'; import {PageData, PageDataObject} from 'types/page-data'; +import ProjectsMenuItems, {projectsNavigationData} from '../ProjectsMenuItems'; import ProjectsMilestones from './ProjectsMilestones'; import ProjectsOverview from './ProjectsOverview'; import ProjectsProposalSubmissionProcess from './ProjectsProposalSubmissionProcess'; diff --git a/src/components/ProjectsMenuItems/ProjectsMenuItems.test.tsx b/src/containers/Projects/ProjectsMenuItems/ProjectsMenuItems.test.tsx similarity index 100% rename from src/components/ProjectsMenuItems/ProjectsMenuItems.test.tsx rename to src/containers/Projects/ProjectsMenuItems/ProjectsMenuItems.test.tsx diff --git a/src/components/ProjectsMenuItems/index.tsx b/src/containers/Projects/ProjectsMenuItems/index.tsx similarity index 100% rename from src/components/ProjectsMenuItems/index.tsx rename to src/containers/Projects/ProjectsMenuItems/index.tsx diff --git a/src/types/projects.ts b/src/types/projects.ts index 2ef02c486..6ceb731c6 100644 --- a/src/types/projects.ts +++ b/src/types/projects.ts @@ -1,4 +1,4 @@ -import {ProjectIconType} from 'components/ProjectIcons'; +import {ProjectIconType} from 'containers/Projects/ProjectIcons'; export type Project = { pk: string; From f550395169f2aa5d555ff9f7d38fbf2dc635ce77 Mon Sep 17 00:00:00 2001 From: Justin Kim Date: Tue, 25 May 2021 18:39:35 -0500 Subject: [PATCH 46/58] minor change --- src/containers/Projects/ListOfProjects/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/containers/Projects/ListOfProjects/index.tsx b/src/containers/Projects/ListOfProjects/index.tsx index 98aa161b1..a1c03740e 100644 --- a/src/containers/Projects/ListOfProjects/index.tsx +++ b/src/containers/Projects/ListOfProjects/index.tsx @@ -1,8 +1,8 @@ import React, {FC} from 'react'; import {Project} from 'types/projects'; -import ProjectCard from '../ProjectCard'; +import ProjectCard from '../ProjectCard'; import './ListOfProjects.scss'; type Props = { From a0c186abbec9e71845163b47f2f76493a81f0599 Mon Sep 17 00:00:00 2001 From: Justin Kim Date: Tue, 25 May 2021 18:40:12 -0500 Subject: [PATCH 47/58] minor change on ListOfProjects --- src/containers/Projects/ListOfProjects/index.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/containers/Projects/ListOfProjects/index.tsx b/src/containers/Projects/ListOfProjects/index.tsx index a1c03740e..b304362cb 100644 --- a/src/containers/Projects/ListOfProjects/index.tsx +++ b/src/containers/Projects/ListOfProjects/index.tsx @@ -12,8 +12,7 @@ type Props = { const ListOfProjects: FC = ({projects}) => { return (
- {projects.map((project) => { - const {description, logo, project_lead: projectLead, title, pk} = project; + {projects.map(({description, logo, project_lead: projectLead, title, pk}) => { return ( Date: Tue, 25 May 2021 18:45:01 -0500 Subject: [PATCH 48/58] minor edit to ProjectDetailsTopic --- .../ProjectDetailsTopic/ProjectDetailsTopic.scss | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/ProjectDetailsTopic.scss b/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/ProjectDetailsTopic.scss index ea3cd7544..52927da96 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/ProjectDetailsTopic.scss +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/ProjectDetailsTopic.scss @@ -29,10 +29,9 @@ } &__content-overview { + @extend %body1; color: var(--color-sail-gray-500); - font-weight: var(--font-weight-regular); margin-bottom: 32px; - @extend %body1; } &__content-title { @@ -42,8 +41,8 @@ } &__content-main { + @extend %h3; color: var(--color-sail-gray-600); font-weight: var(--font-weight-regular); - @extend %h3; } } From 98c6182e661b2e8d33990d412b6097aab41eacd1 Mon Sep 17 00:00:00 2001 From: Justin Kim Date: Tue, 25 May 2021 18:49:31 -0500 Subject: [PATCH 49/58] remove eslint-disable --- .../Projects/ProjectDetails/constants.ts | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/src/containers/Projects/ProjectDetails/constants.ts b/src/containers/Projects/ProjectDetails/constants.ts index 372dee27e..7b3d98aed 100644 --- a/src/containers/Projects/ProjectDetails/constants.ts +++ b/src/containers/Projects/ProjectDetails/constants.ts @@ -1,27 +1,7 @@ import {ProjectTopicAnchor, ProjectTopicMap, ProjectTopicTitle} from 'types/projects'; import {ProjectIconType} from '../ProjectIcons'; -/* eslint-disable */ export const projectDetailsTopic: ProjectTopicMap = { - overview: { - anchor: ProjectTopicAnchor.Overview, - iconType: ProjectIconType.Overview, - overview: - 'A brief summary, situation, plan, and outline about the project, bigger picture, functionality and the possible outcome from this project', - title: ProjectTopicTitle.Overview, - }, - problem: { - anchor: ProjectTopicAnchor.Problem, - iconType: ProjectIconType.Problem, - overview: 'A precise information about the problem that this project is going to solve.', - title: ProjectTopicTitle.Problem, - }, - target_market: { - anchor: ProjectTopicAnchor.TargetMarket, - iconType: ProjectIconType.Target, - overview: 'A description of the group of users to whom TNB wants to provide the service.', - title: ProjectTopicTitle.TargetMarket, - }, benefits: { anchor: ProjectTopicAnchor.Benefits, iconType: ProjectIconType.Benefits, @@ -41,10 +21,29 @@ export const projectDetailsTopic: ProjectTopicMap = { overview: 'A specific date of project completion.', title: ProjectTopicTitle.EstimatedCompletionDate, }, + overview: { + anchor: ProjectTopicAnchor.Overview, + iconType: ProjectIconType.Overview, + overview: + 'A brief summary, situation, plan, and outline about the project, bigger picture, functionality and the possible outcome from this project', + title: ProjectTopicTitle.Overview, + }, + problem: { + anchor: ProjectTopicAnchor.Problem, + iconType: ProjectIconType.Problem, + overview: 'A precise information about the problem that this project is going to solve.', + title: ProjectTopicTitle.Problem, + }, roadmap: { anchor: ProjectTopicAnchor.Roadmap, iconType: ProjectIconType.Roadmap, overview: 'A schedule of a lengthy project by breaking into realistic achiveable milestones.', title: ProjectTopicTitle.Roadmap, }, + target_market: { + anchor: ProjectTopicAnchor.TargetMarket, + iconType: ProjectIconType.Target, + overview: 'A description of the group of users to whom TNB wants to provide the service.', + title: ProjectTopicTitle.TargetMarket, + }, }; From ef2f9d4e8dc324d2d4d542dbe98087b060f6b4da Mon Sep 17 00:00:00 2001 From: Justin Kim Date: Tue, 25 May 2021 18:57:44 -0500 Subject: [PATCH 50/58] ProjectDetailsSideMenu --- .../ProjectDetailsSideMenu/index.tsx | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx index e075d411d..0a1c4fe88 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx @@ -10,13 +10,15 @@ import './ProjectDetailsSideMenu.scss'; type Props = { currentTopic: ProjectTopic; - onClick: (topic: ProjectTopic) => void; + onClick(topic: ProjectTopic): void; }; const ProjectDetailsSideMenu: FC = ({currentTopic, onClick}) => { const [hoveredTopicTitle, setHoveredTopicTitle] = useState(''); const {width} = useWindowDimensions(); + const shouldShowDetails = width > 992; + const handleMouseEnter = (title: string) => { setHoveredTopicTitle(title); }; @@ -24,15 +26,21 @@ const ProjectDetailsSideMenu: FC = ({currentTopic, onClick}) => { const handleMouseLeave = () => { setHoveredTopicTitle(''); }; - const shouldShowDetails = width > 992; + return (
{Object.values(projectDetailsTopic).map((topic) => { const {iconType, title} = topic; const isActive = currentTopic.title === title; const isHovered = hoveredTopicTitle === title; - /* eslint-disable-next-line no-nested-ternary */ - const iconState = isActive ? 'active' : isHovered ? 'hover' : 'default'; + + let iconState: 'default' | 'active' | 'hover' = 'default'; + if (isActive) { + iconState = 'active'; + } else if (isHovered) { + iconState = 'hover'; + } + return (
Date: Tue, 25 May 2021 18:59:02 -0500 Subject: [PATCH 51/58] ProjectDetailsSideMenu.scss --- .../ProjectDetailsSideMenu/ProjectDetailsSideMenu.scss | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/ProjectDetailsSideMenu.scss b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/ProjectDetailsSideMenu.scss index 46896ce42..75dcf2f69 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/ProjectDetailsSideMenu.scss +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/ProjectDetailsSideMenu.scss @@ -3,8 +3,8 @@ .ProjectDetailsSideMenu { background-color: var(--color-white); - border-radius: 0px 0px 0px 12px; - box-shadow: 0px 8px 88px rgba(0, 0, 0, 0.05); + border-radius: 0 0 0 12px; + box-shadow: 0 8px 88px rgba(0, 0, 0, 0.05); flex-shrink: 0; height: fit-content; left: 0; @@ -40,9 +40,9 @@ } &__topic-title { + @extend %h3; color: var(--color-gray-500); font-weight: var(--font-weight-regular); - @extend %h3; &:hover { color: var(--color-cyan-800); From 579dba832efd54a0252d04ae7da8744534b8919d Mon Sep 17 00:00:00 2001 From: Justin Kim Date: Wed, 26 May 2021 19:20:49 -0500 Subject: [PATCH 52/58] projectLeadDisplayName --- src/apis/projects/api.ts | 8 ------- .../Projects/ListOfProjects/index.tsx | 4 ++-- src/containers/Projects/ProjectCard/index.tsx | 22 ++++-------------- .../ProjectDetailsHeader/index.tsx | 23 ++++--------------- .../Projects/ProjectDetails/index.tsx | 9 ++++++-- src/types/projects.ts | 1 + 6 files changed, 18 insertions(+), 49 deletions(-) diff --git a/src/apis/projects/api.ts b/src/apis/projects/api.ts index 0902f62a2..a443f83e6 100644 --- a/src/apis/projects/api.ts +++ b/src/apis/projects/api.ts @@ -11,11 +11,3 @@ export async function getProjects(): Promise { } return response.data.results; } - -export async function getProjectMemberById(id: string) { - const response = await axios.get(`${process.env.REACT_APP_BACKEND_API}/project_members/${id}`); - if (!response.data) { - throw new Error('Error while fetching project member, please try again.'); - } - return response.data; -} diff --git a/src/containers/Projects/ListOfProjects/index.tsx b/src/containers/Projects/ListOfProjects/index.tsx index b304362cb..c28f3932b 100644 --- a/src/containers/Projects/ListOfProjects/index.tsx +++ b/src/containers/Projects/ListOfProjects/index.tsx @@ -12,13 +12,13 @@ type Props = { const ListOfProjects: FC = ({projects}) => { return (
- {projects.map(({description, logo, project_lead: projectLead, title, pk}) => { + {projects.map(({description, logo, project_lead_display_name: projectLeadDisplayName, title, pk}) => { return ( diff --git a/src/containers/Projects/ProjectCard/index.tsx b/src/containers/Projects/ProjectCard/index.tsx index 66b198618..61a99d127 100644 --- a/src/containers/Projects/ProjectCard/index.tsx +++ b/src/containers/Projects/ProjectCard/index.tsx @@ -1,11 +1,8 @@ -import React, {FC, useEffect, useState} from 'react'; +import React, {FC} from 'react'; import {useHistory} from 'react-router-dom'; -import {getUser} from 'apis/users'; -import {api as projectApi} from 'apis/projects'; import {Avatar, Button} from 'components'; import {useWindowDimensions} from 'hooks'; -import {User} from 'types/app/User'; import {Icon, IconType} from '@thenewboston/ui'; import './ProjectCard.scss'; @@ -14,25 +11,14 @@ type Props = { description: string; id: string; logoUrl: string; - projectLead: string; + projectLeadDisplayName: string; title: string; }; -const ProjectCard: FC = ({description, id, logoUrl, projectLead, title}) => { +const ProjectCard: FC = ({description, id, logoUrl, projectLeadDisplayName, title}) => { const history = useHistory(); - const [projectLeadUser, setProjectLeadUser] = useState(null); const {width} = useWindowDimensions(); - useEffect(() => { - (async () => { - // We require to call two extra APIs just to get the project lead's name, perhaps we - // should adopt a BFF design - const projectMemberResponse = await projectApi.getProjectMemberById(projectLead); - const userResponse = await getUser({uuid: projectMemberResponse.user}); - setProjectLeadUser(userResponse); - })(); - }, [projectLead]); - const handleButtonClick = (): void => { history.push(`/projects/${id}`); }; @@ -45,7 +31,7 @@ const ProjectCard: FC = ({description, id, logoUrl, projectLead, title})

{title}

Project Lead: - {projectLeadUser?.display_name || ''} + {projectLeadDisplayName}
diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsHeader/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsHeader/index.tsx index 2b1c0eeb4..e7388d311 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsHeader/index.tsx +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsHeader/index.tsx @@ -1,32 +1,17 @@ -import React, {FC, useEffect, useState} from 'react'; +import React, {FC} from 'react'; import {Icon, IconType} from '@thenewboston/ui'; -import {getUser} from 'apis/users'; -import {api as projectApi} from 'apis/projects'; import {Avatar, Button} from 'components'; -import {User} from 'types/app/User'; import './ProjectDetailsHeader.scss'; type Props = { github: string; logoUrl: string; - projectLead: string; + projectLeadDisplayName: string; title: string; }; -const ProjectDetailsHeader: FC = ({github, logoUrl, projectLead, title}) => { - const [projectLeadUser, setProjectLeadUser] = useState(null); - - useEffect(() => { - (async () => { - // We require to call two extra APIs just to get the project lead's name, perhaps we - // should adopt a BFF design - const projectMemberResponse = await projectApi.getProjectMemberById(projectLead); - const userResponse = await getUser({uuid: projectMemberResponse.user}); - setProjectLeadUser(userResponse); - })(); - }, [projectLead]); - +const ProjectDetailsHeader: FC = ({github, logoUrl, projectLeadDisplayName, title}) => { return (
@@ -36,7 +21,7 @@ const ProjectDetailsHeader: FC = ({github, logoUrl, projectLead, title})

{title}

Project Lead: - {projectLeadUser?.display_name || ''} + {projectLeadDisplayName}
diff --git a/src/containers/Projects/ProjectDetails/index.tsx b/src/containers/Projects/ProjectDetails/index.tsx index 3a010be41..f714fc735 100644 --- a/src/containers/Projects/ProjectDetails/index.tsx +++ b/src/containers/Projects/ProjectDetails/index.tsx @@ -13,7 +13,7 @@ type Props = { const ProjectDetails: FC = ({project}) => { const [currentTopic, setCurrentTopic] = useState(projectDetailsTopic.overview); - const {title, logo, github_url: github, project_lead: projectLead} = project; + const {title, logo, github_url: github, project_lead_display_name: projectLeadDisplayName} = project; const handleSideMenuClick = (topic: ProjectTopic) => { setCurrentTopic(topic); @@ -21,7 +21,12 @@ const ProjectDetails: FC = ({project}) => { return (
- +
diff --git a/src/types/projects.ts b/src/types/projects.ts index 6ceb731c6..d1a5478e2 100644 --- a/src/types/projects.ts +++ b/src/types/projects.ts @@ -15,6 +15,7 @@ export type Project = { centered_around_tnb: string; estimated_completion_date: string; project_lead: string; + project_lead_display_name: string; milestones: Milestone[]; }; From 4786e2d26334547b692c48d3d9d2353667d02a47 Mon Sep 17 00:00:00 2001 From: Justin Kim Date: Wed, 26 May 2021 19:54:19 -0500 Subject: [PATCH 53/58] correct position of the side menu --- .../ProjectDetails/ProjectDetailsContent/index.tsx | 1 + .../ProjectDetails/ProjectDetailsSideMenu/index.tsx | 5 ++++- src/containers/Projects/ProjectDetails/constants.ts | 7 +++++++ src/types/projects.ts | 1 + 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx index 4f7d993f4..47fc51e39 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx @@ -20,6 +20,7 @@ const DETAILS_CONTAINER_HEIGHT_480 = 241; const ProjectDetailsContent: FC = ({project, currentTopic}) => { const {width} = useWindowDimensions(); const detailsHeaderHeight = width >= 480 ? DETAILS_CONTAINER_HEIGHT : DETAILS_CONTAINER_HEIGHT_480; + useEffect(() => { const element = document.getElementById(currentTopic.anchor); const scrollBehavior = element ? 'smooth' : 'auto'; diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx index 0a1c4fe88..b5c28c90f 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx @@ -3,6 +3,7 @@ import clsx from 'clsx'; import {useWindowDimensions} from 'hooks'; import {ProjectTopic} from 'types/projects'; +import {sortByNumberKey} from 'utils/sort'; import ProjectIcon, {ProjectIconSize} from '../../ProjectIcons'; import {projectDetailsTopic} from '../constants'; @@ -13,6 +14,8 @@ type Props = { onClick(topic: ProjectTopic): void; }; +const orderedProjectDetailsTopic = Object.values(projectDetailsTopic).sort(sortByNumberKey('position')); + const ProjectDetailsSideMenu: FC = ({currentTopic, onClick}) => { const [hoveredTopicTitle, setHoveredTopicTitle] = useState(''); @@ -29,7 +32,7 @@ const ProjectDetailsSideMenu: FC = ({currentTopic, onClick}) => { return (
- {Object.values(projectDetailsTopic).map((topic) => { + {orderedProjectDetailsTopic.map((topic) => { const {iconType, title} = topic; const isActive = currentTopic.title === title; const isHovered = hoveredTopicTitle === title; diff --git a/src/containers/Projects/ProjectDetails/constants.ts b/src/containers/Projects/ProjectDetails/constants.ts index 7b3d98aed..d6e753114 100644 --- a/src/containers/Projects/ProjectDetails/constants.ts +++ b/src/containers/Projects/ProjectDetails/constants.ts @@ -7,18 +7,21 @@ export const projectDetailsTopic: ProjectTopicMap = { iconType: ProjectIconType.Benefits, overview: 'A brief description, how this service would bring the people together and providing opportunities of interaction', + position: 4, title: ProjectTopicTitle.Benefits, }, centered_around_tnb: { anchor: ProjectTopicAnchor.CenteredAroundTNB, iconType: ProjectIconType.Integration, overview: 'A brief description how this service would blend into the TNB services.', + position: 5, title: ProjectTopicTitle.CenteredAroundTNB, }, estimated_completion_date: { anchor: ProjectTopicAnchor.EstimatedCompletionDate, iconType: ProjectIconType.Timeline, overview: 'A specific date of project completion.', + position: 6, title: ProjectTopicTitle.EstimatedCompletionDate, }, overview: { @@ -26,24 +29,28 @@ export const projectDetailsTopic: ProjectTopicMap = { iconType: ProjectIconType.Overview, overview: 'A brief summary, situation, plan, and outline about the project, bigger picture, functionality and the possible outcome from this project', + position: 1, title: ProjectTopicTitle.Overview, }, problem: { anchor: ProjectTopicAnchor.Problem, iconType: ProjectIconType.Problem, overview: 'A precise information about the problem that this project is going to solve.', + position: 2, title: ProjectTopicTitle.Problem, }, roadmap: { anchor: ProjectTopicAnchor.Roadmap, iconType: ProjectIconType.Roadmap, overview: 'A schedule of a lengthy project by breaking into realistic achiveable milestones.', + position: 7, title: ProjectTopicTitle.Roadmap, }, target_market: { anchor: ProjectTopicAnchor.TargetMarket, iconType: ProjectIconType.Target, overview: 'A description of the group of users to whom TNB wants to provide the service.', + position: 3, title: ProjectTopicTitle.TargetMarket, }, }; diff --git a/src/types/projects.ts b/src/types/projects.ts index d1a5478e2..c79882d2b 100644 --- a/src/types/projects.ts +++ b/src/types/projects.ts @@ -36,6 +36,7 @@ export type ProjectTopic = { anchor: ProjectTopicAnchor; iconType: ProjectIconType; overview: string; + position: number; title: ProjectTopicTitle; }; From 70cf3e2fa35a2d94c988e9cc8c9595f9293ebf35 Mon Sep 17 00:00:00 2001 From: Justin Kim Date: Fri, 28 May 2021 21:37:55 -0500 Subject: [PATCH 54/58] dynamic side menu (when you scroll, it highlights correct one) --- .../ProjectDetails/ProjectDetails.scss | 26 +++ .../ProjectDetailsContent.scss | 26 --- .../ProjectDetailsContent/index.tsx | 102 ---------- .../ProjectDetailsSideMenu/index.tsx | 22 ++- .../ProjectDetailsTopic.scss | 16 ++ .../ProjectDetailsTopic/index.tsx | 38 ++-- .../Projects/ProjectDetails/constants.ts | 17 +- .../Projects/ProjectDetails/index.tsx | 175 +++++++++++++++++- 8 files changed, 258 insertions(+), 164 deletions(-) delete mode 100644 src/containers/Projects/ProjectDetails/ProjectDetailsContent/ProjectDetailsContent.scss delete mode 100644 src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx diff --git a/src/containers/Projects/ProjectDetails/ProjectDetails.scss b/src/containers/Projects/ProjectDetails/ProjectDetails.scss index 8effb259e..3dcffca67 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetails.scss +++ b/src/containers/Projects/ProjectDetails/ProjectDetails.scss @@ -1,3 +1,5 @@ +@import 'styles/font-mixins'; + .ProjectDetails { background-color: var(--color-white); margin-bottom: 160px; @@ -6,4 +8,28 @@ display: flex; flex-direction: row; } + + &__main-content { + background-color: var(--color-white); + box-shadow: 0 8px 88px 0 #0000000d; + margin-bottom: 120px; + padding: 32px; + } + + &__milestone { + color: var(--color-sail-gray-600); + } + + &__milestone-description { + @extend %h3; + color: var(--color-sail-gray-600); + font-weight: var(--font-weight-regular); + margin-bottom: 40px; + white-space: pre-line; + } + + &__milestone-number { + font-weight: var(--font-weight-bold); + margin-bottom: 8px; + } } diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsContent/ProjectDetailsContent.scss b/src/containers/Projects/ProjectDetails/ProjectDetailsContent/ProjectDetailsContent.scss deleted file mode 100644 index f93c438e7..000000000 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsContent/ProjectDetailsContent.scss +++ /dev/null @@ -1,26 +0,0 @@ -@import '../../shared'; -@import 'styles/font-mixins'; - -.ProjectDetailsContent { - background-color: var(--color-white); - box-shadow: 0 8px 88px 0 #0000000d; - margin-bottom: 120px; - padding: 32px; - - &__milestone { - color: var(--color-sail-gray-600); - } - - &__milestone-description { - @extend %h3; - color: var(--color-sail-gray-600); - font-weight: var(--font-weight-regular); - margin-bottom: 40px; - white-space: pre-line; - } - - &__milestone-number { - font-weight: var(--font-weight-bold); - margin-bottom: 8px; - } -} diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx deleted file mode 100644 index 47fc51e39..000000000 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsContent/index.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import React, {FC, useEffect} from 'react'; -import format from 'date-fns/format'; -import parseISO from 'date-fns/parseISO'; - -import {useWindowDimensions} from 'hooks'; -import {Project, ProjectTopic, ProjectTopicTitle} from 'types/projects'; -import ProjectDetailsTopic from '../ProjectDetailsTopic'; -import {projectDetailsTopic} from '../constants'; -import './ProjectDetailsContent.scss'; - -type Props = { - project: Project; - currentTopic: ProjectTopic; -}; - -const TOP_NAV_HEIGHT = 60; -const DETAILS_CONTAINER_HEIGHT = 158; -const DETAILS_CONTAINER_HEIGHT_480 = 241; - -const ProjectDetailsContent: FC = ({project, currentTopic}) => { - const {width} = useWindowDimensions(); - const detailsHeaderHeight = width >= 480 ? DETAILS_CONTAINER_HEIGHT : DETAILS_CONTAINER_HEIGHT_480; - - useEffect(() => { - const element = document.getElementById(currentTopic.anchor); - const scrollBehavior = element ? 'smooth' : 'auto'; - - // scroll to top if it is the first topic, else scroll directly to the topic - const top = - currentTopic.title === ProjectTopicTitle.Overview || !element - ? 0 - : element.offsetTop - TOP_NAV_HEIGHT - detailsHeaderHeight; - - window.scrollTo({behavior: scrollBehavior, top}); - }, [currentTopic, detailsHeaderHeight]); - - const renderMilestones = () => { - return project.milestones.map((milestone) => { - return ( -
-

Milestone {milestone.number}

-
{milestone.description}
-
- ); - }); - }; - return ( -
- - - - - - - -
- ); -}; - -export default ProjectDetailsContent; diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx index b5c28c90f..f1484035d 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx @@ -1,27 +1,33 @@ import React, {FC, useState} from 'react'; +import {useHistory, useLocation} from 'react-router-dom'; import clsx from 'clsx'; import {useWindowDimensions} from 'hooks'; import {ProjectTopic} from 'types/projects'; -import {sortByNumberKey} from 'utils/sort'; import ProjectIcon, {ProjectIconSize} from '../../ProjectIcons'; -import {projectDetailsTopic} from '../constants'; +import {orderedProjectDetailsTopic} from '../constants'; import './ProjectDetailsSideMenu.scss'; type Props = { - currentTopic: ProjectTopic; - onClick(topic: ProjectTopic): void; + currentTopicPosition: number; + onClick(position: number): void; }; -const orderedProjectDetailsTopic = Object.values(projectDetailsTopic).sort(sortByNumberKey('position')); - -const ProjectDetailsSideMenu: FC = ({currentTopic, onClick}) => { +const ProjectDetailsSideMenu: FC = ({currentTopicPosition, onClick}) => { + const history = useHistory(); + const {pathname} = useLocation(); const [hoveredTopicTitle, setHoveredTopicTitle] = useState(''); + const currentTopic = orderedProjectDetailsTopic[currentTopicPosition]; const {width} = useWindowDimensions(); const shouldShowDetails = width > 992; + const handleMenuClick = (topic: ProjectTopic) => (): void => { + onClick(topic.position); + history.push(`${pathname}#${topic.anchor}`); + }; + const handleMouseEnter = (title: string) => { setHoveredTopicTitle(title); }; @@ -49,7 +55,7 @@ const ProjectDetailsSideMenu: FC = ({currentTopic, onClick}) => { className="ProjectDetailsSideMenu__topic" key={title} role="button" - onClick={() => onClick(topic)} + onClick={handleMenuClick(topic)} onMouseEnter={() => handleMouseEnter(title)} onMouseLeave={handleMouseLeave} tabIndex={0} diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/ProjectDetailsTopic.scss b/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/ProjectDetailsTopic.scss index 52927da96..8911c46cf 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/ProjectDetailsTopic.scss +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/ProjectDetailsTopic.scss @@ -1,15 +1,31 @@ @import 'styles/font-mixins'; +$top-nav-height: 60px; +$details-container-height: 158px; +$details-container-height-480: 241px; +$wiggle-room: 32px; +$offset: $top-nav-height + $details-container-height + $wiggle-room; +$offset-480: $top-nav-height + $details-container-height-480 + $wiggle-room; .ProjectDetailsTopic { align-items: flex-start; display: flex; flex-direction: row; margin-bottom: 120px; + position: relative; @media (max-width: 480px) { flex-direction: column; } + &__anchor { + position: absolute; + top: #{-$offset}; + + @media (max-width: 480px) { + top: #{-$offset-480}; + } + } + &__icon { margin-right: 32px; diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/index.tsx index e0f681439..58a3f2378 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/index.tsx +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/index.tsx @@ -1,4 +1,5 @@ -import React, {FC} from 'react'; +import React, {forwardRef} from 'react'; +import {useHistory, useLocation} from 'react-router-dom'; import ProjectIcon, {ProjectIconSize, ProjectIconType} from '../../ProjectIcons'; import './ProjectDetailsTopic.scss'; @@ -11,17 +12,30 @@ interface ComponentProps { title: string; } -const ProjectDetailsTopic: FC = ({content, iconType, id, title, overview}) => { - return ( -
- -
-

{title}

-

{overview}

-
{content}
+const ProjectDetailsTopic = forwardRef( + ({content, iconType, id, title, overview}, ref) => { + const history = useHistory(); + const {pathname} = useLocation(); + + return ( +
+ +
+
+

history.push(`${pathname}#${id}`)}> + {title} +

+

{overview}

+
{content}
+
-
- ); -}; + ); + }, +); export default ProjectDetailsTopic; diff --git a/src/containers/Projects/ProjectDetails/constants.ts b/src/containers/Projects/ProjectDetails/constants.ts index d6e753114..2f245a594 100644 --- a/src/containers/Projects/ProjectDetails/constants.ts +++ b/src/containers/Projects/ProjectDetails/constants.ts @@ -1,4 +1,5 @@ import {ProjectTopicAnchor, ProjectTopicMap, ProjectTopicTitle} from 'types/projects'; +import {sortByNumberKey} from 'utils/sort'; import {ProjectIconType} from '../ProjectIcons'; export const projectDetailsTopic: ProjectTopicMap = { @@ -7,21 +8,21 @@ export const projectDetailsTopic: ProjectTopicMap = { iconType: ProjectIconType.Benefits, overview: 'A brief description, how this service would bring the people together and providing opportunities of interaction', - position: 4, + position: 3, title: ProjectTopicTitle.Benefits, }, centered_around_tnb: { anchor: ProjectTopicAnchor.CenteredAroundTNB, iconType: ProjectIconType.Integration, overview: 'A brief description how this service would blend into the TNB services.', - position: 5, + position: 4, title: ProjectTopicTitle.CenteredAroundTNB, }, estimated_completion_date: { anchor: ProjectTopicAnchor.EstimatedCompletionDate, iconType: ProjectIconType.Timeline, overview: 'A specific date of project completion.', - position: 6, + position: 5, title: ProjectTopicTitle.EstimatedCompletionDate, }, overview: { @@ -29,28 +30,30 @@ export const projectDetailsTopic: ProjectTopicMap = { iconType: ProjectIconType.Overview, overview: 'A brief summary, situation, plan, and outline about the project, bigger picture, functionality and the possible outcome from this project', - position: 1, + position: 0, title: ProjectTopicTitle.Overview, }, problem: { anchor: ProjectTopicAnchor.Problem, iconType: ProjectIconType.Problem, overview: 'A precise information about the problem that this project is going to solve.', - position: 2, + position: 1, title: ProjectTopicTitle.Problem, }, roadmap: { anchor: ProjectTopicAnchor.Roadmap, iconType: ProjectIconType.Roadmap, overview: 'A schedule of a lengthy project by breaking into realistic achiveable milestones.', - position: 7, + position: 6, title: ProjectTopicTitle.Roadmap, }, target_market: { anchor: ProjectTopicAnchor.TargetMarket, iconType: ProjectIconType.Target, overview: 'A description of the group of users to whom TNB wants to provide the service.', - position: 3, + position: 2, title: ProjectTopicTitle.TargetMarket, }, }; + +export const orderedProjectDetailsTopic = Object.values(projectDetailsTopic).sort(sortByNumberKey('position')); diff --git a/src/containers/Projects/ProjectDetails/index.tsx b/src/containers/Projects/ProjectDetails/index.tsx index f714fc735..19e9e34c3 100644 --- a/src/containers/Projects/ProjectDetails/index.tsx +++ b/src/containers/Projects/ProjectDetails/index.tsx @@ -1,22 +1,179 @@ -import React, {FC, useState} from 'react'; +import React, {FC, ReactNode, useRef, useState} from 'react'; +import format from 'date-fns/format'; +import parseISO from 'date-fns/parseISO'; +import throttle from 'lodash/throttle'; -import {Project, ProjectTopic} from 'types/projects'; -import ProjectDetailsContent from './ProjectDetailsContent'; +import {useEventListener, useWindowDimensions} from 'hooks'; +import {Project, ProjectTopicTitle} from 'types/projects'; + +import {orderedProjectDetailsTopic, projectDetailsTopic} from './constants'; import ProjectDetailsHeader from './ProjectDetailsHeader'; import ProjectDetailsSideMenu from './ProjectDetailsSideMenu'; -import {projectDetailsTopic} from './constants'; +import ProjectDetailsTopic from './ProjectDetailsTopic'; import './ProjectDetails.scss'; type Props = { project: Project; }; +const TOP_NAV_HEIGHT = 60; +const DETAILS_CONTAINER_HEIGHT = 158; +const DETAILS_CONTAINER_HEIGHT_480 = 241; +const WIGGLE_ROOM = 32; + const ProjectDetails: FC = ({project}) => { - const [currentTopic, setCurrentTopic] = useState(projectDetailsTopic.overview); + const overviewRef = useRef(null); + const problemRef = useRef(null); + const targetMarketRef = useRef(null); + const benefitsRef = useRef(null); + const centeredAroundTnbRef = useRef(null); + const estimatedCompletionDateRef = useRef(null); + const roadmapRef = useRef(null); + + const problemOffset = problemRef.current?.offsetTop || -1; + const targetMarketOffset = targetMarketRef.current?.offsetTop || -1; + const benefitsOffset = benefitsRef.current?.offsetTop || -1; + const centeredAroundTnbOffset = centeredAroundTnbRef.current?.offsetTop || -1; + const estimatedCompletionDateOffset = estimatedCompletionDateRef.current?.offsetTop || -1; + const roadmapOffset = roadmapRef.current?.offsetTop || -1; + + const [currentTopicPosition, setCurrentTopicPosition] = useState(0); + const [disableScrollEvent, setDisableScrollEvent] = useState(false); const {title, logo, github_url: github, project_lead_display_name: projectLeadDisplayName} = project; - const handleSideMenuClick = (topic: ProjectTopic) => { - setCurrentTopic(topic); + const {width} = useWindowDimensions(); + const detailsHeaderHeight = width >= 480 ? DETAILS_CONTAINER_HEIGHT : DETAILS_CONTAINER_HEIGHT_480; + const currentTopic = orderedProjectDetailsTopic[currentTopicPosition]; + + useEventListener( + 'scroll', + throttle(() => { + if (disableScrollEvent) { + return; + } + + const scrollHeight = window.scrollY + TOP_NAV_HEIGHT + detailsHeaderHeight + WIGGLE_ROOM; + + if (scrollHeight > roadmapOffset) { + setCurrentTopicPosition(6); + return; + } + if (scrollHeight > estimatedCompletionDateOffset) { + setCurrentTopicPosition(5); + return; + } + if (scrollHeight > centeredAroundTnbOffset) { + setCurrentTopicPosition(4); + return; + } + if (scrollHeight > benefitsOffset) { + setCurrentTopicPosition(3); + return; + } + if (scrollHeight > targetMarketOffset) { + setCurrentTopicPosition(2); + return; + } + if (scrollHeight > problemOffset) { + setCurrentTopicPosition(1); + return; + } + setCurrentTopicPosition(0); + }, 300), + window, + true, + ); + + const handleSideMenuClick = (position: number) => { + const positionTopic = orderedProjectDetailsTopic[position]; + + const element = document.getElementById(positionTopic.anchor)!; + + setDisableScrollEvent(true); + // scroll to top if it is the first topic, else scroll directly to the topic + const top = + currentTopic.title === ProjectTopicTitle.Overview + ? 0 + : element.offsetTop - TOP_NAV_HEIGHT - detailsHeaderHeight - WIGGLE_ROOM; + + window.scrollTo({behavior: 'smooth', top}); + setTimeout(() => { + setDisableScrollEvent(false); + }, 300); + }; + + const renderMainContent = (): ReactNode => { + return ( +
+ + + + + + + +
+ ); + }; + + const renderMilestones = (): ReactNode => { + return project.milestones.map((milestone) => { + return ( +
+

Milestone {milestone.number}

+
{milestone.description}
+
+ ); + }); }; return ( @@ -28,8 +185,8 @@ const ProjectDetails: FC = ({project}) => { projectLeadDisplayName={projectLeadDisplayName} />
- - + + {renderMainContent()}
); From 54da3e39d8209c471b24fb26926641054c6dfe40 Mon Sep 17 00:00:00 2001 From: Justin Kim Date: Fri, 28 May 2021 21:58:53 -0500 Subject: [PATCH 55/58] fix the leftMenu bug --- .../ProjectDetailsSideMenu/index.tsx | 11 ++--- .../Projects/ProjectDetails/index.tsx | 48 ++++++++----------- 2 files changed, 26 insertions(+), 33 deletions(-) diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx index f1484035d..f838f8475 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx @@ -1,5 +1,5 @@ import React, {FC, useState} from 'react'; -import {useHistory, useLocation} from 'react-router-dom'; +import {useHistory} from 'react-router-dom'; import clsx from 'clsx'; import {useWindowDimensions} from 'hooks'; @@ -11,12 +11,11 @@ import './ProjectDetailsSideMenu.scss'; type Props = { currentTopicPosition: number; - onClick(position: number): void; + setCurrentTopicPosition(position: number): void; }; -const ProjectDetailsSideMenu: FC = ({currentTopicPosition, onClick}) => { +const ProjectDetailsSideMenu: FC = ({currentTopicPosition, setCurrentTopicPosition}) => { const history = useHistory(); - const {pathname} = useLocation(); const [hoveredTopicTitle, setHoveredTopicTitle] = useState(''); const currentTopic = orderedProjectDetailsTopic[currentTopicPosition]; @@ -24,8 +23,8 @@ const ProjectDetailsSideMenu: FC = ({currentTopicPosition, onClick}) => { const shouldShowDetails = width > 992; const handleMenuClick = (topic: ProjectTopic) => (): void => { - onClick(topic.position); - history.push(`${pathname}#${topic.anchor}`); + setCurrentTopicPosition(topic.position); + history.push(`#${topic.anchor}`); }; const handleMouseEnter = (title: string) => { diff --git a/src/containers/Projects/ProjectDetails/index.tsx b/src/containers/Projects/ProjectDetails/index.tsx index 19e9e34c3..da7b13a70 100644 --- a/src/containers/Projects/ProjectDetails/index.tsx +++ b/src/containers/Projects/ProjectDetails/index.tsx @@ -1,12 +1,13 @@ -import React, {FC, ReactNode, useRef, useState} from 'react'; +import React, {FC, ReactNode, useEffect, useRef, useState} from 'react'; +import {useLocation} from 'react-router-dom'; import format from 'date-fns/format'; import parseISO from 'date-fns/parseISO'; import throttle from 'lodash/throttle'; import {useEventListener, useWindowDimensions} from 'hooks'; -import {Project, ProjectTopicTitle} from 'types/projects'; +import {Project} from 'types/projects'; -import {orderedProjectDetailsTopic, projectDetailsTopic} from './constants'; +import {projectDetailsTopic} from './constants'; import ProjectDetailsHeader from './ProjectDetailsHeader'; import ProjectDetailsSideMenu from './ProjectDetailsSideMenu'; import ProjectDetailsTopic from './ProjectDetailsTopic'; @@ -21,7 +22,11 @@ const DETAILS_CONTAINER_HEIGHT = 158; const DETAILS_CONTAINER_HEIGHT_480 = 241; const WIGGLE_ROOM = 32; +let debounce = false; + const ProjectDetails: FC = ({project}) => { + const {hash} = useLocation(); + const overviewRef = useRef(null); const problemRef = useRef(null); const targetMarketRef = useRef(null); @@ -38,19 +43,23 @@ const ProjectDetails: FC = ({project}) => { const roadmapOffset = roadmapRef.current?.offsetTop || -1; const [currentTopicPosition, setCurrentTopicPosition] = useState(0); - const [disableScrollEvent, setDisableScrollEvent] = useState(false); const {title, logo, github_url: github, project_lead_display_name: projectLeadDisplayName} = project; const {width} = useWindowDimensions(); const detailsHeaderHeight = width >= 480 ? DETAILS_CONTAINER_HEIGHT : DETAILS_CONTAINER_HEIGHT_480; - const currentTopic = orderedProjectDetailsTopic[currentTopicPosition]; + + // This is used so that the hash change does not trigger the scroll event listener + useEffect(() => { + debounce = true; + setTimeout(() => { + debounce = false; + }, 100); + }, [hash]); useEventListener( 'scroll', throttle(() => { - if (disableScrollEvent) { - return; - } + if (debounce) return; const scrollHeight = window.scrollY + TOP_NAV_HEIGHT + detailsHeaderHeight + WIGGLE_ROOM; @@ -84,24 +93,6 @@ const ProjectDetails: FC = ({project}) => { true, ); - const handleSideMenuClick = (position: number) => { - const positionTopic = orderedProjectDetailsTopic[position]; - - const element = document.getElementById(positionTopic.anchor)!; - - setDisableScrollEvent(true); - // scroll to top if it is the first topic, else scroll directly to the topic - const top = - currentTopic.title === ProjectTopicTitle.Overview - ? 0 - : element.offsetTop - TOP_NAV_HEIGHT - detailsHeaderHeight - WIGGLE_ROOM; - - window.scrollTo({behavior: 'smooth', top}); - setTimeout(() => { - setDisableScrollEvent(false); - }, 300); - }; - const renderMainContent = (): ReactNode => { return (
@@ -185,7 +176,10 @@ const ProjectDetails: FC = ({project}) => { projectLeadDisplayName={projectLeadDisplayName} />
- + {renderMainContent()}
From d65411852e6b0cd77a9d165540010b5554d17199 Mon Sep 17 00:00:00 2001 From: Justin Kim Date: Fri, 28 May 2021 22:42:27 -0500 Subject: [PATCH 56/58] making a couple minor adjustments --- src/containers/Projects/ProjectDetails/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/containers/Projects/ProjectDetails/index.tsx b/src/containers/Projects/ProjectDetails/index.tsx index da7b13a70..435c6a5ad 100644 --- a/src/containers/Projects/ProjectDetails/index.tsx +++ b/src/containers/Projects/ProjectDetails/index.tsx @@ -20,7 +20,7 @@ type Props = { const TOP_NAV_HEIGHT = 60; const DETAILS_CONTAINER_HEIGHT = 158; const DETAILS_CONTAINER_HEIGHT_480 = 241; -const WIGGLE_ROOM = 32; +const WIGGLE_ROOM = 64; let debounce = false; @@ -88,7 +88,7 @@ const ProjectDetails: FC = ({project}) => { return; } setCurrentTopicPosition(0); - }, 300), + }, 100), window, true, ); From 6197985d0ce9619162cc11c61bb1908bf7fdeca8 Mon Sep 17 00:00:00 2001 From: jamessspanggg Date: Sat, 29 May 2021 22:25:48 +0800 Subject: [PATCH 57/58] Remove hover effect for touch screen devices --- .../Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx | 5 +++++ src/utils/device.ts | 3 +++ 2 files changed, 8 insertions(+) create mode 100644 src/utils/device.ts diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx index f838f8475..334d85ddc 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsSideMenu/index.tsx @@ -4,6 +4,7 @@ import clsx from 'clsx'; import {useWindowDimensions} from 'hooks'; import {ProjectTopic} from 'types/projects'; +import {isTouchScreenDevice} from 'utils/device'; import ProjectIcon, {ProjectIconSize} from '../../ProjectIcons'; import {orderedProjectDetailsTopic} from '../constants'; @@ -28,6 +29,10 @@ const ProjectDetailsSideMenu: FC = ({currentTopicPosition, setCurrentTopi }; const handleMouseEnter = (title: string) => { + // touch screen devices does not need to have hover effect + if (isTouchScreenDevice()) { + return; + } setHoveredTopicTitle(title); }; diff --git a/src/utils/device.ts b/src/utils/device.ts new file mode 100644 index 000000000..aced98607 --- /dev/null +++ b/src/utils/device.ts @@ -0,0 +1,3 @@ +export const isTouchScreenDevice = () => { + return 'ontouchstart' in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0; +}; From 3bd813896ab9b7a752131c436a7d76ce4963606a Mon Sep 17 00:00:00 2001 From: jamessspanggg Date: Sat, 29 May 2021 23:11:53 +0800 Subject: [PATCH 58/58] Project card css fix and tidy up css --- .../Projects/ProjectCard/ProjectCard.scss | 1 + .../ProjectDetailsTopic.scss | 37 +++++++++---------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/containers/Projects/ProjectCard/ProjectCard.scss b/src/containers/Projects/ProjectCard/ProjectCard.scss index a2fe4276f..0e0828ef4 100644 --- a/src/containers/Projects/ProjectCard/ProjectCard.scss +++ b/src/containers/Projects/ProjectCard/ProjectCard.scss @@ -11,6 +11,7 @@ $padding-768: 24px; max-width: $card-width-original; padding: $padding; position: relative; + width: 100%; &:hover { box-shadow: 0 7px 40px 0 #e9effd; diff --git a/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/ProjectDetailsTopic.scss b/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/ProjectDetailsTopic.scss index 8911c46cf..f332511f6 100644 --- a/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/ProjectDetailsTopic.scss +++ b/src/containers/Projects/ProjectDetails/ProjectDetailsTopic/ProjectDetailsTopic.scss @@ -37,28 +37,25 @@ $offset-480: $top-nav-height + $details-container-height-480 + $wiggle-room; &__content { display: flex; flex-direction: column; - } - - &__content-main { - @extend %h3; - white-space: pre-line; - } - &__content-overview { - @extend %body1; - color: var(--color-sail-gray-500); - margin-bottom: 32px; - } + &-main { + @extend %h3; + color: var(--color-sail-gray-600); + font-weight: var(--font-weight-regular); + white-space: pre-line; + } - &__content-title { - color: var(--color-sail-blue-900); - font-weight: var(--font-weight-bold); - margin-bottom: 8px; - } + &-overview { + @extend %body1; + color: var(--color-sail-gray-500); + font-weight: var(--font-weight-medium); + margin-bottom: 32px; + } - &__content-main { - @extend %h3; - color: var(--color-sail-gray-600); - font-weight: var(--font-weight-regular); + &-title { + color: var(--color-sail-blue-900); + font-weight: var(--font-weight-bold); + margin-bottom: 8px; + } } }