From 840a9e50eb844a683fbf9eda8540e9951be0a2c0 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Wed, 31 Aug 2022 14:52:10 +0300 Subject: [PATCH] feat: tournament mocks api, header component, navigation component, 2 sections of the overview page --- api/functions/graphql/nexus-typegen.ts | 9 ++ api/functions/graphql/schema.graphql | 3 + api/functions/graphql/types/tournament.js | 5 ++ src/App.tsx | 4 + src/features/Tournaments/api/tournament.ts | 46 ---------- .../pages/OverviewPage/OverviewPage.tsx | 64 +++++++++++++- .../PrizesSection/PrizesSection.tsx | 25 ++++++ .../PrizesSection/styles.module.scss | 88 +++++++++++++++++++ .../TournamentBasePage/TournamentBasePage.tsx | 7 -- .../TournamentDetailsPage/Header/Header.tsx | 36 ++++++++ .../Navigation/Navigation.tsx | 72 +++++++++++++++ .../TournamentDetailsPage.tsx | 43 +++++++++ .../tournamentDetails.graphql | 5 ++ src/graphql/index.tsx | 8 +- src/mocks/data/tournament.ts | 7 +- src/styles/index.scss | 2 +- src/utils/routing/routes.ts | 3 + 17 files changed, 368 insertions(+), 59 deletions(-) delete mode 100644 src/features/Tournaments/api/tournament.ts create mode 100644 src/features/Tournaments/pages/OverviewPage/PrizesSection/PrizesSection.tsx create mode 100644 src/features/Tournaments/pages/OverviewPage/PrizesSection/styles.module.scss delete mode 100644 src/features/Tournaments/pages/TournamentBasePage/TournamentBasePage.tsx create mode 100644 src/features/Tournaments/pages/TournamentDetailsPage/Header/Header.tsx create mode 100644 src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx create mode 100644 src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx rename src/features/Tournaments/pages/{TournamentBasePage => TournamentDetailsPage}/tournamentDetails.graphql (89%) diff --git a/api/functions/graphql/nexus-typegen.ts b/api/functions/graphql/nexus-typegen.ts index be73b78..bea81f9 100644 --- a/api/functions/graphql/nexus-typegen.ts +++ b/api/functions/graphql/nexus-typegen.ts @@ -213,11 +213,14 @@ export interface NexusGenObjects { description: string; // String! end_date: NexusGenScalars['Date']; // Date! events: NexusGenRootTypes['TournamentEvent'][]; // [TournamentEvent!]! + events_count: number; // Int! faqs: NexusGenRootTypes['TournamentFAQ'][]; // [TournamentFAQ!]! id: number; // Int! judges: NexusGenRootTypes['TournamentJudge'][]; // [TournamentJudge!]! location: string; // String! + makers_count: number; // Int! prizes: NexusGenRootTypes['TournamentPrize'][]; // [TournamentPrize!]! + projects_count: number; // Int! start_date: NexusGenScalars['Date']; // Date! thumbnail_image: string; // String! title: string; // String! @@ -488,11 +491,14 @@ export interface NexusGenFieldTypes { description: string; // String! end_date: NexusGenScalars['Date']; // Date! events: NexusGenRootTypes['TournamentEvent'][]; // [TournamentEvent!]! + events_count: number; // Int! faqs: NexusGenRootTypes['TournamentFAQ'][]; // [TournamentFAQ!]! id: number; // Int! judges: NexusGenRootTypes['TournamentJudge'][]; // [TournamentJudge!]! location: string; // String! + makers_count: number; // Int! prizes: NexusGenRootTypes['TournamentPrize'][]; // [TournamentPrize!]! + projects_count: number; // Int! start_date: NexusGenScalars['Date']; // Date! thumbnail_image: string; // String! title: string; // String! @@ -778,11 +784,14 @@ export interface NexusGenFieldTypeNames { description: 'String' end_date: 'Date' events: 'TournamentEvent' + events_count: 'Int' faqs: 'TournamentFAQ' id: 'Int' judges: 'TournamentJudge' location: 'String' + makers_count: 'Int' prizes: 'TournamentPrize' + projects_count: 'Int' start_date: 'Date' thumbnail_image: 'String' title: 'String' diff --git a/api/functions/graphql/schema.graphql b/api/functions/graphql/schema.graphql index 5d9562b..9c8446e 100644 --- a/api/functions/graphql/schema.graphql +++ b/api/functions/graphql/schema.graphql @@ -277,11 +277,14 @@ type Tournament { description: String! end_date: Date! events: [TournamentEvent!]! + events_count: Int! faqs: [TournamentFAQ!]! id: Int! judges: [TournamentJudge!]! location: String! + makers_count: Int! prizes: [TournamentPrize!]! + projects_count: Int! start_date: Date! thumbnail_image: String! title: String! diff --git a/api/functions/graphql/types/tournament.js b/api/functions/graphql/types/tournament.js index 8221eb2..c60de12 100644 --- a/api/functions/graphql/types/tournament.js +++ b/api/functions/graphql/types/tournament.js @@ -62,6 +62,11 @@ const Tournament = objectType({ t.nonNull.date('end_date'); t.nonNull.string('location'); t.nonNull.string('website'); + + t.nonNull.int('events_count'); + t.nonNull.int('makers_count'); + t.nonNull.int('projects_count'); + t.nonNull.list.nonNull.field('prizes', { type: TournamentPrize, }); t.nonNull.list.nonNull.field('judges', { type: TournamentJudge, }); t.nonNull.list.nonNull.field('faqs', { type: TournamentFAQ, }); diff --git a/src/App.tsx b/src/App.tsx index 74b7d24..cfb7e6f 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -25,6 +25,8 @@ const ExplorePage = Loadable(React.lazy(() => import( /* webpackChunkName: "expl const HackathonsPage = Loadable(React.lazy(() => import( /* webpackChunkName: "hackathons_page" */ "./features/Hackathons/pages/HackathonsPage/HackathonsPage"))) +const TournamentDetailsPage = Loadable(React.lazy(() => import( /* webpackChunkName: "hackathons_page" */ "./features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage"))) + const DonatePage = Loadable(React.lazy(() => import( /* webpackChunkName: "donate_page" */ "./features/Donations/pages/DonatePage/DonatePage"))) const LoginPage = Loadable(React.lazy(() => import( /* webpackChunkName: "login_page" */ "./features/Auth/pages/LoginPage/LoginPage"))) const LogoutPage = Loadable(React.lazy(() => import( /* webpackChunkName: "logout_page" */ "./features/Auth/pages/LogoutPage/LogoutPage"))) @@ -103,6 +105,8 @@ function App() { } /> + } /> + } /> } /> diff --git a/src/features/Tournaments/api/tournament.ts b/src/features/Tournaments/api/tournament.ts deleted file mode 100644 index e4b56e3..0000000 --- a/src/features/Tournaments/api/tournament.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { Tournament } from '../types/tournaments.types' - - -export function getTournament(): Tournament { - - return { - id: 12, - title: "The Long Night", - start_date: "2022-09-30T21:00:00.000Z", - end_date: "2022-10-30T22:00:00.000Z", - cover_image: "https://imagedelivery.net/wyrwp3c-j0gDDUWgnE7lig/1d5d2c86-fe46-4478-6909-bb3c425c0d00/public", - thumbnail_image: "https://imagedelivery.net/wyrwp3c-j0gDDUWgnE7lig/37fb9cd6-e4f1-43f9-c3fe-7c3e119d5600/public", - location: "Online", - website: "#", - description: ` -Lorem ipsum dolor sit **amet**, consectetur adipiscing elit. Semper turpis est, ac eget nullam. In leo at pharetra morbi ornare eget. Ultrices posuere senectus purus nulla vitae volutpat id id suspendisse. Urna mattis nulla diam semper erat. Mattis gravida ultrices aliquam odio. Praesent viverra egestas sed elementum nisl imperdiet a, non. - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac eget nullam. In leo at pharetra morbi ornare eget. Ultrices posuere senectus purus nulla vitae volutpat id id suspendisse. Urna mattis nulla diam semper erat. Mattis gravida ultrices aliquam odio. Praesent viverra egestas sed elementum nisl imperdiet a, non. - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac eget nullam. In leo at pharetra morbi ornare eget. Ultrices posuere senectus purus nulla vitae volutpat id id suspendisse. - `, // markdown - prizes: [{ - title: "stw3 champion", - amount: "$ 20k", - image: "https://imagedelivery.net/wyrwp3c-j0gDDUWgnE7lig/39217dcf-c900-46be-153f-169e3a1f0400/public", - }, - { - title: "2nd place", - amount: "$ 5k", - image: "https://imagedelivery.net/wyrwp3c-j0gDDUWgnE7lig/39cdb7c8-5fbf-49ff-32cf-fdabc3aa2d00/public", - }, - { - title: "3rd place ", - amount: "$ 2k", - image: "https://imagedelivery.net/wyrwp3c-j0gDDUWgnE7lig/75958797-73b2-4a62-52df-9f0f98c53900/public", - }, - { - title: "best design ", - amount: "$ 1k", - image: "https://imagedelivery.net/wyrwp3c-j0gDDUWgnE7lig/fa7b7cdd-7c06-4ebe-1a2d-94af9d2dae00/public", - }], - events: [], - faqs: [], - judges: [], - } -} \ No newline at end of file diff --git a/src/features/Tournaments/pages/OverviewPage/OverviewPage.tsx b/src/features/Tournaments/pages/OverviewPage/OverviewPage.tsx index e2e332f..ff79155 100644 --- a/src/features/Tournaments/pages/OverviewPage/OverviewPage.tsx +++ b/src/features/Tournaments/pages/OverviewPage/OverviewPage.tsx @@ -1,7 +1,67 @@ import React from 'react' +import { FaUsers } from 'react-icons/fa' +import Button from 'src/Components/Button/Button' +import Card from 'src/Components/Card/Card' +import Avatar from 'src/features/Profiles/Components/Avatar/Avatar' +import { Tournament } from 'src/graphql' +import PrizesSection from './PrizesSection/PrizesSection' -export default function OverviewPage() { +interface Props { + data: Pick +} + +export default function OverviewPage({ data }: Props) { return ( -
OverviewPage
+ +
+
+

Tournament details

+

{data.description}

+
+ +
+

+ + {data.makers_count} makers +

+ +
+
+

+ Tournament starts in +

+
+
+ 17d +
+
+ 12h +
+
+ 36m +
+
+
+
+

+ Sponsors +

+
+ + + + +
+
+
+
+ + +
) } diff --git a/src/features/Tournaments/pages/OverviewPage/PrizesSection/PrizesSection.tsx b/src/features/Tournaments/pages/OverviewPage/PrizesSection/PrizesSection.tsx new file mode 100644 index 0000000..02262c6 --- /dev/null +++ b/src/features/Tournaments/pages/OverviewPage/PrizesSection/PrizesSection.tsx @@ -0,0 +1,25 @@ +import React from 'react' +import { Tournament } from 'src/graphql' +import styles from './styles.module.scss' + +interface Props { + prizes: Tournament['prizes'] +} + +export default function PrizesSection({ prizes }: Props) { + return ( +
+ +

Prizes

+
+ {prizes.map(prize =>
+ +
+

{prize.title}

+

{prize.amount}

+
+
)} +
+
+ ) +} diff --git a/src/features/Tournaments/pages/OverviewPage/PrizesSection/styles.module.scss b/src/features/Tournaments/pages/OverviewPage/PrizesSection/styles.module.scss new file mode 100644 index 0000000..8e681e0 --- /dev/null +++ b/src/features/Tournaments/pages/OverviewPage/PrizesSection/styles.module.scss @@ -0,0 +1,88 @@ +@import "/src/styles/mixins"; + +@import url("https://fonts.googleapis.com/css2?family=Luckiest+Guy&display=swap"); + +.grid { + font-family: "Luckiest Guy", cursive; + display: grid; + gap: 24px; + > div { + display: flex; + align-items: center; + h3 { + font-size: 20px; + color: white; + -webkit-text-stroke: 2px black; + } + p { + font-size: 24px; + } + + &:first-child { + flex-direction: column; + justify-content: center; + align-items: center; + text-align: center; + + img { + max-width: 100px; + } + h3 { + font-size: 24px; + margin: 40px auto 0 auto; + } + p { + font-size: 40px; + } + } + + &:not(:first-child) { + justify-content: space-between; + text-align: right; + img { + max-width: 42px; + } + } + } + + grid-auto-rows: 120px; + grid-template-columns: 1fr; + + > div:first-child { + grid-row: span 3; + } + + @include gt-md { + grid-auto-rows: 150px; + grid-template-columns: 1fr 1fr; + + > div { + h3 { + font-size: 32px; + } + p { + font-size: 40px; + } + + &:first-child { + grid-row: 1/4; + grid-column: 1/2; + img { + max-width: 160px; + } + h3 { + font-size: 32px; + margin: 24px auto 24px auto; + } + p { + font-size: 56px; + } + } + &:not(:first-child) { + img { + max-width: 64px; + } + } + } + } +} diff --git a/src/features/Tournaments/pages/TournamentBasePage/TournamentBasePage.tsx b/src/features/Tournaments/pages/TournamentBasePage/TournamentBasePage.tsx deleted file mode 100644 index 22fe347..0000000 --- a/src/features/Tournaments/pages/TournamentBasePage/TournamentBasePage.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react' - -export default function TournamentBasePage() { - return ( -
TournamentBasePage
- ) -} diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/Header/Header.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/Header/Header.tsx new file mode 100644 index 0000000..3a02bfb --- /dev/null +++ b/src/features/Tournaments/pages/TournamentDetailsPage/Header/Header.tsx @@ -0,0 +1,36 @@ +import dayjs from 'dayjs' +import advancedFormat from 'dayjs/plugin/advancedFormat' +import React from 'react' +import { IoLocationOutline } from 'react-icons/io5' +import { Tournament } from 'src/graphql' +import Navigation from '../Navigation/Navigation' +dayjs.extend(advancedFormat) + +interface Props { + data: Pick +} + +export default function Header({ data }: Props) { + return ( +
+ +
+
+ +
+

TOURNAMENT 🏆

+

{data.title}

+

{`${dayjs(data.start_date).format('Do')} - ${dayjs(data.end_date).format('Do MMMM, YYYY')}`}

+ +

{data.location}

+
+
+
+ ) +} diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx new file mode 100644 index 0000000..a359a78 --- /dev/null +++ b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx @@ -0,0 +1,72 @@ +import React, { useMemo } from 'react' +import { Link, NavLink } from 'react-router-dom' +import { Tournament } from 'src/graphql' +import { useCarousel } from 'src/utils/hooks' + +interface Props { + data: Pick +} + +export default function Navigation({ data }: Props) { + + const { viewportRef, scrollSlides, canScrollNext, canScrollPrev, isClickAllowed } = useCarousel({ + align: 'start', slidesToScroll: 2, + containScroll: "trimSnaps", + }) + + const links = useMemo(() => [ + { + text: "Overview", + path: "overview", + }, + { + text: `Events (${data.events_count})`, + path: "events", + }, + { + text: `Makers (${data.makers_count})`, + path: "makers", + }, + { + text: `Projects (${data.projects_count})`, + path: "projects", + }, + { + text: "Ideas", + path: "ideas", + }, + { + text: "Resources", + path: "resources", + }, + ], [data.events_count, data.makers_count, data.projects_count]) + + return ( +
+
+
+
+ {links.map((link) => ` + min-w-max rounded-48 px-16 py-8 cursor-pointer font-medium text-body5 + active:scale-95 transition-transform + ${isActive ? 'bg-primary-100 text-primary-600' : 'bg-gray-100 hover:bg-gray-200 text-gray-600'}`} + // onClick={() => filterClicked(f.value)} + role='button' + > + {link.text} + )} +
+
+ {/* + */} +
+
+ ) +} diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx new file mode 100644 index 0000000..26e0234 --- /dev/null +++ b/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx @@ -0,0 +1,43 @@ +import React from 'react' +import { useGetTournamentByIdQuery } from 'src/graphql' +import LoadingPage from 'src/Components/LoadingPage/LoadingPage' +import NotFoundPage from 'src/features/Shared/pages/NotFoundPage/NotFoundPage' +import Header from './Header/Header' +import { Navigate, Route, Routes } from 'react-router-dom' +import OverviewPage from '../OverviewPage/OverviewPage' +import { Helmet } from 'react-helmet' +import Navigation from './Navigation/Navigation' + +export default function TournamentDetailsPage() { + + const query = useGetTournamentByIdQuery({ + variables: { + id: 12, + } + }) + + if (query.loading) + return + + if (!query.data?.getTournamentById) + return + + return ( +
+ + {query.data.getTournamentById.title} Tournament + +
+ + +
+ + } /> + } /> + +
+
+ ) +} diff --git a/src/features/Tournaments/pages/TournamentBasePage/tournamentDetails.graphql b/src/features/Tournaments/pages/TournamentDetailsPage/tournamentDetails.graphql similarity index 89% rename from src/features/Tournaments/pages/TournamentBasePage/tournamentDetails.graphql rename to src/features/Tournaments/pages/TournamentDetailsPage/tournamentDetails.graphql index fb01ac5..046a5a2 100644 --- a/src/features/Tournaments/pages/TournamentBasePage/tournamentDetails.graphql +++ b/src/features/Tournaments/pages/TournamentDetailsPage/tournamentDetails.graphql @@ -9,6 +9,11 @@ query GetTournamentById($id: Int!) { end_date location website + + events_count + makers_count + projects_count + prizes { title amount diff --git a/src/graphql/index.tsx b/src/graphql/index.tsx index f9f38cb..3ced6ab 100644 --- a/src/graphql/index.tsx +++ b/src/graphql/index.tsx @@ -433,11 +433,14 @@ export type Tournament = { description: Scalars['String']; end_date: Scalars['Date']; events: Array; + events_count: Scalars['Int']; faqs: Array; id: Scalars['Int']; judges: Array; location: Scalars['String']; + makers_count: Scalars['Int']; prizes: Array; + projects_count: Scalars['Int']; start_date: Scalars['Date']; thumbnail_image: Scalars['String']; title: Scalars['String']; @@ -691,7 +694,7 @@ export type GetTournamentByIdQueryVariables = Exact<{ }>; -export type GetTournamentByIdQuery = { __typename?: 'Query', getTournamentById: { __typename?: 'Tournament', id: number, title: string, description: string, thumbnail_image: string, cover_image: string, start_date: any, end_date: any, location: string, website: string, prizes: Array<{ __typename?: 'TournamentPrize', title: string, amount: string, image: string }>, judges: Array<{ __typename?: 'TournamentJudge', name: string, jobTitle: string, avatar: string }>, events: Array<{ __typename?: 'TournamentEvent', id: number, title: string, image: string, description: string, date: any, location: string, website: string, type: string, links: Array }>, faqs: Array<{ __typename?: 'TournamentFAQ', question: string, answer: string }> } }; +export type GetTournamentByIdQuery = { __typename?: 'Query', getTournamentById: { __typename?: 'Tournament', id: number, title: string, description: string, thumbnail_image: string, cover_image: string, start_date: any, end_date: any, location: string, website: string, events_count: number, makers_count: number, projects_count: number, prizes: Array<{ __typename?: 'TournamentPrize', title: string, amount: string, image: string }>, judges: Array<{ __typename?: 'TournamentJudge', name: string, jobTitle: string, avatar: string }>, events: Array<{ __typename?: 'TournamentEvent', id: number, title: string, image: string, description: string, date: any, location: string, website: string, type: string, links: Array }>, faqs: Array<{ __typename?: 'TournamentFAQ', question: string, answer: string }> } }; export type VoteMutationVariables = Exact<{ itemType: Vote_Item_Type; @@ -1933,6 +1936,9 @@ export const GetTournamentByIdDocument = gql` end_date location website + events_count + makers_count + projects_count prizes { title amount diff --git a/src/mocks/data/tournament.ts b/src/mocks/data/tournament.ts index 85e72b7..45e4fcd 100644 --- a/src/mocks/data/tournament.ts +++ b/src/mocks/data/tournament.ts @@ -10,8 +10,8 @@ export const tournaments: Tournament[] = [{ thumbnail_image: "https://imagedelivery.net/wyrwp3c-j0gDDUWgnE7lig/37fb9cd6-e4f1-43f9-c3fe-7c3e119d5600/public", location: "Online", website: "#", - description: ` -Lorem ipsum dolor sit **amet**, consectetur adipiscing elit. Semper turpis est, ac eget nullam. In leo at pharetra morbi ornare eget. Ultrices posuere senectus purus nulla vitae volutpat id id suspendisse. Urna mattis nulla diam semper erat. Mattis gravida ultrices aliquam odio. Praesent viverra egestas sed elementum nisl imperdiet a, non. + description: + `Lorem ipsum dolor sit **amet**, consectetur adipiscing elit. Semper turpis est, ac eget nullam. In leo at pharetra morbi ornare eget. Ultrices posuere senectus purus nulla vitae volutpat id id suspendisse. Urna mattis nulla diam semper erat. Mattis gravida ultrices aliquam odio. Praesent viverra egestas sed elementum nisl imperdiet a, non. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac eget nullam. In leo at pharetra morbi ornare eget. Ultrices posuere senectus purus nulla vitae volutpat id id suspendisse. Urna mattis nulla diam semper erat. Mattis gravida ultrices aliquam odio. Praesent viverra egestas sed elementum nisl imperdiet a, non. @@ -37,6 +37,9 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e amount: "$ 1k", image: "https://imagedelivery.net/wyrwp3c-j0gDDUWgnE7lig/fa7b7cdd-7c06-4ebe-1a2d-94af9d2dae00/public", }], + events_count: 28, + makers_count: 668, + projects_count: 21, events: [], faqs: [], judges: [], diff --git a/src/styles/index.scss b/src/styles/index.scss index 96fdc2e..74fe6ac 100644 --- a/src/styles/index.scss +++ b/src/styles/index.scss @@ -26,7 +26,7 @@ body { @include gt-md { --padding: 32px; } - width: calc(min(100% - 2 * var(--padding), 1440px)); + width: calc(min(100% - 2 * var(--padding), var(--maxPageWidth, 1440px))); margin: 0 auto; } diff --git a/src/utils/routing/routes.ts b/src/utils/routing/routes.ts index f4c338f..29613d1 100644 --- a/src/utils/routing/routes.ts +++ b/src/utils/routing/routes.ts @@ -81,6 +81,9 @@ export const PAGES_ROUTES = { editProfile: "/edit-profile/*", byId: "/profile/:id/*", }, + tournament: { + byId: "/tournaments/:id/*", + }, auth: { login: "/login", logout: "/logout",