From 5dea9526dea21978451060e3897365d4fe73e360 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Wed, 31 Aug 2022 11:36:10 +0300 Subject: [PATCH 01/53] feat: base tournament api schema --- api/functions/graphql/nexus-typegen.ts | 125 +++++++++++++++++ api/functions/graphql/schema.graphql | 46 ++++++ api/functions/graphql/types/index.js | 2 + api/functions/graphql/types/tournament.js | 92 ++++++++++++ src/features/Tournaments/api/tournament.ts | 46 ++++++ .../pages/OverviewPage/OverviewPage.tsx | 7 + .../TournamentBasePage/TournamentBasePage.tsx | 7 + .../tournamentDetails.graphql | 38 +++++ src/graphql/index.tsx | 131 ++++++++++++++++++ src/mocks/data.ts | 4 +- src/mocks/data/tournament.ts | 44 ++++++ src/mocks/handlers.ts | 15 +- src/mocks/resolvers.ts | 4 + 13 files changed, 559 insertions(+), 2 deletions(-) create mode 100644 api/functions/graphql/types/tournament.js create mode 100644 src/features/Tournaments/api/tournament.ts create mode 100644 src/features/Tournaments/pages/OverviewPage/OverviewPage.tsx create mode 100644 src/features/Tournaments/pages/TournamentBasePage/TournamentBasePage.tsx create mode 100644 src/features/Tournaments/pages/TournamentBasePage/tournamentDetails.graphql create mode 100644 src/mocks/data/tournament.ts diff --git a/api/functions/graphql/nexus-typegen.ts b/api/functions/graphql/nexus-typegen.ts index bd8c67e..be73b78 100644 --- a/api/functions/graphql/nexus-typegen.ts +++ b/api/functions/graphql/nexus-typegen.ts @@ -208,6 +208,46 @@ export interface NexusGenObjects { isOfficial?: boolean | null; // Boolean title: string; // String! } + Tournament: { // root type + cover_image: string; // String! + description: string; // String! + end_date: NexusGenScalars['Date']; // Date! + events: NexusGenRootTypes['TournamentEvent'][]; // [TournamentEvent!]! + faqs: NexusGenRootTypes['TournamentFAQ'][]; // [TournamentFAQ!]! + id: number; // Int! + judges: NexusGenRootTypes['TournamentJudge'][]; // [TournamentJudge!]! + location: string; // String! + prizes: NexusGenRootTypes['TournamentPrize'][]; // [TournamentPrize!]! + start_date: NexusGenScalars['Date']; // Date! + thumbnail_image: string; // String! + title: string; // String! + website: string; // String! + } + TournamentEvent: { // root type + date: NexusGenScalars['Date']; // Date! + description: string; // String! + id: number; // Int! + image: string; // String! + links: string[]; // [String!]! + location: string; // String! + title: string; // String! + type: string; // String! + website: string; // String! + } + TournamentFAQ: { // root type + answer: string; // String! + question: string; // String! + } + TournamentJudge: { // root type + avatar: string; // String! + jobTitle: string; // String! + name: string; // String! + } + TournamentPrize: { // root type + amount: string; // String! + image: string; // String! + title: string; // String! + } User: { // root type avatar: string; // String! bio?: string | null; // String @@ -396,6 +436,7 @@ export interface NexusGenFieldTypes { getMyDrafts: NexusGenRootTypes['Post'][]; // [Post!]! getPostById: NexusGenRootTypes['Post']; // Post! getProject: NexusGenRootTypes['Project']; // Project! + getTournamentById: NexusGenRootTypes['Tournament']; // Tournament! getTrendingPosts: NexusGenRootTypes['Post'][]; // [Post!]! hottestProjects: NexusGenRootTypes['Project'][]; // [Project!]! me: NexusGenRootTypes['MyProfile'] | null; // MyProfile @@ -442,6 +483,46 @@ export interface NexusGenFieldTypes { isOfficial: boolean | null; // Boolean title: string; // String! } + Tournament: { // field return type + cover_image: string; // String! + description: string; // String! + end_date: NexusGenScalars['Date']; // Date! + events: NexusGenRootTypes['TournamentEvent'][]; // [TournamentEvent!]! + faqs: NexusGenRootTypes['TournamentFAQ'][]; // [TournamentFAQ!]! + id: number; // Int! + judges: NexusGenRootTypes['TournamentJudge'][]; // [TournamentJudge!]! + location: string; // String! + prizes: NexusGenRootTypes['TournamentPrize'][]; // [TournamentPrize!]! + start_date: NexusGenScalars['Date']; // Date! + thumbnail_image: string; // String! + title: string; // String! + website: string; // String! + } + TournamentEvent: { // field return type + date: NexusGenScalars['Date']; // Date! + description: string; // String! + id: number; // Int! + image: string; // String! + links: string[]; // [String!]! + location: string; // String! + title: string; // String! + type: string; // String! + website: string; // String! + } + TournamentFAQ: { // field return type + answer: string; // String! + question: string; // String! + } + TournamentJudge: { // field return type + avatar: string; // String! + jobTitle: string; // String! + name: string; // String! + } + TournamentPrize: { // field return type + amount: string; // String! + image: string; // String! + title: string; // String! + } User: { // field return type avatar: string; // String! bio: string | null; // String @@ -645,6 +726,7 @@ export interface NexusGenFieldTypeNames { getMyDrafts: 'Post' getPostById: 'Post' getProject: 'Project' + getTournamentById: 'Tournament' getTrendingPosts: 'Post' hottestProjects: 'Project' me: 'MyProfile' @@ -691,6 +773,46 @@ export interface NexusGenFieldTypeNames { isOfficial: 'Boolean' title: 'String' } + Tournament: { // field return type name + cover_image: 'String' + description: 'String' + end_date: 'Date' + events: 'TournamentEvent' + faqs: 'TournamentFAQ' + id: 'Int' + judges: 'TournamentJudge' + location: 'String' + prizes: 'TournamentPrize' + start_date: 'Date' + thumbnail_image: 'String' + title: 'String' + website: 'String' + } + TournamentEvent: { // field return type name + date: 'Date' + description: 'String' + id: 'Int' + image: 'String' + links: 'String' + location: 'String' + title: 'String' + type: 'String' + website: 'String' + } + TournamentFAQ: { // field return type name + answer: 'String' + question: 'String' + } + TournamentJudge: { // field return type name + avatar: 'String' + jobTitle: 'String' + name: 'String' + } + TournamentPrize: { // field return type name + amount: 'String' + image: 'String' + title: 'String' + } User: { // field return type name avatar: 'String' bio: 'String' @@ -812,6 +934,9 @@ export interface NexusGenArgTypes { getProject: { // args id: number; // Int! } + getTournamentById: { // args + id: number; // Int! + } hottestProjects: { // args skip?: number | null; // Int take: number | null; // Int diff --git a/api/functions/graphql/schema.graphql b/api/functions/graphql/schema.graphql index 8a3947c..5d9562b 100644 --- a/api/functions/graphql/schema.graphql +++ b/api/functions/graphql/schema.graphql @@ -212,6 +212,7 @@ type Query { getMyDrafts(type: POST_TYPE!): [Post!]! getPostById(id: Int!, type: POST_TYPE!): Post! getProject(id: Int!): Project! + getTournamentById(id: Int!): Tournament! getTrendingPosts: [Post!]! hottestProjects(skip: Int = 0, take: Int = 50): [Project!]! me: MyProfile @@ -271,6 +272,51 @@ type Tag { title: String! } +type Tournament { + cover_image: String! + description: String! + end_date: Date! + events: [TournamentEvent!]! + faqs: [TournamentFAQ!]! + id: Int! + judges: [TournamentJudge!]! + location: String! + prizes: [TournamentPrize!]! + start_date: Date! + thumbnail_image: String! + title: String! + website: String! +} + +type TournamentEvent { + date: Date! + description: String! + id: Int! + image: String! + links: [String!]! + location: String! + title: String! + type: String! + website: String! +} + +type TournamentFAQ { + answer: String! + question: String! +} + +type TournamentJudge { + avatar: String! + jobTitle: String! + name: String! +} + +type TournamentPrize { + amount: String! + image: String! + title: String! +} + type User implements BaseUser { avatar: String! bio: String diff --git a/api/functions/graphql/types/index.js b/api/functions/graphql/types/index.js index 75e2db0..91cd7d2 100644 --- a/api/functions/graphql/types/index.js +++ b/api/functions/graphql/types/index.js @@ -5,6 +5,7 @@ const vote = require('./vote') const post = require('./post') const users = require('./users') const hackathon = require('./hackathon') +const tournament = require('./tournament') const donation = require('./donation') const tag = require('./tag') @@ -17,5 +18,6 @@ module.exports = { ...post, ...users, ...hackathon, + ...tournament, ...donation, } \ No newline at end of file diff --git a/api/functions/graphql/types/tournament.js b/api/functions/graphql/types/tournament.js new file mode 100644 index 0000000..8221eb2 --- /dev/null +++ b/api/functions/graphql/types/tournament.js @@ -0,0 +1,92 @@ +const { + intArg, + objectType, + stringArg, + extendType, + nonNull, +} = require('nexus'); +const { prisma } = require('../../../prisma'); + + + +const TournamentPrize = objectType({ + name: 'TournamentPrize', + definition(t) { + t.nonNull.string('title'); + t.nonNull.string('amount'); + t.nonNull.string('image'); + } +}) + +const TournamentJudge = objectType({ + name: 'TournamentJudge', + definition(t) { + t.nonNull.string('name'); + t.nonNull.string('jobTitle'); + t.nonNull.string('avatar'); + } +}) + +const TournamentFAQ = objectType({ + name: 'TournamentFAQ', + definition(t) { + t.nonNull.string('question'); + t.nonNull.string('answer'); + } +}) + +const TournamentEvent = objectType({ + name: 'TournamentEvent', + definition(t) { + t.nonNull.int('id'); + t.nonNull.string('title'); + t.nonNull.string('image'); + t.nonNull.string('description'); + t.nonNull.date('date'); + t.nonNull.string('location'); + t.nonNull.string('website'); + t.nonNull.string('type'); + t.nonNull.list.nonNull.string('links'); + } +}) + +const Tournament = objectType({ + name: 'Tournament', + definition(t) { + t.nonNull.int('id'); + t.nonNull.string('title'); + t.nonNull.string('description'); + t.nonNull.string('thumbnail_image'); + t.nonNull.string('cover_image'); + t.nonNull.date('start_date'); + t.nonNull.date('end_date'); + t.nonNull.string('location'); + t.nonNull.string('website'); + t.nonNull.list.nonNull.field('prizes', { type: TournamentPrize, }); + t.nonNull.list.nonNull.field('judges', { type: TournamentJudge, }); + t.nonNull.list.nonNull.field('faqs', { type: TournamentFAQ, }); + t.nonNull.list.nonNull.field('events', { type: TournamentEvent, }); + } +}) + +const getTournamentById = extendType({ + type: "Query", + definition(t) { + t.nonNull.field('getTournamentById', { + type: Tournament, + args: { + id: nonNull(intArg()), + }, + resolve(_, { id }) { + return null + } + }) + } +}) + +module.exports = { + // Types + Tournament, + // Queries + getTournamentById, +} \ No newline at end of file diff --git a/src/features/Tournaments/api/tournament.ts b/src/features/Tournaments/api/tournament.ts new file mode 100644 index 0000000..e4b56e3 --- /dev/null +++ b/src/features/Tournaments/api/tournament.ts @@ -0,0 +1,46 @@ +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 new file mode 100644 index 0000000..e2e332f --- /dev/null +++ b/src/features/Tournaments/pages/OverviewPage/OverviewPage.tsx @@ -0,0 +1,7 @@ +import React from 'react' + +export default function OverviewPage() { + return ( +
OverviewPage
+ ) +} diff --git a/src/features/Tournaments/pages/TournamentBasePage/TournamentBasePage.tsx b/src/features/Tournaments/pages/TournamentBasePage/TournamentBasePage.tsx new file mode 100644 index 0000000..22fe347 --- /dev/null +++ b/src/features/Tournaments/pages/TournamentBasePage/TournamentBasePage.tsx @@ -0,0 +1,7 @@ +import React from 'react' + +export default function TournamentBasePage() { + return ( +
TournamentBasePage
+ ) +} diff --git a/src/features/Tournaments/pages/TournamentBasePage/tournamentDetails.graphql b/src/features/Tournaments/pages/TournamentBasePage/tournamentDetails.graphql new file mode 100644 index 0000000..fb01ac5 --- /dev/null +++ b/src/features/Tournaments/pages/TournamentBasePage/tournamentDetails.graphql @@ -0,0 +1,38 @@ +query GetTournamentById($id: Int!) { + getTournamentById(id: $id) { + id + title + description + thumbnail_image + cover_image + start_date + end_date + location + website + prizes { + title + amount + image + } + judges { + name + jobTitle + avatar + } + events { + id + title + image + description + date + location + website + type + links + } + faqs { + question + answer + } + } +} # diff --git a/src/graphql/index.tsx b/src/graphql/index.tsx index f9f95ac..f9f38cb 100644 --- a/src/graphql/index.tsx +++ b/src/graphql/index.tsx @@ -282,6 +282,7 @@ export type Query = { getMyDrafts: Array; getPostById: Post; getProject: Project; + getTournamentById: Tournament; getTrendingPosts: Array; hottestProjects: Array; me: Maybe; @@ -340,6 +341,11 @@ export type QueryGetProjectArgs = { }; +export type QueryGetTournamentByIdArgs = { + id: Scalars['Int']; +}; + + export type QueryHottestProjectsArgs = { skip?: InputMaybe; take?: InputMaybe; @@ -421,6 +427,56 @@ export type Tag = { title: Scalars['String']; }; +export type Tournament = { + __typename?: 'Tournament'; + cover_image: Scalars['String']; + description: Scalars['String']; + end_date: Scalars['Date']; + events: Array; + faqs: Array; + id: Scalars['Int']; + judges: Array; + location: Scalars['String']; + prizes: Array; + start_date: Scalars['Date']; + thumbnail_image: Scalars['String']; + title: Scalars['String']; + website: Scalars['String']; +}; + +export type TournamentEvent = { + __typename?: 'TournamentEvent'; + date: Scalars['Date']; + description: Scalars['String']; + id: Scalars['Int']; + image: Scalars['String']; + links: Array; + location: Scalars['String']; + title: Scalars['String']; + type: Scalars['String']; + website: Scalars['String']; +}; + +export type TournamentFaq = { + __typename?: 'TournamentFAQ'; + answer: Scalars['String']; + question: Scalars['String']; +}; + +export type TournamentJudge = { + __typename?: 'TournamentJudge'; + avatar: Scalars['String']; + jobTitle: Scalars['String']; + name: Scalars['String']; +}; + +export type TournamentPrize = { + __typename?: 'TournamentPrize'; + amount: Scalars['String']; + image: Scalars['String']; + title: Scalars['String']; +}; + export type User = BaseUser & { __typename?: 'User'; avatar: Scalars['String']; @@ -630,6 +686,13 @@ export type ProjectDetailsQueryVariables = Exact<{ export type ProjectDetailsQuery = { __typename?: 'Query', getProject: { __typename?: 'Project', id: number, title: string, description: string, cover_image: string, thumbnail_image: string, screenshots: Array, website: string, lightning_address: string | null, lnurl_callback_url: string | null, votes_count: number, category: { __typename?: 'Category', id: number, title: string }, awards: Array<{ __typename?: 'Award', title: string, image: string, url: string, id: number }>, tags: Array<{ __typename?: 'Tag', id: number, title: string }> } }; +export type GetTournamentByIdQueryVariables = Exact<{ + id: Scalars['Int']; +}>; + + +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 VoteMutationVariables = Exact<{ itemType: Vote_Item_Type; itemId: Scalars['Int']; @@ -1858,6 +1921,74 @@ export function useProjectDetailsLazyQuery(baseOptions?: Apollo.LazyQueryHookOpt export type ProjectDetailsQueryHookResult = ReturnType; export type ProjectDetailsLazyQueryHookResult = ReturnType; export type ProjectDetailsQueryResult = Apollo.QueryResult; +export const GetTournamentByIdDocument = gql` + query GetTournamentById($id: Int!) { + getTournamentById(id: $id) { + id + title + description + thumbnail_image + cover_image + start_date + end_date + location + website + prizes { + title + amount + image + } + judges { + name + jobTitle + avatar + } + events { + id + title + image + description + date + location + website + type + links + } + faqs { + question + answer + } + } +} + `; + +/** + * __useGetTournamentByIdQuery__ + * + * To run a query within a React component, call `useGetTournamentByIdQuery` and pass it any options that fit your needs. + * When your component renders, `useGetTournamentByIdQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetTournamentByIdQuery({ + * variables: { + * id: // value for 'id' + * }, + * }); + */ +export function useGetTournamentByIdQuery(baseOptions: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(GetTournamentByIdDocument, options); + } +export function useGetTournamentByIdLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(GetTournamentByIdDocument, options); + } +export type GetTournamentByIdQueryHookResult = ReturnType; +export type GetTournamentByIdLazyQueryHookResult = ReturnType; +export type GetTournamentByIdQueryResult = Apollo.QueryResult; export const VoteDocument = gql` mutation Vote($itemType: VOTE_ITEM_TYPE!, $itemId: Int!, $amountInSat: Int!) { vote(item_type: $itemType, item_id: $itemId, amount_in_sat: $amountInSat) { diff --git a/src/mocks/data.ts b/src/mocks/data.ts index a660dcf..532027c 100644 --- a/src/mocks/data.ts +++ b/src/mocks/data.ts @@ -1,6 +1,7 @@ import { hackathons } from "./data/hackathon"; import { posts, feed, generatePostComments } from "./data/posts"; import { categories, projects } from "./data/projects"; +import { tournaments } from "./data/tournament"; import { user } from "./data/users"; export const MOCK_DATA = { @@ -10,5 +11,6 @@ export const MOCK_DATA = { feed, hackathons, generatePostComments: generatePostComments, - user: user + user: user, + tournaments: tournaments, } \ No newline at end of file diff --git a/src/mocks/data/tournament.ts b/src/mocks/data/tournament.ts new file mode 100644 index 0000000..85e72b7 --- /dev/null +++ b/src/mocks/data/tournament.ts @@ -0,0 +1,44 @@ +import { Tournament } from "src/graphql"; + +export const tournaments: Tournament[] = [{ + __typename: "Tournament", + 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/mocks/handlers.ts b/src/mocks/handlers.ts index 94b5557..9610e6b 100644 --- a/src/mocks/handlers.ts +++ b/src/mocks/handlers.ts @@ -1,6 +1,6 @@ import { graphql } from 'msw' -import { allCategories, getAllHackathons, getCategory, getFeed, getMyDrafts, getPostById, getProject, getTrendingPosts, hottestProjects, me, newProjects, popularTags, profile, projectsByCategory, searchProjects } from './resolvers' +import { allCategories, getAllHackathons, getCategory, getFeed, getMyDrafts, getPostById, getProject, getTournamentById, getTrendingPosts, hottestProjects, me, newProjects, popularTags, profile, projectsByCategory, searchProjects } from './resolvers' import { NavCategoriesQuery, ExploreProjectsQuery, @@ -31,6 +31,7 @@ import { GetMyDraftsQuery, MyProfileAboutQuery, MyProfilePreferencesQuery, + GetTournamentByIdQuery, } from 'src/graphql' const delay = (ms = 1000) => new Promise((res) => setTimeout(res, ms + Math.random() * 1000)) @@ -247,4 +248,16 @@ export const handlers = [ ) }), + + + graphql.query('GetTournamentById', async (req, res, ctx) => { + await delay() + + return res( + ctx.data({ + getTournamentById: getTournamentById(12) + }) + ) + }), + ] \ No newline at end of file diff --git a/src/mocks/resolvers.ts b/src/mocks/resolvers.ts index d09f614..1160d73 100644 --- a/src/mocks/resolvers.ts +++ b/src/mocks/resolvers.ts @@ -86,4 +86,8 @@ export function profile() { export function getMyDrafts(): Query['getMyDrafts'] { return MOCK_DATA['posts'].stories; +} + +export function getTournamentById(id: number) { + return MOCK_DATA['tournaments'][0] } \ No newline at end of file From 840a9e50eb844a683fbf9eda8540e9951be0a2c0 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Wed, 31 Aug 2022 14:52:10 +0300 Subject: [PATCH 02/53] 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", From 2dc324d94cc0a1c12110d3e2d18d921c6e1850e6 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Thu, 1 Sep 2022 10:07:51 +0300 Subject: [PATCH 03/53] fix merge confilicts with tournaments --- api/functions/graphql/nexus-typegen.ts | 2 +- api/functions/graphql/schema.graphql | 13 +- api/functions/graphql/types/tournaments.js | 55 ---- api/functions/graphql/types/users.js | 2 +- src/graphql/index.tsx | 306 ++++++++++----------- 5 files changed, 159 insertions(+), 219 deletions(-) delete mode 100644 api/functions/graphql/types/tournaments.js diff --git a/api/functions/graphql/nexus-typegen.ts b/api/functions/graphql/nexus-typegen.ts index 0c66210..b5d78da 100644 --- a/api/functions/graphql/nexus-typegen.ts +++ b/api/functions/graphql/nexus-typegen.ts @@ -24,7 +24,7 @@ declare global { declare global { - interface NexusGen extends NexusGenTypes { } + interface NexusGen extends NexusGenTypes {} } export interface NexusGenInputs { diff --git a/api/functions/graphql/schema.graphql b/api/functions/graphql/schema.graphql index bf033bc..0a8c099 100644 --- a/api/functions/graphql/schema.graphql +++ b/api/functions/graphql/schema.graphql @@ -1,6 +1,7 @@ ### This file was generated by Nexus Schema ### Do not make changes to this file directly + type Author { avatar: String! id: Int! @@ -75,9 +76,7 @@ type Category { votes_sum: Int! } -""" -Date custom scalar type -""" +"""Date custom scalar type""" scalar Date type Donation { @@ -264,11 +263,7 @@ type Query { officialTags: [Tag!]! popularTags: [Tag!]! profile(id: Int!): User - projectsByCategory( - category_id: Int! - skip: Int = 0 - take: Int = 10 - ): [Project!]! + projectsByCategory(category_id: Int!, skip: Int = 0, take: Int = 10): [Project!]! searchProjects(search: String!, skip: Int = 0, take: Int = 50): [Project!]! similarMakers(id: Int!): [User!]! } @@ -426,4 +421,4 @@ type Vote { type WalletKey { key: String! name: String! -} +} \ No newline at end of file diff --git a/api/functions/graphql/types/tournaments.js b/api/functions/graphql/types/tournaments.js deleted file mode 100644 index 9f04081..0000000 --- a/api/functions/graphql/types/tournaments.js +++ /dev/null @@ -1,55 +0,0 @@ -const { - intArg, - objectType, - stringArg, - extendType, - nonNull, -} = require('nexus'); -const { prisma } = require('../../../prisma'); - - - -const Tournament = objectType({ - name: 'Tournament', - definition(t) { - t.nonNull.int('id'); - t.nonNull.string('title'); - t.nonNull.string('description'); - t.nonNull.string('thumbnail_image'); - t.nonNull.string('cover_image'); - t.nonNull.date('start_date'); - t.nonNull.date('end_date'); - t.nonNull.string('website'); - t.nonNull.list.nonNull.field('tags', { - type: "Tag", - resolve: (parent) => { - // return prisma.hackathon.findUnique({ where: { id: parent.id } }).tags(); - return []; - } - }); - } -}) - -const getAllTournaments = extendType({ - type: "Query", - definition(t) { - t.nonNull.list.nonNull.field('getAllTournaments', { - type: Tournament, - args: { - sortBy: stringArg(), - tag: intArg(), - }, - resolve(_, args) { - const { sortBy, tag } = args; - return []; - } - }) - } -}) - -module.exports = { - // Types - Tournament, - // Queries - getAllTournaments, -} \ No newline at end of file diff --git a/api/functions/graphql/types/users.js b/api/functions/graphql/types/users.js index 7173b36..fb8a9df 100644 --- a/api/functions/graphql/types/users.js +++ b/api/functions/graphql/types/users.js @@ -3,7 +3,7 @@ const { prisma } = require('../../../prisma'); const { objectType, extendType, intArg, nonNull, inputObjectType, interfaceType, list, enumType } = require("nexus"); const { getUserByPubKey } = require("../../../auth/utils/helperFuncs"); const { removeNulls } = require("./helpers"); -const { Tournament } = require('./tournaments'); +const { Tournament } = require('./tournament'); diff --git a/src/graphql/index.tsx b/src/graphql/index.tsx index 1019468..7a8f40c 100644 --- a/src/graphql/index.tsx +++ b/src/graphql/index.tsx @@ -865,13 +865,13 @@ export const OfficialTagsDocument = gql` * }); */ export function useOfficialTagsQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useQuery(OfficialTagsDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(OfficialTagsDocument, options); + } export function useOfficialTagsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useLazyQuery(OfficialTagsDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(OfficialTagsDocument, options); + } export type OfficialTagsQueryHookResult = ReturnType; export type OfficialTagsLazyQueryHookResult = ReturnType; export type OfficialTagsQueryResult = Apollo.QueryResult; @@ -902,13 +902,13 @@ export const NavCategoriesDocument = gql` * }); */ export function useNavCategoriesQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useQuery(NavCategoriesDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(NavCategoriesDocument, options); + } export function useNavCategoriesLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useLazyQuery(NavCategoriesDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(NavCategoriesDocument, options); + } export type NavCategoriesQueryHookResult = ReturnType; export type NavCategoriesLazyQueryHookResult = ReturnType; export type NavCategoriesQueryResult = Apollo.QueryResult; @@ -943,13 +943,13 @@ export const SearchProjectsDocument = gql` * }); */ export function useSearchProjectsQuery(baseOptions: Apollo.QueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useQuery(SearchProjectsDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(SearchProjectsDocument, options); + } export function useSearchProjectsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useLazyQuery(SearchProjectsDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(SearchProjectsDocument, options); + } export type SearchProjectsQueryHookResult = ReturnType; export type SearchProjectsLazyQueryHookResult = ReturnType; export type SearchProjectsQueryResult = Apollo.QueryResult; @@ -982,13 +982,13 @@ export const MeDocument = gql` * }); */ export function useMeQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useQuery(MeDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(MeDocument, options); + } export function useMeLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useLazyQuery(MeDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(MeDocument, options); + } export type MeQueryHookResult = ReturnType; export type MeLazyQueryHookResult = ReturnType; export type MeQueryResult = Apollo.QueryResult; @@ -1019,13 +1019,13 @@ export const DonationsStatsDocument = gql` * }); */ export function useDonationsStatsQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useQuery(DonationsStatsDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(DonationsStatsDocument, options); + } export function useDonationsStatsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useLazyQuery(DonationsStatsDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(DonationsStatsDocument, options); + } export type DonationsStatsQueryHookResult = ReturnType; export type DonationsStatsLazyQueryHookResult = ReturnType; export type DonationsStatsQueryResult = Apollo.QueryResult; @@ -1059,9 +1059,9 @@ export type DonateMutationFn = Apollo.MutationFunction) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useMutation(DonateDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(DonateDocument, options); + } export type DonateMutationHookResult = ReturnType; export type DonateMutationResult = Apollo.MutationResult; export type DonateMutationOptions = Apollo.BaseMutationOptions; @@ -1095,9 +1095,9 @@ export type ConfirmDonationMutationFn = Apollo.MutationFunction) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useMutation(ConfirmDonationDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(ConfirmDonationDocument, options); + } export type ConfirmDonationMutationHookResult = ReturnType; export type ConfirmDonationMutationResult = Apollo.MutationResult; export type ConfirmDonationMutationOptions = Apollo.BaseMutationOptions; @@ -1139,13 +1139,13 @@ export const GetHackathonsDocument = gql` * }); */ export function useGetHackathonsQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useQuery(GetHackathonsDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(GetHackathonsDocument, options); + } export function useGetHackathonsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useLazyQuery(GetHackathonsDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(GetHackathonsDocument, options); + } export type GetHackathonsQueryHookResult = ReturnType; export type GetHackathonsLazyQueryHookResult = ReturnType; export type GetHackathonsQueryResult = Apollo.QueryResult; @@ -1196,13 +1196,13 @@ export const TrendingPostsDocument = gql` * }); */ export function useTrendingPostsQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useQuery(TrendingPostsDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(TrendingPostsDocument, options); + } export function useTrendingPostsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useLazyQuery(TrendingPostsDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(TrendingPostsDocument, options); + } export type TrendingPostsQueryHookResult = ReturnType; export type TrendingPostsLazyQueryHookResult = ReturnType; export type TrendingPostsQueryResult = Apollo.QueryResult; @@ -1245,13 +1245,13 @@ export const GetMyDraftsDocument = gql` * }); */ export function useGetMyDraftsQuery(baseOptions: Apollo.QueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useQuery(GetMyDraftsDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(GetMyDraftsDocument, options); + } export function useGetMyDraftsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useLazyQuery(GetMyDraftsDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(GetMyDraftsDocument, options); + } export type GetMyDraftsQueryHookResult = ReturnType; export type GetMyDraftsLazyQueryHookResult = ReturnType; export type GetMyDraftsQueryResult = Apollo.QueryResult; @@ -1293,9 +1293,9 @@ export type CreateStoryMutationFn = Apollo.MutationFunction) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useMutation(CreateStoryDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(CreateStoryDocument, options); + } export type CreateStoryMutationHookResult = ReturnType; export type CreateStoryMutationResult = Apollo.MutationResult; export type CreateStoryMutationOptions = Apollo.BaseMutationOptions; @@ -1326,9 +1326,9 @@ export type DeleteStoryMutationFn = Apollo.MutationFunction) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useMutation(DeleteStoryDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(DeleteStoryDocument, options); + } export type DeleteStoryMutationHookResult = ReturnType; export type DeleteStoryMutationResult = Apollo.MutationResult; export type DeleteStoryMutationOptions = Apollo.BaseMutationOptions; @@ -1358,13 +1358,13 @@ export const PopularTagsDocument = gql` * }); */ export function usePopularTagsQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useQuery(PopularTagsDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(PopularTagsDocument, options); + } export function usePopularTagsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useLazyQuery(PopularTagsDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(PopularTagsDocument, options); + } export type PopularTagsQueryHookResult = ReturnType; export type PopularTagsLazyQueryHookResult = ReturnType; export type PopularTagsQueryResult = Apollo.QueryResult; @@ -1455,13 +1455,13 @@ export const FeedDocument = gql` * }); */ export function useFeedQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useQuery(FeedDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(FeedDocument, options); + } export function useFeedLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useLazyQuery(FeedDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(FeedDocument, options); + } export type FeedQueryHookResult = ReturnType; export type FeedLazyQueryHookResult = ReturnType; export type FeedQueryResult = Apollo.QueryResult; @@ -1560,13 +1560,13 @@ export const PostDetailsDocument = gql` * }); */ export function usePostDetailsQuery(baseOptions: Apollo.QueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useQuery(PostDetailsDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(PostDetailsDocument, options); + } export function usePostDetailsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useLazyQuery(PostDetailsDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(PostDetailsDocument, options); + } export type PostDetailsQueryHookResult = ReturnType; export type PostDetailsLazyQueryHookResult = ReturnType; export type PostDetailsQueryResult = Apollo.QueryResult; @@ -1594,13 +1594,13 @@ export const MyProfileAboutDocument = gql` * }); */ export function useMyProfileAboutQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useQuery(MyProfileAboutDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(MyProfileAboutDocument, options); + } export function useMyProfileAboutLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useLazyQuery(MyProfileAboutDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(MyProfileAboutDocument, options); + } export type MyProfileAboutQueryHookResult = ReturnType; export type MyProfileAboutLazyQueryHookResult = ReturnType; export type MyProfileAboutQueryResult = Apollo.QueryResult; @@ -1631,9 +1631,9 @@ export type UpdateProfileAboutMutationFn = Apollo.MutationFunction) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useMutation(UpdateProfileAboutDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(UpdateProfileAboutDocument, options); + } export type UpdateProfileAboutMutationHookResult = ReturnType; export type UpdateProfileAboutMutationResult = Apollo.MutationResult; export type UpdateProfileAboutMutationOptions = Apollo.BaseMutationOptions; @@ -1667,13 +1667,13 @@ export const MyProfilePreferencesDocument = gql` * }); */ export function useMyProfilePreferencesQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useQuery(MyProfilePreferencesDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(MyProfilePreferencesDocument, options); + } export function useMyProfilePreferencesLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useLazyQuery(MyProfilePreferencesDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(MyProfilePreferencesDocument, options); + } export type MyProfilePreferencesQueryHookResult = ReturnType; export type MyProfilePreferencesLazyQueryHookResult = ReturnType; export type MyProfilePreferencesQueryResult = Apollo.QueryResult; @@ -1710,9 +1710,9 @@ export type UpdateUserPreferencesMutationFn = Apollo.MutationFunction) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useMutation(UpdateUserPreferencesDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(UpdateUserPreferencesDocument, options); + } export type UpdateUserPreferencesMutationHookResult = ReturnType; export type UpdateUserPreferencesMutationResult = Apollo.MutationResult; export type UpdateUserPreferencesMutationOptions = Apollo.BaseMutationOptions; @@ -1750,13 +1750,13 @@ export const MyProfileRolesSkillsDocument = gql` * }); */ export function useMyProfileRolesSkillsQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useQuery(MyProfileRolesSkillsDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(MyProfileRolesSkillsDocument, options); + } export function useMyProfileRolesSkillsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useLazyQuery(MyProfileRolesSkillsDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(MyProfileRolesSkillsDocument, options); + } export type MyProfileRolesSkillsQueryHookResult = ReturnType; export type MyProfileRolesSkillsLazyQueryHookResult = ReturnType; export type MyProfileRolesSkillsQueryResult = Apollo.QueryResult; @@ -1797,9 +1797,9 @@ export type UpdateUserRolesSkillsMutationFn = Apollo.MutationFunction) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useMutation(UpdateUserRolesSkillsDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(UpdateUserRolesSkillsDocument, options); + } export type UpdateUserRolesSkillsMutationHookResult = ReturnType; export type UpdateUserRolesSkillsMutationResult = Apollo.MutationResult; export type UpdateUserRolesSkillsMutationOptions = Apollo.BaseMutationOptions; @@ -1853,13 +1853,13 @@ ${UserRolesSkillsFragmentDoc}`; * }); */ export function useProfileQuery(baseOptions: Apollo.QueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useQuery(ProfileDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(ProfileDocument, options); + } export function useProfileLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useLazyQuery(ProfileDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(ProfileDocument, options); + } export type ProfileQueryHookResult = ReturnType; export type ProfileLazyQueryHookResult = ReturnType; export type ProfileQueryResult = Apollo.QueryResult; @@ -1901,13 +1901,13 @@ export const CategoryPageDocument = gql` * }); */ export function useCategoryPageQuery(baseOptions: Apollo.QueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useQuery(CategoryPageDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(CategoryPageDocument, options); + } export function useCategoryPageLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useLazyQuery(CategoryPageDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(CategoryPageDocument, options); + } export type CategoryPageQueryHookResult = ReturnType; export type CategoryPageLazyQueryHookResult = ReturnType; export type CategoryPageQueryResult = Apollo.QueryResult; @@ -1937,13 +1937,13 @@ export const AllCategoriesDocument = gql` * }); */ export function useAllCategoriesQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useQuery(AllCategoriesDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(AllCategoriesDocument, options); + } export function useAllCategoriesLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useLazyQuery(AllCategoriesDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(AllCategoriesDocument, options); + } export type AllCategoriesQueryHookResult = ReturnType; export type AllCategoriesLazyQueryHookResult = ReturnType; export type AllCategoriesQueryResult = Apollo.QueryResult; @@ -2002,13 +2002,13 @@ export const ExploreProjectsDocument = gql` * }); */ export function useExploreProjectsQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useQuery(ExploreProjectsDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(ExploreProjectsDocument, options); + } export function useExploreProjectsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useLazyQuery(ExploreProjectsDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(ExploreProjectsDocument, options); + } export type ExploreProjectsQueryHookResult = ReturnType; export type ExploreProjectsLazyQueryHookResult = ReturnType; export type ExploreProjectsQueryResult = Apollo.QueryResult; @@ -2043,13 +2043,13 @@ export const HottestProjectsDocument = gql` * }); */ export function useHottestProjectsQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useQuery(HottestProjectsDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(HottestProjectsDocument, options); + } export function useHottestProjectsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useLazyQuery(HottestProjectsDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(HottestProjectsDocument, options); + } export type HottestProjectsQueryHookResult = ReturnType; export type HottestProjectsLazyQueryHookResult = ReturnType; export type HottestProjectsQueryResult = Apollo.QueryResult; @@ -2101,13 +2101,13 @@ export const ProjectDetailsDocument = gql` * }); */ export function useProjectDetailsQuery(baseOptions: Apollo.QueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useQuery(ProjectDetailsDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(ProjectDetailsDocument, options); + } export function useProjectDetailsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useLazyQuery(ProjectDetailsDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(ProjectDetailsDocument, options); + } export type ProjectDetailsQueryHookResult = ReturnType; export type ProjectDetailsLazyQueryHookResult = ReturnType; export type ProjectDetailsQueryResult = Apollo.QueryResult; @@ -2172,13 +2172,13 @@ export const GetTournamentByIdDocument = gql` * }); */ export function useGetTournamentByIdQuery(baseOptions: Apollo.QueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useQuery(GetTournamentByIdDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(GetTournamentByIdDocument, options); + } export function useGetTournamentByIdLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useLazyQuery(GetTournamentByIdDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(GetTournamentByIdDocument, options); + } export type GetTournamentByIdQueryHookResult = ReturnType; export type GetTournamentByIdLazyQueryHookResult = ReturnType; export type GetTournamentByIdQueryResult = Apollo.QueryResult; @@ -2217,9 +2217,9 @@ export type VoteMutationFn = Apollo.MutationFunction) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useMutation(VoteDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(VoteDocument, options); + } export type VoteMutationHookResult = ReturnType; export type VoteMutationResult = Apollo.MutationResult; export type VoteMutationOptions = Apollo.BaseMutationOptions; @@ -2257,9 +2257,9 @@ export type ConfirmVoteMutationFn = Apollo.MutationFunction) { - const options = { ...defaultOptions, ...baseOptions } - return Apollo.useMutation(ConfirmVoteDocument, options); -} + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(ConfirmVoteDocument, options); + } export type ConfirmVoteMutationHookResult = ReturnType; export type ConfirmVoteMutationResult = Apollo.MutationResult; export type ConfirmVoteMutationOptions = Apollo.BaseMutationOptions; \ No newline at end of file From e6a19ecd6f21b89f0abdae9911fe4c4d74656592 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Thu, 1 Sep 2022 11:04:03 +0300 Subject: [PATCH 04/53] feat (overview-page): judges, faqs, counter --- src/Components/VoteButton/VoteButton.tsx | 6 +- .../ProjectPage/VoteButton/VoteButton.tsx | 6 +- .../OverviewPage/FAQsSection/FAQsSection.tsx | 21 ++++ .../JudgesSection/JudgesSection.tsx | 34 ++++++ .../pages/OverviewPage/OverviewPage.tsx | 45 ++----- .../PrizesSection/PrizesSection.tsx | 3 +- .../RegisterCard/RegisterCard.tsx | 60 +++++++++ src/mocks/data/tournament.ts | 115 +++++++++++++++++- src/mocks/data/users.ts | 14 +-- src/utils/helperFunctions.tsx | 2 +- src/utils/hooks/index.ts | 1 + src/utils/hooks/useCountdown.ts | 33 +++++ 12 files changed, 285 insertions(+), 55 deletions(-) create mode 100644 src/features/Tournaments/pages/OverviewPage/FAQsSection/FAQsSection.tsx create mode 100644 src/features/Tournaments/pages/OverviewPage/JudgesSection/JudgesSection.tsx create mode 100644 src/features/Tournaments/pages/OverviewPage/RegisterCard/RegisterCard.tsx create mode 100644 src/utils/hooks/useCountdown.ts diff --git a/src/Components/VoteButton/VoteButton.tsx b/src/Components/VoteButton/VoteButton.tsx index 7defb67..3b1abd6 100644 --- a/src/Components/VoteButton/VoteButton.tsx +++ b/src/Components/VoteButton/VoteButton.tsx @@ -18,7 +18,7 @@ interface Particle { offsetY: number, color: string animation: 'fly-spark-1' | 'fly-spark-2', - animationSpeed: 1 | 2 | 3, + animationSpeed: number, scale: number } @@ -108,11 +108,11 @@ export default function VoteButton({ id: (Math.random() + 1).toString(), offsetX: random(-10, 99), offsetY: random(10, 90), - animation: randomItem(styles.fly_spark_1, styles.fly_spark_1), + animation: randomItem(styles.fly_spark_1, styles.fly_spark_1) as any, animationSpeed: randomItem(1, 1.5, 2), color: `hsl(0deg 86% ${random(50, 63)}%)`, scale: random(1, 1.5) - })) + } as const)) // if on mobile screen, reduce number of sparks particles to 60% setSparks(oldSparks => [...oldSparks, ...newSparks]) diff --git a/src/features/Projects/pages/ProjectPage/VoteButton/VoteButton.tsx b/src/features/Projects/pages/ProjectPage/VoteButton/VoteButton.tsx index c73df42..5bb71dc 100644 --- a/src/features/Projects/pages/ProjectPage/VoteButton/VoteButton.tsx +++ b/src/features/Projects/pages/ProjectPage/VoteButton/VoteButton.tsx @@ -12,7 +12,7 @@ interface Particle { offsetX: number, color: '#ff6a00' | '#ff7717' | '#ff6217' | '#ff8217' | '#ff5717' animation: 'fly-spark-1' | 'fly-spark-2', - animationSpeed: 1 | 2 | 3, + animationSpeed: number, scale: number } @@ -40,11 +40,11 @@ export default function VoteButton({ onVote = () => { }, ...props }: Props) { const newSpark = { id: Math.random().toString(), offsetX: random(1, 99), - animation: randomItem(styles.fly_spark_1, styles.fly_spark_1), + animation: randomItem(styles.fly_spark_1, styles.fly_spark_1) as any, animationSpeed: randomItem(1, 1.5, 2), color: randomItem('#ff6a00', '#ff7717', '#ff6217', '#ff8217', '#ff5717'), scale: random(1.2, 2.2) - }; + } as const; // if on mobile screen, reduce number of sparks particles to 60% if (!isMobileScreen || Math.random() > .4) { diff --git a/src/features/Tournaments/pages/OverviewPage/FAQsSection/FAQsSection.tsx b/src/features/Tournaments/pages/OverviewPage/FAQsSection/FAQsSection.tsx new file mode 100644 index 0000000..2d45895 --- /dev/null +++ b/src/features/Tournaments/pages/OverviewPage/FAQsSection/FAQsSection.tsx @@ -0,0 +1,21 @@ +import React, { useMemo } from 'react' +import Accordion from 'src/Components/Accordion/Accordion'; +import { Tournament } from 'src/graphql' + +interface Props { + faqs: Tournament['faqs'] +} + + +export default function FAQsSection({ faqs }: Props) { + + + return ( +
+

FAQs

+ ({ heading: faq.question, content:

{faq.answer}

}))} + /> +
+ ) +} diff --git a/src/features/Tournaments/pages/OverviewPage/JudgesSection/JudgesSection.tsx b/src/features/Tournaments/pages/OverviewPage/JudgesSection/JudgesSection.tsx new file mode 100644 index 0000000..b510257 --- /dev/null +++ b/src/features/Tournaments/pages/OverviewPage/JudgesSection/JudgesSection.tsx @@ -0,0 +1,34 @@ +import React, { useMemo } from 'react' +import { Tournament } from 'src/graphql' + +interface Props { + judges: Tournament['judges'] +} + +const bgColors = ['#FDE68A', '#FECACA', '#BFDBFE', '#BBF7D0', '#DDD6FE', '#FBCFE8', '#FED7AA']; + +export default function JudgesSection({ judges }: Props) { + + const colors = useMemo(() => { + return judges.map((_, i) => bgColors[i % bgColors.length]) + }, [judges]) + + return ( +
+

Judges

+
+ {judges.map((judge, idx) =>
+ +
+

{judge.name}

+

{judge.jobTitle}

+
+
)} +
+
+ ) +} diff --git a/src/features/Tournaments/pages/OverviewPage/OverviewPage.tsx b/src/features/Tournaments/pages/OverviewPage/OverviewPage.tsx index ff79155..ec3196c 100644 --- a/src/features/Tournaments/pages/OverviewPage/OverviewPage.tsx +++ b/src/features/Tournaments/pages/OverviewPage/OverviewPage.tsx @@ -4,7 +4,10 @@ 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 FAQsSection from './FAQsSection/FAQsSection' +import JudgesSection from './JudgesSection/JudgesSection' import PrizesSection from './PrizesSection/PrizesSection' +import RegisterCard from './RegisterCard/RegisterCard' interface Props { data: Pick } @@ -21,47 +25,14 @@ export default function OverviewPage({ data }: Props) {
-

Tournament details

+

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 index 02262c6..541567c 100644 --- a/src/features/Tournaments/pages/OverviewPage/PrizesSection/PrizesSection.tsx +++ b/src/features/Tournaments/pages/OverviewPage/PrizesSection/PrizesSection.tsx @@ -9,8 +9,7 @@ interface Props { export default function PrizesSection({ prizes }: Props) { return (
- -

Prizes

+

Prizes

{prizes.map(prize =>
diff --git a/src/features/Tournaments/pages/OverviewPage/RegisterCard/RegisterCard.tsx b/src/features/Tournaments/pages/OverviewPage/RegisterCard/RegisterCard.tsx new file mode 100644 index 0000000..7777863 --- /dev/null +++ b/src/features/Tournaments/pages/OverviewPage/RegisterCard/RegisterCard.tsx @@ -0,0 +1,60 @@ +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 { useCountdown } from 'src/utils/hooks' + +interface Props { + start_date: string; + makers_count: number +} + +export default function RegisterCard({ makers_count, start_date }: Props) { + + const counter = useCountdown(start_date) + + return ( + +
+

+ + {makers_count} makers +

+ +
+
+ {counter.isExpired ? +

Tournament running!

+ : + <> +

+ Tournament starts in +

+
+
+ {counter.days}d +
+
+ {counter.hours}h +
+
+ {counter.minutes}m +
+
+ + } +
+
+

+ Sponsors +

+
+ + + + +
+
+
+ ) +} diff --git a/src/mocks/data/tournament.ts b/src/mocks/data/tournament.ts index 45e4fcd..b04a534 100644 --- a/src/mocks/data/tournament.ts +++ b/src/mocks/data/tournament.ts @@ -41,7 +41,118 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e makers_count: 668, projects_count: 21, events: [], - faqs: [], - judges: [], + judges: [ + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + ], + faqs: [ + { + question: "What is Shock the Web?", + answer: + `Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there. + +Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.` + }, + { + question: "When and where will it take place?", + answer: + `Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there. + +Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.` + }, + { + question: "What will we be doing?", + answer: + `Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there. + +Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.` + }, + { + question: "This is my first time hacking on lightning, will there be help?", + answer: + `Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there. + +Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.` + }, + { + question: "This is my first time hacking on lightning, will there be help?", + answer: + `Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there. + +Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.` + }, + { + question: "How many members can I have on my team?", + answer: + `Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there. + +Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.` + }, + { + question: "Who will choose the winners?", + answer: + `Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there. + +Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.` + }, + ], }] \ No newline at end of file diff --git a/src/mocks/data/users.ts b/src/mocks/data/users.ts index eade93e..0d3c720 100644 --- a/src/mocks/data/users.ts +++ b/src/mocks/data/users.ts @@ -1,5 +1,5 @@ import { Chance } from "chance"; -import { GenericMakerRole, MakerSkill, MyProfile, RoleLevelEnum, User } from "src/graphql"; +import { GenericMakerRole, MakerSkill, MyProfile, RoleLevelEnum, User, Tournament } from "src/graphql"; import { randomItem, randomItems } from "src/utils/helperFunctions"; import { posts } from "./posts"; import { getCoverImage, getAvatarImage } from "./utils"; @@ -135,9 +135,9 @@ export const user: User & MyProfile = { thumbnail_image: getCoverImage(), start_date: new Date(2021, 3).toISOString(), end_date: new Date(2021, 4).toISOString(), - tags: [], - website: "https://breez-conf.com" - }, + website: "https://breez-conf.com", + + } as Tournament, { id: 2, title: "Shock the Web 3", @@ -146,9 +146,9 @@ export const user: User & MyProfile = { thumbnail_image: getCoverImage(), start_date: new Date(2022, 7).toISOString(), end_date: new Date(2022, 11).toISOString(), - tags: [], - website: "https://shock-the-web.com" - }, + website: "https://shock-the-web.com", + + } as Tournament, ], similar_makers: [ { diff --git a/src/utils/helperFunctions.tsx b/src/utils/helperFunctions.tsx index f842ac8..23a2e9c 100644 --- a/src/utils/helperFunctions.tsx +++ b/src/utils/helperFunctions.tsx @@ -8,7 +8,7 @@ export function random(min: number, max: number) { return Math.random() * (max - min) + min; } -export function randomItem(...args: any[]) { +export function randomItem(...args: T[]): T { return args[Math.floor(Math.random() * args.length)]; } diff --git a/src/utils/hooks/index.ts b/src/utils/hooks/index.ts index 9d8e667..b1e9be8 100644 --- a/src/utils/hooks/index.ts +++ b/src/utils/hooks/index.ts @@ -12,4 +12,5 @@ export * from './useCurrentSection' export * from './usePreload' export * from './useCarousel' export * from './usePrompt' +export * from './useCountdown' diff --git a/src/utils/hooks/useCountdown.ts b/src/utils/hooks/useCountdown.ts new file mode 100644 index 0000000..f524901 --- /dev/null +++ b/src/utils/hooks/useCountdown.ts @@ -0,0 +1,33 @@ +import { useEffect, useState } from 'react'; + +const useCountdown = (targetDate: string | number | Date) => { + const countDownDate = new Date(targetDate).getTime(); + + const [countDown, setCountDown] = useState( + countDownDate - new Date().getTime() + ); + + useEffect(() => { + const interval = setInterval(() => { + setCountDown(countDownDate - new Date().getTime()); + }, 1000); + + return () => clearInterval(interval); + }, [countDownDate]); + + return getReturnValues(countDown); +}; + +const getReturnValues = (countDown: number) => { + // calculate time left + const days = Math.floor(countDown / (1000 * 60 * 60 * 24)); + const hours = Math.floor( + (countDown % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60) + ); + const minutes = Math.floor((countDown % (1000 * 60 * 60)) / (1000 * 60)); + const seconds = Math.floor((countDown % (1000 * 60)) / 1000); + + return { days, hours, minutes, seconds, isExpired: days + hours + minutes + seconds <= 0 }; +}; + +export { useCountdown }; \ No newline at end of file From 9b4031ea8f9d5457ba7949ea8569276ad14186f7 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Thu, 1 Sep 2022 12:06:26 +0300 Subject: [PATCH 05/53] events card --- package-lock.json | 380 ++++++++++++------ package.json | 1 + .../pages/EventsPage/EventCard/EventCard.tsx | 46 +++ .../pages/EventsPage/EventsPage.tsx | 22 + .../TournamentDetailsPage.tsx | 2 + src/mocks/data/tournament.ts | 72 +++- tailwind.config.js | 1 + 7 files changed, 395 insertions(+), 129 deletions(-) create mode 100644 src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx create mode 100644 src/features/Tournaments/pages/EventsPage/EventsPage.tsx diff --git a/package-lock.json b/package-lock.json index 9af5605..c56d075 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "@remirror/react": "^1.0.34", "@shopify/react-web-worker": "^5.0.1", "@szhsin/react-menu": "^3.0.2", + "@tailwindcss/line-clamp": "^0.4.0", "@testing-library/jest-dom": "^5.16.4", "@testing-library/react": "^13.1.1", "@testing-library/user-event": "^13.5.0", @@ -15306,6 +15307,14 @@ "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1" } }, + "node_modules/@tailwindcss/line-clamp": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.4.0.tgz", + "integrity": "sha512-HQZo6gfx1D0+DU3nWlNLD5iA6Ef4JAXh0LeD8lOGrJwEDBwwJNKQza6WoXhhY1uQrxOuU8ROxV7CqiQV4CoiLw==", + "peerDependencies": { + "tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1" + } + }, "node_modules/@testing-library/dom": { "version": "8.13.0", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.13.0.tgz", @@ -16386,7 +16395,7 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", - "dev": true + "devOptional": true }, "node_modules/@types/stack-utils": { "version": "2.0.1", @@ -16397,7 +16406,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.8.tgz", "integrity": "sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ==", - "dev": true + "devOptional": true }, "node_modules/@types/tern": { "version": "0.23.4", @@ -16434,7 +16443,7 @@ "version": "3.13.2", "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.2.tgz", "integrity": "sha512-/xFrPIo+4zOeNGtVMbf9rUm0N+i4pDf1ynExomqtokIJmVzR3962lJ1UE+MmexMkA0cmN9oTzg5Xcbwge0Ij2Q==", - "dev": true, + "devOptional": true, "dependencies": { "source-map": "^0.6.1" } @@ -16443,7 +16452,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -16462,7 +16471,7 @@ "version": "4.41.32", "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.32.tgz", "integrity": "sha512-cb+0ioil/7oz5//7tZUSwbrSAN/NWHrQylz5cW8G0dWTcF/g+/dSdMlKVZspBYuMAN1+WnwHrkxiRrLcwd0Heg==", - "dev": true, + "devOptional": true, "dependencies": { "@types/node": "*", "@types/tapable": "^1", @@ -16482,7 +16491,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-3.2.0.tgz", "integrity": "sha512-Ft7YH3lEVRQ6ls8k4Ff1oB4jN6oy/XmU6tQISKdhfh+1mR+viZFphS6WL0IrtDOzvefmJg5a0s7ZQoRXwqTEFg==", - "dev": true, + "devOptional": true, "dependencies": { "@types/node": "*", "@types/source-list-map": "*", @@ -16493,7 +16502,7 @@ "version": "0.7.3", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, + "devOptional": true, "engines": { "node": ">= 8" } @@ -16502,7 +16511,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -21543,7 +21552,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "devOptional": true }, "node_modules/cron-parser": { "version": "2.18.0", @@ -22760,7 +22769,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.3.1" } @@ -26563,7 +26572,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.7.0.tgz", "integrity": "sha512-8yYuvnyqIjlJ/WfebOyu2GSOQeFauRxnfuTveY9yvrDGs2g3kR9Nv4gu40AKvRHbXlSJwTbMJ6dVxAtEyKwVRA==", - "dev": true, + "devOptional": true, "engines": { "node": ">=10" }, @@ -37278,7 +37287,9 @@ "version": "1.19.2", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "extraneous": true, + "dev": true, + "optional": true, + "peer": true, "dependencies": { "@types/connect": "*", "@types/node": "*" @@ -37300,7 +37311,9 @@ "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "extraneous": true, + "dev": true, + "optional": true, + "peer": true, "dependencies": { "@types/node": "*" } @@ -37329,7 +37342,9 @@ "version": "4.17.13", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", - "extraneous": true, + "dev": true, + "optional": true, + "peer": true, "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.18", @@ -37341,7 +37356,9 @@ "version": "4.17.28", "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", - "extraneous": true, + "dev": true, + "optional": true, + "peer": true, "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -37440,7 +37457,9 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", - "extraneous": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/netlify-cli/node_modules/@types/minimatch": { "version": "3.0.5", @@ -37500,13 +37519,17 @@ "version": "6.9.7", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", - "extraneous": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/netlify-cli/node_modules/@types/range-parser": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", - "extraneous": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/netlify-cli/node_modules/@types/responselike": { "version": "1.0.0", @@ -37527,7 +37550,9 @@ "version": "1.13.10", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", - "extraneous": true, + "dev": true, + "optional": true, + "peer": true, "dependencies": { "@types/mime": "^1", "@types/node": "*" @@ -60890,7 +60915,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz", "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==", - "dev": true, + "devOptional": true, "bin": { "prettier": "bin-prettier.js" }, @@ -61694,7 +61719,7 @@ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz", "integrity": "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==", "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.4.x" } @@ -67976,7 +68001,7 @@ "version": "9.1.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", - "dev": true, + "devOptional": true, "dependencies": { "arg": "^4.1.0", "create-require": "^1.1.0", @@ -68002,7 +68027,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "devOptional": true }, "node_modules/ts-pnp": { "version": "1.2.0", @@ -69843,7 +69868,7 @@ "version": "2.25.1", "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.25.1.tgz", "integrity": "sha512-Koh0KyU/RPYwel/khxbsDz9ibDivmUbrRuKSSQvW42KSDdO4w23WI3SkHpSUKHE76LrFnnM/L7JCrpBwu8AXYw==", - "dev": true, + "devOptional": true, "dependencies": { "ansi-html-community": "0.0.8", "html-entities": "^2.1.0", @@ -69921,7 +69946,7 @@ "version": "0.4.4", "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.4.4.tgz", "integrity": "sha512-h9atBP/bsZohWpHnr+2sic8Iecb60GxftXsWNLLLSqewgIsGzByd2gcIID4nXcG+3tNe4GQG3dLcff3kXupdRA==", - "dev": true + "devOptional": true }, "node_modules/webpack/node_modules/eslint-scope": { "version": "5.1.1", @@ -70730,7 +70755,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, + "devOptional": true, "engines": { "node": ">=6" } @@ -70873,7 +70898,8 @@ "@apollographql/apollo-tools": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/@apollographql/apollo-tools/-/apollo-tools-0.5.3.tgz", - "integrity": "sha512-VcsXHfTFoCodDAgJZxN04GdFK1kqOhZQnQY/9Fa147P+I8xfvOSz5d+lKAPB+hwSgBNyd7ncAKGIs4+utbL+yA==" + "integrity": "sha512-VcsXHfTFoCodDAgJZxN04GdFK1kqOhZQnQY/9Fa147P+I8xfvOSz5d+lKAPB+hwSgBNyd7ncAKGIs4+utbL+yA==", + "requires": {} }, "@apollographql/graphql-playground-html": { "version": "1.6.29", @@ -72606,7 +72632,8 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/@envelop/disable-introspection/-/disable-introspection-3.3.1.tgz", "integrity": "sha512-THR8UnRQQB5nCLmITXvebwXwSHvFjS+ThA3RRVXpFX9EupMbTFN5a4NHty7+BYD798c3VrBZ/InbMlEWqw1c9g==", - "dev": true + "dev": true, + "requires": {} }, "@envelop/parser-cache": { "version": "4.3.1", @@ -72621,7 +72648,8 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/@envelop/types/-/types-2.2.0.tgz", "integrity": "sha512-Lghvfs0kh53G5mUKpCMlB/FhHh3O8SSR4hewB7JyE9hOEu/9h/6u+GHH/OEgdaRHky1Sae5Jf4grO+h21ka4ig==", - "dev": true + "dev": true, + "requires": {} }, "@envelop/validation-cache": { "version": "4.3.1", @@ -73259,7 +73287,8 @@ "version": "8.5.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", - "dev": true + "dev": true, + "requires": {} } } }, @@ -73287,7 +73316,8 @@ "@graphql-typed-document-node/core": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.1.1.tgz", - "integrity": "sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg==" + "integrity": "sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg==", + "requires": {} }, "@graphql-yoga/common": { "version": "2.3.0", @@ -73683,7 +73713,8 @@ "@hookform/resolvers": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-2.8.8.tgz", - "integrity": "sha512-meAEDur1IJBfKyTo9yPYAuzjIfrxA7m9Ov+1nxaW/YupsqMeseWifoUjWK03+hz/RJizsVQAaUjVxFEkyu0GWg==" + "integrity": "sha512-meAEDur1IJBfKyTo9yPYAuzjIfrxA7m9Ov+1nxaW/YupsqMeseWifoUjWK03+hz/RJizsVQAaUjVxFEkyu0GWg==", + "requires": {} }, "@humanwhocodes/config-array": { "version": "0.9.5", @@ -73709,7 +73740,8 @@ "@icons/material": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz", - "integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==" + "integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==", + "requires": {} }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", @@ -74366,7 +74398,8 @@ "version": "1.6.22", "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-1.6.22.tgz", "integrity": "sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg==", - "dev": true + "dev": true, + "requires": {} }, "@mdx-js/util": { "version": "1.6.22", @@ -74420,7 +74453,8 @@ "version": "0.9.0", "resolved": "https://registry.npmjs.org/@n1ru4l/graphql-live-query/-/graphql-live-query-0.9.0.tgz", "integrity": "sha512-BTpWy1e+FxN82RnLz4x1+JcEewVdfmUhV1C6/XYD5AjS7PQp9QFF7K8bCD6gzPTr2l+prvqOyVueQhFJxB1vfg==", - "dev": true + "dev": true, + "requires": {} }, "@noble/hashes": { "version": "0.5.9", @@ -75645,7 +75679,8 @@ "reakit-utils": { "version": "0.15.2", "resolved": "https://registry.npmjs.org/reakit-utils/-/reakit-utils-0.15.2.tgz", - "integrity": "sha512-i/RYkq+W6hvfFmXw5QW7zvfJJT/K8a4qZ0hjA79T61JAFPGt23DsfxwyBbyK91GZrJ9HMrXFVXWMovsKBc1qEQ==" + "integrity": "sha512-i/RYkq+W6hvfFmXw5QW7zvfJJT/K8a4qZ0hjA79T61JAFPGt23DsfxwyBbyK91GZrJ9HMrXFVXWMovsKBc1qEQ==", + "requires": {} }, "use-previous": { "version": "1.1.0", @@ -76253,7 +76288,8 @@ "@shopify/react-hooks": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@shopify/react-hooks/-/react-hooks-3.0.1.tgz", - "integrity": "sha512-RfTrJoEgDQ4TZhD1iT8Tg1u3Bjobo/ZceL9xgGssXjA8Qih1/VOgkdbnH3jKOkj1L2nDT4lfuo/DsTSFwLTQ9A==" + "integrity": "sha512-RfTrJoEgDQ4TZhD1iT8Tg1u3Bjobo/ZceL9xgGssXjA8Qih1/VOgkdbnH3jKOkj1L2nDT4lfuo/DsTSFwLTQ9A==", + "requires": {} }, "@shopify/react-web-worker": { "version": "5.0.1", @@ -79809,7 +79845,8 @@ "version": "8.5.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", - "dev": true + "dev": true, + "requires": {} }, "y18n": { "version": "4.0.3", @@ -82042,7 +82079,8 @@ "version": "14.1.1", "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.1.1.tgz", "integrity": "sha512-XrjH/iEUqNl9lF2HX9YhPNV7Amntkcnpw0Bo1KkRzowNDcgSN9i0nm4Q8Oi5wupgdfPaJNMAWa61A+voD6Kmwg==", - "dev": true + "dev": true, + "requires": {} } } }, @@ -82315,6 +82353,12 @@ "mini-svg-data-uri": "^1.2.3" } }, + "@tailwindcss/line-clamp": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.4.0.tgz", + "integrity": "sha512-HQZo6gfx1D0+DU3nWlNLD5iA6Ef4JAXh0LeD8lOGrJwEDBwwJNKQza6WoXhhY1uQrxOuU8ROxV7CqiQV4CoiLw==", + "requires": {} + }, "@testing-library/dom": { "version": "8.13.0", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.13.0.tgz", @@ -83325,7 +83369,7 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", - "dev": true + "devOptional": true }, "@types/stack-utils": { "version": "2.0.1", @@ -83336,7 +83380,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.8.tgz", "integrity": "sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ==", - "dev": true + "devOptional": true }, "@types/tern": { "version": "0.23.4", @@ -83373,7 +83417,7 @@ "version": "3.13.2", "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.2.tgz", "integrity": "sha512-/xFrPIo+4zOeNGtVMbf9rUm0N+i4pDf1ynExomqtokIJmVzR3962lJ1UE+MmexMkA0cmN9oTzg5Xcbwge0Ij2Q==", - "dev": true, + "devOptional": true, "requires": { "source-map": "^0.6.1" }, @@ -83382,7 +83426,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "devOptional": true } } }, @@ -83400,7 +83444,7 @@ "version": "4.41.32", "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.32.tgz", "integrity": "sha512-cb+0ioil/7oz5//7tZUSwbrSAN/NWHrQylz5cW8G0dWTcF/g+/dSdMlKVZspBYuMAN1+WnwHrkxiRrLcwd0Heg==", - "dev": true, + "devOptional": true, "requires": { "@types/node": "*", "@types/tapable": "^1", @@ -83414,7 +83458,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "devOptional": true } } }, @@ -83428,7 +83472,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-3.2.0.tgz", "integrity": "sha512-Ft7YH3lEVRQ6ls8k4Ff1oB4jN6oy/XmU6tQISKdhfh+1mR+viZFphS6WL0IrtDOzvefmJg5a0s7ZQoRXwqTEFg==", - "dev": true, + "devOptional": true, "requires": { "@types/node": "*", "@types/source-list-map": "*", @@ -83439,7 +83483,7 @@ "version": "0.7.3", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true + "devOptional": true } } }, @@ -83959,12 +84003,14 @@ "acorn-import-assertions": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==" + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "requires": {} }, "acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==" + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "requires": {} }, "acorn-node": { "version": "1.8.2", @@ -84075,7 +84121,8 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", - "dev": true + "dev": true, + "requires": {} }, "ajv-formats": { "version": "2.1.1", @@ -84106,7 +84153,8 @@ "ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "requires": {} }, "ansi-align": { "version": "3.0.1", @@ -84246,7 +84294,8 @@ "apollo-server-errors": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/apollo-server-errors/-/apollo-server-errors-3.3.1.tgz", - "integrity": "sha512-xnZJ5QWs6FixHICXHxUfm+ZWqqxrNuPlQ+kj5m6RtEgIpekOPssH/SD9gf2B4HuWV0QozorrygwZnux8POvyPA==" + "integrity": "sha512-xnZJ5QWs6FixHICXHxUfm+ZWqqxrNuPlQ+kj5m6RtEgIpekOPssH/SD9gf2B4HuWV0QozorrygwZnux8POvyPA==", + "requires": {} }, "apollo-server-express": { "version": "3.6.7", @@ -85011,7 +85060,8 @@ "babel-plugin-named-asset-import": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.8.tgz", - "integrity": "sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q==" + "integrity": "sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q==", + "requires": {} }, "babel-plugin-polyfill-corejs2": { "version": "0.3.1", @@ -87441,7 +87491,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "devOptional": true }, "cron-parser": { "version": "2.18.0", @@ -87547,7 +87597,8 @@ "css-declaration-sorter": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.2.2.tgz", - "integrity": "sha512-Ufadglr88ZLsrvS11gjeu/40Lw74D9Am/Jpr3LlYm5Q4ZP5KdlUhG+6u2EjyXeZcxmZ2h1ebCKngDjolpeLHpg==" + "integrity": "sha512-Ufadglr88ZLsrvS11gjeu/40Lw74D9Am/Jpr3LlYm5Q4ZP5KdlUhG+6u2EjyXeZcxmZ2h1ebCKngDjolpeLHpg==", + "requires": {} }, "css-has-pseudo": { "version": "3.0.4", @@ -87638,7 +87689,8 @@ "css-prefers-color-scheme": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz", - "integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==" + "integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==", + "requires": {} }, "css-select": { "version": "4.3.0", @@ -87757,7 +87809,8 @@ "cssnano-utils": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", - "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==" + "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", + "requires": {} }, "csso": { "version": "4.2.0", @@ -88371,7 +88424,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true + "devOptional": true }, "diff-sequences": { "version": "27.5.1", @@ -88755,7 +88808,8 @@ "emojibase-data": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/emojibase-data/-/emojibase-data-6.2.0.tgz", - "integrity": "sha512-SWKaXD2QeQs06IE7qfJftsI5924Dqzp+V9xaa5RzZIEWhmlrG6Jt2iKwfgOPHu+5S8MEtOI7GdpKsXj46chXOw==" + "integrity": "sha512-SWKaXD2QeQs06IE7qfJftsI5924Dqzp+V9xaa5RzZIEWhmlrG6Jt2iKwfgOPHu+5S8MEtOI7GdpKsXj46chXOw==", + "requires": {} }, "emojibase-regex": { "version": "6.0.1", @@ -89462,7 +89516,8 @@ "eslint-plugin-react-hooks": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.4.0.tgz", - "integrity": "sha512-U3RVIfdzJaeKDQKEJbz5p3NW8/L80PCATJAfuojwbaEL+gBjfGdhUcGde+WGUW46Q5sr/NgxevsIiDtNXrvZaQ==" + "integrity": "sha512-U3RVIfdzJaeKDQKEJbz5p3NW8/L80PCATJAfuojwbaEL+gBjfGdhUcGde+WGUW46Q5sr/NgxevsIiDtNXrvZaQ==", + "requires": {} }, "eslint-plugin-testing-library": { "version": "5.3.1", @@ -90841,7 +90896,8 @@ "fslightbox-react": { "version": "1.6.2-2", "resolved": "https://registry.npmjs.org/fslightbox-react/-/fslightbox-react-1.6.2-2.tgz", - "integrity": "sha512-7jpiU6AiQkauIhKhN9ko3UIZ9GY4SUO1AoMzOypUFnmfH0+UgPgPeShJFN+B70bZHhmFjjH7r7xjyPFSo4mzCQ==" + "integrity": "sha512-7jpiU6AiQkauIhKhN9ko3UIZ9GY4SUO1AoMzOypUFnmfH0+UgPgPeShJFN+B70bZHhmFjjH7r7xjyPFSo4mzCQ==", + "requires": {} }, "function-bind": { "version": "1.1.1", @@ -91284,7 +91340,8 @@ "version": "0.0.23", "resolved": "https://registry.npmjs.org/graphql-executor/-/graphql-executor-0.0.23.tgz", "integrity": "sha512-3Ivlyfjaw3BWmGtUSnMpP/a4dcXCp0mJtj0PiPG14OKUizaMKlSEX+LX2Qed0LrxwniIwvU6B4w/koVjEPyWJg==", - "dev": true + "dev": true, + "requires": {} }, "graphql-request": { "version": "4.2.0", @@ -91328,7 +91385,8 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.7.0.tgz", "integrity": "sha512-8yYuvnyqIjlJ/WfebOyu2GSOQeFauRxnfuTveY9yvrDGs2g3kR9Nv4gu40AKvRHbXlSJwTbMJ6dVxAtEyKwVRA==", - "dev": true + "devOptional": true, + "requires": {} }, "gzip-size": { "version": "6.0.0", @@ -91963,7 +92021,8 @@ "icss-utils": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==" + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "requires": {} }, "idb": { "version": "6.1.5", @@ -92792,7 +92851,8 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", - "dev": true + "dev": true, + "requires": {} }, "isomorphic.js": { "version": "0.2.5", @@ -93578,7 +93638,8 @@ "jest-pnp-resolver": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", - "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==" + "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", + "requires": {} }, "jest-regex-util": { "version": "27.5.1", @@ -94702,7 +94763,8 @@ "linkify-html": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/linkify-html/-/linkify-html-3.0.5.tgz", - "integrity": "sha512-3O7HEYjkugX+C/G2C2wyBmIt8Mt0pmeaHNIxRHodCFeQQeSxSoZHR+5hC1pi0WrmoEvfnSemyZyYTM8w3lo9cA==" + "integrity": "sha512-3O7HEYjkugX+C/G2C2wyBmIt8Mt0pmeaHNIxRHodCFeQQeSxSoZHR+5hC1pi0WrmoEvfnSemyZyYTM8w3lo9cA==", + "requires": {} }, "linkifyjs": { "version": "3.0.5", @@ -95560,7 +95622,8 @@ "version": "7.1.7", "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.1.7.tgz", "integrity": "sha512-VI3TyyHlGkO8uFle0IOibzpO1c1iJDcXcS/zBrQrXQQvJ2tpdwVzVZ7XdKsyRz1NdRmre4dqQkMZzUHaKIG/1w==", - "dev": true + "dev": true, + "requires": {} }, "marked": { "version": "4.0.14", @@ -95803,7 +95866,8 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/meros/-/meros-1.2.0.tgz", "integrity": "sha512-3QRZIS707pZQnijHdhbttXRWwrHhZJ/gzolneoxKVz9N/xmsvY/7Ls8lpnI9gxbgxjcHsAVEW3mgwiZCo6kkJQ==", - "dev": true + "dev": true, + "requires": {} }, "messageformat-parser": { "version": "4.1.3", @@ -99023,7 +99087,8 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", - "dev": true + "dev": true, + "requires": {} }, "@octokit/plugin-rest-endpoint-methods": { "version": "5.13.0", @@ -99196,7 +99261,9 @@ "version": "1.19.2", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "extraneous": true, + "dev": true, + "optional": true, + "peer": true, "requires": { "@types/connect": "*", "@types/node": "*" @@ -99218,7 +99285,9 @@ "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "extraneous": true, + "dev": true, + "optional": true, + "peer": true, "requires": { "@types/node": "*" } @@ -99244,9 +99313,12 @@ } }, "@types/express": { - "version": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", - "extraneous": true, + "dev": true, + "optional": true, + "peer": true, "requires": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.18", @@ -99258,7 +99330,9 @@ "version": "4.17.28", "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", - "extraneous": true, + "dev": true, + "optional": true, + "peer": true, "requires": { "@types/node": "*", "@types/qs": "*", @@ -99357,7 +99431,9 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", - "extraneous": true + "dev": true, + "optional": true, + "peer": true }, "@types/minimatch": { "version": "3.0.5", @@ -99416,13 +99492,17 @@ "version": "6.9.7", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", - "extraneous": true + "dev": true, + "optional": true, + "peer": true }, "@types/range-parser": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", - "extraneous": true + "dev": true, + "optional": true, + "peer": true }, "@types/responselike": { "version": "1.0.0", @@ -99443,7 +99523,9 @@ "version": "1.13.10", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", - "extraneous": true, + "dev": true, + "optional": true, + "peer": true, "requires": { "@types/mime": "^1", "@types/node": "*" @@ -99750,7 +99832,8 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "extraneous": true + "extraneous": true, + "requires": {} }, "acorn-walk": { "version": "8.2.0", @@ -103969,13 +104052,15 @@ "version": "8.5.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", - "extraneous": true + "extraneous": true, + "requires": {} }, "eslint-config-standard": { "version": "17.0.0-1", "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.0.0-1.tgz", "integrity": "sha512-aqRG58dqoBNfOLN+PsitasxmW+W9Os4oQrx081B16T4E4WogsSbpUL6hnKSnyv35sSRYA2XjBtKMOrUboL6jgw==", - "extraneous": true + "extraneous": true, + "requires": {} }, "eslint-formatter-codeframe": { "version": "7.32.1", @@ -104316,7 +104401,8 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.0.0.tgz", "integrity": "sha512-7GPezalm5Bfi/E22PnQxDWH2iW9GTvAlUNTztemeHb6c1BniSyoeTrM87JkC0wYdi6aQrZX9p2qEiAno8aTcbw==", - "extraneous": true + "extraneous": true, + "requires": {} }, "eslint-plugin-react": { "version": "7.29.4", @@ -114860,7 +114946,8 @@ "version": "7.5.6", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.6.tgz", "integrity": "sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==", - "extraneous": true + "extraneous": true, + "requires": {} }, "xdg-basedir": { "version": "4.0.0", @@ -116288,7 +116375,8 @@ "pg-pool": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.5.1.tgz", - "integrity": "sha512-6iCR0wVrro6OOHFsyavV+i6KYL4lVNyYAB9RD18w66xSzN+d8b66HiwuP30Gp1SH5O9T82fckkzsRjlrhD0ioQ==" + "integrity": "sha512-6iCR0wVrro6OOHFsyavV+i6KYL4lVNyYAB9RD18w66xSzN+d8b66HiwuP30Gp1SH5O9T82fckkzsRjlrhD0ioQ==", + "requires": {} }, "pg-protocol": { "version": "1.5.0", @@ -116532,7 +116620,8 @@ "postcss-browser-comments": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/postcss-browser-comments/-/postcss-browser-comments-4.0.0.tgz", - "integrity": "sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg==" + "integrity": "sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg==", + "requires": {} }, "postcss-calc": { "version": "8.2.4", @@ -116597,7 +116686,8 @@ "postcss-custom-media": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-8.0.0.tgz", - "integrity": "sha512-FvO2GzMUaTN0t1fBULDeIvxr5IvbDXcIatt6pnJghc736nqNgsGao5NT+5+WVLAQiTt6Cb3YUms0jiPaXhL//g==" + "integrity": "sha512-FvO2GzMUaTN0t1fBULDeIvxr5IvbDXcIatt6pnJghc736nqNgsGao5NT+5+WVLAQiTt6Cb3YUms0jiPaXhL//g==", + "requires": {} }, "postcss-custom-properties": { "version": "12.1.7", @@ -116626,22 +116716,26 @@ "postcss-discard-comments": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.1.tgz", - "integrity": "sha512-5JscyFmvkUxz/5/+TB3QTTT9Gi9jHkcn8dcmmuN68JQcv3aQg4y88yEHHhwFB52l/NkaJ43O0dbksGMAo49nfQ==" + "integrity": "sha512-5JscyFmvkUxz/5/+TB3QTTT9Gi9jHkcn8dcmmuN68JQcv3aQg4y88yEHHhwFB52l/NkaJ43O0dbksGMAo49nfQ==", + "requires": {} }, "postcss-discard-duplicates": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", - "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==" + "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", + "requires": {} }, "postcss-discard-empty": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", - "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==" + "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", + "requires": {} }, "postcss-discard-overridden": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", - "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==" + "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", + "requires": {} }, "postcss-double-position-gradients": { "version": "3.1.1", @@ -116663,7 +116757,8 @@ "postcss-flexbugs-fixes": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz", - "integrity": "sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==" + "integrity": "sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==", + "requires": {} }, "postcss-focus-visible": { "version": "6.0.4", @@ -116684,12 +116779,14 @@ "postcss-font-variant": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", - "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==" + "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", + "requires": {} }, "postcss-gap-properties": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.3.tgz", - "integrity": "sha512-rPPZRLPmEKgLk/KlXMqRaNkYTUpE7YC+bOIQFN5xcu1Vp11Y4faIXv6/Jpft6FMnl6YRxZqDZG0qQOW80stzxQ==" + "integrity": "sha512-rPPZRLPmEKgLk/KlXMqRaNkYTUpE7YC+bOIQFN5xcu1Vp11Y4faIXv6/Jpft6FMnl6YRxZqDZG0qQOW80stzxQ==", + "requires": {} }, "postcss-image-set-function": { "version": "4.0.6", @@ -116702,7 +116799,8 @@ "postcss-initial": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", - "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==" + "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==", + "requires": {} }, "postcss-js": { "version": "4.0.0", @@ -116743,12 +116841,14 @@ "postcss-logical": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.4.tgz", - "integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==" + "integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==", + "requires": {} }, "postcss-media-minmax": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz", - "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==" + "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==", + "requires": {} }, "postcss-merge-longhand": { "version": "5.1.4", @@ -116809,7 +116909,8 @@ "postcss-modules-extract-imports": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==" + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "requires": {} }, "postcss-modules-local-by-default": { "version": "4.0.0", @@ -116866,7 +116967,8 @@ "postcss-normalize-charset": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", - "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==" + "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", + "requires": {} }, "postcss-normalize-display-values": { "version": "5.1.0", @@ -116951,12 +117053,14 @@ "postcss-overflow-shorthand": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.3.tgz", - "integrity": "sha512-CxZwoWup9KXzQeeIxtgOciQ00tDtnylYIlJBBODqkgS/PU2jISuWOL/mYLHmZb9ZhZiCaNKsCRiLp22dZUtNsg==" + "integrity": "sha512-CxZwoWup9KXzQeeIxtgOciQ00tDtnylYIlJBBODqkgS/PU2jISuWOL/mYLHmZb9ZhZiCaNKsCRiLp22dZUtNsg==", + "requires": {} }, "postcss-page-break": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", - "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==" + "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", + "requires": {} }, "postcss-place": { "version": "7.0.4", @@ -117044,7 +117148,8 @@ "postcss-replace-overflow-wrap": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", - "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==" + "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", + "requires": {} }, "postcss-selector-not": { "version": "5.0.0", @@ -117287,7 +117392,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz", "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==", - "dev": true + "devOptional": true }, "pretty-bytes": { "version": "5.6.0", @@ -117887,7 +117992,8 @@ "qrcode.react": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-3.0.2.tgz", - "integrity": "sha512-8F3SGxSkNb3fMIHdlseqjFjLbsPrF3WvF/1MOboSUUHytT537W8f/FtbdA3XFIHDrc+TrRBjTI/QLmwhAIGWWw==" + "integrity": "sha512-8F3SGxSkNb3fMIHdlseqjFjLbsPrF3WvF/1MOboSUUHytT537W8f/FtbdA3XFIHDrc+TrRBjTI/QLmwhAIGWWw==", + "requires": {} }, "qs": { "version": "6.10.3", @@ -117901,7 +118007,7 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz", "integrity": "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==", - "dev": true + "devOptional": true }, "querystring-es3": { "version": "0.2.1", @@ -118031,7 +118137,8 @@ "react-accessible-accordion": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/react-accessible-accordion/-/react-accessible-accordion-5.0.0.tgz", - "integrity": "sha512-MT2obYpTgLIIfPr9d7hEyvPB5rg8uJcHpgA83JSRlEUHvzH48+8HJPvzSs+nM+XprTugDgLfhozO5qyJpBvYRQ==" + "integrity": "sha512-MT2obYpTgLIIfPr9d7hEyvPB5rg8uJcHpgA83JSRlEUHvzH48+8HJPvzSs+nM+XprTugDgLfhozO5qyJpBvYRQ==", + "requires": {} }, "react-app-polyfill": { "version": "3.0.0", @@ -118064,7 +118171,8 @@ "version": "5.5.1", "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.5.1.tgz", "integrity": "sha512-M1TJH2X3RXEt12sWkpa6hLc/bbYS0H6F4rIqjQZ+RxNBstpY67d9TrFXtqdZwhpmBXcCwEi7stKqFue3ZRkiOg==", - "dev": true + "dev": true, + "requires": {} }, "react-confetti": { "version": "6.0.1", @@ -118212,7 +118320,8 @@ "version": "2.2.2", "resolved": "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-2.2.2.tgz", "integrity": "sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg==", - "dev": true + "dev": true, + "requires": {} }, "react-dom": { "version": "18.1.0", @@ -118284,7 +118393,8 @@ "react-side-effect": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.1.tgz", - "integrity": "sha512-2FoTQzRNTncBVtnzxFOk2mCpcfxQpenBMbk5kSVBg5UcPqV9fRbgY2zhb7GTWWOlpFmAxhClBDlIq8Rsubz1yQ==" + "integrity": "sha512-2FoTQzRNTncBVtnzxFOk2mCpcfxQpenBMbk5kSVBg5UcPqV9fRbgY2zhb7GTWWOlpFmAxhClBDlIq8Rsubz1yQ==", + "requires": {} } } }, @@ -118304,12 +118414,14 @@ "react-hook-form": { "version": "7.30.0", "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.30.0.tgz", - "integrity": "sha512-DzjiM6o2vtDGNMB9I4yCqW8J21P314SboNG1O0obROkbg7KVS0I7bMtwSdKyapnCPjHgnxc3L7E5PEdISeEUcQ==" + "integrity": "sha512-DzjiM6o2vtDGNMB9I4yCqW8J21P314SboNG1O0obROkbg7KVS0I7bMtwSdKyapnCPjHgnxc3L7E5PEdISeEUcQ==", + "requires": {} }, "react-icons": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.3.1.tgz", - "integrity": "sha512-cB10MXLTs3gVuXimblAdI71jrJx8njrJZmNMEMC+sQu5B/BIOmlsAjskdqpn81y8UBVEGuHODd7/ci5DvoSzTQ==" + "integrity": "sha512-cB10MXLTs3gVuXimblAdI71jrJx8njrJZmNMEMC+sQu5B/BIOmlsAjskdqpn81y8UBVEGuHODd7/ci5DvoSzTQ==", + "requires": {} }, "react-inspector": { "version": "5.1.1", @@ -118347,7 +118459,8 @@ "react-loading-skeleton": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/react-loading-skeleton/-/react-loading-skeleton-3.1.0.tgz", - "integrity": "sha512-j1U1CWWs68nBPOg7tkQqnlFcAMFF6oEK6MgqAo15f8A5p7mjH6xyKn2gHbkcimpwfO0VQXqxAswnSYVr8lWzjw==" + "integrity": "sha512-j1U1CWWs68nBPOg7tkQqnlFcAMFF6oEK6MgqAo15f8A5p7mjH6xyKn2gHbkcimpwfO0VQXqxAswnSYVr8lWzjw==", + "requires": {} }, "react-modal": { "version": "3.15.1", @@ -118363,7 +118476,8 @@ "react-onclickoutside": { "version": "6.12.1", "resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.12.1.tgz", - "integrity": "sha512-a5Q7CkWznBRUWPmocCvE8b6lEYw1s6+opp/60dCunhO+G6E4tDTO2Sd2jKE+leEnnrLAE2Wj5DlDHNqj5wPv1Q==" + "integrity": "sha512-a5Q7CkWznBRUWPmocCvE8b6lEYw1s6+opp/60dCunhO+G6E4tDTO2Sd2jKE+leEnnrLAE2Wj5DlDHNqj5wPv1Q==", + "requires": {} }, "react-popper": { "version": "2.2.5", @@ -118632,12 +118746,14 @@ "react-transition-state": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/react-transition-state/-/react-transition-state-1.1.4.tgz", - "integrity": "sha512-6nQLWWx95gYazCm6OdtD1zGbRiirvVXPrDtHAGsYb4xs9spMM7bA8Vx77KCpjL8PJ8qz1lXFGz2PTboCSvt7iw==" + "integrity": "sha512-6nQLWWx95gYazCm6OdtD1zGbRiirvVXPrDtHAGsYb4xs9spMM7bA8Vx77KCpjL8PJ8qz1lXFGz2PTboCSvt7iw==", + "requires": {} }, "react-universal-interface": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/react-universal-interface/-/react-universal-interface-0.6.2.tgz", - "integrity": "sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==" + "integrity": "sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==", + "requires": {} }, "reactcss": { "version": "1.2.3", @@ -118821,7 +118937,8 @@ "redux-thunk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz", - "integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==" + "integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==", + "requires": {} }, "refractor": { "version": "3.6.0", @@ -121949,7 +122066,8 @@ "style-loader": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", - "integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==" + "integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==", + "requires": {} }, "style-to-object": { "version": "0.3.0", @@ -122780,7 +122898,7 @@ "version": "9.1.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", - "dev": true, + "devOptional": true, "requires": { "arg": "^4.1.0", "create-require": "^1.1.0", @@ -122794,7 +122912,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "devOptional": true } } }, @@ -123472,12 +123590,14 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.2.1.tgz", "integrity": "sha512-6+X1FLlIcjvFMAeAD/hcxDT8tmyrWnbSPMU0EnxQuDLIxokuFzWliXBiYZuGIx+mrAMLBw0WFfCkaPw8ebzAhw==", - "dev": true + "dev": true, + "requires": {} }, "use-isomorphic-layout-effect": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz", - "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==" + "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==", + "requires": {} }, "use-latest": { "version": "1.2.0", @@ -123491,7 +123611,8 @@ "use-sync-external-store": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.0.0.tgz", - "integrity": "sha512-AFVsxg5GkFg8GDcxnl+Z0lMAz9rE8DGJCc28qnBuQF7lac57B5smLcT37aXpXIIPz75rW4g3eXHPjhHwdGskOw==" + "integrity": "sha512-AFVsxg5GkFg8GDcxnl+Z0lMAz9rE8DGJCc28qnBuQF7lac57B5smLcT37aXpXIIPz75rW4g3eXHPjhHwdGskOw==", + "requires": {} }, "utf-8-validate": { "version": "5.0.9", @@ -124212,7 +124333,8 @@ "ws": { "version": "8.5.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==" + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "requires": {} } } }, @@ -124220,13 +124342,14 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/webpack-filter-warnings-plugin/-/webpack-filter-warnings-plugin-1.2.1.tgz", "integrity": "sha512-Ez6ytc9IseDMLPo0qCuNNYzgtUl8NovOqjIq4uAU8LTD4uoa1w1KpZyyzFtLTEMZpkkOkLfL9eN+KGYdk1Qtwg==", - "dev": true + "dev": true, + "requires": {} }, "webpack-hot-middleware": { "version": "2.25.1", "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.25.1.tgz", "integrity": "sha512-Koh0KyU/RPYwel/khxbsDz9ibDivmUbrRuKSSQvW42KSDdO4w23WI3SkHpSUKHE76LrFnnM/L7JCrpBwu8AXYw==", - "dev": true, + "devOptional": true, "requires": { "ansi-html-community": "0.0.8", "html-entities": "^2.1.0", @@ -124286,7 +124409,7 @@ "version": "0.4.4", "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.4.4.tgz", "integrity": "sha512-h9atBP/bsZohWpHnr+2sic8Iecb60GxftXsWNLLLSqewgIsGzByd2gcIID4nXcG+3tNe4GQG3dLcff3kXupdRA==", - "dev": true + "devOptional": true }, "websocket": { "version": "1.0.34", @@ -124792,7 +124915,8 @@ "ws": { "version": "7.5.7", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", - "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==" + "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", + "requires": {} }, "xdg-basedir": { "version": "4.0.0", @@ -124940,7 +125064,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true + "devOptional": true }, "yocto-queue": { "version": "0.1.0", diff --git a/package.json b/package.json index 6e12909..f22b832 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "@remirror/react": "^1.0.34", "@shopify/react-web-worker": "^5.0.1", "@szhsin/react-menu": "^3.0.2", + "@tailwindcss/line-clamp": "^0.4.0", "@testing-library/jest-dom": "^5.16.4", "@testing-library/react": "^13.1.1", "@testing-library/user-event": "^13.5.0", diff --git a/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx b/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx new file mode 100644 index 0000000..54c478f --- /dev/null +++ b/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx @@ -0,0 +1,46 @@ +import { IoLocationOutline } from 'react-icons/io5' +import Button from "src/Components/Button/Button" +import dayjs from "dayjs"; +import advancedFormat from 'dayjs/plugin/advancedFormat' +import { trimText } from "src/utils/helperFunctions"; +import { Override } from "src/utils/interfaces"; +import { Tag, Tournament } from "src/graphql"; +dayjs.extend(advancedFormat) + + +interface Props { + event: Pick +} + +export default function EventCard({ event }: Props) { + return ( +
+ +
+
+

+ {event.title} +

+

+ {event.date} +

+

+ {event.location} +

+

+ {trimText(event.description, 90)} +

+
+
+
+ ) +} diff --git a/src/features/Tournaments/pages/EventsPage/EventsPage.tsx b/src/features/Tournaments/pages/EventsPage/EventsPage.tsx new file mode 100644 index 0000000..8fdcb06 --- /dev/null +++ b/src/features/Tournaments/pages/EventsPage/EventsPage.tsx @@ -0,0 +1,22 @@ +import React from 'react' +import { Tournament } from 'src/graphql' +import EventCard from './EventCard/EventCard'; + +interface Props { + data: Pick +} + +export default function EventsPage({ data: { events, events_count } }: Props) { + return ( +
+

Events 📆 ({events_count})

+
+ { + events.map(event => ) + } +
+
+ ) +} diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx index 26e0234..04c1c75 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx +++ b/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx @@ -7,6 +7,7 @@ import { Navigate, Route, Routes } from 'react-router-dom' import OverviewPage from '../OverviewPage/OverviewPage' import { Helmet } from 'react-helmet' import Navigation from './Navigation/Navigation' +import EventsPage from '../EventsPage/EventsPage' export default function TournamentDetailsPage() { @@ -36,6 +37,7 @@ export default function TournamentDetailsPage() { } /> } /> + } />
diff --git a/src/mocks/data/tournament.ts b/src/mocks/data/tournament.ts index b04a534..c735487 100644 --- a/src/mocks/data/tournament.ts +++ b/src/mocks/data/tournament.ts @@ -1,4 +1,5 @@ import { Tournament } from "src/graphql"; +import { getCoverImage } from "./utils"; export const tournaments: Tournament[] = [{ __typename: "Tournament", @@ -40,7 +41,76 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e events_count: 28, makers_count: 668, projects_count: 21, - events: [], + events: [ + { + id: 12, + title: "STW3 Round Table #1", + date: "13:00 - 14:00 UTC, 23rd June", + description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", + image: getCoverImage(), + links: [], + location: "Online", + type: "🐦 Twitter space", + website: "https://event.name" + }, + { + id: 13, + title: "STW3 Round Table #2", + date: "15:00 - 16:00 UTC, 23rd June", + description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", + image: getCoverImage(), + links: [], + location: "Online", + type: "🛠 Workshop", + website: "https://event.name" + }, + { + id: 14, + title: "STW3 Round Table #3", + date: "13:00 - 14:00 UTC, 24rd June", + description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", + image: getCoverImage(), + links: [], + location: "Online", + type: "🤝 IRL meetup", + website: "https://event.name" + }, + { + id: 44, + title: "Lightning Login", + date: "15:00 - 16:00 UTC, 24rd June", + description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", + image: getCoverImage(), + links: [], + location: "Online", + type: "🛠 Workshop", + website: "https://event.name" + }, + + { + id: 46, + title: "Escrow contracts", + date: "15:00 - 16:00 UTC, 23rd June", + description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", + image: getCoverImage(), + links: [], + location: "Online", + type: "🛠 Workshop", + website: "https://event.name" + }, + + { + id: 444, + title: "Lsats - What & Why", + date: "15:00 - 16:00 UTC, 23rd June", + description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", + image: getCoverImage(), + links: [], + location: "Online", + type: "🛠 Workshop", + website: "https://event.name" + }, + ], judges: [ { name: "Ben Arc", diff --git a/tailwind.config.js b/tailwind.config.js index 094c3c8..71ca766 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -99,5 +99,6 @@ module.exports = { }, plugins: [ require('@tailwindcss/forms'), + require('@tailwindcss/line-clamp'), ], } From b512b1980450a5fe3dce9e16799c0961bc21f2db Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Thu, 1 Sep 2022 13:26:44 +0300 Subject: [PATCH 06/53] feat: event card, event modal --- api/functions/graphql/nexus-typegen.ts | 7 ++- api/functions/graphql/schema.graphql | 8 ++- api/functions/graphql/types/tournament.js | 15 ++++- .../pages/EventsPage/EventCard/EventCard.tsx | 45 +++++++++++-- .../EventsPage/EventModal/EventModal.tsx | 63 +++++++++++++++++++ .../pages/EventsPage/EventModal/index.tsx | 6 ++ .../pages/EventsPage/EventsPage.tsx | 2 +- .../Navigation/Navigation.tsx | 2 +- src/graphql/index.tsx | 10 ++- src/mocks/data/tournament.ts | 14 ++--- src/redux/features/modals.slice.ts | 10 ++- 11 files changed, 159 insertions(+), 23 deletions(-) create mode 100644 src/features/Tournaments/pages/EventsPage/EventModal/EventModal.tsx create mode 100644 src/features/Tournaments/pages/EventsPage/EventModal/index.tsx diff --git a/api/functions/graphql/nexus-typegen.ts b/api/functions/graphql/nexus-typegen.ts index b5d78da..44f453f 100644 --- a/api/functions/graphql/nexus-typegen.ts +++ b/api/functions/graphql/nexus-typegen.ts @@ -69,6 +69,7 @@ export interface NexusGenInputs { export interface NexusGenEnums { POST_TYPE: "Bounty" | "Question" | "Story" RoleLevelEnum: 3 | 0 | 1 | 2 | 4 + TournamentEventTypeEnum: 2 | 0 | 1 VOTE_ITEM_TYPE: "Bounty" | "PostComment" | "Project" | "Question" | "Story" | "User" } @@ -261,7 +262,7 @@ export interface NexusGenObjects { links: string[]; // [String!]! location: string; // String! title: string; // String! - type: string; // String! + type: NexusGenEnums['TournamentEventTypeEnum']; // TournamentEventTypeEnum! website: string; // String! } TournamentFAQ: { // root type @@ -562,7 +563,7 @@ export interface NexusGenFieldTypes { links: string[]; // [String!]! location: string; // String! title: string; // String! - type: string; // String! + type: NexusGenEnums['TournamentEventTypeEnum']; // TournamentEventTypeEnum! website: string; // String! } TournamentFAQ: { // field return type @@ -886,7 +887,7 @@ export interface NexusGenFieldTypeNames { links: 'String' location: 'String' title: 'String' - type: 'String' + type: 'TournamentEventTypeEnum' website: 'String' } TournamentFAQ: { // field return type name diff --git a/api/functions/graphql/schema.graphql b/api/functions/graphql/schema.graphql index 0a8c099..2944fcc 100644 --- a/api/functions/graphql/schema.graphql +++ b/api/functions/graphql/schema.graphql @@ -351,10 +351,16 @@ type TournamentEvent { links: [String!]! location: String! title: String! - type: String! + type: TournamentEventTypeEnum! website: String! } +enum TournamentEventTypeEnum { + IRLMeetup + TwitterSpace + Workshop +} + type TournamentFAQ { answer: String! question: String! diff --git a/api/functions/graphql/types/tournament.js b/api/functions/graphql/types/tournament.js index c60de12..6952ff8 100644 --- a/api/functions/graphql/types/tournament.js +++ b/api/functions/graphql/types/tournament.js @@ -4,6 +4,7 @@ const { stringArg, extendType, nonNull, + enumType, } = require('nexus'); const { prisma } = require('../../../prisma'); @@ -35,6 +36,18 @@ const TournamentFAQ = objectType({ } }) + + +const TournamentEventTypeEnum = enumType({ + name: 'TournamentEventTypeEnum', + members: { + TwitterSpace: 0, + Workshop: 1, + IRLMeetup: 2, + }, +}); + + const TournamentEvent = objectType({ name: 'TournamentEvent', definition(t) { @@ -45,7 +58,7 @@ const TournamentEvent = objectType({ t.nonNull.date('date'); t.nonNull.string('location'); t.nonNull.string('website'); - t.nonNull.string('type'); + t.nonNull.field('type', { type: TournamentEventTypeEnum }) t.nonNull.list.nonNull.string('links'); } }) diff --git a/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx b/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx index 54c478f..07f74de 100644 --- a/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx +++ b/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx @@ -4,8 +4,10 @@ import dayjs from "dayjs"; import advancedFormat from 'dayjs/plugin/advancedFormat' import { trimText } from "src/utils/helperFunctions"; import { Override } from "src/utils/interfaces"; -import { Tag, Tournament } from "src/graphql"; -dayjs.extend(advancedFormat) +import { Tag, Tournament, TournamentEventTypeEnum } from "src/graphql"; +import { UnionToObjectKeys } from 'src/utils/types/utils'; +import { useAppDispatch, } from "src/utils/hooks"; +import { openModal } from "src/redux/features/modals.slice"; interface Props { @@ -22,8 +24,25 @@ interface Props { } export default function EventCard({ event }: Props) { + + const dispatch = useAppDispatch() + + const openEventModal = () => { + dispatch(openModal({ + Modal: "EventModal", + isPageModal: true, + props: { + event + } + })) + } + return ( -
+
@@ -34,13 +53,31 @@ export default function EventCard({ event }: Props) { {event.date}

- {event.location} + {event.location}

{trimText(event.description, 90)}

+ + {mapTypeToBadge[event.type].text} +
) } + +export const mapTypeToBadge: UnionToObjectKeys = { + [TournamentEventTypeEnum.TwitterSpace]: { + text: "🐦 Twitter space", + color: "bg-blue-50 text-blue-500" + }, + [TournamentEventTypeEnum.Workshop]: { + text: "🛠️ Workshop", + color: "bg-green-50 text-green-500" + }, + [TournamentEventTypeEnum.IrlMeetup]: { + text: "🤝 IRL meetup", + color: "bg-red-50 text-red-500" + }, +} diff --git a/src/features/Tournaments/pages/EventsPage/EventModal/EventModal.tsx b/src/features/Tournaments/pages/EventsPage/EventModal/EventModal.tsx new file mode 100644 index 0000000..0151bf8 --- /dev/null +++ b/src/features/Tournaments/pages/EventsPage/EventModal/EventModal.tsx @@ -0,0 +1,63 @@ + +import { MdClose, } from 'react-icons/md'; +import { ModalCard } from 'src/Components/Modals/ModalsContainer/ModalsContainer'; +import { useMediaQuery } from 'src/utils/hooks'; +import { Tournament, } from 'src/graphql'; +import { MEDIA_QUERIES } from 'src/utils/theme'; +import { IoGlobe, IoLocationOutline } from 'react-icons/io5'; +import { mapTypeToBadge } from '../EventCard/EventCard'; + + +interface Props extends ModalCard { + event: Pick +} + +export default function ProjectDetailsCard({ direction, event, ...props }: Props) { + + const closeModal = () => { + props.onClose?.(); + } + + + const isMdScreen = useMediaQuery(MEDIA_QUERIES.isMedium) + + return ( +
+
+ + + + {mapTypeToBadge[event.type].text} + +
+
+

{event.title}

+

+ {event.date} +

+
+

+ {event.location} +

+

+ + {event.website} +

+
+

+ {event.description} +

+
+
+ ) +} diff --git a/src/features/Tournaments/pages/EventsPage/EventModal/index.tsx b/src/features/Tournaments/pages/EventsPage/EventModal/index.tsx new file mode 100644 index 0000000..26ef497 --- /dev/null +++ b/src/features/Tournaments/pages/EventsPage/EventModal/index.tsx @@ -0,0 +1,6 @@ + +import { lazyModal } from 'src/utils/helperFunctions'; + + + +export const { LazyComponent: EventModal, preload: projectDetailsCardPreload } = lazyModal(() => import('./EventModal')) diff --git a/src/features/Tournaments/pages/EventsPage/EventsPage.tsx b/src/features/Tournaments/pages/EventsPage/EventsPage.tsx index 8fdcb06..36b7cec 100644 --- a/src/features/Tournaments/pages/EventsPage/EventsPage.tsx +++ b/src/features/Tournaments/pages/EventsPage/EventsPage.tsx @@ -10,7 +10,7 @@ interface Props { export default function EventsPage({ data: { events, events_count } }: Props) { return ( -
+

Events 📆 ({events_count})

{ diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx index a359a78..97c1757 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx +++ b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx @@ -42,7 +42,7 @@ export default function Navigation({ data }: Props) { ], [data.events_count, data.makers_count, data.projects_count]) return ( -
+
diff --git a/src/graphql/index.tsx b/src/graphql/index.tsx index 7a8f40c..0870f54 100644 --- a/src/graphql/index.tsx +++ b/src/graphql/index.tsx @@ -521,10 +521,16 @@ export type TournamentEvent = { links: Array; location: Scalars['String']; title: Scalars['String']; - type: Scalars['String']; + type: TournamentEventTypeEnum; website: Scalars['String']; }; +export enum TournamentEventTypeEnum { + IrlMeetup = 'IRLMeetup', + TwitterSpace = 'TwitterSpace', + Workshop = 'Workshop' +} + export type TournamentFaq = { __typename?: 'TournamentFAQ'; answer: Scalars['String']; @@ -787,7 +793,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, 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 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: TournamentEventTypeEnum, links: Array }>, faqs: Array<{ __typename?: 'TournamentFAQ', question: string, answer: string }> } }; export type VoteMutationVariables = Exact<{ itemType: Vote_Item_Type; diff --git a/src/mocks/data/tournament.ts b/src/mocks/data/tournament.ts index c735487..e96172d 100644 --- a/src/mocks/data/tournament.ts +++ b/src/mocks/data/tournament.ts @@ -1,4 +1,4 @@ -import { Tournament } from "src/graphql"; +import { Tournament, TournamentEventTypeEnum } from "src/graphql"; import { getCoverImage } from "./utils"; export const tournaments: Tournament[] = [{ @@ -50,7 +50,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e image: getCoverImage(), links: [], location: "Online", - type: "🐦 Twitter space", + type: TournamentEventTypeEnum.TwitterSpace, website: "https://event.name" }, { @@ -61,7 +61,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e image: getCoverImage(), links: [], location: "Online", - type: "🛠 Workshop", + type: TournamentEventTypeEnum.Workshop, website: "https://event.name" }, { @@ -72,7 +72,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e image: getCoverImage(), links: [], location: "Online", - type: "🤝 IRL meetup", + type: TournamentEventTypeEnum.IrlMeetup, website: "https://event.name" }, { @@ -83,7 +83,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e image: getCoverImage(), links: [], location: "Online", - type: "🛠 Workshop", + type: TournamentEventTypeEnum.Workshop, website: "https://event.name" }, @@ -95,7 +95,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e image: getCoverImage(), links: [], location: "Online", - type: "🛠 Workshop", + type: TournamentEventTypeEnum.Workshop, website: "https://event.name" }, @@ -107,7 +107,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e image: getCoverImage(), links: [], location: "Online", - type: "🛠 Workshop", + type: TournamentEventTypeEnum.Workshop, website: "https://event.name" }, ], diff --git a/src/redux/features/modals.slice.ts b/src/redux/features/modals.slice.ts index f4e547e..d3e58ed 100644 --- a/src/redux/features/modals.slice.ts +++ b/src/redux/features/modals.slice.ts @@ -14,6 +14,7 @@ import { LinkingAccountModal } from "src/features/Profiles/pages/EditProfilePage import { ComponentProps } from "react"; import { generateId } from "src/utils/helperFunctions"; import { NoWeblnModal } from "src/Components/Modals/NoWeblnModal"; +import { EventModal } from "src/features/Tournaments/pages/EventsPage/EventModal"; export enum Direction { START, @@ -38,6 +39,9 @@ export const ALL_MODALS = { Claim_SubmittedCard, Claim_FundWithdrawCard, + // Tournaments + EventModal: EventModal, + // Misc ConfirmModal, VoteCard, @@ -63,9 +67,9 @@ type NonNullableObject = { type ModalAction = U extends any ? {} extends NonNullableObject> ? - { Modal: U } + { Modal: U, isPageModal?: boolean, } : - { Modal: U, props: ModalProps } + { Modal: U, isPageModal?: boolean, props: ModalProps } : never; @@ -134,7 +138,7 @@ export const modalSlice = createSlice({ state.isOpen = true; let props: any = {}; - props.isPageModal = action.payload.Modal === 'ProjectDetailsCard'; + props.isPageModal = action.payload.isPageModal; if ('props' in action.payload) props = { ...props, ...action.payload.props } From ce848a51723fcbd8c1c03df1aef548d8baadd7eb Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Thu, 1 Sep 2022 13:34:30 +0300 Subject: [PATCH 07/53] fix: update project modals to be pageModals --- .../CategoryPage/ProjectsGrid/ProjectsGrid.tsx | 5 +++-- .../pages/ExplorePage/ProjectsRow/ProjectsRow.tsx | 2 +- .../ProjectDetailsCard.Skeleton.tsx | 11 +++++------ .../ProjectDetailsCard/ProjectDetailsCard.tsx | 13 +++++++------ src/mocks/data/tournament.ts | 2 +- 5 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/features/Projects/pages/CategoryPage/ProjectsGrid/ProjectsGrid.tsx b/src/features/Projects/pages/CategoryPage/ProjectsGrid/ProjectsGrid.tsx index 48243bb..044f8b3 100644 --- a/src/features/Projects/pages/CategoryPage/ProjectsGrid/ProjectsGrid.tsx +++ b/src/features/Projects/pages/CategoryPage/ProjectsGrid/ProjectsGrid.tsx @@ -2,7 +2,6 @@ import ProjectCardMini from "src/features/Projects/Components/ProjectCardMini/ProjectCardMini"; import ProjectCardMiniSkeleton from 'src/features/Projects/Components/ProjectCardMini/ProjectCardMini.Skeleton'; import { openModal } from 'src/redux/features/modals.slice'; -import { openProject } from 'src/redux/features/project.slice'; import { useAppDispatch } from 'src/utils/hooks'; import { ProjectCard } from 'src/utils/interfaces'; @@ -17,7 +16,9 @@ export default function ProjectsGrid({ isLoading, projects }: Props) { const handleClick = (projectId: number) => { dispatch(openModal({ - Modal: "ProjectDetailsCard", props: { + Modal: "ProjectDetailsCard", + isPageModal: true, + props: { projectId } })) diff --git a/src/features/Projects/pages/ExplorePage/ProjectsRow/ProjectsRow.tsx b/src/features/Projects/pages/ExplorePage/ProjectsRow/ProjectsRow.tsx index 71da859..718a644 100644 --- a/src/features/Projects/pages/ExplorePage/ProjectsRow/ProjectsRow.tsx +++ b/src/features/Projects/pages/ExplorePage/ProjectsRow/ProjectsRow.tsx @@ -51,7 +51,7 @@ export default function ProjectsRow({ title, link, projects }: Props) { const handleClick = (projectId: number) => { if (isClickAllowed()) { - dispatch(openModal({ Modal: "ProjectDetailsCard", props: { projectId } })) + dispatch(openModal({ Modal: "ProjectDetailsCard", isPageModal: true, props: { projectId } })) } } diff --git a/src/features/Projects/pages/ProjectPage/ProjectDetailsCard/ProjectDetailsCard.Skeleton.tsx b/src/features/Projects/pages/ProjectPage/ProjectDetailsCard/ProjectDetailsCard.Skeleton.tsx index 0e1c1e1..8da03ca 100644 --- a/src/features/Projects/pages/ProjectPage/ProjectDetailsCard/ProjectDetailsCard.Skeleton.tsx +++ b/src/features/Projects/pages/ProjectPage/ProjectDetailsCard/ProjectDetailsCard.Skeleton.tsx @@ -3,7 +3,8 @@ import { MdClose, } from 'react-icons/md'; import { ModalCard, modalCardVariants } from 'src/Components/Modals/ModalsContainer/ModalsContainer'; import Skeleton from 'react-loading-skeleton'; import Badge from 'src/Components/Badge/Badge'; -import { useAppSelector } from 'src/utils/hooks'; +import { useMediaQuery } from 'src/utils/hooks'; +import { MEDIA_QUERIES } from 'src/utils/theme'; interface Props extends ModalCard { @@ -13,9 +14,7 @@ export default function ProjectDetailsCardSkeleton({ onClose, direction, ...prop - const { isMobileScreen } = useAppSelector(state => ({ - isMobileScreen: state.ui.isMobileScreen - })); + const isMdScreen = useMediaQuery(MEDIA_QUERIES.isMedium) @@ -27,12 +26,12 @@ export default function ProjectDetailsCardSkeleton({ onClose, direction, ...prop initial='initial' animate="animate" exit='exit' - className={`modal-card max-w-[768px] ${props.isPageModal && isMobileScreen && 'rounded-0 w-full min-h-screen'}`} + className={`modal-card max-w-[768px] ${props.isPageModal && !isMdScreen && 'rounded-0 w-full min-h-screen'}`} >
- +
diff --git a/src/features/Projects/pages/ProjectPage/ProjectDetailsCard/ProjectDetailsCard.tsx b/src/features/Projects/pages/ProjectPage/ProjectDetailsCard/ProjectDetailsCard.tsx index c69fe75..9e8de59 100644 --- a/src/features/Projects/pages/ProjectPage/ProjectDetailsCard/ProjectDetailsCard.tsx +++ b/src/features/Projects/pages/ProjectPage/ProjectDetailsCard/ProjectDetailsCard.tsx @@ -2,7 +2,7 @@ import { useEffect, useState } from 'react' import { BsJoystick } from 'react-icons/bs' import { MdClose, MdLocalFireDepartment } from 'react-icons/md'; import { ModalCard } from 'src/Components/Modals/ModalsContainer/ModalsContainer'; -import { useAppDispatch, useAppSelector } from 'src/utils/hooks'; +import { useAppDispatch, useAppSelector, useMediaQuery } from 'src/utils/hooks'; import { openModal, scheduleModal } from 'src/redux/features/modals.slice'; import { setProject } from 'src/redux/features/project.slice'; import Button from 'src/Components/Button/Button'; @@ -16,6 +16,7 @@ import linkifyHtml from 'linkify-html'; import ErrorMessage from 'src/Components/ErrorMessage/ErrorMessage'; import { setVoteAmount } from 'src/redux/features/vote.slice'; import { numberFormatter } from 'src/utils/helperFunctions'; +import { MEDIA_QUERIES } from 'src/utils/theme'; interface Props extends ModalCard { @@ -28,11 +29,11 @@ export default function ProjectDetailsCard({ direction, projectId, ...props }: P const [screenshotsOpen, setScreenshotsOpen] = useState(-1); - const { isWalletConnected, project, isMobileScreen } = useAppSelector(state => ({ + const { isWalletConnected, project } = useAppSelector(state => ({ isWalletConnected: state.wallet.isConnected, - project: state.project.project, - isMobileScreen: state.ui.isMobileScreen + project: state.project.project })); + const isMdScreen = useMediaQuery(MEDIA_QUERIES.isMedium) const { loading, error } = useProjectDetailsQuery({ variables: { projectId: projectId! }, @@ -57,7 +58,7 @@ export default function ProjectDetailsCard({ direction, projectId, ...props }: P if (error) return
@@ -98,7 +99,7 @@ export default function ProjectDetailsCard({ direction, projectId, ...props }: P return (
diff --git a/src/mocks/data/tournament.ts b/src/mocks/data/tournament.ts index e96172d..fec6b78 100644 --- a/src/mocks/data/tournament.ts +++ b/src/mocks/data/tournament.ts @@ -38,7 +38,7 @@ 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, + events_count: 6, makers_count: 668, projects_count: 21, events: [ From 1755213f3acf7c493647e82f2e47a9a6002f0b9f Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Thu, 1 Sep 2022 13:40:55 +0300 Subject: [PATCH 08/53] feat: base events filters components --- .../EventsFilters/EventsFilters.tsx | 25 +++++++++++++++++++ .../pages/EventsPage/EventsPage.tsx | 2 ++ 2 files changed, 27 insertions(+) create mode 100644 src/features/Tournaments/pages/EventsPage/EventsFilters/EventsFilters.tsx diff --git a/src/features/Tournaments/pages/EventsPage/EventsFilters/EventsFilters.tsx b/src/features/Tournaments/pages/EventsPage/EventsFilters/EventsFilters.tsx new file mode 100644 index 0000000..dfc95bf --- /dev/null +++ b/src/features/Tournaments/pages/EventsPage/EventsFilters/EventsFilters.tsx @@ -0,0 +1,25 @@ +import React from 'react' +import { MdSearch } from 'react-icons/md' + +export default function EventsFilters() { + return ( + <> +
+ + + +
+
+ +
+ + ) +} diff --git a/src/features/Tournaments/pages/EventsPage/EventsPage.tsx b/src/features/Tournaments/pages/EventsPage/EventsPage.tsx index 36b7cec..3b75db2 100644 --- a/src/features/Tournaments/pages/EventsPage/EventsPage.tsx +++ b/src/features/Tournaments/pages/EventsPage/EventsPage.tsx @@ -1,6 +1,7 @@ import React from 'react' import { Tournament } from 'src/graphql' import EventCard from './EventCard/EventCard'; +import EventsFilters from './EventsFilters/EventsFilters'; interface Props { data: Pick

Events 📆 ({events_count})

+ { events.map(event => ) } From 8deacd290f2a8fc8af71c0290323319e0869d5a9 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Thu, 1 Sep 2022 14:48:54 +0300 Subject: [PATCH 09/53] feat: events filters components & functionality --- .../Inputs/Autocomplete/Autocomplete.tsx | 20 +++++++- .../EventsFilters/EventsFilters.tsx | 50 ++++++++++++++----- .../pages/EventsPage/EventsPage.tsx | 28 +++++++++-- .../JudgesSection/JudgesSection.tsx | 2 +- .../pages/OverviewPage/OverviewPage.tsx | 2 +- .../PrizesSection/PrizesSection.tsx | 4 +- .../PrizesSection/styles.module.scss | 3 +- .../Navigation/Navigation.tsx | 2 +- 8 files changed, 86 insertions(+), 25 deletions(-) diff --git a/src/Components/Inputs/Autocomplete/Autocomplete.tsx b/src/Components/Inputs/Autocomplete/Autocomplete.tsx index bd7b873..db52b28 100644 --- a/src/Components/Inputs/Autocomplete/Autocomplete.tsx +++ b/src/Components/Inputs/Autocomplete/Autocomplete.tsx @@ -42,8 +42,24 @@ export default function AutoComplete( const colourStyles: StylesConfig = useMemo(() => ({ control: (styles, state) => ({ ...styles, - padding: size === 'md' ? '1px 4px' : '8px 12px', - borderRadius: size === 'md' ? 8 : 12, + padding: '5px 12px', + borderRadius: 12, + // border: 'none', + // boxShadow: 'none', + + ":hover": { + cursor: "pointer" + }, + ":focus-within": { + '--tw-border-opacity': '1', + borderColor: 'rgb(179 160 255 / var(--tw-border-opacity))', + outlineColor: '#9E88FF', + '--tw-ring-offset-shadow': 'var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)', + '--tw-ring-shadow': 'var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color)', + boxShadow: 'var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000)', + '--tw-ring-color': 'rgb(179 160 255 / var(--tw-ring-opacity))', + '--tw-ring-opacity': '0.5' + } }), indicatorSeparator: (styles, state) => ({ ...styles, diff --git a/src/features/Tournaments/pages/EventsPage/EventsFilters/EventsFilters.tsx b/src/features/Tournaments/pages/EventsPage/EventsFilters/EventsFilters.tsx index dfc95bf..a16b30d 100644 --- a/src/features/Tournaments/pages/EventsPage/EventsFilters/EventsFilters.tsx +++ b/src/features/Tournaments/pages/EventsPage/EventsFilters/EventsFilters.tsx @@ -1,25 +1,49 @@ -import React from 'react' -import { MdSearch } from 'react-icons/md' +import { FiSearch } from 'react-icons/fi' +import AutoComplete from 'src/Components/Inputs/Autocomplete/Autocomplete'; +import { TournamentEventTypeEnum } from 'src/graphql'; +import { mapTypeToBadge } from '../EventCard/EventCard'; + +interface Props { + searchValue: string; + onSearchChange: (new_value: string) => void; + + eventValue: TournamentEventTypeEnum | null + onEventChange: (new_value: TournamentEventTypeEnum | null) => void; +} + +export default function EventsFilters(props: Props) { + + const options = [{ + label: "📆 All events", + value: null as TournamentEventTypeEnum | null, + }] + .concat(Object.values(TournamentEventTypeEnum).map((v: TournamentEventTypeEnum) => ({ label: mapTypeToBadge[v].text, value: v }))) -export default function EventsFilters() { return ( <> -
- - +
+ props.onSearchChange(e.target.value)} />
-
- -
+ props.onEventChange(v ? v.value : null)} + options={options} + + /> ) } + +// const x = Object.values(TournamentEventTypeEnum) \ No newline at end of file diff --git a/src/features/Tournaments/pages/EventsPage/EventsPage.tsx b/src/features/Tournaments/pages/EventsPage/EventsPage.tsx index 3b75db2..a688abc 100644 --- a/src/features/Tournaments/pages/EventsPage/EventsPage.tsx +++ b/src/features/Tournaments/pages/EventsPage/EventsPage.tsx @@ -1,5 +1,5 @@ -import React from 'react' -import { Tournament } from 'src/graphql' +import React, { useState } from 'react' +import { Tournament, TournamentEventTypeEnum } from 'src/graphql' import EventCard from './EventCard/EventCard'; import EventsFilters from './EventsFilters/EventsFilters'; @@ -10,13 +10,31 @@ interface Props { } export default function EventsPage({ data: { events, events_count } }: Props) { + + const [searchFilter, setSearchFilter] = useState("") + const [eventFilter, setEventFilter] = useState(null) + return (

Events 📆 ({events_count})

-
- +
+ { - events.map(event => ) + events + .filter(event => { + if (!searchFilter) return true; + return event.title.search(new RegExp(searchFilter, 'i')) !== -1 || event.description.search(new RegExp(searchFilter, 'i')) !== -1 + }) + .filter(event => { + if (!eventFilter) return true; + return event.type === eventFilter; + }) + .map(event => ) }
diff --git a/src/features/Tournaments/pages/OverviewPage/JudgesSection/JudgesSection.tsx b/src/features/Tournaments/pages/OverviewPage/JudgesSection/JudgesSection.tsx index b510257..02626cc 100644 --- a/src/features/Tournaments/pages/OverviewPage/JudgesSection/JudgesSection.tsx +++ b/src/features/Tournaments/pages/OverviewPage/JudgesSection/JudgesSection.tsx @@ -16,7 +16,7 @@ export default function JudgesSection({ judges }: Props) { return (

Judges

-
+
{judges.map((judge, idx) =>
+

Tournament details

diff --git a/src/features/Tournaments/pages/OverviewPage/PrizesSection/PrizesSection.tsx b/src/features/Tournaments/pages/OverviewPage/PrizesSection/PrizesSection.tsx index 541567c..d910a2e 100644 --- a/src/features/Tournaments/pages/OverviewPage/PrizesSection/PrizesSection.tsx +++ b/src/features/Tournaments/pages/OverviewPage/PrizesSection/PrizesSection.tsx @@ -11,7 +11,9 @@ export default function PrizesSection({ prizes }: Props) {

Prizes

- {prizes.map(prize =>
+ {prizes.map((prize, idx) =>

{prize.title}

diff --git a/src/features/Tournaments/pages/OverviewPage/PrizesSection/styles.module.scss b/src/features/Tournaments/pages/OverviewPage/PrizesSection/styles.module.scss index 8e681e0..baecc03 100644 --- a/src/features/Tournaments/pages/OverviewPage/PrizesSection/styles.module.scss +++ b/src/features/Tournaments/pages/OverviewPage/PrizesSection/styles.module.scss @@ -12,7 +12,7 @@ h3 { font-size: 20px; color: white; - -webkit-text-stroke: 2px black; + -webkit-text-stroke: 1px black; } p { font-size: 24px; @@ -59,6 +59,7 @@ > div { h3 { font-size: 32px; + -webkit-text-stroke: 2px black; } p { font-size: 40px; diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx index 97c1757..166e975 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx +++ b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx @@ -42,7 +42,7 @@ export default function Navigation({ data }: Props) { ], [data.events_count, data.makers_count, data.projects_count]) return ( -
+
From 355871d57fdfc8e2456e86200ced17bfa3945a4b Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Thu, 1 Sep 2022 14:50:37 +0300 Subject: [PATCH 10/53] chore: remove unused imports --- src/Components/Inputs/Autocomplete/Autocomplete.tsx | 2 +- .../RolesSkillsTab/UpdateSkillsCard/SkillsInput.tsx | 5 +---- .../Tournaments/pages/OverviewPage/OverviewPage.tsx | 4 ---- .../pages/TournamentDetailsPage/Navigation/Navigation.tsx | 6 +++--- 4 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/Components/Inputs/Autocomplete/Autocomplete.tsx b/src/Components/Inputs/Autocomplete/Autocomplete.tsx index db52b28..d5c5df2 100644 --- a/src/Components/Inputs/Autocomplete/Autocomplete.tsx +++ b/src/Components/Inputs/Autocomplete/Autocomplete.tsx @@ -71,7 +71,7 @@ export default function AutoComplete( boxShadow: 'none !important' }, }), - }), [size]) + }), []) return (
diff --git a/src/features/Profiles/pages/EditProfilePage/RolesSkillsTab/UpdateSkillsCard/SkillsInput.tsx b/src/features/Profiles/pages/EditProfilePage/RolesSkillsTab/UpdateSkillsCard/SkillsInput.tsx index c410c4d..fcaae43 100644 --- a/src/features/Profiles/pages/EditProfilePage/RolesSkillsTab/UpdateSkillsCard/SkillsInput.tsx +++ b/src/features/Profiles/pages/EditProfilePage/RolesSkillsTab/UpdateSkillsCard/SkillsInput.tsx @@ -1,10 +1,7 @@ import Select from 'react-select'; -import { OnChangeValue, StylesConfig, components, OptionProps } from "react-select"; -import Avatar from "src/features/Profiles/Components/Avatar/Avatar"; -import { FiSearch } from 'react-icons/fi'; -import { useState } from 'react'; +import { OnChangeValue, StylesConfig, } from "react-select"; import { MyProfileRolesSkillsQuery } from 'src/graphql'; diff --git a/src/features/Tournaments/pages/OverviewPage/OverviewPage.tsx b/src/features/Tournaments/pages/OverviewPage/OverviewPage.tsx index 170e866..068d05e 100644 --- a/src/features/Tournaments/pages/OverviewPage/OverviewPage.tsx +++ b/src/features/Tournaments/pages/OverviewPage/OverviewPage.tsx @@ -1,8 +1,4 @@ -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 FAQsSection from './FAQsSection/FAQsSection' import JudgesSection from './JudgesSection/JudgesSection' diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx index 166e975..b027046 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx +++ b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx @@ -1,5 +1,5 @@ -import React, { useMemo } from 'react' -import { Link, NavLink } from 'react-router-dom' +import { useMemo } from 'react' +import { NavLink } from 'react-router-dom' import { Tournament } from 'src/graphql' import { useCarousel } from 'src/utils/hooks' @@ -9,7 +9,7 @@ interface Props { export default function Navigation({ data }: Props) { - const { viewportRef, scrollSlides, canScrollNext, canScrollPrev, isClickAllowed } = useCarousel({ + const { viewportRef, } = useCarousel({ align: 'start', slidesToScroll: 2, containScroll: "trimSnaps", }) From c9df0a96a64a238b0dc929c792be12f4f1cef4db Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Thu, 1 Sep 2022 14:53:18 +0300 Subject: [PATCH 11/53] style: underline event title on hover --- .../Tournaments/pages/EventsPage/EventCard/EventCard.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx b/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx index 07f74de..577a7e6 100644 --- a/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx +++ b/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx @@ -40,13 +40,13 @@ export default function EventCard({ event }: Props) { return (
-

+

{event.title}

From 3bebc91d6e9abe0c5575aafb4e051f34a2cd80d7 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Sun, 4 Sep 2022 10:57:01 +0300 Subject: [PATCH 12/53] feat: create reusable select component --- package-lock.json | 14 +- package.json | 4 +- src/Components/Card/Card.tsx | 4 +- .../Autocomplete/Autocomplete.stories.tsx | 171 ------------------ .../Inputs/Autocomplete/Autocomplete.tsx | 111 ------------ .../BasicSelectInput/BasicSelectInput.tsx | 136 ++++++++++++++ .../Components/SortByFilter/SortByFilter.tsx | 1 - .../pages/EventsPage/EventCard/EventCard.tsx | 4 +- .../EventsFilters/EventsFilters.tsx | 8 +- src/utils/interfaces/misc.interfaces.ts | 6 +- 10 files changed, 155 insertions(+), 304 deletions(-) delete mode 100644 src/Components/Inputs/Autocomplete/Autocomplete.stories.tsx delete mode 100644 src/Components/Inputs/Autocomplete/Autocomplete.tsx create mode 100644 src/Components/Inputs/Selects/BasicSelectInput/BasicSelectInput.tsx diff --git a/package-lock.json b/package-lock.json index c5bfa65..df76061 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ "@remirror/react": "^1.0.34", "@shopify/react-web-worker": "^5.0.1", "@szhsin/react-menu": "^3.0.2", - "@tailwindcss/line-clamp": "^0.4.0", + "@tailwindcss/line-clamp": "^0.4.2", "@testing-library/jest-dom": "^5.16.4", "@testing-library/react": "^13.1.1", "@testing-library/user-event": "^13.5.0", @@ -15324,9 +15324,9 @@ } }, "node_modules/@tailwindcss/line-clamp": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.4.0.tgz", - "integrity": "sha512-HQZo6gfx1D0+DU3nWlNLD5iA6Ef4JAXh0LeD8lOGrJwEDBwwJNKQza6WoXhhY1uQrxOuU8ROxV7CqiQV4CoiLw==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.4.2.tgz", + "integrity": "sha512-HFzAQuqYCjyy/SX9sLGB1lroPzmcnWv1FHkIpmypte10hptf4oPUfucryMKovZh2u0uiS9U5Ty3GghWfEJGwVw==", "peerDependencies": { "tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1" } @@ -82381,9 +82381,9 @@ } }, "@tailwindcss/line-clamp": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.4.0.tgz", - "integrity": "sha512-HQZo6gfx1D0+DU3nWlNLD5iA6Ef4JAXh0LeD8lOGrJwEDBwwJNKQza6WoXhhY1uQrxOuU8ROxV7CqiQV4CoiLw==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.4.2.tgz", + "integrity": "sha512-HFzAQuqYCjyy/SX9sLGB1lroPzmcnWv1FHkIpmypte10hptf4oPUfucryMKovZh2u0uiS9U5Ty3GghWfEJGwVw==", "requires": {} }, "@testing-library/dom": { diff --git a/package.json b/package.json index 0b3b6f4..eeb56f4 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "my-app", + "name": "makers-bolt-fun", "version": "0.1.0", "private": true, "dependencies": { @@ -14,7 +14,7 @@ "@remirror/react": "^1.0.34", "@shopify/react-web-worker": "^5.0.1", "@szhsin/react-menu": "^3.0.2", - "@tailwindcss/line-clamp": "^0.4.0", + "@tailwindcss/line-clamp": "^0.4.2", "@testing-library/jest-dom": "^5.16.4", "@testing-library/react": "^13.1.1", "@testing-library/user-event": "^13.5.0", diff --git a/src/Components/Card/Card.tsx b/src/Components/Card/Card.tsx index edc6123..e9727e7 100644 --- a/src/Components/Card/Card.tsx +++ b/src/Components/Card/Card.tsx @@ -21,8 +21,8 @@ const Card = React.forwardRef>(({ ref={ref} className={` ${onlyMd ? - `md:bg-white md:rounded-16 md:border-2 border-gray-200 ${defaultPadding && "md:p-24"}` : - `bg-white rounded-12 md:rounded-16 border-2 border-gray-200 ${defaultPadding && "p-16 md:p-24"}` + `md:bg-white md:rounded-16 md:outline outline-2 outline-gray-200 ${defaultPadding && "md:p-24"}` : + `bg-white rounded-12 md:rounded-16 outline outline-2 outline-gray-200 ${defaultPadding && "p-16 md:p-24"}` } ${className} `} diff --git a/src/Components/Inputs/Autocomplete/Autocomplete.stories.tsx b/src/Components/Inputs/Autocomplete/Autocomplete.stories.tsx deleted file mode 100644 index 02df6f4..0000000 --- a/src/Components/Inputs/Autocomplete/Autocomplete.stories.tsx +++ /dev/null @@ -1,171 +0,0 @@ -import { ComponentStory, ComponentMeta } from '@storybook/react'; -import { useWatch } from 'react-hook-form'; -import { WrapForm } from 'src/utils/storybook/decorators'; - -import Autocomplete from './Autocomplete'; - -export default { - title: 'Shared/Inputs/AutoComplete', - component: Autocomplete, - decorators: [WrapForm({ - defaultValues: { - autocomplete: null - } - })], - -} as ComponentMeta; - -const options = [ - { - "id": "20f0eb8d-c0cd-4e12-8a08-0d9846fc8704", - "name": "Nichole Bailey", - "username": "Cassie14", - "email": "Daisy_Auer50@hotmail.com", - "address": { - "street": "Anastasia Tunnel", - "suite": 95587, - "city": "Port Casperview", - "zipcode": "04167-6996", - "geo": { - "lat": "-73.4727", - "lng": "-142.9435" - } - }, - "phone": "324-615-9195 x5902", - "website": "ron.net", - "company": { - "name": "Roberts, Tremblay and Christiansen", - "catchPhrase": "Vision-oriented actuating access", - "bs": "bricks-and-clicks strategize portals" - } - }, - { - "id": "62b70f76-85ba-4241-9ffd-07582008c497", - "name": "Robert Blick", - "username": "Madilyn93", - "email": "Ronaldo82@gmail.com", - "address": { - "street": "Charlie Plain", - "suite": 83070, - "city": "Lake Bonitaland", - "zipcode": "01109", - "geo": { - "lat": "50.0971", - "lng": "-2.3057" - } - }, - "phone": "1-541-367-2047 x9006", - "website": "jovani.com", - "company": { - "name": "Parisian - Kling", - "catchPhrase": "Multi-tiered tertiary toolset", - "bs": "plug-and-play benchmark content" - } - }, - { - "id": "d02f74d9-bf99-4e41-b678-15e903abc1b3", - "name": "Eli O'Kon", - "username": "Rosario.Davis", - "email": "Mckayla59@hotmail.com", - "address": { - "street": "Wilford Drive", - "suite": 69742, - "city": "North Dianna", - "zipcode": "80620", - "geo": { - "lat": "-61.4191", - "lng": "126.7878" - } - }, - "phone": "(339) 709-4080", - "website": "clay.name", - "company": { - "name": "Gerlach - Metz", - "catchPhrase": "Pre-emptive user-facing service-desk", - "bs": "frictionless monetize markets" - } - }, - { - "id": "21077fa6-6a53-4b84-8407-6cd949718945", - "name": "Marilie Feil", - "username": "Antwon.Carter92", - "email": "Demario.Hyatt20@yahoo.com", - "address": { - "street": "Kenton Spurs", - "suite": 20079, - "city": "Beahanberg", - "zipcode": "79385", - "geo": { - "lat": "-70.7199", - "lng": "4.6977" - } - }, - "phone": "608.750.4947", - "website": "jacynthe.org", - "company": { - "name": "Kuhn and Sons", - "catchPhrase": "Total eco-centric matrices", - "bs": "out-of-the-box target communities" - } - }, - { - "id": "e07cf1b4-ff43-4c4a-a670-fd7417d6bbaf", - "name": "Ella Pagac", - "username": "Damien.Jaskolski", - "email": "Delmer1@gmail.com", - "address": { - "street": "VonRueden Shoals", - "suite": 14035, - "city": "Starkmouth", - "zipcode": "72448-1915", - "geo": { - "lat": "55.2157", - "lng": "98.0822" - } - }, - "phone": "(165) 247-5332 x71067", - "website": "chad.info", - "company": { - "name": "Nicolas, Doyle and Rempel", - "catchPhrase": "Adaptive real-time strategy", - "bs": "innovative whiteboard supply-chains" - } - } -] -const Template: ComponentStory = (args) => { - - const value = useWatch({ name: 'autocomplete' }) - - console.log(value); - - - return -} - - -export const Default = Template.bind({}); -Default.args = { - onChange: console.log -} - - -export const Lodaing = Template.bind({}); -Lodaing.args = { - isLoading: true -} - -export const Clearable = Template.bind({}); -Clearable.args = { - isClearable: true -} - -export const MultipleAllowed = Template.bind({}); -MultipleAllowed.args = { - isMulti: true -} - diff --git a/src/Components/Inputs/Autocomplete/Autocomplete.tsx b/src/Components/Inputs/Autocomplete/Autocomplete.tsx deleted file mode 100644 index d5c5df2..0000000 --- a/src/Components/Inputs/Autocomplete/Autocomplete.tsx +++ /dev/null @@ -1,111 +0,0 @@ - -import { useMemo } from "react"; -import Select, { StylesConfig } from "react-select"; -import { ControlledStateHandler } from "src/utils/interfaces"; - - -type Props = { - options: T[]; - labelField?: keyof T - valueField?: keyof T - placeholder?: string - disabled?: boolean - isLoading?: boolean; - isClearable?: boolean; - control?: any, - name?: string, - className?: string, - onBlur?: () => void; - size?: 'sm' | 'md' | 'lg' -} & ControlledStateHandler - - - - -export default function AutoComplete({ - options, - labelField, - valueField, - placeholder = "Select Option...", - isMulti, - isClearable, - disabled, - className, - value, - onChange, - onBlur, - size = 'md', - ...props -}: Props) { - - - const colourStyles: StylesConfig = useMemo(() => ({ - control: (styles, state) => ({ - ...styles, - padding: '5px 12px', - borderRadius: 12, - // border: 'none', - // boxShadow: 'none', - - ":hover": { - cursor: "pointer" - }, - ":focus-within": { - '--tw-border-opacity': '1', - borderColor: 'rgb(179 160 255 / var(--tw-border-opacity))', - outlineColor: '#9E88FF', - '--tw-ring-offset-shadow': 'var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)', - '--tw-ring-shadow': 'var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color)', - boxShadow: 'var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000)', - '--tw-ring-color': 'rgb(179 160 255 / var(--tw-ring-opacity))', - '--tw-ring-opacity': '0.5' - } - }), - indicatorSeparator: (styles, state) => ({ - ...styles, - display: "none" - }), - input: (styles, state) => ({ - ...styles, - " input": { - boxShadow: 'none !important' - }, - }), - }), []) - - return ( -

- o[labelField]} + getOptionValue={o => o[valueField]} + + value={value as any} + onChange={v => onChange?.(v as any)} + onBlur={onBlur} + components={{ + Option: getOptionComponent(renderOption, labelField), + // ValueContainer: CustomValueContainer + }} + + styles={selectCustomStyle as any} + theme={(theme) => ({ + ...theme, + borderRadius: 8, + colors: { + ...theme.colors, + primary: 'var(--primary)', + }, + })} + /> + +
+ + ); +} + +function getOptionComponent>(renderOption: Props['renderOption'], labelField: Props['labelField']) { + const _render = renderOption ?? ((option) =>
+ {option.data[labelField]} +
) + + return function OptionComponent(props: OptionProps) { + return ( + + {_render(props)} + + ); + }; +} \ No newline at end of file diff --git a/src/features/Hackathons/Components/SortByFilter/SortByFilter.tsx b/src/features/Hackathons/Components/SortByFilter/SortByFilter.tsx index 037b88c..7f3eb4d 100644 --- a/src/features/Hackathons/Components/SortByFilter/SortByFilter.tsx +++ b/src/features/Hackathons/Components/SortByFilter/SortByFilter.tsx @@ -1,5 +1,4 @@ import React, { useState } from 'react' -import AutoComplete from 'src/Components/Inputs/Autocomplete/Autocomplete'; import { useMediaQuery } from 'src/utils/hooks'; import { MEDIA_QUERIES } from 'src/utils/theme'; diff --git a/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx b/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx index 577a7e6..e4aeccc 100644 --- a/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx +++ b/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx @@ -40,10 +40,10 @@ export default function EventCard({ event }: Props) { return (
- +

diff --git a/src/features/Tournaments/pages/EventsPage/EventsFilters/EventsFilters.tsx b/src/features/Tournaments/pages/EventsPage/EventsFilters/EventsFilters.tsx index a16b30d..18ae1eb 100644 --- a/src/features/Tournaments/pages/EventsPage/EventsFilters/EventsFilters.tsx +++ b/src/features/Tournaments/pages/EventsPage/EventsFilters/EventsFilters.tsx @@ -1,5 +1,5 @@ import { FiSearch } from 'react-icons/fi' -import AutoComplete from 'src/Components/Inputs/Autocomplete/Autocomplete'; +import BasicSelectInput from 'src/Components/Inputs/Selects/BasicSelectInput/BasicSelectInput'; import { TournamentEventTypeEnum } from 'src/graphql'; import { mapTypeToBadge } from '../EventCard/EventCard'; @@ -31,12 +31,12 @@ export default function EventsFilters(props: Props) { onChange={e => props.onSearchChange(e.target.value)} />

- props.onEventChange(v ? v.value : null)} options={options} diff --git a/src/utils/interfaces/misc.interfaces.ts b/src/utils/interfaces/misc.interfaces.ts index f3fc015..c906a59 100644 --- a/src/utils/interfaces/misc.interfaces.ts +++ b/src/utils/interfaces/misc.interfaces.ts @@ -13,12 +13,10 @@ export type ListComponentProps = { export type ControlledStateHandler = { isMulti?: IsMulti; value?: - | (true extends IsMulti ? T[] : never) - | (false extends IsMulti ? T : never) + | (true extends IsMulti ? T[] : T) | null onChange?: ( - nv: | (true extends IsMulti ? T[] : never) - | (false extends IsMulti ? T : never) + nv: | (true extends IsMulti ? T[] : T) | null ) => void onBlur?: () => void From 17bcd29be2ca60e0e458d6a696024edf2079a6bf Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Sun, 4 Sep 2022 11:39:41 +0300 Subject: [PATCH 13/53] refactor: mock data to client side & split it into parts, add new eventType --- api/functions/graphql/nexus-typegen.ts | 2 +- api/functions/graphql/schema.graphql | 1 + api/functions/graphql/types/tournament.js | 1 + package-lock.json | 44 ++++++++++- package.json | 1 + .../BasicSelectInput.stories.tsx | 31 ++++++++ .../pages/EventsPage/EventCard/EventCard.tsx | 6 +- .../pages/OverviewPage/OverviewPage.tsx | 9 ++- .../Navigation/Navigation.tsx | 18 +++-- .../TournamentDetailsPage.tsx | 32 ++++---- .../TournamentDetailsPage/data/description.ts | 11 +++ .../TournamentDetailsPage/data/events.ts | 74 +++++++++++++++++++ .../pages/TournamentDetailsPage/data/faqs.ts | 54 ++++++++++++++ .../pages/TournamentDetailsPage/data/index.ts | 27 +++++++ .../TournamentDetailsPage/data/judeges.ts | 65 ++++++++++++++++ .../TournamentDetailsPage/data/prizes.ts | 23 ++++++ src/graphql/index.tsx | 1 + tailwind.config.js | 1 + 18 files changed, 375 insertions(+), 26 deletions(-) create mode 100644 src/Components/Inputs/Selects/BasicSelectInput/BasicSelectInput.stories.tsx create mode 100644 src/features/Tournaments/pages/TournamentDetailsPage/data/description.ts create mode 100644 src/features/Tournaments/pages/TournamentDetailsPage/data/events.ts create mode 100644 src/features/Tournaments/pages/TournamentDetailsPage/data/faqs.ts create mode 100644 src/features/Tournaments/pages/TournamentDetailsPage/data/index.ts create mode 100644 src/features/Tournaments/pages/TournamentDetailsPage/data/judeges.ts create mode 100644 src/features/Tournaments/pages/TournamentDetailsPage/data/prizes.ts diff --git a/api/functions/graphql/nexus-typegen.ts b/api/functions/graphql/nexus-typegen.ts index 41db1ba..6ea9d98 100644 --- a/api/functions/graphql/nexus-typegen.ts +++ b/api/functions/graphql/nexus-typegen.ts @@ -69,7 +69,7 @@ export interface NexusGenInputs { export interface NexusGenEnums { POST_TYPE: "Bounty" | "Question" | "Story" RoleLevelEnum: 3 | 0 | 1 | 2 | 4 - TournamentEventTypeEnum: 2 | 0 | 1 + TournamentEventTypeEnum: 2 | 3 | 0 | 1 VOTE_ITEM_TYPE: "Bounty" | "PostComment" | "Project" | "Question" | "Story" | "User" } diff --git a/api/functions/graphql/schema.graphql b/api/functions/graphql/schema.graphql index 1e7b8cc..8b739e8 100644 --- a/api/functions/graphql/schema.graphql +++ b/api/functions/graphql/schema.graphql @@ -357,6 +357,7 @@ type TournamentEvent { enum TournamentEventTypeEnum { IRLMeetup + OnlineMeetup TwitterSpace Workshop } diff --git a/api/functions/graphql/types/tournament.js b/api/functions/graphql/types/tournament.js index 6952ff8..e7a2768 100644 --- a/api/functions/graphql/types/tournament.js +++ b/api/functions/graphql/types/tournament.js @@ -44,6 +44,7 @@ const TournamentEventTypeEnum = enumType({ TwitterSpace: 0, Workshop: 1, IRLMeetup: 2, + OnlineMeetup: 3, }, }); diff --git a/package-lock.json b/package-lock.json index df76061..64fd3a5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "my-app", + "name": "makers-bolt-fun", "version": "0.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "my-app", + "name": "makers-bolt-fun", "version": "0.1.0", "dependencies": { "@apollo/client": "^3.6.9", @@ -114,6 +114,7 @@ "@storybook/react": "^6.4.22", "@storybook/testing-library": "^0.0.10", "@tailwindcss/forms": "^0.5.0", + "@tailwindcss/typography": "^0.5.7", "@types/chance": "^1.1.3", "@types/dompurify": "^2.3.3", "@types/fslightbox-react": "^1.4.2", @@ -15331,6 +15332,21 @@ "tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1" } }, + "node_modules/@tailwindcss/typography": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.7.tgz", + "integrity": "sha512-JTTSTrgZfp6Ki4svhPA4mkd9nmQ/j9EfE7SbHJ1cLtthKkpW2OxsFXzSmxbhYbEkfNIyAyhle5p4SYyKRbz/jg==", + "dev": true, + "dependencies": { + "lodash.castarray": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "postcss-selector-parser": "6.0.10" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || insiders" + } + }, "node_modules/@testing-library/dom": { "version": "8.13.0", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.13.0.tgz", @@ -31597,6 +31613,12 @@ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" }, + "node_modules/lodash.castarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", + "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==", + "dev": true + }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -82386,6 +82408,18 @@ "integrity": "sha512-HFzAQuqYCjyy/SX9sLGB1lroPzmcnWv1FHkIpmypte10hptf4oPUfucryMKovZh2u0uiS9U5Ty3GghWfEJGwVw==", "requires": {} }, + "@tailwindcss/typography": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.7.tgz", + "integrity": "sha512-JTTSTrgZfp6Ki4svhPA4mkd9nmQ/j9EfE7SbHJ1cLtthKkpW2OxsFXzSmxbhYbEkfNIyAyhle5p4SYyKRbz/jg==", + "dev": true, + "requires": { + "lodash.castarray": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "postcss-selector-parser": "6.0.10" + } + }, "@testing-library/dom": { "version": "8.13.0", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.13.0.tgz", @@ -95136,6 +95170,12 @@ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" }, + "lodash.castarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", + "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==", + "dev": true + }, "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", diff --git a/package.json b/package.json index eeb56f4..40533fb 100644 --- a/package.json +++ b/package.json @@ -166,6 +166,7 @@ "@storybook/react": "^6.4.22", "@storybook/testing-library": "^0.0.10", "@tailwindcss/forms": "^0.5.0", + "@tailwindcss/typography": "^0.5.7", "@types/chance": "^1.1.3", "@types/dompurify": "^2.3.3", "@types/fslightbox-react": "^1.4.2", diff --git a/src/Components/Inputs/Selects/BasicSelectInput/BasicSelectInput.stories.tsx b/src/Components/Inputs/Selects/BasicSelectInput/BasicSelectInput.stories.tsx new file mode 100644 index 0000000..72af3cc --- /dev/null +++ b/src/Components/Inputs/Selects/BasicSelectInput/BasicSelectInput.stories.tsx @@ -0,0 +1,31 @@ +import { ComponentStory, ComponentMeta } from '@storybook/react'; +import { MdOutlineKingBed } from 'react-icons/md'; + +import BasicSelectInput from './BasicSelectInput'; + +export default { + title: 'Shared/Inputs/Select/Basic', + component: BasicSelectInput, + +} as ComponentMeta; + +const Template: ComponentStory = (args) => + + +export const Default = Template.bind({}); +Default.args = { + // defaultValue: 4, + options: [ + { value: 1, label: "Option 1" }, + { value: 2, label: 'Option 2' }, + { value: 3, label: 'Option 3' }, + { value: 4, label: 'Option 4' }, + ], + onChange: (nv) => alert("New value is: " + nv), + labelField: 'label', + valueField: "value" +} + + + + diff --git a/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx b/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx index e4aeccc..57dc2c8 100644 --- a/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx +++ b/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx @@ -77,7 +77,11 @@ export const mapTypeToBadge: UnionToObjectKeys
-

Tournament details

-

{data.description}

+
+
diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx index b027046..77ed8ea 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx +++ b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx @@ -24,20 +24,24 @@ export default function Navigation({ data }: Props) { path: "events", }, { - text: `Makers (${data.makers_count})`, + text: `????? 🚧`, path: "makers", + isDisabled: true, }, { - text: `Projects (${data.projects_count})`, + text: `??????? 🚧`, path: "projects", + isDisabled: true, }, { - text: "Ideas", + text: "???? 🚧", path: "ideas", + isDisabled: true, }, { - text: "Resources", + text: "?????????? 🚧", path: "resources", + isDisabled: true, }, ], [data.events_count, data.makers_count, data.projects_count]) @@ -52,8 +56,10 @@ export default function Navigation({ data }: Props) { className={({ isActive }) => ` 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)} + ${isActive ? 'bg-primary-100 text-primary-600' : 'bg-gray-100 hover:bg-gray-200 text-gray-600'} + ${link.isDisabled && "pointer-events-none opacity-60"} + `} + role='button' > {link.text} diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx index 04c1c75..d74bbea 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx +++ b/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx @@ -8,36 +8,40 @@ import OverviewPage from '../OverviewPage/OverviewPage' import { Helmet } from 'react-helmet' import Navigation from './Navigation/Navigation' import EventsPage from '../EventsPage/EventsPage' +import { tournamentData } from './data' + +const data = tournamentData export default function TournamentDetailsPage() { - const query = useGetTournamentByIdQuery({ - variables: { - id: 12, - } - }) + // const query = useGetTournamentByIdQuery({ + // variables: { + // id: 12, + // }, - if (query.loading) - return + // }) - if (!query.data?.getTournamentById) - return + // if (query.loading) + // return + + // if (!query.data?.getTournamentById) + // return return (
- {query.data.getTournamentById.title} Tournament + {data.title} Tournament -
- +
+
} /> - } /> - } /> + } /> + } />
diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/data/description.ts b/src/features/Tournaments/pages/TournamentDetailsPage/data/description.ts new file mode 100644 index 0000000..9ff4ead --- /dev/null +++ b/src/features/Tournaments/pages/TournamentDetailsPage/data/description.ts @@ -0,0 +1,11 @@ +export const description = + `## Tournament Details +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. + +#### Subtitle1 +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. + +#### Subtitle2 +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. + +` \ No newline at end of file diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/data/events.ts b/src/features/Tournaments/pages/TournamentDetailsPage/data/events.ts new file mode 100644 index 0000000..58cdc6c --- /dev/null +++ b/src/features/Tournaments/pages/TournamentDetailsPage/data/events.ts @@ -0,0 +1,74 @@ +import { Tournament, TournamentEventTypeEnum } from "src/graphql"; +import { getCoverImage } from "src/mocks/data/utils"; + + +export const events: Tournament['events'] = [ + { + id: 12, + title: "STW3 Round Table #1", + date: "13:00 - 14:00 UTC, 23rd June", + description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", + image: getCoverImage(), + links: [], + location: "Online", + type: TournamentEventTypeEnum.TwitterSpace, + website: "https://event.name" + }, + { + id: 13, + title: "STW3 Round Table #2", + date: "15:00 - 16:00 UTC, 23rd June", + description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", + image: getCoverImage(), + links: [], + location: "Online", + type: TournamentEventTypeEnum.Workshop, + website: "https://event.name" + }, + { + id: 14, + title: "STW3 Round Table #3", + date: "13:00 - 14:00 UTC, 24rd June", + description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", + image: getCoverImage(), + links: [], + location: "Online", + type: TournamentEventTypeEnum.IrlMeetup, + website: "https://event.name" + }, + { + id: 44, + title: "Lightning Login", + date: "15:00 - 16:00 UTC, 24rd June", + description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", + image: getCoverImage(), + links: [], + location: "Online", + type: TournamentEventTypeEnum.Workshop, + website: "https://event.name" + }, + + { + id: 46, + title: "Escrow contracts", + date: "15:00 - 16:00 UTC, 23rd June", + description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", + image: getCoverImage(), + links: [], + location: "Online", + type: TournamentEventTypeEnum.Workshop, + website: "https://event.name" + }, + + { + id: 444, + title: "Lsats - What & Why", + date: "15:00 - 16:00 UTC, 23rd June", + description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", + image: getCoverImage(), + links: [], + location: "Online", + type: TournamentEventTypeEnum.Workshop, + website: "https://event.name" + }, +] \ No newline at end of file diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/data/faqs.ts b/src/features/Tournaments/pages/TournamentDetailsPage/data/faqs.ts new file mode 100644 index 0000000..f3e9dce --- /dev/null +++ b/src/features/Tournaments/pages/TournamentDetailsPage/data/faqs.ts @@ -0,0 +1,54 @@ +import { Tournament } from "src/graphql"; + + +export const faqs: Tournament['faqs'] = [ + { + question: "What is Shock the Web?", + answer: + `Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there. + +Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.` + }, + { + question: "When and where will it take place?", + answer: + `Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there. + +Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.` + }, + { + question: "What will we be doing?", + answer: + `Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there. + +Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.` + }, + { + question: "This is my first time hacking on lightning, will there be help?", + answer: + `Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there. + +Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.` + }, + { + question: "This is my first time hacking on lightning, will there be help?", + answer: + `Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there. + +Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.` + }, + { + question: "How many members can I have on my team?", + answer: + `Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there. + +Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.` + }, + { + question: "Who will choose the winners?", + answer: + `Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there. + +Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.` + }, +] \ No newline at end of file diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/data/index.ts b/src/features/Tournaments/pages/TournamentDetailsPage/data/index.ts new file mode 100644 index 0000000..344f7b1 --- /dev/null +++ b/src/features/Tournaments/pages/TournamentDetailsPage/data/index.ts @@ -0,0 +1,27 @@ +import { Tournament, } from "src/graphql"; +import { description } from "./description"; +import { events } from "./events"; +import { faqs } from "./faqs"; +import { judges } from "./judeges"; +import { prizes } from "./prizes"; + +export const tournamentData: Tournament = { + __typename: "Tournament", + 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: description, + prizes: prizes, + events_count: events.length, + makers_count: 668, + projects_count: 21, + + events: events, + judges: judges, + faqs: faqs, +} \ No newline at end of file diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/data/judeges.ts b/src/features/Tournaments/pages/TournamentDetailsPage/data/judeges.ts new file mode 100644 index 0000000..113f122 --- /dev/null +++ b/src/features/Tournaments/pages/TournamentDetailsPage/data/judeges.ts @@ -0,0 +1,65 @@ +import { Tournament } from "src/graphql"; + + +export const judges: Tournament['judges'] = [ + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, +] \ No newline at end of file diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/data/prizes.ts b/src/features/Tournaments/pages/TournamentDetailsPage/data/prizes.ts new file mode 100644 index 0000000..1504b20 --- /dev/null +++ b/src/features/Tournaments/pages/TournamentDetailsPage/data/prizes.ts @@ -0,0 +1,23 @@ +import { Tournament } from "src/graphql"; + + +export const prizes: Tournament['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", +}] \ No newline at end of file diff --git a/src/graphql/index.tsx b/src/graphql/index.tsx index a8ff59b..9d63e7b 100644 --- a/src/graphql/index.tsx +++ b/src/graphql/index.tsx @@ -527,6 +527,7 @@ export type TournamentEvent = { export enum TournamentEventTypeEnum { IrlMeetup = 'IRLMeetup', + OnlineMeetup = 'OnlineMeetup', TwitterSpace = 'TwitterSpace', Workshop = 'Workshop' } diff --git a/tailwind.config.js b/tailwind.config.js index 71ca766..e5a3fba 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -100,5 +100,6 @@ module.exports = { plugins: [ require('@tailwindcss/forms'), require('@tailwindcss/line-clamp'), + require('@tailwindcss/typography'), ], } From 19780ea8156d9bdf1cbc762d0048ec031307e1ee Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Sun, 4 Sep 2022 13:14:08 +0300 Subject: [PATCH 14/53] feat: base maker card, markers tournament api schema --- api/functions/graphql/nexus-typegen.ts | 9 ++ api/functions/graphql/schema.graphql | 1 + api/functions/graphql/types/tournament.js | 20 +++ .../Profiles/Components/Avatar/Avatar.tsx | 4 +- .../EventsFilters/EventsFilters.tsx | 6 +- .../pages/MakersPage/MakerCard/MakerCard.tsx | 61 +++++++++ .../MakersFilters/MakersFilters.tsx | 51 +++++++ .../pages/MakersPage/MakersPage.tsx | 56 ++++++++ .../MakersPage/makersInTournament.graphql | 45 +++++++ .../Navigation/Navigation.tsx | 7 +- .../TournamentDetailsPage.tsx | 2 + src/graphql/index.tsx | 126 ++++++++++++++++++ src/mocks/handlers.ts | 36 +++++ 13 files changed, 413 insertions(+), 11 deletions(-) create mode 100644 src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx create mode 100644 src/features/Tournaments/pages/MakersPage/MakersFilters/MakersFilters.tsx create mode 100644 src/features/Tournaments/pages/MakersPage/MakersPage.tsx create mode 100644 src/features/Tournaments/pages/MakersPage/makersInTournament.graphql diff --git a/api/functions/graphql/nexus-typegen.ts b/api/functions/graphql/nexus-typegen.ts index 6ea9d98..d5efd5f 100644 --- a/api/functions/graphql/nexus-typegen.ts +++ b/api/functions/graphql/nexus-typegen.ts @@ -487,6 +487,7 @@ export interface NexusGenFieldTypes { getDonationsStats: NexusGenRootTypes['DonationsStats']; // DonationsStats! getFeed: NexusGenRootTypes['Post'][]; // [Post!]! getLnurlDetailsForProject: NexusGenRootTypes['LnurlDetails']; // LnurlDetails! + getMakersInTournament: NexusGenRootTypes['User'][]; // [User!]! getMyDrafts: NexusGenRootTypes['Post'][]; // [Post!]! getPostById: NexusGenRootTypes['Post']; // Post! getProject: NexusGenRootTypes['Project']; // Project! @@ -812,6 +813,7 @@ export interface NexusGenFieldTypeNames { getDonationsStats: 'DonationsStats' getFeed: 'Post' getLnurlDetailsForProject: 'LnurlDetails' + getMakersInTournament: 'User' getMyDrafts: 'Post' getPostById: 'Post' getProject: 'Project' @@ -1029,6 +1031,13 @@ export interface NexusGenArgTypes { getLnurlDetailsForProject: { // args project_id: number; // Int! } + getMakersInTournament: { // args + roleId?: number | null; // Int + search?: string | null; // String + skip?: number | null; // Int + take: number | null; // Int + tournamentId: number; // Int! + } getMyDrafts: { // args type: NexusGenEnums['POST_TYPE']; // POST_TYPE! } diff --git a/api/functions/graphql/schema.graphql b/api/functions/graphql/schema.graphql index 8b739e8..878e998 100644 --- a/api/functions/graphql/schema.graphql +++ b/api/functions/graphql/schema.graphql @@ -252,6 +252,7 @@ type Query { getDonationsStats: DonationsStats! getFeed(skip: Int = 0, sortBy: String, tag: Int = 0, take: Int = 10): [Post!]! getLnurlDetailsForProject(project_id: Int!): LnurlDetails! + getMakersInTournament(roleId: Int, search: String, skip: Int = 0, take: Int = 10, tournamentId: Int!): [User!]! getMyDrafts(type: POST_TYPE!): [Post!]! getPostById(id: Int!, type: POST_TYPE!): Post! getProject(id: Int!): Project! diff --git a/api/functions/graphql/types/tournament.js b/api/functions/graphql/types/tournament.js index e7a2768..f9b400a 100644 --- a/api/functions/graphql/types/tournament.js +++ b/api/functions/graphql/types/tournament.js @@ -7,6 +7,7 @@ const { enumType, } = require('nexus'); const { prisma } = require('../../../prisma'); +const { paginationArgs } = require('./helpers'); @@ -103,9 +104,28 @@ const getTournamentById = extendType({ } }) +const getMakersInTournament = extendType({ + type: "Query", + definition(t) { + t.nonNull.list.nonNull.field('getMakersInTournament', { + type: "User", + args: { + tournamentId: nonNull(intArg()), + ...paginationArgs({ take: 10 }), + search: stringArg(), + roleId: intArg(), + }, + resolve(_, { tournamentId }) { + return [] + } + }) + } +}) + module.exports = { // Types Tournament, // Queries getTournamentById, + getMakersInTournament, } \ No newline at end of file diff --git a/src/features/Profiles/Components/Avatar/Avatar.tsx b/src/features/Profiles/Components/Avatar/Avatar.tsx index 48d6995..01090b6 100644 --- a/src/features/Profiles/Components/Avatar/Avatar.tsx +++ b/src/features/Profiles/Components/Avatar/Avatar.tsx @@ -2,14 +2,14 @@ interface Props { src: string; alt?: string; - width?: number; + width?: number | string; } export default function Avatar({ src, alt, width = 40 }: Props) { return ( {alt ) } diff --git a/src/features/Tournaments/pages/EventsPage/EventsFilters/EventsFilters.tsx b/src/features/Tournaments/pages/EventsPage/EventsFilters/EventsFilters.tsx index 18ae1eb..e238c19 100644 --- a/src/features/Tournaments/pages/EventsPage/EventsFilters/EventsFilters.tsx +++ b/src/features/Tournaments/pages/EventsPage/EventsFilters/EventsFilters.tsx @@ -13,11 +13,7 @@ interface Props { export default function EventsFilters(props: Props) { - const options = [{ - label: "📆 All events", - value: null as TournamentEventTypeEnum | null, - }] - .concat(Object.values(TournamentEventTypeEnum).map((v: TournamentEventTypeEnum) => ({ label: mapTypeToBadge[v].text, value: v }))) + const options = Object.values(TournamentEventTypeEnum).map((v: TournamentEventTypeEnum) => ({ label: mapTypeToBadge[v].text, value: v })) return ( <> diff --git a/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx b/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx new file mode 100644 index 0000000..78c40c3 --- /dev/null +++ b/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx @@ -0,0 +1,61 @@ +import { IoLocationOutline } from 'react-icons/io5' +import Button from "src/Components/Button/Button" +import dayjs from "dayjs"; +import advancedFormat from 'dayjs/plugin/advancedFormat' +import { trimText } from "src/utils/helperFunctions"; +import { Override } from "src/utils/interfaces"; +import { GetMakersInTournamentQuery, GetMakersInTournamentQueryResult, Tag, Tournament, TournamentEventTypeEnum, User } from "src/graphql"; +import { UnionToObjectKeys } from 'src/utils/types/utils'; +import { useAppDispatch, } from "src/utils/hooks"; +import { openModal } from "src/redux/features/modals.slice"; +import Card from 'src/Components/Card/Card'; +import Avatar from 'src/features/Profiles/Components/Avatar/Avatar'; +import Badge from 'src/Components/Badge/Badge'; +import { PAGES_ROUTES } from 'src/utils/routing'; + +type MakerType = GetMakersInTournamentQuery['getMakersInTournament'][number] + +interface Props { + maker: GetMakersInTournamentQuery['getMakersInTournament'][number], + isMe?: boolean; +} + +export default function MakerCard({ maker }: Props) { + + const dispatch = useAppDispatch() + + + return ( + +
+
+ +
+
+

{maker.name}

+

{maker.jobTitle}

+
    + {maker.roles.map(role =>
  • {role.icon} {role.title}
  • )} +
+
+ +
+
+ +
+

🌈 Roles

+
    + {maker.roles.map(role =>
  • {role.icon}
  • )} +
+
+ +
+

🛠️ Skills

+
    + {maker.skills.map(skill =>
  • {skill.title}
  • )} +
+
+ +
+ ) +} diff --git a/src/features/Tournaments/pages/MakersPage/MakersFilters/MakersFilters.tsx b/src/features/Tournaments/pages/MakersPage/MakersFilters/MakersFilters.tsx new file mode 100644 index 0000000..fc43406 --- /dev/null +++ b/src/features/Tournaments/pages/MakersPage/MakersFilters/MakersFilters.tsx @@ -0,0 +1,51 @@ +import { FiSearch } from 'react-icons/fi' +import BasicSelectInput from 'src/Components/Inputs/Selects/BasicSelectInput/BasicSelectInput'; +import { GenericMakerRole, useGetAllRolesQuery } from 'src/graphql'; + +interface Props { + searchValue: string; + onSearchChange: (new_value: string) => void; + + roleValue: GenericMakerRole | null + onRoleChange: (new_value: GenericMakerRole | null) => void; +} + +export default function MakersFilters(props: Props) { + + const allRolesQuery = useGetAllRolesQuery(); + + const options = allRolesQuery.data?.getAllMakersRoles + + + return ( + <> +
+ + props.onSearchChange(e.target.value)} + /> +
+
+ {option.data.icon} {option.data.title} +
} + + /> + + ) +} + +// const x = Object.values(TournamentEventTypeEnum) \ No newline at end of file diff --git a/src/features/Tournaments/pages/MakersPage/MakersPage.tsx b/src/features/Tournaments/pages/MakersPage/MakersPage.tsx new file mode 100644 index 0000000..24dccf3 --- /dev/null +++ b/src/features/Tournaments/pages/MakersPage/MakersPage.tsx @@ -0,0 +1,56 @@ +import React, { useState } from 'react' +import { GenericMakerRole, Tournament, TournamentEventTypeEnum, useGetMakersInTournamentQuery, User } from 'src/graphql' +import MakerCard from './MakerCard/MakerCard'; +import EventCard from './MakerCard/MakerCard'; +import MakersFilters from './MakersFilters/MakersFilters'; +import EventsFilters from './MakersFilters/MakersFilters'; + +interface Props { + data: Pick +} + +export default function MakersPage({ data: { id } }: Props) { + + const query = useGetMakersInTournamentQuery({ + variables: { + tournamentId: id, + roleId: null, + search: null, + skip: null, + take: null, + }, + }) + + + const [searchFilter, setSearchFilter] = useState("") + const [roleFilter, setRoleFilter] = useState(null) + + if (query.loading) return <> + + return ( +
+
+
+ + {/* { + events + .filter(event => { + if (!searchFilter) return true; + return event.title.search(new RegExp(searchFilter, 'i')) !== -1 || event.description.search(new RegExp(searchFilter, 'i')) !== -1 + }) + .filter(event => { + if (!eventFilter) return true; + return event.type === eventFilter; + }) + .map(event => ) + } */} +
+
+ ) +} diff --git a/src/features/Tournaments/pages/MakersPage/makersInTournament.graphql b/src/features/Tournaments/pages/MakersPage/makersInTournament.graphql new file mode 100644 index 0000000..72828fa --- /dev/null +++ b/src/features/Tournaments/pages/MakersPage/makersInTournament.graphql @@ -0,0 +1,45 @@ +query GetMakersInTournament( + $tournamentId: Int! + $take: Int + $skip: Int + $search: String + $roleId: Int +) { + me { + id + name + avatar + jobTitle + ...UserRolesSkills + } + + getMakersInTournament( + tournamentId: $tournamentId + take: $take + skip: $skip + search: $search + roleId: $roleId + ) { + id + name + avatar + jobTitle + roles { + id + icon + title + } + skills { + id + title + } + } +} + +query GetAllRoles { + getAllMakersRoles { + id + title + icon + } +} diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx index 77ed8ea..2d17e71 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx +++ b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx @@ -24,9 +24,8 @@ export default function Navigation({ data }: Props) { path: "events", }, { - text: `????? 🚧`, + text: `Makers (${data.makers_count})`, path: "makers", - isDisabled: true, }, { text: `??????? 🚧`, @@ -43,10 +42,10 @@ export default function Navigation({ data }: Props) { path: "resources", isDisabled: true, }, - ], [data.events_count, data.makers_count, data.projects_count]) + ], [data.events_count, data.makers_count]) return ( -
+
diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx index d74bbea..a4b1d0e 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx +++ b/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx @@ -9,6 +9,7 @@ import { Helmet } from 'react-helmet' import Navigation from './Navigation/Navigation' import EventsPage from '../EventsPage/EventsPage' import { tournamentData } from './data' +import MakersPage from '../MakersPage/MakersPage' const data = tournamentData @@ -42,6 +43,7 @@ export default function TournamentDetailsPage() { } /> } /> } /> + } />
diff --git a/src/graphql/index.tsx b/src/graphql/index.tsx index 9d63e7b..feb5a39 100644 --- a/src/graphql/index.tsx +++ b/src/graphql/index.tsx @@ -330,6 +330,7 @@ export type Query = { getDonationsStats: DonationsStats; getFeed: Array; getLnurlDetailsForProject: LnurlDetails; + getMakersInTournament: Array; getMyDrafts: Array; getPostById: Post; getProject: Project; @@ -377,6 +378,15 @@ export type QueryGetLnurlDetailsForProjectArgs = { }; +export type QueryGetMakersInTournamentArgs = { + roleId: InputMaybe; + search: InputMaybe; + skip?: InputMaybe; + take?: InputMaybe; + tournamentId: Scalars['Int']; +}; + + export type QueryGetMyDraftsArgs = { type: Post_Type; }; @@ -790,6 +800,22 @@ export type ProjectDetailsQueryVariables = Exact<{ export type ProjectDetailsQuery = { __typename?: 'Query', getProject: { __typename?: 'Project', id: number, title: string, description: string, cover_image: string, thumbnail_image: string, screenshots: Array, website: string, lightning_address: string | null, lnurl_callback_url: string | null, votes_count: number, category: { __typename?: 'Category', id: number, title: string }, awards: Array<{ __typename?: 'Award', title: string, image: string, url: string, id: number }>, tags: Array<{ __typename?: 'Tag', id: number, title: string }> } }; +export type GetMakersInTournamentQueryVariables = Exact<{ + tournamentId: Scalars['Int']; + take: InputMaybe; + skip: InputMaybe; + search: InputMaybe; + roleId: InputMaybe; +}>; + + +export type GetMakersInTournamentQuery = { __typename?: 'Query', me: { __typename?: 'MyProfile', id: number, name: string, avatar: string, jobTitle: string | null, skills: Array<{ __typename?: 'MakerSkill', id: number, title: string }>, roles: Array<{ __typename?: 'MakerRole', id: number, title: string, icon: string, level: RoleLevelEnum }> } | null, getMakersInTournament: Array<{ __typename?: 'User', id: number, name: string, avatar: string, jobTitle: string | null, roles: Array<{ __typename?: 'MakerRole', id: number, icon: string, title: string }>, skills: Array<{ __typename?: 'MakerSkill', id: number, title: string }> }> }; + +export type GetAllRolesQueryVariables = Exact<{ [key: string]: never; }>; + + +export type GetAllRolesQuery = { __typename?: 'Query', getAllMakersRoles: Array<{ __typename?: 'GenericMakerRole', id: number, title: string, icon: string }> }; + export type GetTournamentByIdQueryVariables = Exact<{ id: Scalars['Int']; }>; @@ -2120,6 +2146,106 @@ export function useProjectDetailsLazyQuery(baseOptions?: Apollo.LazyQueryHookOpt export type ProjectDetailsQueryHookResult = ReturnType; export type ProjectDetailsLazyQueryHookResult = ReturnType; export type ProjectDetailsQueryResult = Apollo.QueryResult; +export const GetMakersInTournamentDocument = gql` + query GetMakersInTournament($tournamentId: Int!, $take: Int, $skip: Int, $search: String, $roleId: Int) { + me { + id + name + avatar + jobTitle + ...UserRolesSkills + } + getMakersInTournament( + tournamentId: $tournamentId + take: $take + skip: $skip + search: $search + roleId: $roleId + ) { + id + name + avatar + jobTitle + roles { + id + icon + title + } + skills { + id + title + } + } +} + ${UserRolesSkillsFragmentDoc}`; + +/** + * __useGetMakersInTournamentQuery__ + * + * To run a query within a React component, call `useGetMakersInTournamentQuery` and pass it any options that fit your needs. + * When your component renders, `useGetMakersInTournamentQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetMakersInTournamentQuery({ + * variables: { + * tournamentId: // value for 'tournamentId' + * take: // value for 'take' + * skip: // value for 'skip' + * search: // value for 'search' + * roleId: // value for 'roleId' + * }, + * }); + */ +export function useGetMakersInTournamentQuery(baseOptions: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(GetMakersInTournamentDocument, options); + } +export function useGetMakersInTournamentLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(GetMakersInTournamentDocument, options); + } +export type GetMakersInTournamentQueryHookResult = ReturnType; +export type GetMakersInTournamentLazyQueryHookResult = ReturnType; +export type GetMakersInTournamentQueryResult = Apollo.QueryResult; +export const GetAllRolesDocument = gql` + query GetAllRoles { + getAllMakersRoles { + id + title + icon + } +} + `; + +/** + * __useGetAllRolesQuery__ + * + * To run a query within a React component, call `useGetAllRolesQuery` and pass it any options that fit your needs. + * When your component renders, `useGetAllRolesQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetAllRolesQuery({ + * variables: { + * }, + * }); + */ +export function useGetAllRolesQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(GetAllRolesDocument, options); + } +export function useGetAllRolesLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(GetAllRolesDocument, options); + } +export type GetAllRolesQueryHookResult = ReturnType; +export type GetAllRolesLazyQueryHookResult = ReturnType; +export type GetAllRolesQueryResult = Apollo.QueryResult; export const GetTournamentByIdDocument = gql` query GetTournamentById($id: Int!) { getTournamentById(id: $id) { diff --git a/src/mocks/handlers.ts b/src/mocks/handlers.ts index 162b58b..947345f 100644 --- a/src/mocks/handlers.ts +++ b/src/mocks/handlers.ts @@ -33,6 +33,8 @@ import { MyProfilePreferencesQuery, GetTournamentByIdQuery, MyProfileRolesSkillsQuery, + GetAllRolesQuery, + GetMakersInTournamentQuery, } from 'src/graphql' const delay = (ms = 1000) => new Promise((res) => setTimeout(res, ms + Math.random() * 1000)) @@ -216,6 +218,19 @@ export const handlers = [ ) }), + + graphql.query('MyProfileRolesSkills', async (req, res, ctx) => { + await delay() + return res( + ctx.data({ + me: { ...me() }, + getAllMakersRoles: getAllMakersRoles(), + getAllMakersSkills: getAllMakersSkills(), + }) + ) + }), + + graphql.query('MyProfilePreferences', async (req, res, ctx) => { await delay() return res( @@ -270,4 +285,25 @@ export const handlers = [ ) }), + graphql.query('GetMakersInTournament', async (req, res, ctx) => { + await delay() + + return res( + ctx.data({ + me: { ...me() }, + getMakersInTournament: [] + }) + ) + }), + + graphql.query('GetAllRoles', async (req, res, ctx) => { + await delay() + + return res( + ctx.data({ + getAllMakersRoles: getAllMakersRoles() + }) + ) + }), + ] \ No newline at end of file From d9a5db2a9dbebe6618b8bf2d5cd63a75676f7338 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Mon, 5 Sep 2022 11:01:20 +0300 Subject: [PATCH 15/53] update: users mocks typing --- src/mocks/data.ts | 5 +- src/mocks/data/users.ts | 185 +++++++++++++++++++++++++++++++--------- 2 files changed, 148 insertions(+), 42 deletions(-) diff --git a/src/mocks/data.ts b/src/mocks/data.ts index c1f5e00..cefe8de 100644 --- a/src/mocks/data.ts +++ b/src/mocks/data.ts @@ -2,7 +2,7 @@ import { hackathons } from "./data/hackathon"; import { posts, feed, generatePostComments } from "./data/posts"; import { categories, projects } from "./data/projects"; import { tournaments } from "./data/tournament"; -import { allMakersRoles, allMakersSkills, user } from "./data/users"; +import { allMakersRoles, allMakersSkills, users } from "./data/users"; export const MOCK_DATA = { projects, @@ -11,7 +11,8 @@ export const MOCK_DATA = { feed, hackathons, generatePostComments: generatePostComments, - user: user, + user: users[0], + users: users, tournaments: tournaments, allMakersRoles: allMakersRoles, allMakersSkills: allMakersSkills, diff --git a/src/mocks/data/users.ts b/src/mocks/data/users.ts index ec9ef73..4f75248 100644 --- a/src/mocks/data/users.ts +++ b/src/mocks/data/users.ts @@ -1,5 +1,5 @@ import { Chance } from "chance"; -import { GenericMakerRole, MakerSkill, MyProfile, RoleLevelEnum, User, Tournament } from "src/graphql"; +import { GenericMakerRole, MakerSkill, MyProfile, RoleLevelEnum, Tournament, User } from "src/graphql"; import { randomItem, randomItems } from "src/utils/helperFunctions"; import { posts } from "./posts"; import { getCoverImage, getAvatarImage } from "./utils"; @@ -97,7 +97,51 @@ export const allMakersSkills: MakerSkill[] = [ }, ] -export const user: User & MyProfile = { +const similar_makers = [ + { + id: 144, + name: "Johns Beharry", + jobTitle: "Manager", + avatar: getAvatarImage(), + }, + { + id: 155, + name: "Edward P", + jobTitle: "Front-end Developer", + avatar: getAvatarImage(), + }, + { + id: 123, + name: "Mohammed T", + jobTitle: "Front-end Developer", + avatar: getAvatarImage(), + }, +] as User[] + +const tournaments = [ + { + id: 1, + title: "BreezConf", + description: chance.paragraph(), + cover_image: getCoverImage(), + thumbnail_image: getCoverImage(), + start_date: new Date(2021, 3).toISOString(), + end_date: new Date(2021, 4).toISOString(), + website: "https://breez-conf.com", + }, + { + id: 2, + title: "Shock the Web 3", + description: chance.paragraph(), + cover_image: getCoverImage(), + thumbnail_image: getCoverImage(), + start_date: new Date(2022, 7).toISOString(), + end_date: new Date(2022, 11).toISOString(), + website: "https://shock-the-web.com" + }, +] as Tournament[]; + +export const users: (User | MyProfile)[] = [{ id: 123, email: "mtg0987654321@gmail.com", avatar: "https://avatars.dicebear.com/api/bottts/Mtgmtg.svg", @@ -128,50 +172,111 @@ export const user: User & MyProfile = { },], roles: randomItems(3, ...allMakersRoles).map(role => ({ ...role, level: randomItem(...Object.values(RoleLevelEnum)) })), skills: randomItems(7, ...allMakersSkills), - tournaments: [ - { - id: 1, - title: "BreezConf", - description: chance.paragraph(), - cover_image: getCoverImage(), - thumbnail_image: getCoverImage(), - start_date: new Date(2021, 3).toISOString(), - end_date: new Date(2021, 4).toISOString(), - website: "https://breez-conf.com", + tournaments, + similar_makers +}, +{ + id: 441, + email: "eddy@gmail.com", + avatar: "https://avatars.dicebear.com/api/bottts/Eduardu.svg", + bio: "Lorem asiop asklh kluiw wekjhl shkj kljhsva klu khsc klhlkbs mjklwqr kmlk sadlfui mewr qiumnk, asdjomi cskhsdf.", + name: "Edward P", + github: "barefoot_88", + jobTitle: "Senior Product Designer", + join_date: new Date(2021).toISOString(), + lightning_address: "ed@getalby.com", + linkedin: "https://www.linkedin.com/in/mtg-softwares-dev/", + location: "Germany, Berlin", + role: "user", + twitter: "john-doe", + website: "https://mtg-dev.tech", + stories: posts.stories, + nostr_prv_key: "123123124asdfsadfsa8d7fsadfasdf", + nostr_pub_key: "123124123123dfsadfsa8d7f11sadfasdf", - } as Tournament, + walletsKeys: [ { - id: 2, - title: "Shock the Web 3", - description: chance.paragraph(), - cover_image: getCoverImage(), - thumbnail_image: getCoverImage(), - start_date: new Date(2022, 7).toISOString(), - end_date: new Date(2022, 11).toISOString(), - website: "https://shock-the-web.com", - - } as Tournament, - ], - similar_makers: [ - { - id: 144, - name: "Johns Beharry", - jobTitle: "Manager", - avatar: getAvatarImage(), + key: "1645h234j2421zxvertw", + name: "My Alby wallet key", + is_current: true }, { - id: 155, - name: "Edward P", - jobTitle: "Front-end Developer", - avatar: getAvatarImage(), + key: "66345134234235", + name: "My Phoenix wallet key", + is_current: false + },], + roles: randomItems(3, ...allMakersRoles).map(role => ({ ...role, level: randomItem(...Object.values(RoleLevelEnum)) })), + skills: randomItems(7, ...allMakersSkills), + tournaments, + similar_makers +}, +{ + id: 422, + email: "johns@gmail.com", + avatar: "https://avatars.dicebear.com/api/bottts/Johns.svg", + bio: "Lorem asiop asklh kluiw wekjhl shkj kljhsva klu khsc klhlkbs mjklwqr kmlk sadlfui mewr qiumnk, asdjomi cskhsdf.", + name: "Johns Beharry", + github: "johnsbehhary", + jobTitle: "Manager", + join_date: new Date(2021).toISOString(), + lightning_address: "johns@getalby.com", + linkedin: "https://www.linkedin.com/in/mtg-softwares-dev/", + location: "Germany, Berlin", + role: "user", + twitter: "john-doe", + website: "https://mtg-dev.tech", + stories: posts.stories, + nostr_prv_key: "123123124asdfsadfsa8d7fsadfasdf", + nostr_pub_key: "123124123123dfsadfsa8d7f11sadfasdf", + walletsKeys: [ + { + key: "1645h234j2421zxvertw", + name: "My Alby wallet key", + is_current: true }, { - id: 166, - name: "Mohammed T", - jobTitle: "Front-end Developer", - avatar: getAvatarImage(), + key: "66345134234235", + name: "My Phoenix wallet key", + is_current: false + },], + roles: randomItems(3, ...allMakersRoles).map(role => ({ ...role, level: randomItem(...Object.values(RoleLevelEnum)) })), + skills: randomItems(7, ...allMakersSkills), + tournaments, + similar_makers +}, +{ + id: 511, + email: "carlos@gmail.com", + avatar: "https://avatars.dicebear.com/api/bottts/Carlos.svg", + bio: "Lorem asiop asklh kluiw wekjhl shkj kljhsva klu khsc klhlkbs mjklwqr kmlk sadlfui mewr qiumnk, asdjomi cskhsdf.", + name: "Mohammed Taher ", + github: "MTG2000", + jobTitle: "Back-end Web Developer", + join_date: new Date(2021).toISOString(), + lightning_address: "carlos@getalby.com", + linkedin: "https://www.linkedin.com/in/mtg-softwares-dev/", + location: "Germany, Berlin", + role: "user", + twitter: "john-doe", + website: "https://mtg-dev.tech", + stories: posts.stories, + nostr_prv_key: "123123124asdfsadfsa8d7fsadfasdf", + nostr_pub_key: "123124123123dfsadfsa8d7f11sadfasdf", + walletsKeys: [ + { + key: "1645h234j2421zxvertw", + name: "My Alby wallet key", + is_current: true }, - ] as User[] -} + { + key: "66345134234235", + name: "My Phoenix wallet key", + is_current: false + },], + roles: randomItems(3, ...allMakersRoles).map(role => ({ ...role, level: randomItem(...Object.values(RoleLevelEnum)) })), + skills: randomItems(7, ...allMakersSkills), + tournaments, + similar_makers +}] From e727cc6aa934204f6b46e768f6f659a3db45669e Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Mon, 5 Sep 2022 14:46:37 +0300 Subject: [PATCH 16/53] feat: makers page base filters, maker card skeleton, update mocks api --- src/Components/IconButton/IconButton.tsx | 10 +- .../BasicSelectInput/BasicSelectInput.tsx | 10 +- .../pages/ExplorePage/Header/Header.tsx | 26 ++-- .../MakerCard/MakerCard.Skeleton.tsx | 39 +++++ .../pages/MakersPage/MakerCard/MakerCard.tsx | 17 +-- .../MakersFilters/MakersFilters.tsx | 10 +- .../pages/MakersPage/MakersPage.tsx | 142 +++++++++++++----- .../TournamentDetailsPage/data/events.ts | 2 +- src/mocks/data/users.ts | 2 +- src/mocks/handlers.ts | 7 +- src/mocks/resolvers.ts | 23 ++- src/utils/routing/routes.ts | 6 + 12 files changed, 224 insertions(+), 70 deletions(-) create mode 100644 src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.Skeleton.tsx diff --git a/src/Components/IconButton/IconButton.tsx b/src/Components/IconButton/IconButton.tsx index 407052e..7a3ea33 100644 --- a/src/Components/IconButton/IconButton.tsx +++ b/src/Components/IconButton/IconButton.tsx @@ -9,6 +9,7 @@ interface Props { className?: string size?: "sm" | 'md' | 'lg' variant?: 'blank' | 'fill' + isDisabled?: boolean } @@ -32,7 +33,8 @@ const IconButton = React.forwardRef>(({ children, onClick = () => { }, onKeyDown, - variant = 'blank' + variant = 'blank', + isDisabled, }, ref) => { if (href) @@ -57,12 +59,16 @@ const IconButton = React.forwardRef>(({ ref={ref} type='button' className={` + ${className} ${sizeToPadding[size]} ${baseBtnStyles[variant]} - active:scale-95 rounded-full ${className}`} + active:scale-95 rounded-full + ${isDisabled && "opacity-60"} + `} style={{ lineHeight: 0 }} onClick={onClick} onKeyDown={onKeyDown} + disabled={isDisabled} > {children} diff --git a/src/Components/Inputs/Selects/BasicSelectInput/BasicSelectInput.tsx b/src/Components/Inputs/Selects/BasicSelectInput/BasicSelectInput.tsx index 10850cb..00d3d0a 100644 --- a/src/Components/Inputs/Selects/BasicSelectInput/BasicSelectInput.tsx +++ b/src/Components/Inputs/Selects/BasicSelectInput/BasicSelectInput.tsx @@ -122,7 +122,15 @@ export default function BasicSelectInput, IsMulti } function getOptionComponent>(renderOption: Props['renderOption'], labelField: Props['labelField']) { - const _render = renderOption ?? ((option) =>
+ const _render = renderOption ?? ((option) =>
{option.data[labelField]}
) diff --git a/src/features/Projects/pages/ExplorePage/Header/Header.tsx b/src/features/Projects/pages/ExplorePage/Header/Header.tsx index 0c2891c..9f67dec 100644 --- a/src/features/Projects/pages/ExplorePage/Header/Header.tsx +++ b/src/features/Projects/pages/ExplorePage/Header/Header.tsx @@ -7,6 +7,18 @@ import useEmblaCarousel from 'embla-carousel-react' import { useCallback, useEffect, useState } from "react"; const headerLinks = [ + { + title: + <> +

The Long Night tournament is coming!!!

+

1st Oct - 31st Nov, 2022

+ , + img: "https://imagedelivery.net/wyrwp3c-j0gDDUWgnE7lig/1d5d2c86-fe46-4478-6909-bb3c425c0d00/public", + link: { + content: "Register Now", + url: "/tournaments/12", + }, + }, { title:

Explore a fun directory of lightning web apps

, img: Assets.Images_ExploreHeader1, @@ -15,18 +27,6 @@ const headerLinks = [ url: "https://form.jotform.com/220301236112030", }, }, - { - title: - <> -

Take part in BOLT🔩FUN’s Shock the Web 2 ⚡️

-

16th - 19th June, 2022

- , - img: Assets.Images_ExploreHeader2, - link: { - content: "Register Now", - url: "https://bolt.fun/hackathons/shock-the-web-2/", - }, - }, ]; @@ -72,7 +72,7 @@ export default function Header() { {headerLinks[0].title}
-
diff --git a/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.Skeleton.tsx b/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.Skeleton.tsx new file mode 100644 index 0000000..935d929 --- /dev/null +++ b/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.Skeleton.tsx @@ -0,0 +1,39 @@ +import Card from 'src/Components/Card/Card'; +import Badge from 'src/Components/Badge/Badge'; +import Skeleton from 'react-loading-skeleton'; + + +export default function MakerCardSkeleton() { + + + return ( + +
+
+ +
+
+

+

+
    + {Array(3).fill(0).map((_, idx) =>
  • Loading role
  • )} +
+
+
+
+ +
+

+
    + {Array(3).fill(0).map((_, idx) =>
  • Loading role
  • )} +
+
+ +
+

+
    + {Array(3).fill(0).map((_, idx) =>
  • Loading role
  • )}
+
+
+ ) +} diff --git a/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx b/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx index 78c40c3..1f21365 100644 --- a/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx +++ b/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx @@ -11,7 +11,7 @@ import { openModal } from "src/redux/features/modals.slice"; import Card from 'src/Components/Card/Card'; import Avatar from 'src/features/Profiles/Components/Avatar/Avatar'; import Badge from 'src/Components/Badge/Badge'; -import { PAGES_ROUTES } from 'src/utils/routing'; +import { createRoute, PAGES_ROUTES } from 'src/utils/routing'; type MakerType = GetMakersInTournamentQuery['getMakersInTournament'][number] @@ -20,7 +20,7 @@ interface Props { isMe?: boolean; } -export default function MakerCard({ maker }: Props) { +export default function MakerCard({ maker, isMe }: Props) { const dispatch = useAppDispatch() @@ -35,27 +35,26 @@ export default function MakerCard({ maker }: Props) {

{maker.name}

{maker.jobTitle}

    - {maker.roles.map(role =>
  • {role.icon} {role.title}
  • )} + {maker.roles.map(role =>
  • {role.icon} {role.title}
  • )}
- + {isMe && }

🌈 Roles

-
    - {maker.roles.map(role =>
  • {role.icon}
  • )} +
      + {maker.roles.map(role =>
    • {role.icon} {role.title}
    • )}

🛠️ Skills

    - {maker.skills.map(skill =>
  • {skill.title}
  • )} + {maker.skills.map(skill =>
  • {skill.title}
  • )}
- - + {isMe && } ) } diff --git a/src/features/Tournaments/pages/MakersPage/MakersFilters/MakersFilters.tsx b/src/features/Tournaments/pages/MakersPage/MakersFilters/MakersFilters.tsx index fc43406..ff53b3b 100644 --- a/src/features/Tournaments/pages/MakersPage/MakersFilters/MakersFilters.tsx +++ b/src/features/Tournaments/pages/MakersPage/MakersFilters/MakersFilters.tsx @@ -39,7 +39,15 @@ export default function MakersFilters(props: Props) { value={props.roleValue} onChange={props.onRoleChange} options={options ?? []} - renderOption={option =>
+ renderOption={option =>
{option.data.icon} {option.data.title}
} diff --git a/src/features/Tournaments/pages/MakersPage/MakersPage.tsx b/src/features/Tournaments/pages/MakersPage/MakersPage.tsx index 24dccf3..3aa1a5b 100644 --- a/src/features/Tournaments/pages/MakersPage/MakersPage.tsx +++ b/src/features/Tournaments/pages/MakersPage/MakersPage.tsx @@ -1,56 +1,128 @@ -import React, { useState } from 'react' -import { GenericMakerRole, Tournament, TournamentEventTypeEnum, useGetMakersInTournamentQuery, User } from 'src/graphql' +import { NetworkStatus } from '@apollo/client'; +import { useDebouncedCallback, useDebouncedState } from '@react-hookz/web'; +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' +import { FaChevronLeft, FaChevronRight } from 'react-icons/fa'; +import IconButton from 'src/Components/IconButton/IconButton'; +import LoadingPage from 'src/Components/LoadingPage/LoadingPage'; +import { GenericMakerRole, GetMakersInTournamentQueryVariables, Tournament, useGetMakersInTournamentQuery, User } from 'src/graphql' +import ScrollToTop from 'src/utils/routing/scrollToTop'; import MakerCard from './MakerCard/MakerCard'; -import EventCard from './MakerCard/MakerCard'; +import MakerCardSkeleton from './MakerCard/MakerCard.Skeleton'; import MakersFilters from './MakersFilters/MakersFilters'; -import EventsFilters from './MakersFilters/MakersFilters'; interface Props { data: Pick } +const ITEMS_PER_PAGE = 15; + export default function MakersPage({ data: { id } }: Props) { + const [page, setPage] = useState(0) + const [searchFilter, setSearchFilter] = useState(""); + const [debouncedsearchFilter, setDebouncedSearchFilter] = useDebouncedState("", 500); + const [roleFilter, setRoleFilter] = useState(null); + + const loadingContainerCbRef = useCallback((e: HTMLDivElement) => { + if (e) + e.scrollIntoView({ + behavior: 'smooth', + block: "center" + }) + }, []) + + const [queryFilter, setQueryFilter] = useState({ + tournamentId: id, + roleId: roleFilter?.id ?? null, + search: debouncedsearchFilter, + skip: ITEMS_PER_PAGE * page, + take: ITEMS_PER_PAGE, + }); + + const query = useGetMakersInTournamentQuery({ - variables: { - tournamentId: id, - roleId: null, - search: null, - skip: null, - take: null, - }, - }) + variables: queryFilter, + notifyOnNetworkStatusChange: true, + }); - const [searchFilter, setSearchFilter] = useState("") - const [roleFilter, setRoleFilter] = useState(null) + useEffect(() => { + setPage(0); + setQueryFilter(f => ({ ...f, search: debouncedsearchFilter, roleId: roleFilter?.id ?? null, skip: 0 })) + }, [debouncedsearchFilter, roleFilter]); + + + + + + if (query.networkStatus === NetworkStatus.loading) return + + + const changeSearchFilter = (new_value: string) => { + setSearchFilter(new_value); + setDebouncedSearchFilter(new_value); + } + + + const nextPage = () => { + setPage(p => p + 1) + setQueryFilter(f => ({ ...f, skip: (f.skip ?? 0) + ITEMS_PER_PAGE })) + } + const prevPage = () => { + if (page === 0) return + setPage(p => p - 1) + setQueryFilter(f => ({ ...f, skip: (f.skip ?? 0) - ITEMS_PER_PAGE })) + } + + + const isFetchingMore = query.networkStatus === NetworkStatus.setVariables; + const itemsCount = query.data?.getMakersInTournament && query.data.getMakersInTournament.length; - if (query.loading) return <> return (
-
-
- - {/* { - events - .filter(event => { - if (!searchFilter) return true; - return event.title.search(new RegExp(searchFilter, 'i')) !== -1 || event.description.search(new RegExp(searchFilter, 'i')) !== -1 - }) - .filter(event => { - if (!eventFilter) return true; - return event.type === eventFilter; - }) - .map(event => ) - } */} +
+ +
+

Makers 👾

+ +
+ +
+
+ {isFetchingMore ? + <> +
+ +
+ + + + : + (itemsCount !== 0 ? + query.data?.getMakersInTournament.map(maker => ) : +
+

No makers found here...

+
) + } + + +
+ + + + + + +
+
) } diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/data/events.ts b/src/features/Tournaments/pages/TournamentDetailsPage/data/events.ts index 58cdc6c..5156e37 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/data/events.ts +++ b/src/features/Tournaments/pages/TournamentDetailsPage/data/events.ts @@ -68,7 +68,7 @@ export const events: Tournament['events'] = [ image: getCoverImage(), links: [], location: "Online", - type: TournamentEventTypeEnum.Workshop, + type: TournamentEventTypeEnum.OnlineMeetup, website: "https://event.name" }, ] \ No newline at end of file diff --git a/src/mocks/data/users.ts b/src/mocks/data/users.ts index 4f75248..5ac031c 100644 --- a/src/mocks/data/users.ts +++ b/src/mocks/data/users.ts @@ -141,7 +141,7 @@ const tournaments = [ }, ] as Tournament[]; -export const users: (User | MyProfile)[] = [{ +export const users: (User & MyProfile)[] = [{ id: 123, email: "mtg0987654321@gmail.com", avatar: "https://avatars.dicebear.com/api/bottts/Mtgmtg.svg", diff --git a/src/mocks/handlers.ts b/src/mocks/handlers.ts index 947345f..06630e1 100644 --- a/src/mocks/handlers.ts +++ b/src/mocks/handlers.ts @@ -1,6 +1,6 @@ import { graphql } from 'msw' -import { allCategories, getAllHackathons, getAllMakersRoles, getAllMakersSkills, getCategory, getFeed, getMyDrafts, getPostById, getProject, getTournamentById, getTrendingPosts, hottestProjects, me, newProjects, popularTags, profile, projectsByCategory, searchProjects } from './resolvers' +import { allCategories, getAllHackathons, getAllMakersRoles, getAllMakersSkills, getCategory, getFeed, getMakersInTournament, getMyDrafts, getPostById, getProject, getTournamentById, getTrendingPosts, hottestProjects, me, newProjects, popularTags, profile, projectsByCategory, searchProjects } from './resolvers' import { NavCategoriesQuery, ExploreProjectsQuery, @@ -35,6 +35,7 @@ import { MyProfileRolesSkillsQuery, GetAllRolesQuery, GetMakersInTournamentQuery, + GetMakersInTournamentQueryVariables, } from 'src/graphql' const delay = (ms = 1000) => new Promise((res) => setTimeout(res, ms + Math.random() * 1000)) @@ -285,13 +286,13 @@ export const handlers = [ ) }), - graphql.query('GetMakersInTournament', async (req, res, ctx) => { + graphql.query('GetMakersInTournament', async (req, res, ctx) => { await delay() return res( ctx.data({ me: { ...me() }, - getMakersInTournament: [] + getMakersInTournament: getMakersInTournament(req.variables) }) ) }), diff --git a/src/mocks/resolvers.ts b/src/mocks/resolvers.ts index 93660b8..b5ffa36 100644 --- a/src/mocks/resolvers.ts +++ b/src/mocks/resolvers.ts @@ -1,5 +1,5 @@ import { MOCK_DATA } from "./data"; -import { MyProfile, Query, QueryGetFeedArgs, QueryGetPostByIdArgs, User } from 'src/graphql' +import { GetMakersInTournamentQueryVariables, MyProfile, Query, QueryGetFeedArgs, QueryGetPostByIdArgs, User } from 'src/graphql' import { Chance } from "chance"; import { tags } from "./data/tags"; import { hackathons } from "./data/hackathon"; @@ -78,8 +78,6 @@ export function me() { } as MyProfile } - - export function profile() { return { ...MOCK_DATA['user'], __typename: 'User' } as User } @@ -97,4 +95,21 @@ export function getMyDrafts(): Query['getMyDrafts'] { export function getTournamentById(id: number) { return MOCK_DATA['tournaments'][0] -} \ No newline at end of file +} + +export function getMakersInTournament(vars: GetMakersInTournamentQueryVariables) { + + const offsetStart = vars.skip ?? 0; + const offsetEnd = offsetStart + (vars.take ?? 15) + + return MOCK_DATA.users.slice(1) + .filter(u => { + if (!vars.search) return true; + return [u.name, u.jobTitle].some(attr => attr?.search(new RegExp(vars.search!, 'i')) !== -1) + }) + .filter(u => { + if (!vars.roleId) return true; + return u.roles.some(r => r.id === vars.roleId) + }) + .slice(offsetStart, offsetEnd) as User[]; +} \ No newline at end of file diff --git a/src/utils/routing/routes.ts b/src/utils/routing/routes.ts index 29613d1..500aabc 100644 --- a/src/utils/routing/routes.ts +++ b/src/utils/routing/routes.ts @@ -31,6 +31,9 @@ type RouteOptions = id: string | number, username?: string, } + | { + type: "edit-profile", + } export function createRoute(options: RouteOptions) { @@ -57,6 +60,9 @@ export function createRoute(options: RouteOptions) { return `/profile/${options.id}` + (options.username ? `/${toSlug(options.username)}` : ""); + if (options.type === 'edit-profile') + return '/edit-profile' + return "" } From 086dac87150cd2781d91fbe7765fb671dbbe31bb Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Mon, 5 Sep 2022 15:32:31 +0300 Subject: [PATCH 17/53] feat: return mock users in makers tab, empty state for maker card --- api/functions/graphql/nexus-typegen.ts | 1 - api/functions/graphql/types/tournament.js | 40 ++++++++++++++++++- .../pages/MakersPage/MakerCard/MakerCard.tsx | 24 ++++++++--- .../pages/MakersPage/MakersPage.tsx | 2 +- 4 files changed, 57 insertions(+), 10 deletions(-) diff --git a/api/functions/graphql/nexus-typegen.ts b/api/functions/graphql/nexus-typegen.ts index d5efd5f..4161f06 100644 --- a/api/functions/graphql/nexus-typegen.ts +++ b/api/functions/graphql/nexus-typegen.ts @@ -203,7 +203,6 @@ export interface NexusGenObjects { lnurl_callback_url?: string | null; // String screenshots: string[]; // [String!]! thumbnail_image: string; // String! - title: string; // String! votes_count: number; // Int! website: string; // String! } diff --git a/api/functions/graphql/types/tournament.js b/api/functions/graphql/types/tournament.js index f9b400a..a69484f 100644 --- a/api/functions/graphql/types/tournament.js +++ b/api/functions/graphql/types/tournament.js @@ -115,8 +115,44 @@ const getMakersInTournament = extendType({ search: stringArg(), roleId: intArg(), }, - resolve(_, { tournamentId }) { - return [] + resolve(_, args) { + + + let filters = []; + + if (args.search) filters.push({ + OR: [ + { + name: { + contains: args.search, + mode: 'insensitive' + }, + jobTitle: { + contains: args.search, + mode: 'insensitive' + } + } + ] + }) + + if (args.roleId) filters.push({ + roles: { + some: { + roleId: args.roleId + } + } + }) + + + return prisma.user.findMany({ + ...(filters.length > 0 && { + where: { + AND: filters + } + }), + skip: args.skip, + take: args.take, + }) } }) } diff --git a/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx b/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx index 1f21365..3ab8a55 100644 --- a/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx +++ b/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx @@ -33,27 +33,39 @@ export default function MakerCard({ maker, isMe }: Props) {

{maker.name}

-

{maker.jobTitle}

-
    + {maker.jobTitle ?

    {maker.jobTitle}

    + : +

    No job title

    } + {maker.roles.length ?
      {maker.roles.map(role =>
    • {role.icon} {role.title}
    • )}
    + : +

    No roles added

    + }
{isMe && }

-

🌈 Roles

-
    +

    🌈 Roles

    + + {maker.roles.length ?
      {maker.roles.map(role =>
    • {role.icon} {role.title}
    • )}
    + : +

    No roles added

    + }
-

🛠️ Skills

-
    +

    🛠️ Skills

    + {maker.skills.length ?
      {maker.skills.map(skill =>
    • {skill.title}
    • )}
    + : +

    No skills added

    + }
{isMe && } ) diff --git a/src/features/Tournaments/pages/MakersPage/MakersPage.tsx b/src/features/Tournaments/pages/MakersPage/MakersPage.tsx index 3aa1a5b..bc18640 100644 --- a/src/features/Tournaments/pages/MakersPage/MakersPage.tsx +++ b/src/features/Tournaments/pages/MakersPage/MakersPage.tsx @@ -83,7 +83,7 @@ export default function MakersPage({ data: { id } }: Props) { return (
- + {(query.data?.me ?? query.previousData?.me) && }

Makers 👾

From b2d073efcbd5a05ca3d2c3b7a1ce6d9ea02cbbd0 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Mon, 5 Sep 2022 15:59:17 +0300 Subject: [PATCH 18/53] fix: makers filters bug --- api/functions/graphql/nexus-typegen.ts | 1 + api/functions/graphql/types/tournament.js | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/api/functions/graphql/nexus-typegen.ts b/api/functions/graphql/nexus-typegen.ts index 4161f06..d5efd5f 100644 --- a/api/functions/graphql/nexus-typegen.ts +++ b/api/functions/graphql/nexus-typegen.ts @@ -203,6 +203,7 @@ export interface NexusGenObjects { lnurl_callback_url?: string | null; // String screenshots: string[]; // [String!]! thumbnail_image: string; // String! + title: string; // String! votes_count: number; // Int! website: string; // String! } diff --git a/api/functions/graphql/types/tournament.js b/api/functions/graphql/types/tournament.js index a69484f..3617f44 100644 --- a/api/functions/graphql/types/tournament.js +++ b/api/functions/graphql/types/tournament.js @@ -126,7 +126,9 @@ const getMakersInTournament = extendType({ name: { contains: args.search, mode: 'insensitive' - }, + } + }, + { jobTitle: { contains: args.search, mode: 'insensitive' @@ -135,6 +137,7 @@ const getMakersInTournament = extendType({ ] }) + if (args.roleId) filters.push({ roles: { some: { @@ -143,6 +146,8 @@ const getMakersInTournament = extendType({ } }) + console.log(filters[0]); + return prisma.user.findMany({ ...(filters.length > 0 && { From 7b285f75177507b423affe320a2ed825e8b44286 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Mon, 5 Sep 2022 15:59:40 +0300 Subject: [PATCH 19/53] chore: remove log --- api/functions/graphql/types/tournament.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/api/functions/graphql/types/tournament.js b/api/functions/graphql/types/tournament.js index 3617f44..c8aaffa 100644 --- a/api/functions/graphql/types/tournament.js +++ b/api/functions/graphql/types/tournament.js @@ -146,8 +146,6 @@ const getMakersInTournament = extendType({ } }) - console.log(filters[0]); - return prisma.user.findMany({ ...(filters.length > 0 && { From 939832a7ac1cc5c91f2a5966921cdd11253ecea9 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Mon, 5 Sep 2022 16:11:11 +0300 Subject: [PATCH 20/53] fix: name overflow in maker card --- .../Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx b/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx index 3ab8a55..4876187 100644 --- a/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx +++ b/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx @@ -31,8 +31,8 @@ export default function MakerCard({ maker, isMe }: Props) {
-
-

{maker.name}

+
+

{maker.name}

{maker.jobTitle ?

{maker.jobTitle}

:

No job title

} From 345ef79cdd0a093f8e3554249a986d68deb01c3d Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Tue, 6 Sep 2022 11:29:23 +0300 Subject: [PATCH 21/53] refactor: split the makers page into sections & functionalities --- api/functions/graphql/nexus-typegen.ts | 20 ++- api/functions/graphql/schema.graphql | 8 +- api/functions/graphql/types/tournament.js | 110 ++++++++++++++++- .../pages/MakersPage/MakerCard/MakerCard.tsx | 4 +- .../pages/MakersPage/MakersPage.tsx | 115 ++---------------- .../ParticipantsSection/MakersList.tsx | 105 ++++++++++++++++ .../ParticipantsSection.tsx | 41 +++++++ .../ProjectCard/ProjectCard.Skeleton.tsx | 40 ++++++ .../MakersPage/ProjectCard/ProjectCard.tsx | 62 ++++++++++ ...ament.graphql => tournamentMakers.graphql} | 40 +++--- src/graphql/index.tsx | 89 ++++++++++---- src/mocks/handlers.ts | 12 +- src/mocks/resolvers.ts | 18 ++- 13 files changed, 503 insertions(+), 161 deletions(-) create mode 100644 src/features/Tournaments/pages/MakersPage/ParticipantsSection/MakersList.tsx create mode 100644 src/features/Tournaments/pages/MakersPage/ParticipantsSection/ParticipantsSection.tsx create mode 100644 src/features/Tournaments/pages/MakersPage/ProjectCard/ProjectCard.Skeleton.tsx create mode 100644 src/features/Tournaments/pages/MakersPage/ProjectCard/ProjectCard.tsx rename src/features/Tournaments/pages/MakersPage/{makersInTournament.graphql => tournamentMakers.graphql} (66%) diff --git a/api/functions/graphql/nexus-typegen.ts b/api/functions/graphql/nexus-typegen.ts index d5efd5f..8cd87c3 100644 --- a/api/functions/graphql/nexus-typegen.ts +++ b/api/functions/graphql/nexus-typegen.ts @@ -246,7 +246,6 @@ export interface NexusGenObjects { 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! @@ -274,6 +273,11 @@ export interface NexusGenObjects { jobTitle: string; // String! name: string; // String! } + TournamentMakersResponse: { // root type + hasNext?: boolean | null; // Boolean + hasPrev?: boolean | null; // Boolean + makers: NexusGenRootTypes['User'][]; // [User!]! + } TournamentPrize: { // root type amount: string; // String! image: string; // String! @@ -487,7 +491,7 @@ export interface NexusGenFieldTypes { getDonationsStats: NexusGenRootTypes['DonationsStats']; // DonationsStats! getFeed: NexusGenRootTypes['Post'][]; // [Post!]! getLnurlDetailsForProject: NexusGenRootTypes['LnurlDetails']; // LnurlDetails! - getMakersInTournament: NexusGenRootTypes['User'][]; // [User!]! + getMakersInTournament: NexusGenRootTypes['TournamentMakersResponse']; // TournamentMakersResponse! getMyDrafts: NexusGenRootTypes['Post'][]; // [Post!]! getPostById: NexusGenRootTypes['Post']; // Post! getProject: NexusGenRootTypes['Project']; // Project! @@ -577,6 +581,11 @@ export interface NexusGenFieldTypes { jobTitle: string; // String! name: string; // String! } + TournamentMakersResponse: { // field return type + hasNext: boolean | null; // Boolean + hasPrev: boolean | null; // Boolean + makers: NexusGenRootTypes['User'][]; // [User!]! + } TournamentPrize: { // field return type amount: string; // String! image: string; // String! @@ -813,7 +822,7 @@ export interface NexusGenFieldTypeNames { getDonationsStats: 'DonationsStats' getFeed: 'Post' getLnurlDetailsForProject: 'LnurlDetails' - getMakersInTournament: 'User' + getMakersInTournament: 'TournamentMakersResponse' getMyDrafts: 'Post' getPostById: 'Post' getProject: 'Project' @@ -903,6 +912,11 @@ export interface NexusGenFieldTypeNames { jobTitle: 'String' name: 'String' } + TournamentMakersResponse: { // field return type name + hasNext: 'Boolean' + hasPrev: 'Boolean' + makers: 'User' + } TournamentPrize: { // field return type name amount: 'String' image: 'String' diff --git a/api/functions/graphql/schema.graphql b/api/functions/graphql/schema.graphql index 878e998..b5e634a 100644 --- a/api/functions/graphql/schema.graphql +++ b/api/functions/graphql/schema.graphql @@ -252,7 +252,7 @@ type Query { getDonationsStats: DonationsStats! getFeed(skip: Int = 0, sortBy: String, tag: Int = 0, take: Int = 10): [Post!]! getLnurlDetailsForProject(project_id: Int!): LnurlDetails! - getMakersInTournament(roleId: Int, search: String, skip: Int = 0, take: Int = 10, tournamentId: Int!): [User!]! + getMakersInTournament(roleId: Int, search: String, skip: Int = 0, take: Int = 10, tournamentId: Int!): TournamentMakersResponse! getMyDrafts(type: POST_TYPE!): [Post!]! getPostById(id: Int!, type: POST_TYPE!): Post! getProject(id: Int!): Project! @@ -374,6 +374,12 @@ type TournamentJudge { name: String! } +type TournamentMakersResponse { + hasNext: Boolean + hasPrev: Boolean + makers: [User!]! +} + type TournamentPrize { amount: String! image: String! diff --git a/api/functions/graphql/types/tournament.js b/api/functions/graphql/types/tournament.js index c8aaffa..eb6e6fc 100644 --- a/api/functions/graphql/types/tournament.js +++ b/api/functions/graphql/types/tournament.js @@ -79,7 +79,11 @@ const Tournament = objectType({ t.nonNull.string('website'); t.nonNull.int('events_count'); - t.nonNull.int('makers_count'); + t.nonNull.int('makers_count', { + resolve(parent) { + return prisma.user.count(); + } + }); t.nonNull.int('projects_count'); t.nonNull.list.nonNull.field('prizes', { type: TournamentPrize, }); @@ -89,6 +93,29 @@ const Tournament = objectType({ } }) + +const TournamentMakersResponse = objectType({ + name: 'TournamentMakersResponse', + definition(t) { + t.boolean('hasNext'); + t.boolean('hasPrev'); + + t.nonNull.list.nonNull.field('makers', { type: "User" }) + } +} +) + +const TournamentProjectsResponse = objectType({ + name: 'TournamentProjectsResponse', + definition(t) { + t.boolean('hasNext'); + t.boolean('hasPrev'); + + t.nonNull.list.nonNull.field('projects', { type: "Project" }) + } +} +) + const getTournamentById = extendType({ type: "Query", definition(t) { @@ -104,18 +131,20 @@ const getTournamentById = extendType({ } }) + + const getMakersInTournament = extendType({ type: "Query", definition(t) { - t.nonNull.list.nonNull.field('getMakersInTournament', { - type: "User", + t.nonNull.field('getMakersInTournament', { + type: TournamentMakersResponse, args: { tournamentId: nonNull(intArg()), ...paginationArgs({ take: 10 }), search: stringArg(), roleId: intArg(), }, - resolve(_, args) { + async resolve(_, args) { let filters = []; @@ -147,15 +176,84 @@ const getMakersInTournament = extendType({ }) - return prisma.user.findMany({ + const makers = await prisma.user.findMany({ ...(filters.length > 0 && { where: { AND: filters } }), skip: args.skip, - take: args.take, + take: args.take + 1, + }); + + return { + hasNext: makers.length === args.take + 1, + hasPrev: args.skip !== 0, + makers: makers.slice(0, args.take) + } + } + }) + } +}) + +const getProjectsInTournament = extendType({ + type: "Query", + definition(t) { + t.nonNull.field('getProjectsInTournament', { + type: TournamentProjectsResponse, + args: { + tournamentId: nonNull(intArg()), + ...paginationArgs({ take: 10 }), + search: stringArg(), + roleId: intArg(), + }, + async resolve(_, args) { + + + let filters = []; + + if (args.search) filters.push({ + OR: [ + { + title: { + contains: args.search, + mode: 'insensitive' + } + }, + { + description: { + contains: args.search, + mode: 'insensitive' + } + } + ] }) + + + // if (args.roleId) filters.push({ + // roles: { + // some: { + // roleId: args.roleId + // } + // } + // }) + + + const makers = await prisma.project.findMany({ + ...(filters.length > 0 && { + where: { + AND: filters + } + }), + skip: args.skip, + take: args.take + 1, + }); + + return { + hasNext: makers.length === args.take + 1, + hasPrev: args.skip !== 0, + makers: makers.slice(0, args.take) + } } }) } diff --git a/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx b/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx index 4876187..3dde58f 100644 --- a/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx +++ b/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx @@ -13,10 +13,10 @@ import Avatar from 'src/features/Profiles/Components/Avatar/Avatar'; import Badge from 'src/Components/Badge/Badge'; import { createRoute, PAGES_ROUTES } from 'src/utils/routing'; -type MakerType = GetMakersInTournamentQuery['getMakersInTournament'][number] +type MakerType = GetMakersInTournamentQuery['getMakersInTournament']['makers'][number] interface Props { - maker: GetMakersInTournamentQuery['getMakersInTournament'][number], + maker: MakerType, isMe?: boolean; } diff --git a/src/features/Tournaments/pages/MakersPage/MakersPage.tsx b/src/features/Tournaments/pages/MakersPage/MakersPage.tsx index bc18640..69b8fad 100644 --- a/src/features/Tournaments/pages/MakersPage/MakersPage.tsx +++ b/src/features/Tournaments/pages/MakersPage/MakersPage.tsx @@ -1,126 +1,29 @@ -import { NetworkStatus } from '@apollo/client'; -import { useDebouncedCallback, useDebouncedState } from '@react-hookz/web'; -import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' -import { FaChevronLeft, FaChevronRight } from 'react-icons/fa'; -import IconButton from 'src/Components/IconButton/IconButton'; -import LoadingPage from 'src/Components/LoadingPage/LoadingPage'; -import { GenericMakerRole, GetMakersInTournamentQueryVariables, Tournament, useGetMakersInTournamentQuery, User } from 'src/graphql' -import ScrollToTop from 'src/utils/routing/scrollToTop'; +import { Tournament, useMeTournamentQuery, User } from 'src/graphql' import MakerCard from './MakerCard/MakerCard'; import MakerCardSkeleton from './MakerCard/MakerCard.Skeleton'; -import MakersFilters from './MakersFilters/MakersFilters'; +import ParticipantsSection from './ParticipantsSection/ParticipantsSection'; interface Props { data: Pick } -const ITEMS_PER_PAGE = 15; export default function MakersPage({ data: { id } }: Props) { - const [page, setPage] = useState(0) - const [searchFilter, setSearchFilter] = useState(""); - const [debouncedsearchFilter, setDebouncedSearchFilter] = useDebouncedState("", 500); - const [roleFilter, setRoleFilter] = useState(null); - - const loadingContainerCbRef = useCallback((e: HTMLDivElement) => { - if (e) - e.scrollIntoView({ - behavior: 'smooth', - block: "center" - }) - }, []) - - const [queryFilter, setQueryFilter] = useState({ - tournamentId: id, - roleId: roleFilter?.id ?? null, - search: debouncedsearchFilter, - skip: ITEMS_PER_PAGE * page, - take: ITEMS_PER_PAGE, - }); - - - const query = useGetMakersInTournamentQuery({ - variables: queryFilter, - notifyOnNetworkStatusChange: true, - }); - - - useEffect(() => { - setPage(0); - setQueryFilter(f => ({ ...f, search: debouncedsearchFilter, roleId: roleFilter?.id ?? null, skip: 0 })) - }, [debouncedsearchFilter, roleFilter]); - - - - - - if (query.networkStatus === NetworkStatus.loading) return - - - const changeSearchFilter = (new_value: string) => { - setSearchFilter(new_value); - setDebouncedSearchFilter(new_value); - } - - - const nextPage = () => { - setPage(p => p + 1) - setQueryFilter(f => ({ ...f, skip: (f.skip ?? 0) + ITEMS_PER_PAGE })) - } - const prevPage = () => { - if (page === 0) return - setPage(p => p - 1) - setQueryFilter(f => ({ ...f, skip: (f.skip ?? 0) - ITEMS_PER_PAGE })) - } - - - const isFetchingMore = query.networkStatus === NetworkStatus.setVariables; - const itemsCount = query.data?.getMakersInTournament && query.data.getMakersInTournament.length; - + const query = useMeTournamentQuery(); return (
- {(query.data?.me ?? query.previousData?.me) && } -
-

Makers 👾

- -
- -
-
- {isFetchingMore ? - <> -
- -
- - - + {query.loading ? + : - (itemsCount !== 0 ? - query.data?.getMakersInTournament.map(maker => ) : -
-

No makers found here...

-
) + query.data?.me ? + + : null } - - -
- - - - - - -
+
diff --git a/src/features/Tournaments/pages/MakersPage/ParticipantsSection/MakersList.tsx b/src/features/Tournaments/pages/MakersPage/ParticipantsSection/MakersList.tsx new file mode 100644 index 0000000..bb281b4 --- /dev/null +++ b/src/features/Tournaments/pages/MakersPage/ParticipantsSection/MakersList.tsx @@ -0,0 +1,105 @@ +import { useEffect, useRef, useState } from 'react' +import { FaChevronLeft, FaChevronRight } from 'react-icons/fa'; +import IconButton from 'src/Components/IconButton/IconButton'; +import { GetMakersInTournamentQueryVariables, useGetMakersInTournamentQuery } from 'src/graphql'; +import MakerCard from '../MakerCard/MakerCard'; +import MakerCardSkeleton from '../MakerCard/MakerCard.Skeleton'; + +interface Props { + tournamentId: number + searchFilter: string, + roleFilter: number | null +} + +const ITEMS_PER_PAGE = 3; + +export default function MakersList(props: Props) { + + + const [page, setPage] = useState(0); + const topContainerRef = useRef(null) + const [scrollToTop, setScrollToTop] = useState(false) + + const [queryFilter, setQueryFilter] = useState({ + tournamentId: props.tournamentId, + roleId: props.roleFilter ?? null, + search: props.searchFilter ?? null, + skip: ITEMS_PER_PAGE * page, + take: ITEMS_PER_PAGE, + }); + + + + + + const query = useGetMakersInTournamentQuery({ + variables: queryFilter, + }); + + + useEffect(() => { + setPage(0); + setQueryFilter(f => ({ ...f, search: props.searchFilter, roleId: props.roleFilter, skip: 0 })) + }, [props.roleFilter, props.searchFilter]); + + + + useEffect(() => { + if (scrollToTop && topContainerRef.current) { + topContainerRef.current.scrollIntoView({ + behavior: 'smooth', + block: "center" + }) + setScrollToTop(false) + } + }, [scrollToTop]) + + + + const nextPage = () => { + setPage(p => p + 1) + setQueryFilter(f => ({ ...f, skip: (f.skip ?? 0) + ITEMS_PER_PAGE })) + setScrollToTop(true) + } + const prevPage = () => { + if (page === 0) return + setPage(p => p - 1) + setQueryFilter(f => ({ ...f, skip: (f.skip ?? 0) - ITEMS_PER_PAGE })) + setScrollToTop(true) + } + + + const itemsCount = query.data?.getMakersInTournament && query.data.getMakersInTournament.makers.length; + + return ( +
+
+
+ { + query.loading ? + <> +
+ +
+ + + + : + (itemsCount !== 0 ? + query.data?.getMakersInTournament.makers.map(maker => ) : +
+

No makers found here...

+
) + } + < div className='flex justify-center gap-36 text-gray-400' > + + + + + + +
+
+
+ ) +} diff --git a/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ParticipantsSection.tsx b/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ParticipantsSection.tsx new file mode 100644 index 0000000..1e73b20 --- /dev/null +++ b/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ParticipantsSection.tsx @@ -0,0 +1,41 @@ +import { useDebouncedState } from '@react-hookz/web'; +import { useState } from 'react' +import { GenericMakerRole } from 'src/graphql' +import MakersFilters from '../MakersFilters/MakersFilters'; +import MakersList from './MakersList'; + +interface Props { + tournamentId: number +} +export default function ParticipantsSection({ tournamentId }: Props) { + + const [searchFilter, setSearchFilter] = useState(""); + const [debouncedsearchFilter, setDebouncedSearchFilter] = useDebouncedState("", 500); + const [roleFilter, setRoleFilter] = useState(null); + + + + const changeSearchFilter = (new_value: string) => { + setSearchFilter(new_value); + setDebouncedSearchFilter(new_value); + } + + + + return (<> +
+

Makers 👾

+ +
+ +
+
+ + + ) +} diff --git a/src/features/Tournaments/pages/MakersPage/ProjectCard/ProjectCard.Skeleton.tsx b/src/features/Tournaments/pages/MakersPage/ProjectCard/ProjectCard.Skeleton.tsx new file mode 100644 index 0000000..9fb5ad1 --- /dev/null +++ b/src/features/Tournaments/pages/MakersPage/ProjectCard/ProjectCard.Skeleton.tsx @@ -0,0 +1,40 @@ +import Card from 'src/Components/Card/Card'; +import Badge from 'src/Components/Badge/Badge'; +import Skeleton from 'react-loading-skeleton'; + + +export default function ProjectCardSkeleton() { + + + return ( + +
+
+ +
+
+

+

+

+
    + {Array(3).fill(0).map((_, idx) =>
  • Loading role
  • )} +
+
+
+
+ +
+

+
    + {Array(3).fill(0).map((_, idx) =>
  • Loading role
  • )} +
+
+ +
+

+
    + {Array(3).fill(0).map((_, idx) =>
  • Loading role
  • )}
+
+
+ ) +} diff --git a/src/features/Tournaments/pages/MakersPage/ProjectCard/ProjectCard.tsx b/src/features/Tournaments/pages/MakersPage/ProjectCard/ProjectCard.tsx new file mode 100644 index 0000000..31da7cf --- /dev/null +++ b/src/features/Tournaments/pages/MakersPage/ProjectCard/ProjectCard.tsx @@ -0,0 +1,62 @@ +import Button from "src/Components/Button/Button" +import { GetMakersInTournamentQuery, } from "src/graphql"; +import { useAppDispatch, } from "src/utils/hooks"; +import Card from 'src/Components/Card/Card'; +import Avatar from 'src/features/Profiles/Components/Avatar/Avatar'; +import Badge from 'src/Components/Badge/Badge'; +import { createRoute } from 'src/utils/routing'; + +type MakerType = GetMakersInTournamentQuery['getMakersInTournament']['makers'][number] + +interface Props { + maker: MakerType, + isMe?: boolean; +} + +export default function ProjectCard({ maker, isMe }: Props) { + + return ( + +
+
+ +
+
+

{maker.name}

+ {maker.jobTitle ?

{maker.jobTitle}

+ : +

No job title

} + {maker.roles.length ?
    + {maker.roles.map(role =>
  • {role.icon} {role.title}
  • )} +
+ : +

No roles added

+ } +
+ {isMe && } +
+
+ +
+

🌈 Roles

+ + {maker.roles.length ?
    + {maker.roles.map(role =>
  • {role.icon} {role.title}
  • )} +
+ : +

No roles added

+ } +
+ +
+

🛠️ Skills

+ {maker.skills.length ?
    + {maker.skills.map(skill =>
  • {skill.title}
  • )} +
+ : +

No skills added

+ } +
+ {isMe && }
+ ) +} diff --git a/src/features/Tournaments/pages/MakersPage/makersInTournament.graphql b/src/features/Tournaments/pages/MakersPage/tournamentMakers.graphql similarity index 66% rename from src/features/Tournaments/pages/MakersPage/makersInTournament.graphql rename to src/features/Tournaments/pages/MakersPage/tournamentMakers.graphql index 72828fa..b58628c 100644 --- a/src/features/Tournaments/pages/MakersPage/makersInTournament.graphql +++ b/src/features/Tournaments/pages/MakersPage/tournamentMakers.graphql @@ -5,14 +5,6 @@ query GetMakersInTournament( $search: String $roleId: Int ) { - me { - id - name - avatar - jobTitle - ...UserRolesSkills - } - getMakersInTournament( tournamentId: $tournamentId take: $take @@ -20,19 +12,33 @@ query GetMakersInTournament( search: $search roleId: $roleId ) { + hasNext + hasPrev + makers { + id + name + avatar + jobTitle + roles { + id + icon + title + } + skills { + id + title + } + } + } +} + +query MeTournament { + me { id name avatar jobTitle - roles { - id - icon - title - } - skills { - id - title - } + ...UserRolesSkills } } diff --git a/src/graphql/index.tsx b/src/graphql/index.tsx index feb5a39..14bc7b7 100644 --- a/src/graphql/index.tsx +++ b/src/graphql/index.tsx @@ -330,7 +330,7 @@ export type Query = { getDonationsStats: DonationsStats; getFeed: Array; getLnurlDetailsForProject: LnurlDetails; - getMakersInTournament: Array; + getMakersInTournament: TournamentMakersResponse; getMyDrafts: Array; getPostById: Post; getProject: Project; @@ -555,6 +555,13 @@ export type TournamentJudge = { name: Scalars['String']; }; +export type TournamentMakersResponse = { + __typename?: 'TournamentMakersResponse'; + hasNext: Maybe; + hasPrev: Maybe; + makers: Array; +}; + export type TournamentPrize = { __typename?: 'TournamentPrize'; amount: Scalars['String']; @@ -809,7 +816,12 @@ export type GetMakersInTournamentQueryVariables = Exact<{ }>; -export type GetMakersInTournamentQuery = { __typename?: 'Query', me: { __typename?: 'MyProfile', id: number, name: string, avatar: string, jobTitle: string | null, skills: Array<{ __typename?: 'MakerSkill', id: number, title: string }>, roles: Array<{ __typename?: 'MakerRole', id: number, title: string, icon: string, level: RoleLevelEnum }> } | null, getMakersInTournament: Array<{ __typename?: 'User', id: number, name: string, avatar: string, jobTitle: string | null, roles: Array<{ __typename?: 'MakerRole', id: number, icon: string, title: string }>, skills: Array<{ __typename?: 'MakerSkill', id: number, title: string }> }> }; +export type GetMakersInTournamentQuery = { __typename?: 'Query', getMakersInTournament: { __typename?: 'TournamentMakersResponse', hasNext: boolean | null, hasPrev: boolean | null, makers: Array<{ __typename?: 'User', id: number, name: string, avatar: string, jobTitle: string | null, roles: Array<{ __typename?: 'MakerRole', id: number, icon: string, title: string }>, skills: Array<{ __typename?: 'MakerSkill', id: number, title: string }> }> } }; + +export type MeTournamentQueryVariables = Exact<{ [key: string]: never; }>; + + +export type MeTournamentQuery = { __typename?: 'Query', me: { __typename?: 'MyProfile', id: number, name: string, avatar: string, jobTitle: string | null, skills: Array<{ __typename?: 'MakerSkill', id: number, title: string }>, roles: Array<{ __typename?: 'MakerRole', id: number, title: string, icon: string, level: RoleLevelEnum }> } | null }; export type GetAllRolesQueryVariables = Exact<{ [key: string]: never; }>; @@ -2148,13 +2160,6 @@ export type ProjectDetailsLazyQueryHookResult = ReturnType; export const GetMakersInTournamentDocument = gql` query GetMakersInTournament($tournamentId: Int!, $take: Int, $skip: Int, $search: String, $roleId: Int) { - me { - id - name - avatar - jobTitle - ...UserRolesSkills - } getMakersInTournament( tournamentId: $tournamentId take: $take @@ -2162,22 +2167,26 @@ export const GetMakersInTournamentDocument = gql` search: $search roleId: $roleId ) { - id - name - avatar - jobTitle - roles { + hasNext + hasPrev + makers { id - icon - title - } - skills { - id - title + name + avatar + jobTitle + roles { + id + icon + title + } + skills { + id + title + } } } } - ${UserRolesSkillsFragmentDoc}`; + `; /** * __useGetMakersInTournamentQuery__ @@ -2210,6 +2219,44 @@ export function useGetMakersInTournamentLazyQuery(baseOptions?: Apollo.LazyQuery export type GetMakersInTournamentQueryHookResult = ReturnType; export type GetMakersInTournamentLazyQueryHookResult = ReturnType; export type GetMakersInTournamentQueryResult = Apollo.QueryResult; +export const MeTournamentDocument = gql` + query MeTournament { + me { + id + name + avatar + jobTitle + ...UserRolesSkills + } +} + ${UserRolesSkillsFragmentDoc}`; + +/** + * __useMeTournamentQuery__ + * + * To run a query within a React component, call `useMeTournamentQuery` and pass it any options that fit your needs. + * When your component renders, `useMeTournamentQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useMeTournamentQuery({ + * variables: { + * }, + * }); + */ +export function useMeTournamentQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(MeTournamentDocument, options); + } +export function useMeTournamentLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(MeTournamentDocument, options); + } +export type MeTournamentQueryHookResult = ReturnType; +export type MeTournamentLazyQueryHookResult = ReturnType; +export type MeTournamentQueryResult = Apollo.QueryResult; export const GetAllRolesDocument = gql` query GetAllRoles { getAllMakersRoles { diff --git a/src/mocks/handlers.ts b/src/mocks/handlers.ts index 06630e1..20e57c4 100644 --- a/src/mocks/handlers.ts +++ b/src/mocks/handlers.ts @@ -36,6 +36,7 @@ import { GetAllRolesQuery, GetMakersInTournamentQuery, GetMakersInTournamentQueryVariables, + MeTournamentQuery, } from 'src/graphql' const delay = (ms = 1000) => new Promise((res) => setTimeout(res, ms + Math.random() * 1000)) @@ -286,12 +287,21 @@ export const handlers = [ ) }), + graphql.query('MeTournament', async (req, res, ctx) => { + await delay() + + return res( + ctx.data({ + me: { ...me() } + }) + ) + }), + graphql.query('GetMakersInTournament', async (req, res, ctx) => { await delay() return res( ctx.data({ - me: { ...me() }, getMakersInTournament: getMakersInTournament(req.variables) }) ) diff --git a/src/mocks/resolvers.ts b/src/mocks/resolvers.ts index b5ffa36..74ffc2d 100644 --- a/src/mocks/resolvers.ts +++ b/src/mocks/resolvers.ts @@ -99,10 +99,13 @@ export function getTournamentById(id: number) { export function getMakersInTournament(vars: GetMakersInTournamentQueryVariables) { - const offsetStart = vars.skip ?? 0; - const offsetEnd = offsetStart + (vars.take ?? 15) + const take = vars.take ?? 15; + const skip = vars.skip ?? 0; - return MOCK_DATA.users.slice(1) + const offsetStart = skip; + const offsetEnd = offsetStart + take; + + const allMakers = MOCK_DATA.users.slice(1) .filter(u => { if (!vars.search) return true; return [u.name, u.jobTitle].some(attr => attr?.search(new RegExp(vars.search!, 'i')) !== -1) @@ -111,5 +114,12 @@ export function getMakersInTournament(vars: GetMakersInTournamentQueryVariables) if (!vars.roleId) return true; return u.roles.some(r => r.id === vars.roleId) }) - .slice(offsetStart, offsetEnd) as User[]; + .slice(offsetStart, offsetEnd + 1) as User[] + ; + + return { + hasNext: allMakers.length === take + 1, + hasPrev: skip !== 0, + makers: allMakers.slice(0, take) + }; } \ No newline at end of file From da769384d56e081dc59b5530655593417cb2d835 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Tue, 6 Sep 2022 12:30:14 +0300 Subject: [PATCH 22/53] feat: project card, project skeleton, participants section wiring --- api/functions/graphql/nexus-typegen.ts | 24 ++ api/functions/graphql/schema.graphql | 7 + api/functions/graphql/types/tournament.js | 21 +- .../pages/EventsPage/EventCard/EventCard.tsx | 6 +- .../pages/EventsPage/EventModal/index.tsx | 2 +- .../pages/EventsPage/EventsPage.tsx | 2 +- .../pages/MakersPage/MakerCard/MakerCard.tsx | 17 +- .../ParticipantsSection.tsx | 27 ++- .../ParticipantsSection/ProjectsList.tsx | 104 ++++++++ .../MakersPage/ProjectCard/ProjectCard.tsx | 83 +++---- .../pages/MakersPage/tournamentMakers.graphql | 66 +++-- .../Navigation/Navigation.tsx | 4 +- .../TournamentDetailsPage.tsx | 5 +- src/graphql/index.tsx | 228 ++++++++++++------ src/redux/features/modals.slice.ts | 3 +- 15 files changed, 436 insertions(+), 163 deletions(-) create mode 100644 src/features/Tournaments/pages/MakersPage/ParticipantsSection/ProjectsList.tsx diff --git a/api/functions/graphql/nexus-typegen.ts b/api/functions/graphql/nexus-typegen.ts index f341ddc..8f6b20a 100644 --- a/api/functions/graphql/nexus-typegen.ts +++ b/api/functions/graphql/nexus-typegen.ts @@ -283,6 +283,11 @@ export interface NexusGenObjects { image: string; // String! title: string; // String! } + TournamentProjectsResponse: { // root type + hasNext?: boolean | null; // Boolean + hasPrev?: boolean | null; // Boolean + projects: NexusGenRootTypes['Project'][]; // [Project!]! + } User: { // root type avatar: string; // String! bio?: string | null; // String @@ -496,6 +501,7 @@ export interface NexusGenFieldTypes { getMyDrafts: NexusGenRootTypes['Post'][]; // [Post!]! getPostById: NexusGenRootTypes['Post']; // Post! getProject: NexusGenRootTypes['Project']; // Project! + getProjectsInTournament: NexusGenRootTypes['TournamentProjectsResponse']; // TournamentProjectsResponse! getTournamentById: NexusGenRootTypes['Tournament']; // Tournament! getTrendingPosts: NexusGenRootTypes['Post'][]; // [Post!]! hottestProjects: NexusGenRootTypes['Project'][]; // [Project!]! @@ -592,6 +598,11 @@ export interface NexusGenFieldTypes { image: string; // String! title: string; // String! } + TournamentProjectsResponse: { // field return type + hasNext: boolean | null; // Boolean + hasPrev: boolean | null; // Boolean + projects: NexusGenRootTypes['Project'][]; // [Project!]! + } User: { // field return type avatar: string; // String! bio: string | null; // String @@ -828,6 +839,7 @@ export interface NexusGenFieldTypeNames { getMyDrafts: 'Post' getPostById: 'Post' getProject: 'Project' + getProjectsInTournament: 'TournamentProjectsResponse' getTournamentById: 'Tournament' getTrendingPosts: 'Post' hottestProjects: 'Project' @@ -924,6 +936,11 @@ export interface NexusGenFieldTypeNames { image: 'String' title: 'String' } + TournamentProjectsResponse: { // field return type name + hasNext: 'Boolean' + hasPrev: 'Boolean' + projects: 'Project' + } User: { // field return type name avatar: 'String' bio: 'String' @@ -1064,6 +1081,13 @@ export interface NexusGenArgTypes { getProject: { // args id: number; // Int! } + getProjectsInTournament: { // args + roleId?: number | null; // Int + search?: string | null; // String + skip?: number | null; // Int + take: number | null; // Int + tournamentId: number; // Int! + } getTournamentById: { // args id: number; // Int! } diff --git a/api/functions/graphql/schema.graphql b/api/functions/graphql/schema.graphql index c2d5393..57950f9 100644 --- a/api/functions/graphql/schema.graphql +++ b/api/functions/graphql/schema.graphql @@ -257,6 +257,7 @@ type Query { getMyDrafts(type: POST_TYPE!): [Post!]! getPostById(id: Int!, type: POST_TYPE!): Post! getProject(id: Int!): Project! + getProjectsInTournament(roleId: Int, search: String, skip: Int = 0, take: Int = 10, tournamentId: Int!): TournamentProjectsResponse! getTournamentById(id: Int!): Tournament! getTrendingPosts: [Post!]! hottestProjects(skip: Int = 0, take: Int = 50): [Project!]! @@ -387,6 +388,12 @@ type TournamentPrize { title: String! } +type TournamentProjectsResponse { + hasNext: Boolean + hasPrev: Boolean + projects: [Project!]! +} + type User implements BaseUser { avatar: String! bio: String diff --git a/api/functions/graphql/types/tournament.js b/api/functions/graphql/types/tournament.js index eb6e6fc..aeb4e22 100644 --- a/api/functions/graphql/types/tournament.js +++ b/api/functions/graphql/types/tournament.js @@ -230,16 +230,16 @@ const getProjectsInTournament = extendType({ }) - // if (args.roleId) filters.push({ - // roles: { - // some: { - // roleId: args.roleId - // } - // } - // }) + if (args.roleId) filters.push({ + recruit_roles: { + some: { + roleId: args.roleId + } + } + }) - const makers = await prisma.project.findMany({ + const projects = await prisma.project.findMany({ ...(filters.length > 0 && { where: { AND: filters @@ -250,9 +250,9 @@ const getProjectsInTournament = extendType({ }); return { - hasNext: makers.length === args.take + 1, + hasNext: projects.length === args.take + 1, hasPrev: args.skip !== 0, - makers: makers.slice(0, args.take) + projects: projects.slice(0, args.take) } } }) @@ -265,4 +265,5 @@ module.exports = { // Queries getTournamentById, getMakersInTournament, + getProjectsInTournament, } \ No newline at end of file diff --git a/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx b/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx index 57dc2c8..589cdde 100644 --- a/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx +++ b/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx @@ -1,10 +1,6 @@ import { IoLocationOutline } from 'react-icons/io5' -import Button from "src/Components/Button/Button" -import dayjs from "dayjs"; -import advancedFormat from 'dayjs/plugin/advancedFormat' import { trimText } from "src/utils/helperFunctions"; -import { Override } from "src/utils/interfaces"; -import { Tag, Tournament, TournamentEventTypeEnum } from "src/graphql"; +import { Tournament, TournamentEventTypeEnum } from "src/graphql"; import { UnionToObjectKeys } from 'src/utils/types/utils'; import { useAppDispatch, } from "src/utils/hooks"; import { openModal } from "src/redux/features/modals.slice"; diff --git a/src/features/Tournaments/pages/EventsPage/EventModal/index.tsx b/src/features/Tournaments/pages/EventsPage/EventModal/index.tsx index 26ef497..9ceafba 100644 --- a/src/features/Tournaments/pages/EventsPage/EventModal/index.tsx +++ b/src/features/Tournaments/pages/EventsPage/EventModal/index.tsx @@ -3,4 +3,4 @@ import { lazyModal } from 'src/utils/helperFunctions'; -export const { LazyComponent: EventModal, preload: projectDetailsCardPreload } = lazyModal(() => import('./EventModal')) +export const { LazyComponent: EventModal, } = lazyModal(() => import('./EventModal')) diff --git a/src/features/Tournaments/pages/EventsPage/EventsPage.tsx b/src/features/Tournaments/pages/EventsPage/EventsPage.tsx index a688abc..66cfcb7 100644 --- a/src/features/Tournaments/pages/EventsPage/EventsPage.tsx +++ b/src/features/Tournaments/pages/EventsPage/EventsPage.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react' +import { useState } from 'react' import { Tournament, TournamentEventTypeEnum } from 'src/graphql' import EventCard from './EventCard/EventCard'; import EventsFilters from './EventsFilters/EventsFilters'; diff --git a/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx b/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx index 3dde58f..1fe99c2 100644 --- a/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx +++ b/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx @@ -1,17 +1,10 @@ -import { IoLocationOutline } from 'react-icons/io5' import Button from "src/Components/Button/Button" -import dayjs from "dayjs"; -import advancedFormat from 'dayjs/plugin/advancedFormat' -import { trimText } from "src/utils/helperFunctions"; -import { Override } from "src/utils/interfaces"; -import { GetMakersInTournamentQuery, GetMakersInTournamentQueryResult, Tag, Tournament, TournamentEventTypeEnum, User } from "src/graphql"; -import { UnionToObjectKeys } from 'src/utils/types/utils'; +import { GetMakersInTournamentQuery, } from "src/graphql"; import { useAppDispatch, } from "src/utils/hooks"; -import { openModal } from "src/redux/features/modals.slice"; import Card from 'src/Components/Card/Card'; import Avatar from 'src/features/Profiles/Components/Avatar/Avatar'; import Badge from 'src/Components/Badge/Badge'; -import { createRoute, PAGES_ROUTES } from 'src/utils/routing'; +import { createRoute } from 'src/utils/routing'; type MakerType = GetMakersInTournamentQuery['getMakersInTournament']['makers'][number] @@ -37,7 +30,7 @@ export default function MakerCard({ maker, isMe }: Props) { :

No job title

} {maker.roles.length ?
    - {maker.roles.map(role =>
  • {role.icon} {role.title}
  • )} + {maker.roles.map(role =>
  • {role.icon} {role.title}
  • )}
:

No roles added

@@ -51,7 +44,7 @@ export default function MakerCard({ maker, isMe }: Props) {

🌈 Roles

{maker.roles.length ?
    - {maker.roles.map(role =>
  • {role.icon} {role.title}
  • )} + {maker.roles.map(role =>
  • {role.icon} {role.title}
  • )}
:

No roles added

@@ -61,7 +54,7 @@ export default function MakerCard({ maker, isMe }: Props) {

🛠️ Skills

{maker.skills.length ?
    - {maker.skills.map(skill =>
  • {skill.title}
  • )} + {maker.skills.map(skill =>
  • {skill.title}
  • )}
:

No skills added

diff --git a/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ParticipantsSection.tsx b/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ParticipantsSection.tsx index 1e73b20..f00f83e 100644 --- a/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ParticipantsSection.tsx +++ b/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ParticipantsSection.tsx @@ -3,6 +3,7 @@ import { useState } from 'react' import { GenericMakerRole } from 'src/graphql' import MakersFilters from '../MakersFilters/MakersFilters'; import MakersList from './MakersList'; +import ProjectsList from './ProjectsList'; interface Props { tournamentId: number @@ -12,6 +13,7 @@ export default function ParticipantsSection({ tournamentId }: Props) { const [searchFilter, setSearchFilter] = useState(""); const [debouncedsearchFilter, setDebouncedSearchFilter] = useDebouncedState("", 500); const [roleFilter, setRoleFilter] = useState(null); + const [curTab, setCurTab] = useState<'makers' | 'projects'>('makers') @@ -35,7 +37,30 @@ export default function ParticipantsSection({ tournamentId }: Props) { />
- +
+ + +
+ {curTab === 'projects' && } + {curTab === 'makers' && } ) } diff --git a/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ProjectsList.tsx b/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ProjectsList.tsx new file mode 100644 index 0000000..db5fd93 --- /dev/null +++ b/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ProjectsList.tsx @@ -0,0 +1,104 @@ +import { useEffect, useRef, useState } from 'react' +import { FaChevronLeft, FaChevronRight } from 'react-icons/fa'; +import IconButton from 'src/Components/IconButton/IconButton'; +import { GetProjectsInTournamentQueryVariables, useGetProjectsInTournamentQuery } from 'src/graphql'; +import ProjectCard from '../ProjectCard/ProjectCard'; +import ProjectCardSkeleton from '../ProjectCard/ProjectCard.Skeleton'; + +interface Props { + tournamentId: number + searchFilter: string, + roleFilter: number | null +} + +const ITEMS_PER_PAGE = 3; + +export default function ProjectsList(props: Props) { + + + const [page, setPage] = useState(0); + const topContainerRef = useRef(null) + const [scrollToTop, setScrollToTop] = useState(false) + + const [queryFilter, setQueryFilter] = useState({ + tournamentId: props.tournamentId, + roleId: props.roleFilter ?? null, + search: props.searchFilter ?? null, + skip: ITEMS_PER_PAGE * page, + take: ITEMS_PER_PAGE, + }); + + + + + + const query = useGetProjectsInTournamentQuery({ + variables: queryFilter, + }); + + + useEffect(() => { + setPage(0); + setQueryFilter(f => ({ ...f, search: props.searchFilter, roleId: props.roleFilter, skip: 0 })) + }, [props.roleFilter, props.searchFilter]); + + + + useEffect(() => { + if (scrollToTop && topContainerRef.current) { + topContainerRef.current.scrollIntoView({ + behavior: 'smooth', + block: "center" + }) + setScrollToTop(false) + } + }, [scrollToTop]) + + + + const nextPage = () => { + setPage(p => p + 1) + setQueryFilter(f => ({ ...f, skip: (f.skip ?? 0) + ITEMS_PER_PAGE })) + setScrollToTop(true) + } + const prevPage = () => { + if (page === 0) return + setPage(p => p - 1) + setQueryFilter(f => ({ ...f, skip: (f.skip ?? 0) - ITEMS_PER_PAGE })) + setScrollToTop(true) + } + + + const itemsCount = query.data?.getProjectsInTournament && query.data.getProjectsInTournament.projects.length; + + return ( +
+
+
+ { + query.loading ? + <> + + + + + + : + (itemsCount !== 0 ? + query.data?.getProjectsInTournament.projects.map(project => ) : +
+

No projects found here...

+
) + } + < div className='flex justify-center gap-36 text-gray-400' > + + + + + + +
+
+
+ ) +} diff --git a/src/features/Tournaments/pages/MakersPage/ProjectCard/ProjectCard.tsx b/src/features/Tournaments/pages/MakersPage/ProjectCard/ProjectCard.tsx index 31da7cf..1ca65f8 100644 --- a/src/features/Tournaments/pages/MakersPage/ProjectCard/ProjectCard.tsx +++ b/src/features/Tournaments/pages/MakersPage/ProjectCard/ProjectCard.tsx @@ -1,62 +1,59 @@ -import Button from "src/Components/Button/Button" -import { GetMakersInTournamentQuery, } from "src/graphql"; -import { useAppDispatch, } from "src/utils/hooks"; +import { GetProjectsInTournamentQuery, } from "src/graphql"; import Card from 'src/Components/Card/Card'; -import Avatar from 'src/features/Profiles/Components/Avatar/Avatar'; import Badge from 'src/Components/Badge/Badge'; -import { createRoute } from 'src/utils/routing'; +import Button from "src/Components/Button/Button" +import { createRoute } from "src/utils/routing"; +import { useAppDispatch } from "src/utils/hooks"; +import { openModal } from "src/redux/features/modals.slice"; -type MakerType = GetMakersInTournamentQuery['getMakersInTournament']['makers'][number] +type ProjectType = GetProjectsInTournamentQuery['getProjectsInTournament']['projects'][number] interface Props { - maker: MakerType, - isMe?: boolean; + project: ProjectType, } -export default function ProjectCard({ maker, isMe }: Props) { +export default function ProjectCard({ project }: Props) { + + const showLookingFor = project.recruit_roles.length > 0; + + const dispatch = useAppDispatch(); + + const openProject = () => { + dispatch(openModal({ + Modal: "ProjectDetailsCard", + isPageModal: true, + props: { + projectId: project.id + } + })) + } return (
-
- -
+
-

{maker.name}

- {maker.jobTitle ?

{maker.jobTitle}

- : -

No job title

} - {maker.roles.length ?
    - {maker.roles.map(role =>
  • {role.icon} {role.title}
  • )} -
- : -

No roles added

- } +

{project.title}

+

{project.category.icon} {project.category.title}

+
+

{project.description}

+
- {isMe && } + +
-
- -
-

🌈 Roles

- - {maker.roles.length ?
    - {maker.roles.map(role =>
  • {role.icon} {role.title}
  • )} + {showLookingFor &&
    } +

    {project.description}

    + {showLookingFor &&
    +

    👀 Looking for

    + {project.recruit_roles.length ?
      + {project.recruit_roles.map(role =>
    • {role.icon} {role.title}
    • )}
    : -

    No roles added

    + null } -
    - -
    -

    🛠️ Skills

    - {maker.skills.length ?
      - {maker.skills.map(skill =>
    • {skill.title}
    • )} -
    - : -

    No skills added

    - } -
    - {isMe && } +
} + +
) } diff --git a/src/features/Tournaments/pages/MakersPage/tournamentMakers.graphql b/src/features/Tournaments/pages/MakersPage/tournamentMakers.graphql index b58628c..0a8856c 100644 --- a/src/features/Tournaments/pages/MakersPage/tournamentMakers.graphql +++ b/src/features/Tournaments/pages/MakersPage/tournamentMakers.graphql @@ -1,3 +1,21 @@ +query MeTournament { + me { + id + name + avatar + jobTitle + ...UserRolesSkills + } +} + +query GetAllRoles { + getAllMakersRoles { + id + title + icon + } +} + query GetMakersInTournament( $tournamentId: Int! $take: Int @@ -32,20 +50,40 @@ query GetMakersInTournament( } } -query MeTournament { - me { - id - name - avatar - jobTitle - ...UserRolesSkills - } -} +query GetProjectsInTournament( + $tournamentId: Int! + $take: Int + $skip: Int + $roleId: Int + $search: String +) { + getProjectsInTournament( + tournamentId: $tournamentId + take: $take + skip: $skip + roleId: $roleId + search: $search + ) { + hasNext + hasPrev + projects { + id + title + description + thumbnail_image -query GetAllRoles { - getAllMakersRoles { - id - title - icon + category { + id + title + icon + } + + recruit_roles { + id + title + icon + level + } + } } } diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx index 2d17e71..6337910 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx +++ b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx @@ -24,7 +24,7 @@ export default function Navigation({ data }: Props) { path: "events", }, { - text: `Makers (${data.makers_count})`, + text: `Makers`, path: "makers", }, { @@ -42,7 +42,7 @@ export default function Navigation({ data }: Props) { path: "resources", isDisabled: true, }, - ], [data.events_count, data.makers_count]) + ], [data.events_count]) return (
diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx index a4b1d0e..14b9686 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx +++ b/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx @@ -1,7 +1,4 @@ -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' diff --git a/src/graphql/index.tsx b/src/graphql/index.tsx index 14bc7b7..c5dc674 100644 --- a/src/graphql/index.tsx +++ b/src/graphql/index.tsx @@ -311,6 +311,7 @@ export type Project = { id: Scalars['Int']; lightning_address: Maybe; lnurl_callback_url: Maybe; + recruit_roles: Array; screenshots: Array; tags: Array; thumbnail_image: Scalars['String']; @@ -334,6 +335,7 @@ export type Query = { getMyDrafts: Array; getPostById: Post; getProject: Project; + getProjectsInTournament: TournamentProjectsResponse; getTournamentById: Tournament; getTrendingPosts: Array; hottestProjects: Array; @@ -403,6 +405,15 @@ export type QueryGetProjectArgs = { }; +export type QueryGetProjectsInTournamentArgs = { + roleId: InputMaybe; + search: InputMaybe; + skip?: InputMaybe; + take?: InputMaybe; + tournamentId: Scalars['Int']; +}; + + export type QueryGetTournamentByIdArgs = { id: Scalars['Int']; }; @@ -569,6 +580,13 @@ export type TournamentPrize = { title: Scalars['String']; }; +export type TournamentProjectsResponse = { + __typename?: 'TournamentProjectsResponse'; + hasNext: Maybe; + hasPrev: Maybe; + projects: Array; +}; + export type User = BaseUser & { __typename?: 'User'; avatar: Scalars['String']; @@ -807,6 +825,16 @@ export type ProjectDetailsQueryVariables = Exact<{ export type ProjectDetailsQuery = { __typename?: 'Query', getProject: { __typename?: 'Project', id: number, title: string, description: string, cover_image: string, thumbnail_image: string, screenshots: Array, website: string, lightning_address: string | null, lnurl_callback_url: string | null, votes_count: number, category: { __typename?: 'Category', id: number, title: string }, awards: Array<{ __typename?: 'Award', title: string, image: string, url: string, id: number }>, tags: Array<{ __typename?: 'Tag', id: number, title: string }> } }; +export type MeTournamentQueryVariables = Exact<{ [key: string]: never; }>; + + +export type MeTournamentQuery = { __typename?: 'Query', me: { __typename?: 'MyProfile', id: number, name: string, avatar: string, jobTitle: string | null, skills: Array<{ __typename?: 'MakerSkill', id: number, title: string }>, roles: Array<{ __typename?: 'MakerRole', id: number, title: string, icon: string, level: RoleLevelEnum }> } | null }; + +export type GetAllRolesQueryVariables = Exact<{ [key: string]: never; }>; + + +export type GetAllRolesQuery = { __typename?: 'Query', getAllMakersRoles: Array<{ __typename?: 'GenericMakerRole', id: number, title: string, icon: string }> }; + export type GetMakersInTournamentQueryVariables = Exact<{ tournamentId: Scalars['Int']; take: InputMaybe; @@ -818,15 +846,16 @@ export type GetMakersInTournamentQueryVariables = Exact<{ export type GetMakersInTournamentQuery = { __typename?: 'Query', getMakersInTournament: { __typename?: 'TournamentMakersResponse', hasNext: boolean | null, hasPrev: boolean | null, makers: Array<{ __typename?: 'User', id: number, name: string, avatar: string, jobTitle: string | null, roles: Array<{ __typename?: 'MakerRole', id: number, icon: string, title: string }>, skills: Array<{ __typename?: 'MakerSkill', id: number, title: string }> }> } }; -export type MeTournamentQueryVariables = Exact<{ [key: string]: never; }>; +export type GetProjectsInTournamentQueryVariables = Exact<{ + tournamentId: Scalars['Int']; + take: InputMaybe; + skip: InputMaybe; + roleId: InputMaybe; + search: InputMaybe; +}>; -export type MeTournamentQuery = { __typename?: 'Query', me: { __typename?: 'MyProfile', id: number, name: string, avatar: string, jobTitle: string | null, skills: Array<{ __typename?: 'MakerSkill', id: number, title: string }>, roles: Array<{ __typename?: 'MakerRole', id: number, title: string, icon: string, level: RoleLevelEnum }> } | null }; - -export type GetAllRolesQueryVariables = Exact<{ [key: string]: never; }>; - - -export type GetAllRolesQuery = { __typename?: 'Query', getAllMakersRoles: Array<{ __typename?: 'GenericMakerRole', id: number, title: string, icon: string }> }; +export type GetProjectsInTournamentQuery = { __typename?: 'Query', getProjectsInTournament: { __typename?: 'TournamentProjectsResponse', hasNext: boolean | null, hasPrev: boolean | null, projects: Array<{ __typename?: 'Project', id: number, title: string, description: string, thumbnail_image: string, category: { __typename?: 'Category', id: number, title: string, icon: string | null }, recruit_roles: Array<{ __typename?: 'MakerRole', id: number, title: string, icon: string, level: RoleLevelEnum }> }> } }; export type GetTournamentByIdQueryVariables = Exact<{ id: Scalars['Int']; @@ -2158,67 +2187,6 @@ export function useProjectDetailsLazyQuery(baseOptions?: Apollo.LazyQueryHookOpt export type ProjectDetailsQueryHookResult = ReturnType; export type ProjectDetailsLazyQueryHookResult = ReturnType; export type ProjectDetailsQueryResult = Apollo.QueryResult; -export const GetMakersInTournamentDocument = gql` - query GetMakersInTournament($tournamentId: Int!, $take: Int, $skip: Int, $search: String, $roleId: Int) { - getMakersInTournament( - tournamentId: $tournamentId - take: $take - skip: $skip - search: $search - roleId: $roleId - ) { - hasNext - hasPrev - makers { - id - name - avatar - jobTitle - roles { - id - icon - title - } - skills { - id - title - } - } - } -} - `; - -/** - * __useGetMakersInTournamentQuery__ - * - * To run a query within a React component, call `useGetMakersInTournamentQuery` and pass it any options that fit your needs. - * When your component renders, `useGetMakersInTournamentQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; - * - * @example - * const { data, loading, error } = useGetMakersInTournamentQuery({ - * variables: { - * tournamentId: // value for 'tournamentId' - * take: // value for 'take' - * skip: // value for 'skip' - * search: // value for 'search' - * roleId: // value for 'roleId' - * }, - * }); - */ -export function useGetMakersInTournamentQuery(baseOptions: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(GetMakersInTournamentDocument, options); - } -export function useGetMakersInTournamentLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(GetMakersInTournamentDocument, options); - } -export type GetMakersInTournamentQueryHookResult = ReturnType; -export type GetMakersInTournamentLazyQueryHookResult = ReturnType; -export type GetMakersInTournamentQueryResult = Apollo.QueryResult; export const MeTournamentDocument = gql` query MeTournament { me { @@ -2293,6 +2261,130 @@ export function useGetAllRolesLazyQuery(baseOptions?: Apollo.LazyQueryHookOption export type GetAllRolesQueryHookResult = ReturnType; export type GetAllRolesLazyQueryHookResult = ReturnType; export type GetAllRolesQueryResult = Apollo.QueryResult; +export const GetMakersInTournamentDocument = gql` + query GetMakersInTournament($tournamentId: Int!, $take: Int, $skip: Int, $search: String, $roleId: Int) { + getMakersInTournament( + tournamentId: $tournamentId + take: $take + skip: $skip + search: $search + roleId: $roleId + ) { + hasNext + hasPrev + makers { + id + name + avatar + jobTitle + roles { + id + icon + title + } + skills { + id + title + } + } + } +} + `; + +/** + * __useGetMakersInTournamentQuery__ + * + * To run a query within a React component, call `useGetMakersInTournamentQuery` and pass it any options that fit your needs. + * When your component renders, `useGetMakersInTournamentQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetMakersInTournamentQuery({ + * variables: { + * tournamentId: // value for 'tournamentId' + * take: // value for 'take' + * skip: // value for 'skip' + * search: // value for 'search' + * roleId: // value for 'roleId' + * }, + * }); + */ +export function useGetMakersInTournamentQuery(baseOptions: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(GetMakersInTournamentDocument, options); + } +export function useGetMakersInTournamentLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(GetMakersInTournamentDocument, options); + } +export type GetMakersInTournamentQueryHookResult = ReturnType; +export type GetMakersInTournamentLazyQueryHookResult = ReturnType; +export type GetMakersInTournamentQueryResult = Apollo.QueryResult; +export const GetProjectsInTournamentDocument = gql` + query GetProjectsInTournament($tournamentId: Int!, $take: Int, $skip: Int, $roleId: Int, $search: String) { + getProjectsInTournament( + tournamentId: $tournamentId + take: $take + skip: $skip + roleId: $roleId + search: $search + ) { + hasNext + hasPrev + projects { + id + title + description + thumbnail_image + category { + id + title + icon + } + recruit_roles { + id + title + icon + level + } + } + } +} + `; + +/** + * __useGetProjectsInTournamentQuery__ + * + * To run a query within a React component, call `useGetProjectsInTournamentQuery` and pass it any options that fit your needs. + * When your component renders, `useGetProjectsInTournamentQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetProjectsInTournamentQuery({ + * variables: { + * tournamentId: // value for 'tournamentId' + * take: // value for 'take' + * skip: // value for 'skip' + * roleId: // value for 'roleId' + * search: // value for 'search' + * }, + * }); + */ +export function useGetProjectsInTournamentQuery(baseOptions: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(GetProjectsInTournamentDocument, options); + } +export function useGetProjectsInTournamentLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(GetProjectsInTournamentDocument, options); + } +export type GetProjectsInTournamentQueryHookResult = ReturnType; +export type GetProjectsInTournamentLazyQueryHookResult = ReturnType; +export type GetProjectsInTournamentQueryResult = Apollo.QueryResult; export const GetTournamentByIdDocument = gql` query GetTournamentById($id: Int!) { getTournamentById(id: $id) { diff --git a/src/redux/features/modals.slice.ts b/src/redux/features/modals.slice.ts index d3e58ed..42193ae 100644 --- a/src/redux/features/modals.slice.ts +++ b/src/redux/features/modals.slice.ts @@ -10,11 +10,10 @@ import { ModalCard } from "src/Components/Modals/ModalsContainer/ModalsContainer import { ConfirmModal } from "src/Components/Modals/ConfirmModal"; import { RemoveWalletKeyModal } from "src/features/Profiles/pages/EditProfilePage/PreferencesTab/RemoveWalletKeyModal"; import { LinkingAccountModal } from "src/features/Profiles/pages/EditProfilePage/PreferencesTab/LinkingAccountModal"; - +import { EventModal } from "src/features/Tournaments/pages/EventsPage/EventModal"; import { ComponentProps } from "react"; import { generateId } from "src/utils/helperFunctions"; import { NoWeblnModal } from "src/Components/Modals/NoWeblnModal"; -import { EventModal } from "src/features/Tournaments/pages/EventsPage/EventModal"; export enum Direction { START, From 58ca7fdd160b2a564ce551aa307d9dcdbb40cfd0 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Tue, 6 Sep 2022 13:30:22 +0300 Subject: [PATCH 23/53] feat: connect with maker modal --- .../ConnectToMakerModal.tsx | 81 +++++++++++++++++++ .../MakersPage/ConnectToMakerModal/index.ts | 3 + .../pages/MakersPage/MakerCard/MakerCard.tsx | 13 ++- .../pages/MakersPage/tournamentMakers.graphql | 4 + src/graphql/index.tsx | 6 +- src/redux/features/modals.slice.ts | 6 +- 6 files changed, 108 insertions(+), 5 deletions(-) create mode 100644 src/features/Tournaments/pages/MakersPage/ConnectToMakerModal/ConnectToMakerModal.tsx create mode 100644 src/features/Tournaments/pages/MakersPage/ConnectToMakerModal/index.ts diff --git a/src/features/Tournaments/pages/MakersPage/ConnectToMakerModal/ConnectToMakerModal.tsx b/src/features/Tournaments/pages/MakersPage/ConnectToMakerModal/ConnectToMakerModal.tsx new file mode 100644 index 0000000..16e58eb --- /dev/null +++ b/src/features/Tournaments/pages/MakersPage/ConnectToMakerModal/ConnectToMakerModal.tsx @@ -0,0 +1,81 @@ +import { motion } from 'framer-motion' +import { ModalCard, modalCardVariants } from 'src/Components/Modals/ModalsContainer/ModalsContainer' +import { FiGithub, FiLinkedin, FiTwitter } from "react-icons/fi"; +import { IoClose } from 'react-icons/io5'; +import { GetMakersInTournamentQuery } from 'src/graphql'; +import Avatar from 'src/features/Profiles/Components/Avatar/Avatar'; +import { withHttp } from 'src/utils/helperFunctions'; + + +interface Props extends ModalCard { + maker: GetMakersInTournamentQuery['getMakersInTournament']['makers'][number] +} + +export default function LinkingAccountModal({ onClose, direction, maker, ...props }: Props) { + + + const links = [ + { + hasValue: maker.twitter, + text: maker.twitter, + icon: FiTwitter, + colors: "bg-blue-100 text-blue-500", + url: `https://twitter.com/@${maker.twitter}` + }, + { + hasValue: maker.github, + text: maker.github, + icon: FiGithub, + colors: "bg-pink-100 text-pink-600", + url: `https://github.com/${maker.github}` + }, + { + hasValue: maker.linkedin, + text: "LinkedIn", + icon: FiLinkedin, + colors: "bg-sky-100 text-cyan-600", + url: maker.linkedin && withHttp(maker.linkedin), + } + ]; + + + return ( + +
+ +

Send team request 🤝

+
+
+
+ +
+

{maker.name}

+

{maker.jobTitle}

+
+ +

Team up with this maker by sending them a message on one of the following platforms.

+
+ {links.filter(link => link.hasValue).map((link, idx) => + + + )} +
+
+
+ ) +} + + + diff --git a/src/features/Tournaments/pages/MakersPage/ConnectToMakerModal/index.ts b/src/features/Tournaments/pages/MakersPage/ConnectToMakerModal/index.ts new file mode 100644 index 0000000..1da3ce6 --- /dev/null +++ b/src/features/Tournaments/pages/MakersPage/ConnectToMakerModal/index.ts @@ -0,0 +1,3 @@ +import { lazyModal } from 'src/utils/helperFunctions'; + +export const { LazyComponent: ConnectToMakerModal } = lazyModal(() => import('./ConnectToMakerModal')) \ No newline at end of file diff --git a/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx b/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx index 1fe99c2..5fce987 100644 --- a/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx +++ b/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx @@ -5,6 +5,7 @@ import Card from 'src/Components/Card/Card'; import Avatar from 'src/features/Profiles/Components/Avatar/Avatar'; import Badge from 'src/Components/Badge/Badge'; import { createRoute } from 'src/utils/routing'; +import { openModal } from "src/redux/features/modals.slice"; type MakerType = GetMakersInTournamentQuery['getMakersInTournament']['makers'][number] @@ -15,7 +16,12 @@ interface Props { export default function MakerCard({ maker, isMe }: Props) { - const dispatch = useAppDispatch() + const dispatch = useAppDispatch(); + + let actionBtn = + + if (isMe) actionBtn = ; + else actionBtn = return ( @@ -36,7 +42,7 @@ export default function MakerCard({ maker, isMe }: Props) {

No roles added

}
- {isMe && } + {actionBtn}

@@ -60,6 +66,7 @@ export default function MakerCard({ maker, isMe }: Props) {

No skills added

}
- {isMe && } +
{actionBtn}
+ ) } diff --git a/src/features/Tournaments/pages/MakersPage/tournamentMakers.graphql b/src/features/Tournaments/pages/MakersPage/tournamentMakers.graphql index 0a8856c..f1ebe98 100644 --- a/src/features/Tournaments/pages/MakersPage/tournamentMakers.graphql +++ b/src/features/Tournaments/pages/MakersPage/tournamentMakers.graphql @@ -37,6 +37,10 @@ query GetMakersInTournament( name avatar jobTitle + email + twitter + linkedin + github roles { id icon diff --git a/src/graphql/index.tsx b/src/graphql/index.tsx index c5dc674..4ae1dba 100644 --- a/src/graphql/index.tsx +++ b/src/graphql/index.tsx @@ -844,7 +844,7 @@ export type GetMakersInTournamentQueryVariables = Exact<{ }>; -export type GetMakersInTournamentQuery = { __typename?: 'Query', getMakersInTournament: { __typename?: 'TournamentMakersResponse', hasNext: boolean | null, hasPrev: boolean | null, makers: Array<{ __typename?: 'User', id: number, name: string, avatar: string, jobTitle: string | null, roles: Array<{ __typename?: 'MakerRole', id: number, icon: string, title: string }>, skills: Array<{ __typename?: 'MakerSkill', id: number, title: string }> }> } }; +export type GetMakersInTournamentQuery = { __typename?: 'Query', getMakersInTournament: { __typename?: 'TournamentMakersResponse', hasNext: boolean | null, hasPrev: boolean | null, makers: Array<{ __typename?: 'User', id: number, name: string, avatar: string, jobTitle: string | null, email: string | null, twitter: string | null, linkedin: string | null, github: string | null, roles: Array<{ __typename?: 'MakerRole', id: number, icon: string, title: string }>, skills: Array<{ __typename?: 'MakerSkill', id: number, title: string }> }> } }; export type GetProjectsInTournamentQueryVariables = Exact<{ tournamentId: Scalars['Int']; @@ -2277,6 +2277,10 @@ export const GetMakersInTournamentDocument = gql` name avatar jobTitle + email + twitter + linkedin + github roles { id icon diff --git a/src/redux/features/modals.slice.ts b/src/redux/features/modals.slice.ts index 42193ae..98b413f 100644 --- a/src/redux/features/modals.slice.ts +++ b/src/redux/features/modals.slice.ts @@ -14,6 +14,9 @@ import { EventModal } from "src/features/Tournaments/pages/EventsPage/EventModal import { ComponentProps } from "react"; import { generateId } from "src/utils/helperFunctions"; import { NoWeblnModal } from "src/Components/Modals/NoWeblnModal"; +import { ConnectToMakerModal } from "src/features/Tournaments/pages/MakersPage/ConnectToMakerModal"; + + export enum Direction { START, @@ -39,7 +42,8 @@ export const ALL_MODALS = { Claim_FundWithdrawCard, // Tournaments - EventModal: EventModal, + EventModal, + ConnectToMakerModal, // Misc ConfirmModal, From fbb8d1cf6d85731f9a50ba29a3a64ccd98a60707 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Tue, 6 Sep 2022 13:59:56 +0300 Subject: [PATCH 24/53] feat: add 'all makers' tab, add email contact to ConnectToMakerModal, make tabs buttons a carousel in makers page --- .../RolesSkillsTab/RolesSkillsTab.tsx | 2 +- .../UpdateRolesCard/UpdateRolesCard.tsx | 2 - .../TournamentsCard/TournamentsCard.tsx | 3 +- .../ConnectToMakerModal.tsx | 13 +++-- .../pages/MakersPage/MakerCard/MakerCard.tsx | 4 +- .../ParticipantsSection/MakersList.tsx | 3 +- .../ParticipantsSection.tsx | 49 +++++++++++++------ .../ParticipantsSection/ProjectsList.tsx | 2 +- 8 files changed, 49 insertions(+), 29 deletions(-) diff --git a/src/features/Profiles/pages/EditProfilePage/RolesSkillsTab/RolesSkillsTab.tsx b/src/features/Profiles/pages/EditProfilePage/RolesSkillsTab/RolesSkillsTab.tsx index b60c2bb..6234bcc 100644 --- a/src/features/Profiles/pages/EditProfilePage/RolesSkillsTab/RolesSkillsTab.tsx +++ b/src/features/Profiles/pages/EditProfilePage/RolesSkillsTab/RolesSkillsTab.tsx @@ -6,7 +6,7 @@ import { Controller, SubmitHandler, useForm } from 'react-hook-form'; import SaveChangesCard from '../SaveChangesCard/SaveChangesCard'; import { toast } from 'react-toastify'; import { NotificationsService } from 'src/services'; -import { gql, NetworkStatus, useApolloClient } from '@apollo/client'; +import { NetworkStatus, useApolloClient } from '@apollo/client'; import { usePrompt } from 'src/utils/hooks'; import { UpdateUserRolesSkillsMutationVariables, useMyProfileRolesSkillsQuery, useUpdateUserRolesSkillsMutation, UserRolesSkillsFragmentDoc } from 'src/graphql' import UpdateRolesCard from "./UpdateRolesCard/UpdateRolesCard"; diff --git a/src/features/Profiles/pages/EditProfilePage/RolesSkillsTab/UpdateRolesCard/UpdateRolesCard.tsx b/src/features/Profiles/pages/EditProfilePage/RolesSkillsTab/UpdateRolesCard/UpdateRolesCard.tsx index 1b15db3..e09d904 100644 --- a/src/features/Profiles/pages/EditProfilePage/RolesSkillsTab/UpdateRolesCard/UpdateRolesCard.tsx +++ b/src/features/Profiles/pages/EditProfilePage/RolesSkillsTab/UpdateRolesCard/UpdateRolesCard.tsx @@ -1,8 +1,6 @@ import React from 'react' -import { Control, useFieldArray } from 'react-hook-form' import Card from 'src/Components/Card/Card' import { GenericMakerRole, MakerRole, RoleLevelEnum } from 'src/graphql' -import { IRolesSkillsForm } from '../RolesSkillsTab' type Value = Pick diff --git a/src/features/Profiles/pages/ProfilePage/TournamentsCard/TournamentsCard.tsx b/src/features/Profiles/pages/ProfilePage/TournamentsCard/TournamentsCard.tsx index ef96f2e..1bf1cfc 100644 --- a/src/features/Profiles/pages/ProfilePage/TournamentsCard/TournamentsCard.tsx +++ b/src/features/Profiles/pages/ProfilePage/TournamentsCard/TournamentsCard.tsx @@ -1,6 +1,5 @@ import Card from 'src/Components/Card/Card' -import Button from 'src/Components/Button/Button' -import { RoleLevelEnum, User } from 'src/graphql'; +import { User } from 'src/graphql'; diff --git a/src/features/Tournaments/pages/MakersPage/ConnectToMakerModal/ConnectToMakerModal.tsx b/src/features/Tournaments/pages/MakersPage/ConnectToMakerModal/ConnectToMakerModal.tsx index 16e58eb..14e802a 100644 --- a/src/features/Tournaments/pages/MakersPage/ConnectToMakerModal/ConnectToMakerModal.tsx +++ b/src/features/Tournaments/pages/MakersPage/ConnectToMakerModal/ConnectToMakerModal.tsx @@ -1,6 +1,6 @@ import { motion } from 'framer-motion' import { ModalCard, modalCardVariants } from 'src/Components/Modals/ModalsContainer/ModalsContainer' -import { FiGithub, FiLinkedin, FiTwitter } from "react-icons/fi"; +import { FiGithub, FiLinkedin, FiMail, FiTwitter } from "react-icons/fi"; import { IoClose } from 'react-icons/io5'; import { GetMakersInTournamentQuery } from 'src/graphql'; import Avatar from 'src/features/Profiles/Components/Avatar/Avatar'; @@ -15,25 +15,28 @@ export default function LinkingAccountModal({ onClose, direction, maker, ...prop const links = [ + { + hasValue: maker.email, + text: maker.email, + icon: FiMail, + url: maker.email && `mailto:${maker.email}` + }, { hasValue: maker.twitter, text: maker.twitter, icon: FiTwitter, - colors: "bg-blue-100 text-blue-500", url: `https://twitter.com/@${maker.twitter}` }, { hasValue: maker.github, text: maker.github, icon: FiGithub, - colors: "bg-pink-100 text-pink-600", url: `https://github.com/${maker.github}` }, { hasValue: maker.linkedin, text: "LinkedIn", icon: FiLinkedin, - colors: "bg-sky-100 text-cyan-600", url: maker.linkedin && withHttp(maker.linkedin), } ]; @@ -66,7 +69,7 @@ export default function LinkingAccountModal({ onClose, direction, maker, ...prop diff --git a/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx b/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx index 5fce987..013d14e 100644 --- a/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx +++ b/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx @@ -18,10 +18,12 @@ export default function MakerCard({ maker, isMe }: Props) { const dispatch = useAppDispatch(); + const contactLinksAvailable = maker.github || maker.email || maker.linkedin || maker.twitter; + let actionBtn = if (isMe) actionBtn = ; - else actionBtn = + else if (contactLinksAvailable) actionBtn = return ( diff --git a/src/features/Tournaments/pages/MakersPage/ParticipantsSection/MakersList.tsx b/src/features/Tournaments/pages/MakersPage/ParticipantsSection/MakersList.tsx index bb281b4..e59d470 100644 --- a/src/features/Tournaments/pages/MakersPage/ParticipantsSection/MakersList.tsx +++ b/src/features/Tournaments/pages/MakersPage/ParticipantsSection/MakersList.tsx @@ -9,9 +9,10 @@ interface Props { tournamentId: number searchFilter: string, roleFilter: number | null + onlyLookingToTeam?: boolean } -const ITEMS_PER_PAGE = 3; +const ITEMS_PER_PAGE = 15; export default function MakersList(props: Props) { diff --git a/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ParticipantsSection.tsx b/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ParticipantsSection.tsx index f00f83e..3ef5805 100644 --- a/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ParticipantsSection.tsx +++ b/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ParticipantsSection.tsx @@ -1,6 +1,7 @@ import { useDebouncedState } from '@react-hookz/web'; import { useState } from 'react' import { GenericMakerRole } from 'src/graphql' +import { useCarousel } from 'src/utils/hooks'; import MakersFilters from '../MakersFilters/MakersFilters'; import MakersList from './MakersList'; import ProjectsList from './ProjectsList'; @@ -13,9 +14,13 @@ export default function ParticipantsSection({ tournamentId }: Props) { const [searchFilter, setSearchFilter] = useState(""); const [debouncedsearchFilter, setDebouncedSearchFilter] = useDebouncedState("", 500); const [roleFilter, setRoleFilter] = useState(null); - const [curTab, setCurTab] = useState<'makers' | 'projects'>('makers') + const [curTab, setCurTab] = useState<'all-makers' | 'makers-to-team' | 'projects'>('all-makers') + const { viewportRef, } = useCarousel({ + align: 'start', slidesToScroll: 1, + containScroll: "trimSnaps", + }) const changeSearchFilter = (new_value: string) => { setSearchFilter(new_value); @@ -37,30 +42,42 @@ export default function ParticipantsSection({ tournamentId }: Props) { />
-
- - + + + onClick={() => setCurTab('projects')} + > + Projects looking for makers + +
{curTab === 'projects' && } - {curTab === 'makers' && } + {curTab !== 'projects' && } ) } diff --git a/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ProjectsList.tsx b/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ProjectsList.tsx index db5fd93..b46da09 100644 --- a/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ProjectsList.tsx +++ b/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ProjectsList.tsx @@ -11,7 +11,7 @@ interface Props { roleFilter: number | null } -const ITEMS_PER_PAGE = 3; +const ITEMS_PER_PAGE = 15; export default function ProjectsList(props: Props) { From 3f71e854048791b11565445701124cf1387561aa Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Wed, 7 Sep 2022 10:04:01 +0300 Subject: [PATCH 25/53] feat: project card & skeleton --- package-lock.json | 4 +- package.json | 2 +- .../ParticipantsSection/ProjectsList.tsx | 4 -- .../ProjectCard/ProjectCard.Skeleton.tsx | 27 ++++++++ .../ProjectsPage/ProjectCard/ProjectCard.tsx | 49 ++++++++++++++ .../pages/ProjectsPage/ProjectsPage.tsx | 67 +++++++++++++++++++ .../Navigation/Navigation.tsx | 3 +- .../TournamentDetailsPage.tsx | 2 + 8 files changed, 150 insertions(+), 8 deletions(-) create mode 100644 src/features/Tournaments/pages/ProjectsPage/ProjectCard/ProjectCard.Skeleton.tsx create mode 100644 src/features/Tournaments/pages/ProjectsPage/ProjectCard/ProjectCard.tsx create mode 100644 src/features/Tournaments/pages/ProjectsPage/ProjectsPage.tsx diff --git a/package-lock.json b/package-lock.json index 64fd3a5..dd2c320 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,6 @@ "@remirror/react": "^1.0.34", "@shopify/react-web-worker": "^5.0.1", "@szhsin/react-menu": "^3.0.2", - "@tailwindcss/line-clamp": "^0.4.2", "@testing-library/jest-dom": "^5.16.4", "@testing-library/react": "^13.1.1", "@testing-library/user-event": "^13.5.0", @@ -114,6 +113,7 @@ "@storybook/react": "^6.4.22", "@storybook/testing-library": "^0.0.10", "@tailwindcss/forms": "^0.5.0", + "@tailwindcss/line-clamp": "^0.4.2", "@tailwindcss/typography": "^0.5.7", "@types/chance": "^1.1.3", "@types/dompurify": "^2.3.3", @@ -15328,6 +15328,7 @@ "version": "0.4.2", "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.4.2.tgz", "integrity": "sha512-HFzAQuqYCjyy/SX9sLGB1lroPzmcnWv1FHkIpmypte10hptf4oPUfucryMKovZh2u0uiS9U5Ty3GghWfEJGwVw==", + "dev": true, "peerDependencies": { "tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1" } @@ -82406,6 +82407,7 @@ "version": "0.4.2", "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.4.2.tgz", "integrity": "sha512-HFzAQuqYCjyy/SX9sLGB1lroPzmcnWv1FHkIpmypte10hptf4oPUfucryMKovZh2u0uiS9U5Ty3GghWfEJGwVw==", + "dev": true, "requires": {} }, "@tailwindcss/typography": { diff --git a/package.json b/package.json index 40533fb..612144f 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,6 @@ "@remirror/react": "^1.0.34", "@shopify/react-web-worker": "^5.0.1", "@szhsin/react-menu": "^3.0.2", - "@tailwindcss/line-clamp": "^0.4.2", "@testing-library/jest-dom": "^5.16.4", "@testing-library/react": "^13.1.1", "@testing-library/user-event": "^13.5.0", @@ -166,6 +165,7 @@ "@storybook/react": "^6.4.22", "@storybook/testing-library": "^0.0.10", "@tailwindcss/forms": "^0.5.0", + "@tailwindcss/line-clamp": "^0.4.2", "@tailwindcss/typography": "^0.5.7", "@types/chance": "^1.1.3", "@types/dompurify": "^2.3.3", diff --git a/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ProjectsList.tsx b/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ProjectsList.tsx index b46da09..9fbfe58 100644 --- a/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ProjectsList.tsx +++ b/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ProjectsList.tsx @@ -28,10 +28,6 @@ export default function ProjectsList(props: Props) { take: ITEMS_PER_PAGE, }); - - - - const query = useGetProjectsInTournamentQuery({ variables: queryFilter, }); diff --git a/src/features/Tournaments/pages/ProjectsPage/ProjectCard/ProjectCard.Skeleton.tsx b/src/features/Tournaments/pages/ProjectsPage/ProjectCard/ProjectCard.Skeleton.tsx new file mode 100644 index 0000000..4de6e3d --- /dev/null +++ b/src/features/Tournaments/pages/ProjectsPage/ProjectCard/ProjectCard.Skeleton.tsx @@ -0,0 +1,27 @@ +import Card from 'src/Components/Card/Card'; +import Skeleton from 'react-loading-skeleton'; +import Button from 'src/Components/Button/Button'; + + +export default function ProjectCardSkeleton() { + + + return ( + +
+
+
+

+

+
+
+

+
+

+ + +
+ + + ) +} diff --git a/src/features/Tournaments/pages/ProjectsPage/ProjectCard/ProjectCard.tsx b/src/features/Tournaments/pages/ProjectsPage/ProjectCard/ProjectCard.tsx new file mode 100644 index 0000000..dc8b7d4 --- /dev/null +++ b/src/features/Tournaments/pages/ProjectsPage/ProjectCard/ProjectCard.tsx @@ -0,0 +1,49 @@ +import { GetProjectsInTournamentQuery, } from "src/graphql"; +import Card from 'src/Components/Card/Card'; +import Badge from 'src/Components/Badge/Badge'; +import Button from "src/Components/Button/Button" +import { createRoute } from "src/utils/routing"; +import { useAppDispatch } from "src/utils/hooks"; +import { openModal } from "src/redux/features/modals.slice"; +import { FaUsers } from "react-icons/fa"; + +type ProjectType = GetProjectsInTournamentQuery['getProjectsInTournament']['projects'][number] + +interface Props { + project: ProjectType, +} + +export default function ProjectCard({ project }: Props) { + + + const dispatch = useAppDispatch(); + + const openProject = () => { + dispatch(openModal({ + Modal: "ProjectDetailsCard", + isPageModal: true, + props: { + projectId: project.id + } + })) + } + + return ( + +
+ +
+

{project.title}

+

{project.category.icon} {project.category.title}

+
+
+

{project.description}

+
+

👾 Makers

+ 6 makers + +
+ +
+ ) +} diff --git a/src/features/Tournaments/pages/ProjectsPage/ProjectsPage.tsx b/src/features/Tournaments/pages/ProjectsPage/ProjectsPage.tsx new file mode 100644 index 0000000..03dbd5e --- /dev/null +++ b/src/features/Tournaments/pages/ProjectsPage/ProjectsPage.tsx @@ -0,0 +1,67 @@ +import { useDebouncedState } from '@react-hookz/web'; +import { useState } from 'react' +import { FiSearch } from 'react-icons/fi'; +import { Tournament, useGetProjectsInTournamentQuery } from 'src/graphql' +import ProjectCard from './ProjectCard/ProjectCard'; +import ProjectCardSkeleton from './ProjectCard/ProjectCard.Skeleton'; + +interface Props { + data: Pick +} + +export default function ProjectsPage({ data: { id } }: Props) { + + + const [searchFilter, setSearchFilter] = useState(""); + const [debouncedsearchFilter, setDebouncedSearchFilter] = useDebouncedState("", 500); + + + + const query = useGetProjectsInTournamentQuery({ + variables: { + tournamentId: id, + roleId: null, + search: debouncedsearchFilter, + skip: 0, + take: 200, + }, + }); + + + const changeSearchFilter = (new_value: string) => { + setSearchFilter(new_value); + setDebouncedSearchFilter(new_value); + } + + const projectsCount = !!query.data?.getProjectsInTournament.projects && query.data.getProjectsInTournament.projects.length; + + + return ( +
+

Projects {projectsCount && `(${projectsCount})`}

+ +
+ + changeSearchFilter(e.target.value)} + /> +
+
+ {query.loading ? + Array(9).fill(0).map((_, idx) => ) + : + query.data?.getProjectsInTournament.projects.map(project => + ) + } +
+
+ ) +} diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx index 6337910..8fb3548 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx +++ b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx @@ -28,9 +28,8 @@ export default function Navigation({ data }: Props) { path: "makers", }, { - text: `??????? 🚧`, + text: `Projects`, path: "projects", - isDisabled: true, }, { text: "???? 🚧", diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx index 14b9686..0beac54 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx +++ b/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx @@ -7,6 +7,7 @@ import Navigation from './Navigation/Navigation' import EventsPage from '../EventsPage/EventsPage' import { tournamentData } from './data' import MakersPage from '../MakersPage/MakersPage' +import ProjectsPage from '../ProjectsPage/ProjectsPage' const data = tournamentData @@ -41,6 +42,7 @@ export default function TournamentDetailsPage() { } /> } /> } /> + } />
From 5cd6b129519d68338c1ed2780ef656e03d5bf082 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Wed, 7 Sep 2022 10:17:39 +0300 Subject: [PATCH 26/53] fix: project grid layout --- .../ProjectsPage/ProjectCard/ProjectCard.tsx | 17 +++++++++-------- .../pages/ProjectsPage/ProjectsPage.tsx | 4 ++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/features/Tournaments/pages/ProjectsPage/ProjectCard/ProjectCard.tsx b/src/features/Tournaments/pages/ProjectsPage/ProjectCard/ProjectCard.tsx index dc8b7d4..c9e65ec 100644 --- a/src/features/Tournaments/pages/ProjectsPage/ProjectCard/ProjectCard.tsx +++ b/src/features/Tournaments/pages/ProjectsPage/ProjectCard/ProjectCard.tsx @@ -29,21 +29,22 @@ export default function ProjectCard({ project }: Props) { } return ( - +
- +

{project.title}

{project.category.icon} {project.category.title}

-

{project.description}

-
-

👾 Makers

- 6 makers - +

{project.description}

+
+ {/*

👾 Makers

*/} +

+ 6 makers +

- + ) } diff --git a/src/features/Tournaments/pages/ProjectsPage/ProjectsPage.tsx b/src/features/Tournaments/pages/ProjectsPage/ProjectsPage.tsx index 03dbd5e..0e7b6b1 100644 --- a/src/features/Tournaments/pages/ProjectsPage/ProjectsPage.tsx +++ b/src/features/Tournaments/pages/ProjectsPage/ProjectsPage.tsx @@ -39,7 +39,7 @@ export default function ProjectsPage({ data: { id } }: Props) { return (
-

Projects {projectsCount && `(${projectsCount})`}

+

Projects {projectsCount && `(${projectsCount})`}

@@ -51,7 +51,7 @@ export default function ProjectsPage({ data: { id } }: Props) { onChange={e => changeSearchFilter(e.target.value)} />
-
+
{query.loading ? Array(9).fill(0).map((_, idx) => ) : From fbedcb53f6fcae80b87432abf9bc1492282dbfb7 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Wed, 7 Sep 2022 10:26:44 +0300 Subject: [PATCH 27/53] style: proejct card btn color --- .../Tournaments/pages/ProjectsPage/ProjectCard/ProjectCard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/Tournaments/pages/ProjectsPage/ProjectCard/ProjectCard.tsx b/src/features/Tournaments/pages/ProjectsPage/ProjectCard/ProjectCard.tsx index c9e65ec..0eda4d0 100644 --- a/src/features/Tournaments/pages/ProjectsPage/ProjectCard/ProjectCard.tsx +++ b/src/features/Tournaments/pages/ProjectsPage/ProjectCard/ProjectCard.tsx @@ -44,7 +44,7 @@ export default function ProjectCard({ project }: Props) { 6 makers

- + ) } From a7203e94f2bb1bf12a57837890b545fc4e55b1ca Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Wed, 7 Sep 2022 11:34:14 +0300 Subject: [PATCH 28/53] data: tournament seed --- api/functions/graphql/types/tournament.js | 3 + prisma/seed/data/tournament.seed.js | 229 ++++++++++++++++++++++ 2 files changed, 232 insertions(+) create mode 100644 prisma/seed/data/tournament.seed.js diff --git a/api/functions/graphql/types/tournament.js b/api/functions/graphql/types/tournament.js index aeb4e22..45e2dd2 100644 --- a/api/functions/graphql/types/tournament.js +++ b/api/functions/graphql/types/tournament.js @@ -266,4 +266,7 @@ module.exports = { getTournamentById, getMakersInTournament, getProjectsInTournament, + + // Enums + TournamentEventTypeEnum, } \ No newline at end of file diff --git a/prisma/seed/data/tournament.seed.js b/prisma/seed/data/tournament.seed.js new file mode 100644 index 0000000..7f77d6a --- /dev/null +++ b/prisma/seed/data/tournament.seed.js @@ -0,0 +1,229 @@ +const { TournamentEventTypeEnum } = require("../../../api/functions/graphql/types/tournament"); + +const tournament = { + __typename: "Tournament", + 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_count: 6, + makers_count: 668, + projects_count: 21, + events: [ + { + id: 12, + title: "STW3 Round Table #1", + date: "13:00 - 14:00 UTC, 23rd June", + description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", + image: 'https://picsum.photos/id/10/400/800', + links: [], + location: "Online", + type: 1, + website: "https://event.name" + }, + { + id: 13, + title: "STW3 Round Table #2", + date: "15:00 - 16:00 UTC, 23rd June", + description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", + image: 'https://picsum.photos/id/10/400/800', + links: [], + location: "Online", + type: 2, + website: "https://event.name" + }, + { + id: 14, + title: "STW3 Round Table #3", + date: "13:00 - 14:00 UTC, 24rd June", + description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", + image: 'https://picsum.photos/id/10/400/800', + links: [], + location: "Online", + type: 3, + website: "https://event.name" + }, + { + id: 44, + title: "Lightning Login", + date: "15:00 - 16:00 UTC, 24rd June", + description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", + image: 'https://picsum.photos/id/10/400/800', + links: [], + location: "Online", + type: 2, + website: "https://event.name" + }, + + { + id: 46, + title: "Escrow contracts", + date: "15:00 - 16:00 UTC, 23rd June", + description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", + image: 'https://picsum.photos/id/10/400/800', + links: [], + location: "Online", + type: 2, + website: "https://event.name" + }, + + { + id: 444, + title: "Lsats - What & Why", + date: "15:00 - 16:00 UTC, 23rd June", + description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", + image: 'https://picsum.photos/id/10/400/800', + links: [], + location: "Online", + type: 2, + website: "https://event.name" + }, + ], + judges: [ + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + { + name: "Ben Arc", + avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", + jobTitle: "Maker" + }, + ], + + faqs: [ + { + question: "What is Shock the Web?", + answer: + `Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there. + +Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.` + }, + { + question: "When and where will it take place?", + answer: + `Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there. + +Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.` + }, + { + question: "What will we be doing?", + answer: + `Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there. + +Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.` + }, + { + question: "This is my first time hacking on lightning, will there be help?", + answer: + `Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there. + +Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.` + }, + { + question: "This is my first time hacking on lightning, will there be help?", + answer: + `Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there. + +Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.` + }, + { + question: "How many members can I have on my team?", + answer: + `Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there. + +Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.` + }, + { + question: "Who will choose the winners?", + answer: + `Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there. + +Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.` + }, + ], +} + +module.exports = tournament; \ No newline at end of file From be0a752fb0df72e85ee5283055bba8b8a8b15b12 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Wed, 7 Sep 2022 11:52:05 +0300 Subject: [PATCH 29/53] chore: tournament seed --- prisma/seed/data/tournament.seed.js | 59 +++++++++++++++++++---------- prisma/seed/index.js | 50 ++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 20 deletions(-) diff --git a/prisma/seed/data/tournament.seed.js b/prisma/seed/data/tournament.seed.js index 7f77d6a..789b2f6 100644 --- a/prisma/seed/data/tournament.seed.js +++ b/prisma/seed/data/tournament.seed.js @@ -1,4 +1,4 @@ -const { TournamentEventTypeEnum } = require("../../../api/functions/graphql/types/tournament"); + const tournament = { __typename: "Tournament", @@ -44,7 +44,9 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e { id: 12, title: "STW3 Round Table #1", - date: "13:00 - 14:00 UTC, 23rd June", + + starts_at: "2022-09-30T21:00:00.000Z", + ends_at: "2022-10-30T22:00:00.000Z", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", image: 'https://picsum.photos/id/10/400/800', links: [], @@ -55,7 +57,8 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e { id: 13, title: "STW3 Round Table #2", - date: "15:00 - 16:00 UTC, 23rd June", + starts_at: "2022-09-30T21:00:00.000Z", + ends_at: "2022-10-30T22:00:00.000Z", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", image: 'https://picsum.photos/id/10/400/800', links: [], @@ -66,7 +69,8 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e { id: 14, title: "STW3 Round Table #3", - date: "13:00 - 14:00 UTC, 24rd June", + starts_at: "2022-09-30T21:00:00.000Z", + ends_at: "2022-10-30T22:00:00.000Z", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", image: 'https://picsum.photos/id/10/400/800', links: [], @@ -77,7 +81,8 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e { id: 44, title: "Lightning Login", - date: "15:00 - 16:00 UTC, 24rd June", + starts_at: "2022-09-30T21:00:00.000Z", + ends_at: "2022-10-30T22:00:00.000Z", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", image: 'https://picsum.photos/id/10/400/800', links: [], @@ -89,7 +94,8 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e { id: 46, title: "Escrow contracts", - date: "15:00 - 16:00 UTC, 23rd June", + starts_at: "2022-09-30T21:00:00.000Z", + ends_at: "2022-10-30T22:00:00.000Z", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", image: 'https://picsum.photos/id/10/400/800', links: [], @@ -101,7 +107,8 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e { id: 444, title: "Lsats - What & Why", - date: "15:00 - 16:00 UTC, 23rd June", + starts_at: "2022-09-30T21:00:00.000Z", + ends_at: "2022-10-30T22:00:00.000Z", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", image: 'https://picsum.photos/id/10/400/800', links: [], @@ -114,62 +121,74 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company", + twitter: "@arcbtc" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company", + twitter: "@arcbtc" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company", + twitter: "@arcbtc" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company", + twitter: "@arcbtc" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company", + twitter: "@arcbtc" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company", + twitter: "@arcbtc" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company", + twitter: "@arcbtc" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company", + twitter: "@arcbtc" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company", + twitter: "@arcbtc" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company", + twitter: "@arcbtc" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company", + twitter: "@arcbtc" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company", + twitter: "@arcbtc" }, ], @@ -226,4 +245,4 @@ Bitcoin development can seem scary for new developers coming in, but it doesn't ], } -module.exports = tournament; \ No newline at end of file +module.exports = { tournament }; \ No newline at end of file diff --git a/prisma/seed/index.js b/prisma/seed/index.js index abc52d5..2f5bd62 100644 --- a/prisma/seed/index.js +++ b/prisma/seed/index.js @@ -3,6 +3,7 @@ const { generatePrivateKey, getPublicKey } = require("../../api/utils/nostr-tool const { categories, projects, tags, hackathons, roles, skills } = require("./data"); const Chance = require('chance'); const { getCoverImage, randomItems, random } = require("./helpers"); +const { tournament: tournamentMock } = require("./data/tournament.seed"); const chance = new Chance(); @@ -64,6 +65,8 @@ async function main() { // await createSkills(); + await createTournament(); + } async function createCategories() { @@ -194,6 +197,53 @@ async function createSkills() { }) } +async function createTournament() { + console.log("Creating Tournament"); + + const createdTournament = await prisma.tournament.create({ + data: { + id: tournamentMock.id, + title: tournamentMock.title, + description: tournamentMock.description, + start_date: tournamentMock.start_date, + end_date: tournamentMock.end_date, + thumbnail_image: tournamentMock.thumbnail_image, + cover_image: tournamentMock.cover_image, + location: tournamentMock.location, + website: tournamentMock.website, + + faqs: { + createMany: { + data: tournamentMock.faqs.map(f => ({ question: f.question, answer: f.answer })) + } + }, + prizes: { + createMany: { + data: tournamentMock.prizes.map(p => ({ title: p.title, image: p.image, amount: p.amount })) + } + }, + judges: { + createMany: { + data: tournamentMock.judges.map(j => ({ name: j.name, company: j.company, twitter: j.twitter, avatar: j.avatar })) + } + }, + events: { + createMany: { + data: tournamentMock.events.map(e => ({ title: e.title, description: e.description, starts_at: e.starts_at, ends_at: e.ends_at, image: e.image, location: e.location, type: e.type, website: e.website })) + } + }, + + } + }) + + await prisma.skill.createMany({ + data: skills.map(item => ({ + id: item.id, + title: item.title, + })) + }) +} + main() .catch((e) => { From 36636b5f0d7eab4fa2ab87ff2af2c6e5e9f91c8e Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Wed, 7 Sep 2022 12:00:40 +0300 Subject: [PATCH 30/53] chore: remove id from tournament seed --- prisma/seed/index.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/prisma/seed/index.js b/prisma/seed/index.js index 2f5bd62..b455e10 100644 --- a/prisma/seed/index.js +++ b/prisma/seed/index.js @@ -202,7 +202,6 @@ async function createTournament() { const createdTournament = await prisma.tournament.create({ data: { - id: tournamentMock.id, title: tournamentMock.title, description: tournamentMock.description, start_date: tournamentMock.start_date, @@ -236,12 +235,6 @@ async function createTournament() { } }) - await prisma.skill.createMany({ - data: skills.map(item => ({ - id: item.id, - title: item.title, - })) - }) } From 0b51f16bbd0bd5d0a26e73fabbeeb32a87500d9c Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Wed, 7 Sep 2022 16:26:57 +0300 Subject: [PATCH 31/53] feat: proper backend api for tournament --- api/functions/graphql/nexus-typegen.ts | 22 ++- api/functions/graphql/schema.graphql | 5 +- api/functions/graphql/types/tournament.js | 128 +++++++++++++----- prisma/seed/data/tournament.seed.js | 12 +- prisma/seed/index.js | 2 +- .../Profiles/Components/Avatar/Avatar.tsx | 5 +- .../pages/EventsPage/EventCard/EventCard.tsx | 8 +- .../EventsPage/EventModal/EventModal.tsx | 7 +- .../JudgesSection/JudgesSection.tsx | 2 +- .../pages/OverviewPage/OverviewPage.tsx | 5 +- .../RegisterCard/RegisterCard.tsx | 8 +- .../Navigation/Navigation.tsx | 4 +- .../TournamentDetailsPage.tsx | 37 ++--- .../TournamentDetailsPage/data/description.ts | 6 +- .../TournamentDetailsPage/data/events.ts | 24 +++- .../TournamentDetailsPage/data/judeges.ts | 24 ++-- .../tournamentDetails.graphql | 14 +- src/graphql/index.tsx | 18 ++- src/mocks/data/tournament.ts | 42 +++--- src/mocks/handlers.ts | 3 +- 20 files changed, 243 insertions(+), 133 deletions(-) diff --git a/api/functions/graphql/nexus-typegen.ts b/api/functions/graphql/nexus-typegen.ts index 8f6b20a..ad69a48 100644 --- a/api/functions/graphql/nexus-typegen.ts +++ b/api/functions/graphql/nexus-typegen.ts @@ -240,26 +240,20 @@ export interface NexusGenObjects { cover_image: string; // String! 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! - prizes: NexusGenRootTypes['TournamentPrize'][]; // [TournamentPrize!]! - projects_count: number; // Int! start_date: NexusGenScalars['Date']; // Date! thumbnail_image: string; // String! title: string; // String! website: string; // String! } TournamentEvent: { // root type - date: NexusGenScalars['Date']; // Date! description: string; // String! + ends_at: NexusGenScalars['Date']; // Date! id: number; // Int! image: string; // String! - links: string[]; // [String!]! location: string; // String! + starts_at: NexusGenScalars['Date']; // Date! title: string; // String! type: NexusGenEnums['TournamentEventTypeEnum']; // TournamentEventTypeEnum! website: string; // String! @@ -270,7 +264,7 @@ export interface NexusGenObjects { } TournamentJudge: { // root type avatar: string; // String! - jobTitle: string; // String! + company: string; // String! name: string; // String! } TournamentMakersResponse: { // root type @@ -569,12 +563,13 @@ export interface NexusGenFieldTypes { website: string; // String! } TournamentEvent: { // field return type - date: NexusGenScalars['Date']; // Date! description: string; // String! + ends_at: NexusGenScalars['Date']; // Date! id: number; // Int! image: string; // String! links: string[]; // [String!]! location: string; // String! + starts_at: NexusGenScalars['Date']; // Date! title: string; // String! type: NexusGenEnums['TournamentEventTypeEnum']; // TournamentEventTypeEnum! website: string; // String! @@ -585,7 +580,7 @@ export interface NexusGenFieldTypes { } TournamentJudge: { // field return type avatar: string; // String! - jobTitle: string; // String! + company: string; // String! name: string; // String! } TournamentMakersResponse: { // field return type @@ -907,12 +902,13 @@ export interface NexusGenFieldTypeNames { website: 'String' } TournamentEvent: { // field return type name - date: 'Date' description: 'String' + ends_at: 'Date' id: 'Int' image: 'String' links: 'String' location: 'String' + starts_at: 'Date' title: 'String' type: 'TournamentEventTypeEnum' website: 'String' @@ -923,7 +919,7 @@ export interface NexusGenFieldTypeNames { } TournamentJudge: { // field return type name avatar: 'String' - jobTitle: 'String' + company: 'String' name: 'String' } TournamentMakersResponse: { // field return type name diff --git a/api/functions/graphql/schema.graphql b/api/functions/graphql/schema.graphql index 57950f9..ccce643 100644 --- a/api/functions/graphql/schema.graphql +++ b/api/functions/graphql/schema.graphql @@ -347,12 +347,13 @@ type Tournament { } type TournamentEvent { - date: Date! description: String! + ends_at: Date! id: Int! image: String! links: [String!]! location: String! + starts_at: Date! title: String! type: TournamentEventTypeEnum! website: String! @@ -372,7 +373,7 @@ type TournamentFAQ { type TournamentJudge { avatar: String! - jobTitle: String! + company: String! name: String! } diff --git a/api/functions/graphql/types/tournament.js b/api/functions/graphql/types/tournament.js index 45e2dd2..f1b3a49 100644 --- a/api/functions/graphql/types/tournament.js +++ b/api/functions/graphql/types/tournament.js @@ -24,7 +24,7 @@ const TournamentJudge = objectType({ name: 'TournamentJudge', definition(t) { t.nonNull.string('name'); - t.nonNull.string('jobTitle'); + t.nonNull.string('company'); t.nonNull.string('avatar'); } }) @@ -57,11 +57,12 @@ const TournamentEvent = objectType({ t.nonNull.string('title'); t.nonNull.string('image'); t.nonNull.string('description'); - t.nonNull.date('date'); + t.nonNull.date('starts_at'); + t.nonNull.date('ends_at'); t.nonNull.string('location'); t.nonNull.string('website'); t.nonNull.field('type', { type: TournamentEventTypeEnum }) - t.nonNull.list.nonNull.string('links'); + t.nonNull.list.nonNull.string('links', { resolve() { return [] } }); } }) @@ -78,18 +79,58 @@ const Tournament = objectType({ t.nonNull.string('location'); t.nonNull.string('website'); - t.nonNull.int('events_count'); - t.nonNull.int('makers_count', { + t.nonNull.int('events_count', { resolve(parent) { - return prisma.user.count(); + return prisma.tournamentEvent.count({ + where: { + tournament_id: parent.id + } + }) + } + }); + t.nonNull.int('makers_count', { + resolve(parent) { + return prisma.tournamentParticipant.count({ + where: { + tournament_id: parent.id + } + }) + } + }); + t.nonNull.int('projects_count', { + resolve(parent) { + return prisma.tournamentProject.count({ + where: { + tournament_id: parent.id + } + }) } }); - 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, }); - t.nonNull.list.nonNull.field('events', { type: TournamentEvent, }); + t.nonNull.list.nonNull.field('prizes', { + type: TournamentPrize, + resolve(parent) { + return prisma.tournament.findUnique({ where: { id: parent.id } }).prizes() + } + }); + t.nonNull.list.nonNull.field('judges', { + type: TournamentJudge, + resolve(parent) { + return prisma.tournament.findUnique({ where: { id: parent.id } }).judges() + } + }); + t.nonNull.list.nonNull.field('faqs', { + type: TournamentFAQ, + resolve(parent) { + return prisma.tournament.findUnique({ where: { id: parent.id } }).faqs() + } + }); + t.nonNull.list.nonNull.field('events', { + type: TournamentEvent, + resolve(parent) { + return prisma.tournament.findUnique({ where: { id: parent.id } }).events() + } + }); } }) @@ -125,7 +166,9 @@ const getTournamentById = extendType({ id: nonNull(intArg()), }, resolve(_, { id }) { - return null + return prisma.tournament.findUnique({ + where: { id } + }) } }) } @@ -175,16 +218,23 @@ const getMakersInTournament = extendType({ } }) - - const makers = await prisma.user.findMany({ - ...(filters.length > 0 && { - where: { - AND: filters - } - }), + const makers = (await prisma.tournamentParticipant.findMany({ + where: { + tournament_id: args.tournamentId, + ...(filters.length > 0 && { + user: { + AND: filters + } + }) + }, + include: { + user: true, + }, skip: args.skip, take: args.take + 1, - }); + })).map(item => item.user) + + return { hasNext: makers.length === args.take + 1, @@ -230,24 +280,34 @@ const getProjectsInTournament = extendType({ }) - if (args.roleId) filters.push({ - recruit_roles: { - some: { - roleId: args.roleId - } - } - }) + // if (args.roleId) filters.push({ + // recruit_roles: { + // some: { + // roleId: args.roleId + // } + // } + // }) - const projects = await prisma.project.findMany({ - ...(filters.length > 0 && { - where: { - AND: filters - } - }), + + const projects = (await prisma.tournamentProject.findMany({ + where: { + tournament_id: args.tournamentId, + ...(filters.length > 0 && { + project: { + AND: filters + } + }) + }, + include: { + project: true, + }, skip: args.skip, take: args.take + 1, - }); + })).map(item => item.project) + + console.log(); + return { hasNext: projects.length === args.take + 1, diff --git a/prisma/seed/data/tournament.seed.js b/prisma/seed/data/tournament.seed.js index 789b2f6..162d613 100644 --- a/prisma/seed/data/tournament.seed.js +++ b/prisma/seed/data/tournament.seed.js @@ -11,12 +11,16 @@ const tournament = { 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. + `## Tournament Details +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. +#### Subtitle1 +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. + + +#### Subtitle2 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 + `, // markdown prizes: [{ title: "stw3 champion", amount: "$ 20k", diff --git a/prisma/seed/index.js b/prisma/seed/index.js index b455e10..2e189ab 100644 --- a/prisma/seed/index.js +++ b/prisma/seed/index.js @@ -65,7 +65,7 @@ async function main() { // await createSkills(); - await createTournament(); + // await createTournament(); } diff --git a/src/features/Profiles/Components/Avatar/Avatar.tsx b/src/features/Profiles/Components/Avatar/Avatar.tsx index 1e0ed60..3864a52 100644 --- a/src/features/Profiles/Components/Avatar/Avatar.tsx +++ b/src/features/Profiles/Components/Avatar/Avatar.tsx @@ -3,11 +3,12 @@ interface Props { src: string; alt?: string; width?: number | string; + className?: string } -export default function Avatar({ src, alt, width = 40 }: Props) { +export default function Avatar({ src, alt, className, width = 40 }: Props) { return ( - {alt diff --git a/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx b/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx index 589cdde..26b60f1 100644 --- a/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx +++ b/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx @@ -4,6 +4,7 @@ import { Tournament, TournamentEventTypeEnum } from "src/graphql"; import { UnionToObjectKeys } from 'src/utils/types/utils'; import { useAppDispatch, } from "src/utils/hooks"; import { openModal } from "src/redux/features/modals.slice"; +import dayjs from 'dayjs'; interface Props { @@ -11,7 +12,8 @@ interface Props { | 'id' | 'title' | 'image' - | 'date' + | 'starts_at' + | 'ends_at' | 'location' | 'description' | 'website' @@ -46,7 +48,9 @@ export default function EventCard({ event }: Props) { {event.title}

- {event.date} + + {`${dayjs(event.starts_at).format('H:mm')} - ${dayjs(event.starts_at).format('H:mm, Do MMM')}`} +

{event.location} diff --git a/src/features/Tournaments/pages/EventsPage/EventModal/EventModal.tsx b/src/features/Tournaments/pages/EventsPage/EventModal/EventModal.tsx index 0151bf8..891a1be 100644 --- a/src/features/Tournaments/pages/EventsPage/EventModal/EventModal.tsx +++ b/src/features/Tournaments/pages/EventsPage/EventModal/EventModal.tsx @@ -6,6 +6,7 @@ import { Tournament, } from 'src/graphql'; import { MEDIA_QUERIES } from 'src/utils/theme'; import { IoGlobe, IoLocationOutline } from 'react-icons/io5'; import { mapTypeToBadge } from '../EventCard/EventCard'; +import dayjs from 'dayjs'; interface Props extends ModalCard { @@ -14,7 +15,8 @@ interface Props extends ModalCard { | "title" | "image" | "description" - | "date" + | "starts_at" + | "ends_at" | "location" | "type" | "website"> @@ -43,7 +45,8 @@ export default function ProjectDetailsCard({ direction, event, ...props }: Props

{event.title}

- {event.date} + + {`${dayjs(event.starts_at).format('H:mm')} - ${dayjs(event.starts_at).format('H:mm, Do MMM')}`}

diff --git a/src/features/Tournaments/pages/OverviewPage/JudgesSection/JudgesSection.tsx b/src/features/Tournaments/pages/OverviewPage/JudgesSection/JudgesSection.tsx index 02626cc..dc04429 100644 --- a/src/features/Tournaments/pages/OverviewPage/JudgesSection/JudgesSection.tsx +++ b/src/features/Tournaments/pages/OverviewPage/JudgesSection/JudgesSection.tsx @@ -25,7 +25,7 @@ export default function JudgesSection({ judges }: Props) {

{judge.name}

-

{judge.jobTitle}

+

{judge.company}

)}
diff --git a/src/features/Tournaments/pages/OverviewPage/OverviewPage.tsx b/src/features/Tournaments/pages/OverviewPage/OverviewPage.tsx index 4e87c45..8b3d1eb 100644 --- a/src/features/Tournaments/pages/OverviewPage/OverviewPage.tsx +++ b/src/features/Tournaments/pages/OverviewPage/OverviewPage.tsx @@ -16,9 +16,10 @@ interface Props { | 'makers_count' | 'faqs' > + avatars: string[] } -export default function OverviewPage({ data }: Props) { +export default function OverviewPage({ data, avatars }: Props) { return (
@@ -29,7 +30,7 @@ export default function OverviewPage({ data }: Props) { >
- +
diff --git a/src/features/Tournaments/pages/OverviewPage/RegisterCard/RegisterCard.tsx b/src/features/Tournaments/pages/OverviewPage/RegisterCard/RegisterCard.tsx index 7777863..18c7554 100644 --- a/src/features/Tournaments/pages/OverviewPage/RegisterCard/RegisterCard.tsx +++ b/src/features/Tournaments/pages/OverviewPage/RegisterCard/RegisterCard.tsx @@ -8,9 +8,10 @@ import { useCountdown } from 'src/utils/hooks' interface Props { start_date: string; makers_count: number + avatars: string[] } -export default function RegisterCard({ makers_count, start_date }: Props) { +export default function RegisterCard({ makers_count, start_date, avatars }: Props) { const counter = useCountdown(start_date) @@ -18,7 +19,10 @@ export default function RegisterCard({ makers_count, start_date }: Props) {

- + {makers_count} makers +

+ {avatars.map((img, idx) =>
)} + + {makers_count} makers +

diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx index 8fb3548..c24ad1f 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx +++ b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx @@ -24,11 +24,11 @@ export default function Navigation({ data }: Props) { path: "events", }, { - text: `Makers`, + text: `Makers (${data.makers_count})`, path: "makers", }, { - text: `Projects`, + text: `Projects (${data.projects_count})`, path: "projects", }, { diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx index 0beac54..b101814 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx +++ b/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx @@ -5,44 +5,45 @@ import OverviewPage from '../OverviewPage/OverviewPage' import { Helmet } from 'react-helmet' import Navigation from './Navigation/Navigation' import EventsPage from '../EventsPage/EventsPage' -import { tournamentData } from './data' import MakersPage from '../MakersPage/MakersPage' import ProjectsPage from '../ProjectsPage/ProjectsPage' +import { useGetTournamentByIdQuery } from 'src/graphql' +import LoadingPage from 'src/Components/LoadingPage/LoadingPage' +import NotFoundPage from 'src/features/Shared/pages/NotFoundPage/NotFoundPage' -const data = tournamentData export default function TournamentDetailsPage() { - // const query = useGetTournamentByIdQuery({ - // variables: { - // id: 12, - // }, + const query = useGetTournamentByIdQuery({ + variables: { + id: 12, + }, - // }) + }) - // if (query.loading) - // return + if (query.loading) + return - // if (!query.data?.getTournamentById) - // return + if (!query.data?.getTournamentById) + return return (
- {data.title} Tournament + {query.data.getTournamentById.title} Tournament -
- +
+
} /> - } /> - } /> - } /> - } /> + m.avatar)} />} /> + } /> + } /> + } />
diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/data/description.ts b/src/features/Tournaments/pages/TournamentDetailsPage/data/description.ts index 9ff4ead..3b9cb1c 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/data/description.ts +++ b/src/features/Tournaments/pages/TournamentDetailsPage/data/description.ts @@ -1,11 +1,11 @@ export const description = `## Tournament Details -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. #### Subtitle1 -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. + #### Subtitle2 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. - ` \ No newline at end of file diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/data/events.ts b/src/features/Tournaments/pages/TournamentDetailsPage/data/events.ts index 5156e37..9738f05 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/data/events.ts +++ b/src/features/Tournaments/pages/TournamentDetailsPage/data/events.ts @@ -6,7 +6,9 @@ export const events: Tournament['events'] = [ { id: 12, title: "STW3 Round Table #1", - date: "13:00 - 14:00 UTC, 23rd June", + + starts_at: "2022-09-30T21:00:00.000Z", + ends_at: "2022-10-30T22:00:00.000Z", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", image: getCoverImage(), links: [], @@ -17,7 +19,9 @@ export const events: Tournament['events'] = [ { id: 13, title: "STW3 Round Table #2", - date: "15:00 - 16:00 UTC, 23rd June", + + starts_at: "2022-09-30T21:00:00.000Z", + ends_at: "2022-10-30T22:00:00.000Z", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", image: getCoverImage(), links: [], @@ -28,7 +32,9 @@ export const events: Tournament['events'] = [ { id: 14, title: "STW3 Round Table #3", - date: "13:00 - 14:00 UTC, 24rd June", + + starts_at: "2022-09-30T21:00:00.000Z", + ends_at: "2022-10-30T22:00:00.000Z", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", image: getCoverImage(), links: [], @@ -39,7 +45,9 @@ export const events: Tournament['events'] = [ { id: 44, title: "Lightning Login", - date: "15:00 - 16:00 UTC, 24rd June", + + starts_at: "2022-09-30T21:00:00.000Z", + ends_at: "2022-10-30T22:00:00.000Z", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", image: getCoverImage(), links: [], @@ -51,7 +59,9 @@ export const events: Tournament['events'] = [ { id: 46, title: "Escrow contracts", - date: "15:00 - 16:00 UTC, 23rd June", + + starts_at: "2022-09-30T21:00:00.000Z", + ends_at: "2022-10-30T22:00:00.000Z", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", image: getCoverImage(), links: [], @@ -63,7 +73,9 @@ export const events: Tournament['events'] = [ { id: 444, title: "Lsats - What & Why", - date: "15:00 - 16:00 UTC, 23rd June", + + starts_at: "2022-09-30T21:00:00.000Z", + ends_at: "2022-10-30T22:00:00.000Z", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", image: getCoverImage(), links: [], diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/data/judeges.ts b/src/features/Tournaments/pages/TournamentDetailsPage/data/judeges.ts index 113f122..c93adaa 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/data/judeges.ts +++ b/src/features/Tournaments/pages/TournamentDetailsPage/data/judeges.ts @@ -5,61 +5,61 @@ export const judges: Tournament['judges'] = [ { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company" }, ] \ No newline at end of file diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/tournamentDetails.graphql b/src/features/Tournaments/pages/TournamentDetailsPage/tournamentDetails.graphql index 046a5a2..62e5f24 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/tournamentDetails.graphql +++ b/src/features/Tournaments/pages/TournamentDetailsPage/tournamentDetails.graphql @@ -21,7 +21,7 @@ query GetTournamentById($id: Int!) { } judges { name - jobTitle + company avatar } events { @@ -29,7 +29,8 @@ query GetTournamentById($id: Int!) { title image description - date + starts_at + ends_at location website type @@ -40,4 +41,11 @@ query GetTournamentById($id: Int!) { answer } } -} # + + getMakersInTournament(tournamentId: $id, take: 4) { + makers { + id + avatar + } + } +} diff --git a/src/graphql/index.tsx b/src/graphql/index.tsx index 4ae1dba..ebe86f4 100644 --- a/src/graphql/index.tsx +++ b/src/graphql/index.tsx @@ -535,12 +535,13 @@ export type Tournament = { export type TournamentEvent = { __typename?: 'TournamentEvent'; - date: Scalars['Date']; description: Scalars['String']; + ends_at: Scalars['Date']; id: Scalars['Int']; image: Scalars['String']; links: Array; location: Scalars['String']; + starts_at: Scalars['Date']; title: Scalars['String']; type: TournamentEventTypeEnum; website: Scalars['String']; @@ -562,7 +563,7 @@ export type TournamentFaq = { export type TournamentJudge = { __typename?: 'TournamentJudge'; avatar: Scalars['String']; - jobTitle: Scalars['String']; + company: Scalars['String']; name: Scalars['String']; }; @@ -862,7 +863,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, 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: TournamentEventTypeEnum, 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, company: string, avatar: string }>, events: Array<{ __typename?: 'TournamentEvent', id: number, title: string, image: string, description: string, starts_at: any, ends_at: any, location: string, website: string, type: TournamentEventTypeEnum, links: Array }>, faqs: Array<{ __typename?: 'TournamentFAQ', question: string, answer: string }> }, getMakersInTournament: { __typename?: 'TournamentMakersResponse', makers: Array<{ __typename?: 'User', id: number, avatar: string }> } }; export type VoteMutationVariables = Exact<{ itemType: Vote_Item_Type; @@ -2411,7 +2412,7 @@ export const GetTournamentByIdDocument = gql` } judges { name - jobTitle + company avatar } events { @@ -2419,7 +2420,8 @@ export const GetTournamentByIdDocument = gql` title image description - date + starts_at + ends_at location website type @@ -2430,6 +2432,12 @@ export const GetTournamentByIdDocument = gql` answer } } + getMakersInTournament(tournamentId: $id, take: 4) { + makers { + id + avatar + } + } } `; diff --git a/src/mocks/data/tournament.ts b/src/mocks/data/tournament.ts index fec6b78..6fba363 100644 --- a/src/mocks/data/tournament.ts +++ b/src/mocks/data/tournament.ts @@ -45,7 +45,8 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e { id: 12, title: "STW3 Round Table #1", - date: "13:00 - 14:00 UTC, 23rd June", + starts_at: "2022-09-30T21:00:00.000Z", + ends_at: "2022-10-30T22:00:00.000Z", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", image: getCoverImage(), links: [], @@ -56,7 +57,8 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e { id: 13, title: "STW3 Round Table #2", - date: "15:00 - 16:00 UTC, 23rd June", + starts_at: "2022-09-30T21:00:00.000Z", + ends_at: "2022-10-30T22:00:00.000Z", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", image: getCoverImage(), links: [], @@ -67,7 +69,8 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e { id: 14, title: "STW3 Round Table #3", - date: "13:00 - 14:00 UTC, 24rd June", + starts_at: "2022-09-30T21:00:00.000Z", + ends_at: "2022-10-30T22:00:00.000Z", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", image: getCoverImage(), links: [], @@ -78,7 +81,8 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e { id: 44, title: "Lightning Login", - date: "15:00 - 16:00 UTC, 24rd June", + starts_at: "2022-09-30T21:00:00.000Z", + ends_at: "2022-10-30T22:00:00.000Z", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", image: getCoverImage(), links: [], @@ -90,7 +94,8 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e { id: 46, title: "Escrow contracts", - date: "15:00 - 16:00 UTC, 23rd June", + starts_at: "2022-09-30T21:00:00.000Z", + ends_at: "2022-10-30T22:00:00.000Z", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", image: getCoverImage(), links: [], @@ -102,7 +107,8 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e { id: 444, title: "Lsats - What & Why", - date: "15:00 - 16:00 UTC, 23rd June", + starts_at: "2022-09-30T21:00:00.000Z", + ends_at: "2022-10-30T22:00:00.000Z", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", image: getCoverImage(), links: [], @@ -115,62 +121,62 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company" }, { name: "Ben Arc", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - jobTitle: "Maker" + company: "Company" }, ], diff --git a/src/mocks/handlers.ts b/src/mocks/handlers.ts index 20e57c4..147c620 100644 --- a/src/mocks/handlers.ts +++ b/src/mocks/handlers.ts @@ -282,7 +282,8 @@ export const handlers = [ return res( ctx.data({ - getTournamentById: getTournamentById(12) + getTournamentById: getTournamentById(12), + getMakersInTournament: getMakersInTournament({ roleId: null, search: null, skip: null, take: 4, tournamentId: 12 }) }) ) }), From 658af73fcbdee58b735d35735810296104948806 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Thu, 8 Sep 2022 09:52:50 +0300 Subject: [PATCH 32/53] feat: add base registration api --- api/functions/graphql/types/tournament.js | 59 ++++++++++++++++++++++- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/api/functions/graphql/types/tournament.js b/api/functions/graphql/types/tournament.js index f1b3a49..cfb8d8c 100644 --- a/api/functions/graphql/types/tournament.js +++ b/api/functions/graphql/types/tournament.js @@ -5,7 +5,9 @@ const { extendType, nonNull, enumType, + inputObjectType, } = require('nexus'); +const { getUserByPubKey } = require('../../../auth/utils/helperFuncs'); const { prisma } = require('../../../prisma'); const { paginationArgs } = require('./helpers'); @@ -49,6 +51,15 @@ const TournamentEventTypeEnum = enumType({ }, }); +const TournamentMakerHackingStatusEnum = enumType({ + name: 'TournamentMakerHackingStatusEnum', + members: { + Solo: 0, + OpenToConnect: 1, + }, +}); + + const TournamentEvent = objectType({ name: 'TournamentEvent', @@ -319,14 +330,58 @@ const getProjectsInTournament = extendType({ } }) + + +const RegisterInTournamentInput = inputObjectType({ + name: 'RegisterInTournamentInput', + definition(t) { + t.nonNull.string('email') + t.nonNull.field('hacking_status', { type: TournamentMakerHackingStatusEnum }) + } +}) + + +const registerInTournament = extendType({ + type: 'Mutation', + definition(t) { + t.field('registerInTournament', { + type: 'boolean', + args: { data: RegisterInTournamentInput }, + async resolve(_root, { email, hacking_status }, ctx) { + const user = await getUserByPubKey(ctx.userPubKey); + + // Do some validation + if (!user) + throw new Error("You have to login"); + + + // Email verification here: + // .... + // .... + + prisma.tournamentParticipant.create({ + data:{ + + } + }) + + } + }) + }, +}) + module.exports = { // Types Tournament, + // Enums + TournamentEventTypeEnum, + // Queries getTournamentById, getMakersInTournament, getProjectsInTournament, - // Enums - TournamentEventTypeEnum, + // Mutations + registerInTournament, + } \ No newline at end of file From a0f09aaa33033632ae9b7f6077ca03d158bbd26a Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Thu, 8 Sep 2022 14:53:08 +0300 Subject: [PATCH 33/53] feat: wired the registeration journey with the api, success modal, reactive data --- api/functions/graphql/nexus-typegen.ts | 32 ++++ api/functions/graphql/schema.graphql | 14 ++ api/functions/graphql/types/tournament.js | 24 ++- api/functions/graphql/types/users.js | 20 +- src/Components/InfoCard/InfoCard.tsx | 4 +- src/Components/Modals/Modal/Modal.tsx | 8 +- .../ModalsContainer/ModalsContainer.tsx | 3 +- .../Auth/pages/LoginPage/LoginPage.tsx | 2 +- .../LinkedAccountsCard/LinkedAccountsCard.tsx | 2 +- .../UpdateSkillsCard/UpdateSkillsCard.tsx | 2 +- .../TournamentsCard/TournamentsCard.tsx | 38 +++- .../ConnectToMakerModal.tsx | 6 - .../pages/MakersPage/MakersPage.tsx | 6 +- .../pages/MakersPage/tournamentMakers.graphql | 10 - .../pages/OverviewPage/OverviewPage.tsx | 5 +- .../RegisterCard/RegisterCard.tsx | 41 +++- .../ConfirmAccount/ConfirmAccount.tsx | 68 +++++++ .../ConfirmAccount/index.ts | 3 + .../LoginModal/LoginModal.tsx | 173 +++++++++++++++++ .../RegisterationModals/LoginModal/index.ts | 3 + .../RegistrationDetails.tsx | 181 ++++++++++++++++++ .../RegistrationDetails/index.ts | 3 + .../registerInTournament.graphql | 9 + .../RegistrationSuccess.tsx | 72 +++++++ .../RegistrationSuccess/index.ts | 3 + .../RegisterationModals/index.tsx | 11 ++ .../Navigation/Navigation.tsx | 2 +- .../TournamentDetailsPage.tsx | 34 ++-- .../meTournament.graphql | 12 ++ .../tournamentDetails.graphql | 11 ++ src/graphql/index.tsx | 180 ++++++++++++----- src/mocks/data/users.ts | 4 + src/mocks/handlers.ts | 3 +- src/redux/features/modals.slice.ts | 5 + src/styles/tw.scss | 2 +- 35 files changed, 878 insertions(+), 118 deletions(-) create mode 100644 src/features/Tournaments/pages/OverviewPage/RegisterationModals/ConfirmAccount/ConfirmAccount.tsx create mode 100644 src/features/Tournaments/pages/OverviewPage/RegisterationModals/ConfirmAccount/index.ts create mode 100644 src/features/Tournaments/pages/OverviewPage/RegisterationModals/LoginModal/LoginModal.tsx create mode 100644 src/features/Tournaments/pages/OverviewPage/RegisterationModals/LoginModal/index.ts create mode 100644 src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationDetails/RegistrationDetails.tsx create mode 100644 src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationDetails/index.ts create mode 100644 src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationDetails/registerInTournament.graphql create mode 100644 src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationSuccess/RegistrationSuccess.tsx create mode 100644 src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationSuccess/index.ts create mode 100644 src/features/Tournaments/pages/OverviewPage/RegisterationModals/index.tsx create mode 100644 src/features/Tournaments/pages/TournamentDetailsPage/meTournament.graphql diff --git a/api/functions/graphql/nexus-typegen.ts b/api/functions/graphql/nexus-typegen.ts index ad69a48..28338b2 100644 --- a/api/functions/graphql/nexus-typegen.ts +++ b/api/functions/graphql/nexus-typegen.ts @@ -52,6 +52,10 @@ export interface NexusGenInputs { roles: NexusGenInputs['MakerRoleInput'][]; // [MakerRoleInput!]! skills: NexusGenInputs['MakerSkillInput'][]; // [MakerSkillInput!]! } + RegisterInTournamentInput: { // input type + email: string; // String! + hacking_status: NexusGenEnums['TournamentMakerHackingStatusEnum']; // TournamentMakerHackingStatusEnum! + } StoryInputType: { // input type body: string; // String! cover_image?: string | null; // String @@ -70,6 +74,7 @@ export interface NexusGenEnums { POST_TYPE: "Bounty" | "Question" | "Story" RoleLevelEnum: 3 | 0 | 1 | 2 | 4 TournamentEventTypeEnum: 2 | 3 | 0 | 1 + TournamentMakerHackingStatusEnum: 1 | 0 VOTE_ITEM_TYPE: "Bounty" | "PostComment" | "Project" | "Question" | "Story" | "User" } @@ -428,6 +433,7 @@ export interface NexusGenFieldTypes { createStory: NexusGenRootTypes['Story'] | null; // Story deleteStory: NexusGenRootTypes['Story'] | null; // Story donate: NexusGenRootTypes['Donation']; // Donation! + registerInTournament: NexusGenRootTypes['User'] | null; // User updateProfileDetails: NexusGenRootTypes['MyProfile'] | null; // MyProfile updateProfileRoles: NexusGenRootTypes['MyProfile'] | null; // MyProfile updateUserPreferences: NexusGenRootTypes['MyProfile']; // MyProfile! @@ -439,6 +445,7 @@ export interface NexusGenFieldTypes { email: string | null; // String github: string | null; // String id: number; // Int! + in_tournament: boolean; // Boolean! jobTitle: string | null; // String join_date: NexusGenScalars['Date']; // Date! lightning_address: string | null; // String @@ -604,6 +611,7 @@ export interface NexusGenFieldTypes { email: string | null; // String github: string | null; // String id: number; // Int! + in_tournament: boolean; // Boolean! jobTitle: string | null; // String join_date: NexusGenScalars['Date']; // Date! lightning_address: string | null; // String @@ -639,6 +647,7 @@ export interface NexusGenFieldTypes { email: string | null; // String github: string | null; // String id: number; // Int! + in_tournament: boolean; // Boolean! jobTitle: string | null; // String join_date: NexusGenScalars['Date']; // Date! lightning_address: string | null; // String @@ -767,6 +776,7 @@ export interface NexusGenFieldTypeNames { createStory: 'Story' deleteStory: 'Story' donate: 'Donation' + registerInTournament: 'User' updateProfileDetails: 'MyProfile' updateProfileRoles: 'MyProfile' updateUserPreferences: 'MyProfile' @@ -778,6 +788,7 @@ export interface NexusGenFieldTypeNames { email: 'String' github: 'String' id: 'Int' + in_tournament: 'Boolean' jobTitle: 'String' join_date: 'Date' lightning_address: 'String' @@ -943,6 +954,7 @@ export interface NexusGenFieldTypeNames { email: 'String' github: 'String' id: 'Int' + in_tournament: 'Boolean' jobTitle: 'String' join_date: 'Date' lightning_address: 'String' @@ -978,6 +990,7 @@ export interface NexusGenFieldTypeNames { email: 'String' github: 'String' id: 'Int' + in_tournament: 'Boolean' jobTitle: 'String' join_date: 'Date' lightning_address: 'String' @@ -1024,6 +1037,10 @@ export interface NexusGenArgTypes { donate: { // args amount_in_sat: number; // Int! } + registerInTournament: { // args + data?: NexusGenInputs['RegisterInTournamentInput'] | null; // RegisterInTournamentInput + tournament_id: number; // Int! + } updateProfileDetails: { // args data?: NexusGenInputs['ProfileDetailsInput'] | null; // ProfileDetailsInput } @@ -1039,6 +1056,11 @@ export interface NexusGenArgTypes { item_type: NexusGenEnums['VOTE_ITEM_TYPE']; // VOTE_ITEM_TYPE! } } + MyProfile: { + in_tournament: { // args + id: number; // Int! + } + } Query: { allProjects: { // args skip?: number | null; // Int @@ -1112,6 +1134,16 @@ export interface NexusGenArgTypes { id: number; // Int! } } + User: { + in_tournament: { // args + id: number; // Int! + } + } + BaseUser: { + in_tournament: { // args + id: number; // Int! + } + } } export interface NexusGenAbstractTypeMembers { diff --git a/api/functions/graphql/schema.graphql b/api/functions/graphql/schema.graphql index ccce643..56b9e0a 100644 --- a/api/functions/graphql/schema.graphql +++ b/api/functions/graphql/schema.graphql @@ -24,6 +24,7 @@ interface BaseUser { email: String github: String id: Int! + in_tournament(id: Int!): Boolean! jobTitle: String join_date: Date! lightning_address: String @@ -148,6 +149,7 @@ type Mutation { createStory(data: StoryInputType): Story deleteStory(id: Int!): Story donate(amount_in_sat: Int!): Donation! + registerInTournament(data: RegisterInTournamentInput, tournament_id: Int!): User updateProfileDetails(data: ProfileDetailsInput): MyProfile updateProfileRoles(data: ProfileRolesInput): MyProfile updateUserPreferences(userKeys: [UserKeyInputType!]): MyProfile! @@ -160,6 +162,7 @@ type MyProfile implements BaseUser { email: String github: String id: Int! + in_tournament(id: Int!): Boolean! jobTitle: String join_date: Date! lightning_address: String @@ -285,6 +288,11 @@ type Question implements PostBase { votes_count: Int! } +input RegisterInTournamentInput { + email: String! + hacking_status: TournamentMakerHackingStatusEnum! +} + enum RoleLevelEnum { Advanced Beginner @@ -377,6 +385,11 @@ type TournamentJudge { name: String! } +enum TournamentMakerHackingStatusEnum { + OpenToConnect + Solo +} + type TournamentMakersResponse { hasNext: Boolean hasPrev: Boolean @@ -401,6 +414,7 @@ type User implements BaseUser { email: String github: String id: Int! + in_tournament(id: Int!): Boolean! jobTitle: String join_date: Date! lightning_address: String diff --git a/api/functions/graphql/types/tournament.js b/api/functions/graphql/types/tournament.js index cfb8d8c..2eb4572 100644 --- a/api/functions/graphql/types/tournament.js +++ b/api/functions/graphql/types/tournament.js @@ -345,9 +345,12 @@ const registerInTournament = extendType({ type: 'Mutation', definition(t) { t.field('registerInTournament', { - type: 'boolean', - args: { data: RegisterInTournamentInput }, - async resolve(_root, { email, hacking_status }, ctx) { + type: 'User', + args: { + data: RegisterInTournamentInput, + tournament_id: nonNull(intArg()) + }, + async resolve(_root, { tournament_id, data: { email, hacking_status } }, ctx) { const user = await getUserByPubKey(ctx.userPubKey); // Do some validation @@ -359,12 +362,17 @@ const registerInTournament = extendType({ // .... // .... - prisma.tournamentParticipant.create({ - data:{ - + return (await prisma.tournamentParticipant.create({ + data: { + tournament_id, + user_id: user.id, + email, + hacking_status + }, + include: { + user: true } - }) - + })).user; } }) }, diff --git a/api/functions/graphql/types/users.js b/api/functions/graphql/types/users.js index 3864637..f7c3d13 100644 --- a/api/functions/graphql/types/users.js +++ b/api/functions/graphql/types/users.js @@ -54,8 +54,15 @@ const BaseUser = interfaceType({ }) t.nonNull.list.nonNull.field('tournaments', { type: Tournament, - resolve: (parent) => { - return [] + resolve: async (parent) => { + return prisma.tournamentParticipant.findMany({ + where: { + user_id: parent.id + }, + include: { + tournament: true + } + }).then(d => d.map(item => item.tournament)) } }) t.nonNull.list.nonNull.field('similar_makers', { @@ -82,6 +89,15 @@ const BaseUser = interfaceType({ } }); + t.nonNull.boolean('in_tournament', { + args: { + id: nonNull(intArg()) + }, + resolve(parent, args) { + return prisma.tournamentParticipant.findFirst({ where: { tournament_id: args.id, user_id: parent.id } }).then(res => !!res) + } + }) + }, resolveType() { diff --git a/src/Components/InfoCard/InfoCard.tsx b/src/Components/InfoCard/InfoCard.tsx index 6e41f47..c14e977 100644 --- a/src/Components/InfoCard/InfoCard.tsx +++ b/src/Components/InfoCard/InfoCard.tsx @@ -1,12 +1,12 @@ import React, { PropsWithChildren } from 'react' interface Props { - + className?: string } export default function InfoCard(props: PropsWithChildren) { return ( -
+

{props.children}

diff --git a/src/Components/Modals/Modal/Modal.tsx b/src/Components/Modals/Modal/Modal.tsx index 66fe3d3..dc5a5e8 100644 --- a/src/Components/Modals/Modal/Modal.tsx +++ b/src/Components/Modals/Modal/Modal.tsx @@ -17,7 +17,11 @@ ReactModal.setAppElement('#root'); export default function Modal({ onClose, children, ...props }: Props) { - const dispatch = useAppDispatch() + const dispatch = useAppDispatch(); + + const onAfterClose = () => { + dispatch(removeClosedModal(props.id)) + } return dispatch(removeClosedModal(props.id))} + onAfterClose={onAfterClose} contentElement={(_props, children) =>
{openModals.map((modal, idx) => { const Child = ALL_MODALS[modal.Modal]; - return ( { return data; } -const useLnurlQuery = () => { +export const useLnurlQuery = () => { const [loading, setLoading] = useState(true) const [error, setError] = useState(null); const [data, setData] = useState<{ lnurl: string, session_token: string }>({ lnurl: '', session_token: '' }) diff --git a/src/features/Profiles/pages/EditProfilePage/PreferencesTab/LinkedAccountsCard/LinkedAccountsCard.tsx b/src/features/Profiles/pages/EditProfilePage/PreferencesTab/LinkedAccountsCard/LinkedAccountsCard.tsx index 34da685..04d94aa 100644 --- a/src/features/Profiles/pages/EditProfilePage/PreferencesTab/LinkedAccountsCard/LinkedAccountsCard.tsx +++ b/src/features/Profiles/pages/EditProfilePage/PreferencesTab/LinkedAccountsCard/LinkedAccountsCard.tsx @@ -64,7 +64,7 @@ export default function LinkedAccountsCard({ value, onChange }: Props) { } - + 💡 Note: if you link a wallet that was used to create another account previously, you won't be able to login to that account until you remove it from here. diff --git a/src/features/Profiles/pages/EditProfilePage/RolesSkillsTab/UpdateSkillsCard/UpdateSkillsCard.tsx b/src/features/Profiles/pages/EditProfilePage/RolesSkillsTab/UpdateSkillsCard/UpdateSkillsCard.tsx index 07c1a01..0f98065 100644 --- a/src/features/Profiles/pages/EditProfilePage/RolesSkillsTab/UpdateSkillsCard/UpdateSkillsCard.tsx +++ b/src/features/Profiles/pages/EditProfilePage/RolesSkillsTab/UpdateSkillsCard/UpdateSkillsCard.tsx @@ -46,7 +46,7 @@ export default function UpdateSkillsCard(props: Props) { )} } - + ℹ️ Can't find a specific skill? You can suggest it to be added here diff --git a/src/features/Profiles/pages/ProfilePage/TournamentsCard/TournamentsCard.tsx b/src/features/Profiles/pages/ProfilePage/TournamentsCard/TournamentsCard.tsx index 1bf1cfc..13f7287 100644 --- a/src/features/Profiles/pages/ProfilePage/TournamentsCard/TournamentsCard.tsx +++ b/src/features/Profiles/pages/ProfilePage/TournamentsCard/TournamentsCard.tsx @@ -1,5 +1,6 @@ import Card from 'src/Components/Card/Card' import { User } from 'src/graphql'; +import { Link } from 'react-router-dom' @@ -26,15 +27,22 @@ export default function TournamentsCard({ tournaments, isOwner }: Props) {
    { tournaments.map((tournament) => { - - const isLive = ((new Date() < new Date(tournament.end_date)) && (new Date() > new Date(tournament.start_date))); - - return
  • - -
    -

    {tournament.title}

    -

    • {isLive ? "Live" : "Completed"}

    -
    + const status = getDateStatus(tournament.start_date, tournament.end_date) + return
  • + + +
    +

    {tournament.title}

    +

    • {status === 'live' && "Running"} + {status === 'upcoming' && "Upcoming"} + {status === 'finished' && "Completed"}

    +
    +
  • })}
@@ -42,3 +50,15 @@ export default function TournamentsCard({ tournaments, isOwner }: Props) { ) } + + +function getDateStatus(start: string, end: string) { + + const start_date = new Date(start); + const now_date = new Date(); + const end_date = new Date(end); + + if (now_date < start_date) return 'upcoming' + if (now_date >= start_date && now_date <= end_date) return 'live' + return 'finished' +} \ No newline at end of file diff --git a/src/features/Tournaments/pages/MakersPage/ConnectToMakerModal/ConnectToMakerModal.tsx b/src/features/Tournaments/pages/MakersPage/ConnectToMakerModal/ConnectToMakerModal.tsx index 0af3a40..dce9916 100644 --- a/src/features/Tournaments/pages/MakersPage/ConnectToMakerModal/ConnectToMakerModal.tsx +++ b/src/features/Tournaments/pages/MakersPage/ConnectToMakerModal/ConnectToMakerModal.tsx @@ -15,12 +15,6 @@ export default function LinkingAccountModal({ onClose, direction, maker, ...prop const links = [ - { - hasValue: maker.email, - text: maker.email, - icon: FiMail, - url: maker.email && `mailto:${maker.email}` - }, { hasValue: maker.twitter, text: maker.twitter, diff --git a/src/features/Tournaments/pages/MakersPage/MakersPage.tsx b/src/features/Tournaments/pages/MakersPage/MakersPage.tsx index 69b8fad..4732a8c 100644 --- a/src/features/Tournaments/pages/MakersPage/MakersPage.tsx +++ b/src/features/Tournaments/pages/MakersPage/MakersPage.tsx @@ -11,7 +11,9 @@ interface Props { export default function MakersPage({ data: { id } }: Props) { - const query = useMeTournamentQuery(); + const query = useMeTournamentQuery({ + variables: { inTournamentId: id } + }); return (
@@ -19,7 +21,7 @@ export default function MakersPage({ data: { id } }: Props) { {query.loading ? : - query.data?.me ? + query.data?.me?.in_tournament ? : null } diff --git a/src/features/Tournaments/pages/MakersPage/tournamentMakers.graphql b/src/features/Tournaments/pages/MakersPage/tournamentMakers.graphql index f1ebe98..949f80d 100644 --- a/src/features/Tournaments/pages/MakersPage/tournamentMakers.graphql +++ b/src/features/Tournaments/pages/MakersPage/tournamentMakers.graphql @@ -1,13 +1,3 @@ -query MeTournament { - me { - id - name - avatar - jobTitle - ...UserRolesSkills - } -} - query GetAllRoles { getAllMakersRoles { id diff --git a/src/features/Tournaments/pages/OverviewPage/OverviewPage.tsx b/src/features/Tournaments/pages/OverviewPage/OverviewPage.tsx index 8b3d1eb..3893659 100644 --- a/src/features/Tournaments/pages/OverviewPage/OverviewPage.tsx +++ b/src/features/Tournaments/pages/OverviewPage/OverviewPage.tsx @@ -17,9 +17,10 @@ interface Props { | 'faqs' > avatars: string[] + isRegistered: boolean; } -export default function OverviewPage({ data, avatars }: Props) { +export default function OverviewPage({ data, avatars, isRegistered }: Props) { return (
@@ -30,7 +31,7 @@ export default function OverviewPage({ data, avatars }: Props) { >
- +
diff --git a/src/features/Tournaments/pages/OverviewPage/RegisterCard/RegisterCard.tsx b/src/features/Tournaments/pages/OverviewPage/RegisterCard/RegisterCard.tsx index 18c7554..70cf9d6 100644 --- a/src/features/Tournaments/pages/OverviewPage/RegisterCard/RegisterCard.tsx +++ b/src/features/Tournaments/pages/OverviewPage/RegisterCard/RegisterCard.tsx @@ -1,30 +1,57 @@ import React from 'react' import { FaUsers } from 'react-icons/fa' +import { useParams } from 'react-router-dom' import Button from 'src/Components/Button/Button' import Card from 'src/Components/Card/Card' import Avatar from 'src/features/Profiles/Components/Avatar/Avatar' +import { openModal } from 'src/redux/features/modals.slice' import { useCountdown } from 'src/utils/hooks' +import { useAppDispatch, useAppSelector } from "src/utils/hooks"; interface Props { start_date: string; makers_count: number avatars: string[] + isRegistered: boolean; } -export default function RegisterCard({ makers_count, start_date, avatars }: Props) { +export default function RegisterCard({ makers_count, start_date, avatars, isRegistered }: Props) { const counter = useCountdown(start_date) + const { id: tournamentId } = useParams() + + + const isLoggedIn = useAppSelector(state => !!state.user.me) + const dispatch = useAppDispatch() + + const onRegister = () => { + if (!tournamentId) return; + + if (isLoggedIn) + dispatch(openModal({ + Modal: "RegisterTournamet_ConfrimAccount", + props: { + tournamentId: Number(tournamentId) + } + })) + else + dispatch(openModal({ + Modal: "RegisterTournamet_Login", + props: { + tournamentId: Number(tournamentId) + } + })) + } + return (
-

-

- {avatars.map((img, idx) =>
)} - + {makers_count} makers -
+

+ {avatars.map((img, idx) =>

)} + + {makers_count} makers

- +
{counter.isExpired ? diff --git a/src/features/Tournaments/pages/OverviewPage/RegisterationModals/ConfirmAccount/ConfirmAccount.tsx b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/ConfirmAccount/ConfirmAccount.tsx new file mode 100644 index 0000000..9ea7762 --- /dev/null +++ b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/ConfirmAccount/ConfirmAccount.tsx @@ -0,0 +1,68 @@ +import { motion } from 'framer-motion' +import { ModalCard, modalCardVariants } from 'src/Components/Modals/ModalsContainer/ModalsContainer' +import { IoClose } from 'react-icons/io5'; +import Avatar from 'src/features/Profiles/Components/Avatar/Avatar'; +import { useAppDispatch, useAppSelector } from "src/utils/hooks"; +import Button from 'src/Components/Button/Button'; +import { Direction, replaceModal } from 'src/redux/features/modals.slice'; + + +interface Props extends ModalCard { + tournamentId: number +} + +export default function ConfirmAccount({ onClose, direction, tournamentId, ...props }: Props) { + + const me = useAppSelector(state => state.user.me) + const dispatch = useAppDispatch(); + + if (!me) + return null; + + const onCancel = () => onClose?.(); + const onContinue = () => { + dispatch(replaceModal({ + Modal: "RegisterTournamet_RegistrationDetails", + direction: Direction.NEXT, + props: { + tournamentId + } + })) + } + + + return ( + +
+ +

Register for tournament

+
+
+
+ +
+

{me.name}

+

{me.jobTitle}

+
+ + +

You are currently signed in using this profile. Would you like to continue with your ⚔️ Tournament registration?

+ +
+ + +
+
+
+ ) +} + + + diff --git a/src/features/Tournaments/pages/OverviewPage/RegisterationModals/ConfirmAccount/index.ts b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/ConfirmAccount/index.ts new file mode 100644 index 0000000..2caf10e --- /dev/null +++ b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/ConfirmAccount/index.ts @@ -0,0 +1,3 @@ +import { lazyModal } from 'src/utils/helperFunctions'; + +export const { LazyComponent: ConfirmAccount } = lazyModal(() => import('./ConfirmAccount')) \ No newline at end of file diff --git a/src/features/Tournaments/pages/OverviewPage/RegisterationModals/LoginModal/LoginModal.tsx b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/LoginModal/LoginModal.tsx new file mode 100644 index 0000000..de6f63b --- /dev/null +++ b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/LoginModal/LoginModal.tsx @@ -0,0 +1,173 @@ +import { motion } from 'framer-motion' +import { ModalCard, modalCardVariants } from 'src/Components/Modals/ModalsContainer/ModalsContainer' +import { FiCopy } from "react-icons/fi"; +import { IoClose, IoRocketOutline } from 'react-icons/io5'; +import { useMeTournamentQuery } from 'src/graphql'; +import Button from 'src/Components/Button/Button'; +import { QRCodeSVG } from 'qrcode.react'; +import { Grid } from 'react-loader-spinner'; +import { useCallback, useEffect, useState } from 'react'; +import { CONSTS } from 'src/utils'; +import useCopyToClipboard from 'src/utils/hooks/useCopyToClipboard'; +import { useLnurlQuery } from 'src/features/Auth/pages/LoginPage/LoginPage'; +import { useAppDispatch } from 'src/utils/hooks'; +import { Direction, replaceModal } from 'src/redux/features/modals.slice'; + + +interface Props extends ModalCard { + tournamentId: number +} + +export default function LinkingAccountModal({ onClose, direction, tournamentId, ...props }: Props) { + + const [copied, setCopied] = useState(false); + + const { loadingLnurl, data: { lnurl, session_token }, error } = useLnurlQuery(); + const clipboard = useCopyToClipboard() + + const dispatch = useAppDispatch(); + + + useEffect(() => { + setCopied(false); + }, [lnurl]) + + const meQuery = useMeTournamentQuery({ + variables: { + inTournamentId: tournamentId + }, + onCompleted: (data) => { + if (data.me) { + const already_registerd = data.me.in_tournament; + if (already_registerd) + onClose?.(); + else dispatch(replaceModal({ + Modal: "RegisterTournamet_RegistrationDetails", + direction: Direction.NEXT, + props: { tournamentId } + })) + + } + + } + }); + + const copyToClipboard = () => { + setCopied(true); + clipboard(lnurl); + } + + const refetch = meQuery.refetch; + const startPolling = useCallback( + () => { + const interval = setInterval(() => { + fetch(CONSTS.apiEndpoint + '/is-logged-in', { + credentials: 'include', + headers: { + session_token + } + }).then(data => data.json()) + .then(data => { + if (data.logged_in) { + clearInterval(interval) + refetch(); + } + }) + }, 2000); + + return interval; + } + , [refetch, session_token], + ) + + + + useEffect(() => { + let interval: NodeJS.Timer; + if (lnurl) + interval = startPolling(); + + return () => { + clearInterval(interval) + } + }, [lnurl, startPolling]) + + + + let content = <> + + if (error) + content =
+

Something wrong happened...

+ Please try again +
+ + else if (loadingLnurl) + content =
+ +

Fetching Lnurl-Auth link

+
+ + + else + content =
+ + + +

+ To register for this tournament, you need a maker profile. Luckily, this is very easy! +
+
+ To sign in or create an account, just scan this QR, or click to connect using any lightning wallet like Alby or Breez. +

+
+ Click to connect + + What is a lightning wallet? +
+ +
; + + + return ( + +
+ +

Connect ⚡️ your maker profile

+
+
+
+ {content} +
+
+ ) +} + + + diff --git a/src/features/Tournaments/pages/OverviewPage/RegisterationModals/LoginModal/index.ts b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/LoginModal/index.ts new file mode 100644 index 0000000..903f38a --- /dev/null +++ b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/LoginModal/index.ts @@ -0,0 +1,3 @@ +import { lazyModal } from 'src/utils/helperFunctions'; + +export const { LazyComponent: LoginModal } = lazyModal(() => import('./LoginModal')) \ No newline at end of file diff --git a/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationDetails/RegistrationDetails.tsx b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationDetails/RegistrationDetails.tsx new file mode 100644 index 0000000..2026ee7 --- /dev/null +++ b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationDetails/RegistrationDetails.tsx @@ -0,0 +1,181 @@ +import { motion } from 'framer-motion' +import { ModalCard, modalCardVariants } from 'src/Components/Modals/ModalsContainer/ModalsContainer' +import { IoClose } from 'react-icons/io5'; +import { useAppDispatch, useAppSelector } from "src/utils/hooks"; +import Button from 'src/Components/Button/Button'; +import { Direction, replaceModal } from 'src/redux/features/modals.slice'; +import BasicSelectInput from 'src/Components/Inputs/Selects/BasicSelectInput/BasicSelectInput'; +import { GetTournamentByIdDocument, TournamentMakerHackingStatusEnum, useRegisterInTournamentMutation } from 'src/graphql'; +import InfoCard from 'src/Components/InfoCard/InfoCard'; +import * as yup from "yup"; +import { yupResolver } from '@hookform/resolvers/yup'; +import { Controller, SubmitHandler, useForm } from 'react-hook-form'; +import { NotificationsService } from "src/services/notifications.service"; + + +interface Props extends ModalCard { + tournamentId: number +} + +const hackingStatusOptions = [ + { + label: "Hacking han solo 👻", + value: TournamentMakerHackingStatusEnum.Solo + }, { + label: "Open to connect 👋", + value: TournamentMakerHackingStatusEnum.OpenToConnect + }, +] + +interface IFormInputs { + email: string; + agreement: boolean; + hacking_status: typeof hackingStatusOptions[number]; +} + + +const schema: yup.SchemaOf = yup.object({ + email: yup.string().required().email(), + hacking_status: yup.object().shape({ + label: yup.string().required(), + value: yup.string().required() + }).required(), + agreement: yup.boolean().required().isTrue("You won't be able to follow the updates/events of the tournament if you don't allow this"), +}).required(); + +export default function RegistrationDetails({ onClose, direction, ...props }: Props) { + + + const me = useAppSelector(state => state.user.me) + const dispatch = useAppDispatch(); + + const [mutate, mutationStatus] = useRegisterInTournamentMutation() + + + const { handleSubmit, control, register, formState: { errors }, } = useForm({ + mode: "onChange", + resolver: yupResolver(schema), + defaultValues: { + email: "", + hacking_status: hackingStatusOptions[0] + } + + }); + + + if (!me) + return null; + + + const onCancel = () => onClose?.(); + + const onSubmit: SubmitHandler = data => { + mutate({ + variables: { + data: { + email: data.email, + hacking_status: data.hacking_status.value, + }, + tournamentId: Number(props.tournamentId) + }, + onCompleted: (data) => { + if (data.registerInTournament?.in_tournament) { + dispatch(replaceModal({ + Modal: "RegisterTournamet_RegistrationSuccess", + direction: Direction.NEXT + })) + + } + }, + refetchQueries: [{ + query: GetTournamentByIdDocument, + variables: { + id: props.tournamentId + } + }] + }) + .catch(() => { + NotificationsService.error("A network error happned...") + mutationStatus.reset() + }) + } + + + return ( + +
+ +

Register for tournament

+
+
+
+

Please provide us with some additional details below.

+ +
+ + } + /> + + + 👋 Details: other makers will be able to see your hacker card and send you Team Up requests. + +
+
+ +
+ +
+ + {errors.email &&

+ {errors.email.message} +

} +
+ + +
+ {errors.agreement &&

+ {errors.agreement.message} +

} +
+ +
+ + +
+
+
+ ) +} + + + diff --git a/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationDetails/index.ts b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationDetails/index.ts new file mode 100644 index 0000000..cd7c9af --- /dev/null +++ b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationDetails/index.ts @@ -0,0 +1,3 @@ +import { lazyModal } from 'src/utils/helperFunctions'; + +export const { LazyComponent: RegistrationDetails } = lazyModal(() => import('./RegistrationDetails')) \ No newline at end of file diff --git a/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationDetails/registerInTournament.graphql b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationDetails/registerInTournament.graphql new file mode 100644 index 0000000..02a3642 --- /dev/null +++ b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationDetails/registerInTournament.graphql @@ -0,0 +1,9 @@ +mutation RegisterInTournament( + $tournamentId: Int! + $data: RegisterInTournamentInput +) { + registerInTournament(tournament_id: $tournamentId, data: $data) { + id + in_tournament(id: $tournamentId) + } +} diff --git a/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationSuccess/RegistrationSuccess.tsx b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationSuccess/RegistrationSuccess.tsx new file mode 100644 index 0000000..e45f8cd --- /dev/null +++ b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationSuccess/RegistrationSuccess.tsx @@ -0,0 +1,72 @@ +import { motion } from 'framer-motion' +import { ModalCard, modalCardVariants } from 'src/Components/Modals/ModalsContainer/ModalsContainer' +import { IoClose } from 'react-icons/io5'; +import Avatar from 'src/features/Profiles/Components/Avatar/Avatar'; +import { useAppSelector } from "src/utils/hooks"; +import Button from 'src/Components/Button/Button'; +import Confetti from "react-confetti"; +import { Portal } from 'src/Components/Portal/Portal'; + + +interface Props extends ModalCard { + +} + +export default function RegistrationSuccess({ onClose, direction, ...props }: Props) { + + const me = useAppSelector(state => state.user.me) + + if (!me) + throw new Error("User not defined"); + + + return ( + +
+ +

Registration succeeded!! ✅

+
+
+
+ +
+

{me.name}

+

{me.jobTitle}

+
+ +

Nice work! You’ve successfully registered for the tournament. You can get started with some of the options below!

+ + +
+
👾
+
+

Complete your maker profile

+

Add details to your maker profile so you stand out.

+
+
+
+
🤝️️️
+
+

Find makers to team up with

+

Recruit or find makers to team up with.

+
+
+ +
+ + +
+
+
+ ) +} + + + diff --git a/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationSuccess/index.ts b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationSuccess/index.ts new file mode 100644 index 0000000..ae9cdab --- /dev/null +++ b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationSuccess/index.ts @@ -0,0 +1,3 @@ +import { lazyModal } from 'src/utils/helperFunctions'; + +export const { LazyComponent: RegistrationSuccess } = lazyModal(() => import('./RegistrationSuccess')) \ No newline at end of file diff --git a/src/features/Tournaments/pages/OverviewPage/RegisterationModals/index.tsx b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/index.tsx new file mode 100644 index 0000000..6d7e22e --- /dev/null +++ b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/index.tsx @@ -0,0 +1,11 @@ +import { LoginModal } from './LoginModal' +import { ConfirmAccount } from './ConfirmAccount' +import { RegistrationDetails } from './RegistrationDetails' +import { RegistrationSuccess } from './RegistrationSuccess' + +export const RegistrationModals = { + LoginModal, + RegistrationDetails, + ConfirmAccount, + RegistrationSuccess, +} diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx index c24ad1f..b6e4f49 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx +++ b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx @@ -41,7 +41,7 @@ export default function Navigation({ data }: Props) { path: "resources", isDisabled: true, }, - ], [data.events_count]) + ], [data.events_count, data.makers_count, data.projects_count]) return (
diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx index b101814..9778532 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx +++ b/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx @@ -1,30 +1,34 @@ import Header from './Header/Header' -import { Navigate, Route, Routes } from 'react-router-dom' +import { Navigate, Route, Routes, useParams } from 'react-router-dom' import OverviewPage from '../OverviewPage/OverviewPage' import { Helmet } from 'react-helmet' import Navigation from './Navigation/Navigation' import EventsPage from '../EventsPage/EventsPage' import MakersPage from '../MakersPage/MakersPage' import ProjectsPage from '../ProjectsPage/ProjectsPage' -import { useGetTournamentByIdQuery } from 'src/graphql' +import { useGetTournamentByIdQuery, GetTournamentByIdQuery } from 'src/graphql' import LoadingPage from 'src/Components/LoadingPage/LoadingPage' import NotFoundPage from 'src/features/Shared/pages/NotFoundPage/NotFoundPage' +export type MeTournament = GetTournamentByIdQuery['me'] + export default function TournamentDetailsPage() { - const query = useGetTournamentByIdQuery({ - variables: { - id: 12, - }, + const { id } = useParams() + const tournaemntQuery = useGetTournamentByIdQuery({ + variables: { + id: Number(id)!, + }, + skip: !id }) - if (query.loading) + if (tournaemntQuery.loading) return - if (!query.data?.getTournamentById) + if (!tournaemntQuery.data?.getTournamentById) return return ( @@ -32,18 +36,18 @@ export default function TournamentDetailsPage() { "--maxPageWidth": "910px" } as any}> - {query.data.getTournamentById.title} Tournament + {tournaemntQuery.data.getTournamentById.title} Tournament -
- +
+
} /> - m.avatar)} />} /> - } /> - } /> - } /> + m.avatar)} isRegistered={!!tournaemntQuery.data.me?.in_tournament} />} /> + } /> + } /> + } />
diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/meTournament.graphql b/src/features/Tournaments/pages/TournamentDetailsPage/meTournament.graphql new file mode 100644 index 0000000..c7615c3 --- /dev/null +++ b/src/features/Tournaments/pages/TournamentDetailsPage/meTournament.graphql @@ -0,0 +1,12 @@ +query MeTournament($inTournamentId: Int!) { + me { + id + name + avatar + jobTitle + + in_tournament(id: $inTournamentId) + + ...UserRolesSkills + } +} diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/tournamentDetails.graphql b/src/features/Tournaments/pages/TournamentDetailsPage/tournamentDetails.graphql index 62e5f24..b1c4b29 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/tournamentDetails.graphql +++ b/src/features/Tournaments/pages/TournamentDetailsPage/tournamentDetails.graphql @@ -48,4 +48,15 @@ query GetTournamentById($id: Int!) { avatar } } + + me { + id + name + avatar + jobTitle + + in_tournament(id: $id) + + ...UserRolesSkills + } } diff --git a/src/graphql/index.tsx b/src/graphql/index.tsx index ebe86f4..f848154 100644 --- a/src/graphql/index.tsx +++ b/src/graphql/index.tsx @@ -41,6 +41,7 @@ export type BaseUser = { email: Maybe; github: Maybe; id: Scalars['Int']; + in_tournament: Scalars['Boolean']; jobTitle: Maybe; join_date: Scalars['Date']; lightning_address: Maybe; @@ -57,6 +58,11 @@ export type BaseUser = { website: Maybe; }; + +export type BaseUserIn_TournamentArgs = { + id: Scalars['Int']; +}; + export type Bounty = PostBase & { __typename?: 'Bounty'; applicants_count: Scalars['Int']; @@ -173,6 +179,7 @@ export type Mutation = { createStory: Maybe; deleteStory: Maybe; donate: Donation; + registerInTournament: Maybe; updateProfileDetails: Maybe; updateProfileRoles: Maybe; updateUserPreferences: MyProfile; @@ -207,6 +214,12 @@ export type MutationDonateArgs = { }; +export type MutationRegisterInTournamentArgs = { + data: InputMaybe; + tournament_id: Scalars['Int']; +}; + + export type MutationUpdateProfileDetailsArgs = { data: InputMaybe; }; @@ -235,6 +248,7 @@ export type MyProfile = BaseUser & { email: Maybe; github: Maybe; id: Scalars['Int']; + in_tournament: Scalars['Boolean']; jobTitle: Maybe; join_date: Scalars['Date']; lightning_address: Maybe; @@ -254,6 +268,11 @@ export type MyProfile = BaseUser & { website: Maybe; }; + +export type MyProfileIn_TournamentArgs = { + id: Scalars['Int']; +}; + export enum Post_Type { Bounty = 'Bounty', Question = 'Question', @@ -469,6 +488,11 @@ export type Question = PostBase & { votes_count: Scalars['Int']; }; +export type RegisterInTournamentInput = { + email: Scalars['String']; + hacking_status: TournamentMakerHackingStatusEnum; +}; + export enum RoleLevelEnum { Advanced = 'Advanced', Beginner = 'Beginner', @@ -567,6 +591,11 @@ export type TournamentJudge = { name: Scalars['String']; }; +export enum TournamentMakerHackingStatusEnum { + OpenToConnect = 'OpenToConnect', + Solo = 'Solo' +} + export type TournamentMakersResponse = { __typename?: 'TournamentMakersResponse'; hasNext: Maybe; @@ -595,6 +624,7 @@ export type User = BaseUser & { email: Maybe; github: Maybe; id: Scalars['Int']; + in_tournament: Scalars['Boolean']; jobTitle: Maybe; join_date: Scalars['Date']; lightning_address: Maybe; @@ -611,6 +641,11 @@ export type User = BaseUser & { website: Maybe; }; + +export type UserIn_TournamentArgs = { + id: Scalars['Int']; +}; + export type UserKeyInputType = { key: Scalars['String']; name: Scalars['String']; @@ -826,11 +861,6 @@ export type ProjectDetailsQueryVariables = Exact<{ export type ProjectDetailsQuery = { __typename?: 'Query', getProject: { __typename?: 'Project', id: number, title: string, description: string, cover_image: string, thumbnail_image: string, screenshots: Array, website: string, lightning_address: string | null, lnurl_callback_url: string | null, votes_count: number, category: { __typename?: 'Category', id: number, title: string }, awards: Array<{ __typename?: 'Award', title: string, image: string, url: string, id: number }>, tags: Array<{ __typename?: 'Tag', id: number, title: string }> } }; -export type MeTournamentQueryVariables = Exact<{ [key: string]: never; }>; - - -export type MeTournamentQuery = { __typename?: 'Query', me: { __typename?: 'MyProfile', id: number, name: string, avatar: string, jobTitle: string | null, skills: Array<{ __typename?: 'MakerSkill', id: number, title: string }>, roles: Array<{ __typename?: 'MakerRole', id: number, title: string, icon: string, level: RoleLevelEnum }> } | null }; - export type GetAllRolesQueryVariables = Exact<{ [key: string]: never; }>; @@ -858,12 +888,27 @@ export type GetProjectsInTournamentQueryVariables = Exact<{ export type GetProjectsInTournamentQuery = { __typename?: 'Query', getProjectsInTournament: { __typename?: 'TournamentProjectsResponse', hasNext: boolean | null, hasPrev: boolean | null, projects: Array<{ __typename?: 'Project', id: number, title: string, description: string, thumbnail_image: string, category: { __typename?: 'Category', id: number, title: string, icon: string | null }, recruit_roles: Array<{ __typename?: 'MakerRole', id: number, title: string, icon: string, level: RoleLevelEnum }> }> } }; +export type RegisterInTournamentMutationVariables = Exact<{ + tournamentId: Scalars['Int']; + data: InputMaybe; +}>; + + +export type RegisterInTournamentMutation = { __typename?: 'Mutation', registerInTournament: { __typename?: 'User', id: number, in_tournament: boolean } | null }; + +export type MeTournamentQueryVariables = Exact<{ + inTournamentId: Scalars['Int']; +}>; + + +export type MeTournamentQuery = { __typename?: 'Query', me: { __typename?: 'MyProfile', id: number, name: string, avatar: string, jobTitle: string | null, in_tournament: boolean, skills: Array<{ __typename?: 'MakerSkill', id: number, title: string }>, roles: Array<{ __typename?: 'MakerRole', id: number, title: string, icon: string, level: RoleLevelEnum }> } | null }; + export type GetTournamentByIdQueryVariables = Exact<{ id: Scalars['Int']; }>; -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, company: string, avatar: string }>, events: Array<{ __typename?: 'TournamentEvent', id: number, title: string, image: string, description: string, starts_at: any, ends_at: any, location: string, website: string, type: TournamentEventTypeEnum, links: Array }>, faqs: Array<{ __typename?: 'TournamentFAQ', question: string, answer: string }> }, getMakersInTournament: { __typename?: 'TournamentMakersResponse', makers: Array<{ __typename?: 'User', id: number, avatar: 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, company: string, avatar: string }>, events: Array<{ __typename?: 'TournamentEvent', id: number, title: string, image: string, description: string, starts_at: any, ends_at: any, location: string, website: string, type: TournamentEventTypeEnum, links: Array }>, faqs: Array<{ __typename?: 'TournamentFAQ', question: string, answer: string }> }, getMakersInTournament: { __typename?: 'TournamentMakersResponse', makers: Array<{ __typename?: 'User', id: number, avatar: string }> }, me: { __typename?: 'MyProfile', id: number, name: string, avatar: string, jobTitle: string | null, in_tournament: boolean, skills: Array<{ __typename?: 'MakerSkill', id: number, title: string }>, roles: Array<{ __typename?: 'MakerRole', id: number, title: string, icon: string, level: RoleLevelEnum }> } | null }; export type VoteMutationVariables = Exact<{ itemType: Vote_Item_Type; @@ -2188,44 +2233,6 @@ export function useProjectDetailsLazyQuery(baseOptions?: Apollo.LazyQueryHookOpt export type ProjectDetailsQueryHookResult = ReturnType; export type ProjectDetailsLazyQueryHookResult = ReturnType; export type ProjectDetailsQueryResult = Apollo.QueryResult; -export const MeTournamentDocument = gql` - query MeTournament { - me { - id - name - avatar - jobTitle - ...UserRolesSkills - } -} - ${UserRolesSkillsFragmentDoc}`; - -/** - * __useMeTournamentQuery__ - * - * To run a query within a React component, call `useMeTournamentQuery` and pass it any options that fit your needs. - * When your component renders, `useMeTournamentQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; - * - * @example - * const { data, loading, error } = useMeTournamentQuery({ - * variables: { - * }, - * }); - */ -export function useMeTournamentQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(MeTournamentDocument, options); - } -export function useMeTournamentLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(MeTournamentDocument, options); - } -export type MeTournamentQueryHookResult = ReturnType; -export type MeTournamentLazyQueryHookResult = ReturnType; -export type MeTournamentQueryResult = Apollo.QueryResult; export const GetAllRolesDocument = gql` query GetAllRoles { getAllMakersRoles { @@ -2390,6 +2397,81 @@ export function useGetProjectsInTournamentLazyQuery(baseOptions?: Apollo.LazyQue export type GetProjectsInTournamentQueryHookResult = ReturnType; export type GetProjectsInTournamentLazyQueryHookResult = ReturnType; export type GetProjectsInTournamentQueryResult = Apollo.QueryResult; +export const RegisterInTournamentDocument = gql` + mutation RegisterInTournament($tournamentId: Int!, $data: RegisterInTournamentInput) { + registerInTournament(tournament_id: $tournamentId, data: $data) { + id + in_tournament(id: $tournamentId) + } +} + `; +export type RegisterInTournamentMutationFn = Apollo.MutationFunction; + +/** + * __useRegisterInTournamentMutation__ + * + * To run a mutation, you first call `useRegisterInTournamentMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useRegisterInTournamentMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [registerInTournamentMutation, { data, loading, error }] = useRegisterInTournamentMutation({ + * variables: { + * tournamentId: // value for 'tournamentId' + * data: // value for 'data' + * }, + * }); + */ +export function useRegisterInTournamentMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(RegisterInTournamentDocument, options); + } +export type RegisterInTournamentMutationHookResult = ReturnType; +export type RegisterInTournamentMutationResult = Apollo.MutationResult; +export type RegisterInTournamentMutationOptions = Apollo.BaseMutationOptions; +export const MeTournamentDocument = gql` + query MeTournament($inTournamentId: Int!) { + me { + id + name + avatar + jobTitle + in_tournament(id: $inTournamentId) + ...UserRolesSkills + } +} + ${UserRolesSkillsFragmentDoc}`; + +/** + * __useMeTournamentQuery__ + * + * To run a query within a React component, call `useMeTournamentQuery` and pass it any options that fit your needs. + * When your component renders, `useMeTournamentQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useMeTournamentQuery({ + * variables: { + * inTournamentId: // value for 'inTournamentId' + * }, + * }); + */ +export function useMeTournamentQuery(baseOptions: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(MeTournamentDocument, options); + } +export function useMeTournamentLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(MeTournamentDocument, options); + } +export type MeTournamentQueryHookResult = ReturnType; +export type MeTournamentLazyQueryHookResult = ReturnType; +export type MeTournamentQueryResult = Apollo.QueryResult; export const GetTournamentByIdDocument = gql` query GetTournamentById($id: Int!) { getTournamentById(id: $id) { @@ -2438,8 +2520,16 @@ export const GetTournamentByIdDocument = gql` avatar } } + me { + id + name + avatar + jobTitle + in_tournament(id: $id) + ...UserRolesSkills + } } - `; + ${UserRolesSkillsFragmentDoc}`; /** * __useGetTournamentByIdQuery__ diff --git a/src/mocks/data/users.ts b/src/mocks/data/users.ts index 5ac031c..4ca7d8b 100644 --- a/src/mocks/data/users.ts +++ b/src/mocks/data/users.ts @@ -157,6 +157,7 @@ export const users: (User & MyProfile)[] = [{ twitter: "mtg", website: "https://mtg-dev.tech", stories: posts.stories, + in_tournament: true, nostr_prv_key: "123123124asdfsadfsa8d7fsadfasdf", nostr_pub_key: "123124123123dfsadfsa8d7f11sadfasdf", walletsKeys: [ @@ -191,6 +192,7 @@ export const users: (User & MyProfile)[] = [{ twitter: "john-doe", website: "https://mtg-dev.tech", stories: posts.stories, + in_tournament: true, nostr_prv_key: "123123124asdfsadfsa8d7fsadfasdf", nostr_pub_key: "123124123123dfsadfsa8d7f11sadfasdf", @@ -226,6 +228,7 @@ export const users: (User & MyProfile)[] = [{ twitter: "john-doe", website: "https://mtg-dev.tech", stories: posts.stories, + in_tournament: true, nostr_prv_key: "123123124asdfsadfsa8d7fsadfasdf", nostr_pub_key: "123124123123dfsadfsa8d7f11sadfasdf", walletsKeys: [ @@ -260,6 +263,7 @@ export const users: (User & MyProfile)[] = [{ twitter: "john-doe", website: "https://mtg-dev.tech", stories: posts.stories, + in_tournament: true, nostr_prv_key: "123123124asdfsadfsa8d7fsadfasdf", nostr_pub_key: "123124123123dfsadfsa8d7f11sadfasdf", walletsKeys: [ diff --git a/src/mocks/handlers.ts b/src/mocks/handlers.ts index 147c620..b6a8bc4 100644 --- a/src/mocks/handlers.ts +++ b/src/mocks/handlers.ts @@ -283,7 +283,8 @@ export const handlers = [ return res( ctx.data({ getTournamentById: getTournamentById(12), - getMakersInTournament: getMakersInTournament({ roleId: null, search: null, skip: null, take: 4, tournamentId: 12 }) + getMakersInTournament: getMakersInTournament({ roleId: null, search: null, skip: null, take: 4, tournamentId: 12 }), + me: { ...me() } }) ) }), diff --git a/src/redux/features/modals.slice.ts b/src/redux/features/modals.slice.ts index 98b413f..eb49b57 100644 --- a/src/redux/features/modals.slice.ts +++ b/src/redux/features/modals.slice.ts @@ -15,6 +15,7 @@ import { ComponentProps } from "react"; import { generateId } from "src/utils/helperFunctions"; import { NoWeblnModal } from "src/Components/Modals/NoWeblnModal"; import { ConnectToMakerModal } from "src/features/Tournaments/pages/MakersPage/ConnectToMakerModal"; +import { RegistrationModals } from "src/features/Tournaments/pages/OverviewPage/RegisterationModals"; @@ -44,6 +45,10 @@ export const ALL_MODALS = { // Tournaments EventModal, ConnectToMakerModal, + RegisterTournamet_Login: RegistrationModals.LoginModal, + RegisterTournamet_ConfrimAccount: RegistrationModals.ConfirmAccount, + RegisterTournamet_RegistrationDetails: RegistrationModals.RegistrationDetails, + RegisterTournamet_RegistrationSuccess: RegistrationModals.RegistrationSuccess, // Misc ConfirmModal, diff --git a/src/styles/tw.scss b/src/styles/tw.scss index a2bb859..18b2141 100644 --- a/src/styles/tw.scss +++ b/src/styles/tw.scss @@ -44,6 +44,6 @@ } .modal-card { - @apply rounded-[40px] bg-gray-50 overflow-hidden w-full shadow-2xl z-10; + @apply rounded-[40px] bg-white overflow-hidden w-full shadow-2xl z-10; } } From 64d8263ae6b613a2a694cb6f91fcba235aa7a8c3 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Fri, 9 Sep 2022 09:46:18 +0300 Subject: [PATCH 34/53] feat: add hacking_status to api, update maker card, halt registration if already registered --- api/functions/graphql/nexus-typegen.ts | 38 +++++++- api/functions/graphql/schema.graphql | 14 ++- api/functions/graphql/types/tournament.js | 67 ++++++++++++-- .../ConnectToMakerModal.tsx | 22 ++--- .../pages/MakersPage/MakerCard/MakerCard.tsx | 55 +++++++++--- .../pages/MakersPage/MakersPage.tsx | 8 +- .../ParticipantsSection/MakersList.tsx | 2 +- .../ParticipantsSection.tsx | 4 +- .../pages/MakersPage/tournamentMakers.graphql | 32 +++---- .../LoginModal/LoginModal.tsx | 9 +- .../Navigation/Navigation.tsx | 23 ++--- .../TournamentDetailsPage.tsx | 2 +- .../meTournament.graphql | 11 ++- .../tournamentDetails.graphql | 15 +++- src/graphql/index.tsx | 87 +++++++++++++------ src/mocks/handlers.ts | 16 +++- src/mocks/resolvers.ts | 5 +- 17 files changed, 301 insertions(+), 109 deletions(-) diff --git a/api/functions/graphql/nexus-typegen.ts b/api/functions/graphql/nexus-typegen.ts index 28338b2..3f35201 100644 --- a/api/functions/graphql/nexus-typegen.ts +++ b/api/functions/graphql/nexus-typegen.ts @@ -192,6 +192,10 @@ export interface NexusGenObjects { twitter?: string | null; // String website?: string | null; // String } + ParticipationInfo: { // root type + createdAt: NexusGenScalars['Date']; // Date! + hacking_status: NexusGenEnums['TournamentMakerHackingStatusEnum']; // TournamentMakerHackingStatusEnum! + } PostComment: { // root type author: NexusGenRootTypes['Author']; // Author! body: string; // String! @@ -275,7 +279,12 @@ export interface NexusGenObjects { TournamentMakersResponse: { // root type hasNext?: boolean | null; // Boolean hasPrev?: boolean | null; // Boolean - makers: NexusGenRootTypes['User'][]; // [User!]! + makers: NexusGenRootTypes['TournamentParticipant'][]; // [TournamentParticipant!]! + } + TournamentParticipant: { // root type + hacking_status: NexusGenEnums['TournamentMakerHackingStatusEnum']; // TournamentMakerHackingStatusEnum! + is_registered?: boolean | null; // Boolean + user: NexusGenRootTypes['User']; // User! } TournamentPrize: { // root type amount: string; // String! @@ -464,6 +473,10 @@ export interface NexusGenFieldTypes { walletsKeys: NexusGenRootTypes['WalletKey'][]; // [WalletKey!]! website: string | null; // String } + ParticipationInfo: { // field return type + createdAt: NexusGenScalars['Date']; // Date! + hacking_status: NexusGenEnums['TournamentMakerHackingStatusEnum']; // TournamentMakerHackingStatusEnum! + } PostComment: { // field return type author: NexusGenRootTypes['Author']; // Author! body: string; // String! @@ -514,6 +527,7 @@ export interface NexusGenFieldTypes { projectsByCategory: NexusGenRootTypes['Project'][]; // [Project!]! searchProjects: NexusGenRootTypes['Project'][]; // [Project!]! similarMakers: NexusGenRootTypes['User'][]; // [User!]! + tournamentParticipationInfo: NexusGenRootTypes['ParticipationInfo'] | null; // ParticipationInfo } Question: { // field return type author: NexusGenRootTypes['Author']; // Author! @@ -593,7 +607,12 @@ export interface NexusGenFieldTypes { TournamentMakersResponse: { // field return type hasNext: boolean | null; // Boolean hasPrev: boolean | null; // Boolean - makers: NexusGenRootTypes['User'][]; // [User!]! + makers: NexusGenRootTypes['TournamentParticipant'][]; // [TournamentParticipant!]! + } + TournamentParticipant: { // field return type + hacking_status: NexusGenEnums['TournamentMakerHackingStatusEnum']; // TournamentMakerHackingStatusEnum! + is_registered: boolean | null; // Boolean + user: NexusGenRootTypes['User']; // User! } TournamentPrize: { // field return type amount: string; // String! @@ -807,6 +826,10 @@ export interface NexusGenFieldTypeNames { walletsKeys: 'WalletKey' website: 'String' } + ParticipationInfo: { // field return type name + createdAt: 'Date' + hacking_status: 'TournamentMakerHackingStatusEnum' + } PostComment: { // field return type name author: 'Author' body: 'String' @@ -857,6 +880,7 @@ export interface NexusGenFieldTypeNames { projectsByCategory: 'Project' searchProjects: 'Project' similarMakers: 'User' + tournamentParticipationInfo: 'ParticipationInfo' } Question: { // field return type name author: 'Author' @@ -936,7 +960,12 @@ export interface NexusGenFieldTypeNames { TournamentMakersResponse: { // field return type name hasNext: 'Boolean' hasPrev: 'Boolean' - makers: 'User' + makers: 'TournamentParticipant' + } + TournamentParticipant: { // field return type name + hacking_status: 'TournamentMakerHackingStatusEnum' + is_registered: 'Boolean' + user: 'User' } TournamentPrize: { // field return type name amount: 'String' @@ -1133,6 +1162,9 @@ export interface NexusGenArgTypes { similarMakers: { // args id: number; // Int! } + tournamentParticipationInfo: { // args + tournamentId: number; // Int! + } } User: { in_tournament: { // args diff --git a/api/functions/graphql/schema.graphql b/api/functions/graphql/schema.graphql index 56b9e0a..ba9a87e 100644 --- a/api/functions/graphql/schema.graphql +++ b/api/functions/graphql/schema.graphql @@ -188,6 +188,11 @@ enum POST_TYPE { Story } +type ParticipationInfo { + createdAt: Date! + hacking_status: TournamentMakerHackingStatusEnum! +} + union Post = Bounty | Question | Story interface PostBase { @@ -272,6 +277,7 @@ type Query { projectsByCategory(category_id: Int!, skip: Int = 0, take: Int = 10): [Project!]! searchProjects(search: String!, skip: Int = 0, take: Int = 50): [Project!]! similarMakers(id: Int!): [User!]! + tournamentParticipationInfo(tournamentId: Int!): ParticipationInfo } type Question implements PostBase { @@ -393,7 +399,13 @@ enum TournamentMakerHackingStatusEnum { type TournamentMakersResponse { hasNext: Boolean hasPrev: Boolean - makers: [User!]! + makers: [TournamentParticipant!]! +} + +type TournamentParticipant { + hacking_status: TournamentMakerHackingStatusEnum! + is_registered: Boolean + user: User! } type TournamentPrize { diff --git a/api/functions/graphql/types/tournament.js b/api/functions/graphql/types/tournament.js index 2eb4572..121cbb3 100644 --- a/api/functions/graphql/types/tournament.js +++ b/api/functions/graphql/types/tournament.js @@ -39,7 +39,14 @@ const TournamentFAQ = objectType({ } }) - +const TournamentParticipant = objectType({ + name: "TournamentParticipant", + definition(t) { + t.nonNull.field('hacking_status', { type: TournamentMakerHackingStatusEnum }); + t.boolean('is_registered') + t.nonNull.field('user', { type: "User" }) + } +}) const TournamentEventTypeEnum = enumType({ name: 'TournamentEventTypeEnum', @@ -152,7 +159,7 @@ const TournamentMakersResponse = objectType({ t.boolean('hasNext'); t.boolean('hasPrev'); - t.nonNull.list.nonNull.field('makers', { type: "User" }) + t.nonNull.list.nonNull.field('makers', { type: TournamentParticipant }) } } ) @@ -185,7 +192,40 @@ const getTournamentById = extendType({ } }) +const ParticipationInfo = objectType({ + name: "ParticipationInfo", + definition(t) { + t.nonNull.date('createdAt') + t.nonNull.field('hacking_status', { type: TournamentMakerHackingStatusEnum }); + } +}) + +const tournamentParticipationInfo = extendType({ + type: "Query", + definition(t) { + t.field('tournamentParticipationInfo', { + type: ParticipationInfo, + args: { + tournamentId: nonNull(intArg()), + }, + async resolve(_, args, ctx) { + + const user = await getUserByPubKey(ctx.userPubKey); + if (!user) + return null + + + return prisma.tournamentParticipant.findFirst({ + where: { + user_id: user.id, + tournament_id: args.tournamentId + } + }) + } + }) + } +}) const getMakersInTournament = extendType({ type: "Query", @@ -198,7 +238,9 @@ const getMakersInTournament = extendType({ search: stringArg(), roleId: intArg(), }, - async resolve(_, args) { + async resolve(_, args, ctx) { + + const user = await getUserByPubKey(ctx.userPubKey); let filters = []; @@ -229,6 +271,12 @@ const getMakersInTournament = extendType({ } }) + if (user?.id) filters.push({ + id: { + not: user.id + } + }) + const makers = (await prisma.tournamentParticipant.findMany({ where: { tournament_id: args.tournamentId, @@ -238,12 +286,19 @@ const getMakersInTournament = extendType({ } }) }, + orderBy: { + createdAt: 'desc' + }, include: { user: true, }, skip: args.skip, take: args.take + 1, - })).map(item => item.user) + })) + .map(item => ({ + hacking_status: item.hacking_status, + user: item.user + })) @@ -381,6 +436,7 @@ const registerInTournament = extendType({ module.exports = { // Types Tournament, + // Enums TournamentEventTypeEnum, @@ -388,8 +444,9 @@ module.exports = { getTournamentById, getMakersInTournament, getProjectsInTournament, + tournamentParticipationInfo, // Mutations registerInTournament, -} \ No newline at end of file +} diff --git a/src/features/Tournaments/pages/MakersPage/ConnectToMakerModal/ConnectToMakerModal.tsx b/src/features/Tournaments/pages/MakersPage/ConnectToMakerModal/ConnectToMakerModal.tsx index dce9916..bf8307c 100644 --- a/src/features/Tournaments/pages/MakersPage/ConnectToMakerModal/ConnectToMakerModal.tsx +++ b/src/features/Tournaments/pages/MakersPage/ConnectToMakerModal/ConnectToMakerModal.tsx @@ -16,22 +16,22 @@ export default function LinkingAccountModal({ onClose, direction, maker, ...prop const links = [ { - hasValue: maker.twitter, - text: maker.twitter, + hasValue: maker.user.twitter, + text: maker.user.twitter, icon: FiTwitter, - url: `https://twitter.com/${maker.twitter}` + url: `https://twitter.com/${maker.user.twitter}` }, { - hasValue: maker.github, - text: maker.github, + hasValue: maker.user.github, + text: maker.user.github, icon: FiGithub, - url: `https://github.com/${maker.github}` + url: `https://github.com/${maker.user.github}` }, { - hasValue: maker.linkedin, + hasValue: maker.user.linkedin, text: "LinkedIn", icon: FiLinkedin, - url: maker.linkedin && withHttp(maker.linkedin), + url: maker.user.linkedin && withHttp(maker.user.linkedin), } ]; @@ -51,10 +51,10 @@ export default function LinkingAccountModal({ onClose, direction, maker, ...prop

- +
-

{maker.name}

-

{maker.jobTitle}

+

{maker.user.name}

+

{maker.user.jobTitle}

Team up with this maker by sending them a message on one of the following platforms.

diff --git a/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx b/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx index 013d14e..697418d 100644 --- a/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx +++ b/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx @@ -1,11 +1,13 @@ import Button from "src/Components/Button/Button" -import { GetMakersInTournamentQuery, } from "src/graphql"; +import { GetMakersInTournamentQuery, TournamentMakerHackingStatusEnum, } from "src/graphql"; import { useAppDispatch, } from "src/utils/hooks"; import Card from 'src/Components/Card/Card'; import Avatar from 'src/features/Profiles/Components/Avatar/Avatar'; import Badge from 'src/Components/Badge/Badge'; import { createRoute } from 'src/utils/routing'; import { openModal } from "src/redux/features/modals.slice"; +import InfoCard from "src/Components/InfoCard/InfoCard"; +import { Link } from "react-router-dom"; type MakerType = GetMakersInTournamentQuery['getMakersInTournament']['makers'][number] @@ -18,27 +20,33 @@ export default function MakerCard({ maker, isMe }: Props) { const dispatch = useAppDispatch(); - const contactLinksAvailable = maker.github || maker.email || maker.linkedin || maker.twitter; + const contactLinksAvailable = maker.user.github || maker.user.linkedin || maker.user.twitter; - let actionBtn = + let actionBtn = <> - if (isMe) actionBtn = ; - else if (contactLinksAvailable) actionBtn = + if (isMe) + actionBtn = ; + else if (maker.hacking_status === TournamentMakerHackingStatusEnum.OpenToConnect && contactLinksAvailable) + actionBtn = + else if (maker.hacking_status === TournamentMakerHackingStatusEnum.Solo) + actionBtn = + const missingFields = isMe && getMissingFields(maker) + return (
- +
-

{maker.name}

- {maker.jobTitle ?

{maker.jobTitle}

+

{maker.user.name}

+ {maker.user.jobTitle ?

{maker.user.jobTitle}

:

No job title

} - {maker.roles.length ?
    - {maker.roles.map(role =>
  • {role.icon} {role.title}
  • )} + {maker.user.roles.length ?
      + {maker.user.roles.map(role =>
    • {role.icon} {role.title}
    • )}
    :

    No roles added

    @@ -51,8 +59,8 @@ export default function MakerCard({ maker, isMe }: Props) {

    🌈 Roles

    - {maker.roles.length ?
      - {maker.roles.map(role =>
    • {role.icon} {role.title}
    • )} + {maker.user.roles.length ?
        + {maker.user.roles.map(role =>
      • {role.icon} {role.title}
      • )}
      :

      No roles added

      @@ -61,14 +69,33 @@ export default function MakerCard({ maker, isMe }: Props) {

      🛠️ Skills

      - {maker.skills.length ?
        - {maker.skills.map(skill =>
      • {skill.title}
      • )} + {maker.user.skills.length ?
          + {maker.user.skills.map(skill =>
        • {skill.title}
        • )}
        :

        No skills added

        }
      {actionBtn}
      + {missingFields && + 👾 Complete your profile: make it easy for other makers to find you by adding your {missingFields}. You can add this information in your profile’s Settings ⚙️ menu. + } ) } + + +function getMissingFields(maker: Props['maker']) { + let res: string[] = []; + + if (!maker.user.jobTitle) res.push("job title") + + if (maker.user.roles.length === 0) res.push('roles') + + if (maker.user.skills.length === 0) res.push('skills') + + if (!maker.user.linkedin && !maker.user.twitter) res.push('contacts') + + return res.join(', '); + +} \ No newline at end of file diff --git a/src/features/Tournaments/pages/MakersPage/MakersPage.tsx b/src/features/Tournaments/pages/MakersPage/MakersPage.tsx index 4732a8c..4c1b90a 100644 --- a/src/features/Tournaments/pages/MakersPage/MakersPage.tsx +++ b/src/features/Tournaments/pages/MakersPage/MakersPage.tsx @@ -1,4 +1,4 @@ -import { Tournament, useMeTournamentQuery, User } from 'src/graphql' +import { Tournament, useMeTournamentQuery, User, } from 'src/graphql' import MakerCard from './MakerCard/MakerCard'; import MakerCardSkeleton from './MakerCard/MakerCard.Skeleton'; import ParticipantsSection from './ParticipantsSection/ParticipantsSection'; @@ -12,7 +12,7 @@ interface Props { export default function MakersPage({ data: { id } }: Props) { const query = useMeTournamentQuery({ - variables: { inTournamentId: id } + variables: { id: id } }); return ( @@ -21,8 +21,8 @@ export default function MakersPage({ data: { id } }: Props) { {query.loading ? : - query.data?.me?.in_tournament ? - + query.data?.me ? + : null } diff --git a/src/features/Tournaments/pages/MakersPage/ParticipantsSection/MakersList.tsx b/src/features/Tournaments/pages/MakersPage/ParticipantsSection/MakersList.tsx index e59d470..b40239c 100644 --- a/src/features/Tournaments/pages/MakersPage/ParticipantsSection/MakersList.tsx +++ b/src/features/Tournaments/pages/MakersPage/ParticipantsSection/MakersList.tsx @@ -87,7 +87,7 @@ export default function MakersList(props: Props) { : (itemsCount !== 0 ? - query.data?.getMakersInTournament.makers.map(maker => ) : + query.data?.getMakersInTournament.makers.map(maker => ) :

      No makers found here...

      ) diff --git a/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ParticipantsSection.tsx b/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ParticipantsSection.tsx index 3ef5805..cf3c1f2 100644 --- a/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ParticipantsSection.tsx +++ b/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ParticipantsSection.tsx @@ -64,7 +64,7 @@ export default function ParticipantsSection({ tournamentId }: Props) { > Makers looking for a team - + */}
{curTab === 'projects' && } diff --git a/src/features/Tournaments/pages/MakersPage/tournamentMakers.graphql b/src/features/Tournaments/pages/MakersPage/tournamentMakers.graphql index 949f80d..08448fc 100644 --- a/src/features/Tournaments/pages/MakersPage/tournamentMakers.graphql +++ b/src/features/Tournaments/pages/MakersPage/tournamentMakers.graphql @@ -23,22 +23,24 @@ query GetMakersInTournament( hasNext hasPrev makers { - id - name - avatar - jobTitle - email - twitter - linkedin - github - roles { + hacking_status + user { id - icon - title - } - skills { - id - title + name + avatar + jobTitle + twitter + linkedin + github + roles { + id + icon + title + } + skills { + id + title + } } } } diff --git a/src/features/Tournaments/pages/OverviewPage/RegisterationModals/LoginModal/LoginModal.tsx b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/LoginModal/LoginModal.tsx index de6f63b..88cdba8 100644 --- a/src/features/Tournaments/pages/OverviewPage/RegisterationModals/LoginModal/LoginModal.tsx +++ b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/LoginModal/LoginModal.tsx @@ -12,6 +12,7 @@ import useCopyToClipboard from 'src/utils/hooks/useCopyToClipboard'; import { useLnurlQuery } from 'src/features/Auth/pages/LoginPage/LoginPage'; import { useAppDispatch } from 'src/utils/hooks'; import { Direction, replaceModal } from 'src/redux/features/modals.slice'; +import { NotificationsService } from 'src/services'; interface Props extends ModalCard { @@ -34,13 +35,15 @@ export default function LinkingAccountModal({ onClose, direction, tournamentId, const meQuery = useMeTournamentQuery({ variables: { - inTournamentId: tournamentId + id: tournamentId }, onCompleted: (data) => { if (data.me) { - const already_registerd = data.me.in_tournament; - if (already_registerd) + const already_registerd = !!data.tournamentParticipationInfo; + if (already_registerd) { onClose?.(); + NotificationsService.info("You are already registered") + } else dispatch(replaceModal({ Modal: "RegisterTournamet_RegistrationDetails", direction: Direction.NEXT, diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx index b6e4f49..fa910a2 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx +++ b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx @@ -28,20 +28,21 @@ export default function Navigation({ data }: Props) { path: "makers", }, { - text: `Projects (${data.projects_count})`, + text: `Projects 🔒`, path: "projects", - }, - { - text: "???? 🚧", - path: "ideas", isDisabled: true, }, - { - text: "?????????? 🚧", - path: "resources", - isDisabled: true, - }, - ], [data.events_count, data.makers_count, data.projects_count]) + // { + // text: "???? 🚧", + // path: "ideas", + // isDisabled: true, + // }, + // { + // text: "?????????? 🚧", + // path: "resources", + // isDisabled: true, + // }, + ], [data.events_count, data.makers_count]) return (
diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx index 9778532..366705b 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx +++ b/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx @@ -44,7 +44,7 @@ export default function TournamentDetailsPage() {
} /> - m.avatar)} isRegistered={!!tournaemntQuery.data.me?.in_tournament} />} /> + m.user.avatar)} isRegistered={!!tournaemntQuery.data.tournamentParticipationInfo} />} /> } /> } /> } /> diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/meTournament.graphql b/src/features/Tournaments/pages/TournamentDetailsPage/meTournament.graphql index c7615c3..aacee27 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/meTournament.graphql +++ b/src/features/Tournaments/pages/TournamentDetailsPage/meTournament.graphql @@ -1,11 +1,16 @@ -query MeTournament($inTournamentId: Int!) { +query MeTournament($id: Int!) { + tournamentParticipationInfo(tournamentId: $id) { + createdAt + hacking_status + } me { id name avatar jobTitle - - in_tournament(id: $inTournamentId) + twitter + linkedin + github ...UserRolesSkills } diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/tournamentDetails.graphql b/src/features/Tournaments/pages/TournamentDetailsPage/tournamentDetails.graphql index b1c4b29..750a881 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/tournamentDetails.graphql +++ b/src/features/Tournaments/pages/TournamentDetailsPage/tournamentDetails.graphql @@ -44,18 +44,25 @@ query GetTournamentById($id: Int!) { getMakersInTournament(tournamentId: $id, take: 4) { makers { - id - avatar + user { + id + avatar + } } } + tournamentParticipationInfo(tournamentId: $id) { + createdAt + hacking_status + } me { id name avatar jobTitle - - in_tournament(id: $id) + twitter + linkedin + github ...UserRolesSkills } diff --git a/src/graphql/index.tsx b/src/graphql/index.tsx index f848154..caced71 100644 --- a/src/graphql/index.tsx +++ b/src/graphql/index.tsx @@ -279,6 +279,12 @@ export enum Post_Type { Story = 'Story' } +export type ParticipationInfo = { + __typename?: 'ParticipationInfo'; + createdAt: Scalars['Date']; + hacking_status: TournamentMakerHackingStatusEnum; +}; + export type Post = Bounty | Question | Story; export type PostBase = { @@ -366,6 +372,7 @@ export type Query = { projectsByCategory: Array; searchProjects: Array; similarMakers: Array; + tournamentParticipationInfo: Maybe; }; @@ -473,6 +480,11 @@ export type QuerySimilarMakersArgs = { id: Scalars['Int']; }; + +export type QueryTournamentParticipationInfoArgs = { + tournamentId: Scalars['Int']; +}; + export type Question = PostBase & { __typename?: 'Question'; author: Author; @@ -600,7 +612,14 @@ export type TournamentMakersResponse = { __typename?: 'TournamentMakersResponse'; hasNext: Maybe; hasPrev: Maybe; - makers: Array; + makers: Array; +}; + +export type TournamentParticipant = { + __typename?: 'TournamentParticipant'; + hacking_status: TournamentMakerHackingStatusEnum; + is_registered: Maybe; + user: User; }; export type TournamentPrize = { @@ -875,7 +894,7 @@ export type GetMakersInTournamentQueryVariables = Exact<{ }>; -export type GetMakersInTournamentQuery = { __typename?: 'Query', getMakersInTournament: { __typename?: 'TournamentMakersResponse', hasNext: boolean | null, hasPrev: boolean | null, makers: Array<{ __typename?: 'User', id: number, name: string, avatar: string, jobTitle: string | null, email: string | null, twitter: string | null, linkedin: string | null, github: string | null, roles: Array<{ __typename?: 'MakerRole', id: number, icon: string, title: string }>, skills: Array<{ __typename?: 'MakerSkill', id: number, title: string }> }> } }; +export type GetMakersInTournamentQuery = { __typename?: 'Query', getMakersInTournament: { __typename?: 'TournamentMakersResponse', hasNext: boolean | null, hasPrev: boolean | null, makers: Array<{ __typename?: 'TournamentParticipant', hacking_status: TournamentMakerHackingStatusEnum, user: { __typename?: 'User', id: number, name: string, avatar: string, jobTitle: string | null, twitter: string | null, linkedin: string | null, github: string | null, roles: Array<{ __typename?: 'MakerRole', id: number, icon: string, title: string }>, skills: Array<{ __typename?: 'MakerSkill', id: number, title: string }> } }> } }; export type GetProjectsInTournamentQueryVariables = Exact<{ tournamentId: Scalars['Int']; @@ -897,18 +916,18 @@ export type RegisterInTournamentMutationVariables = Exact<{ export type RegisterInTournamentMutation = { __typename?: 'Mutation', registerInTournament: { __typename?: 'User', id: number, in_tournament: boolean } | null }; export type MeTournamentQueryVariables = Exact<{ - inTournamentId: Scalars['Int']; + id: Scalars['Int']; }>; -export type MeTournamentQuery = { __typename?: 'Query', me: { __typename?: 'MyProfile', id: number, name: string, avatar: string, jobTitle: string | null, in_tournament: boolean, skills: Array<{ __typename?: 'MakerSkill', id: number, title: string }>, roles: Array<{ __typename?: 'MakerRole', id: number, title: string, icon: string, level: RoleLevelEnum }> } | null }; +export type MeTournamentQuery = { __typename?: 'Query', tournamentParticipationInfo: { __typename?: 'ParticipationInfo', createdAt: any, hacking_status: TournamentMakerHackingStatusEnum } | null, me: { __typename?: 'MyProfile', id: number, name: string, avatar: string, jobTitle: string | null, twitter: string | null, linkedin: string | null, github: string | null, skills: Array<{ __typename?: 'MakerSkill', id: number, title: string }>, roles: Array<{ __typename?: 'MakerRole', id: number, title: string, icon: string, level: RoleLevelEnum }> } | null }; export type GetTournamentByIdQueryVariables = Exact<{ id: Scalars['Int']; }>; -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, company: string, avatar: string }>, events: Array<{ __typename?: 'TournamentEvent', id: number, title: string, image: string, description: string, starts_at: any, ends_at: any, location: string, website: string, type: TournamentEventTypeEnum, links: Array }>, faqs: Array<{ __typename?: 'TournamentFAQ', question: string, answer: string }> }, getMakersInTournament: { __typename?: 'TournamentMakersResponse', makers: Array<{ __typename?: 'User', id: number, avatar: string }> }, me: { __typename?: 'MyProfile', id: number, name: string, avatar: string, jobTitle: string | null, in_tournament: boolean, skills: Array<{ __typename?: 'MakerSkill', id: number, title: string }>, roles: Array<{ __typename?: 'MakerRole', id: number, title: string, icon: string, level: RoleLevelEnum }> } | null }; +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, company: string, avatar: string }>, events: Array<{ __typename?: 'TournamentEvent', id: number, title: string, image: string, description: string, starts_at: any, ends_at: any, location: string, website: string, type: TournamentEventTypeEnum, links: Array }>, faqs: Array<{ __typename?: 'TournamentFAQ', question: string, answer: string }> }, getMakersInTournament: { __typename?: 'TournamentMakersResponse', makers: Array<{ __typename?: 'TournamentParticipant', user: { __typename?: 'User', id: number, avatar: string } }> }, tournamentParticipationInfo: { __typename?: 'ParticipationInfo', createdAt: any, hacking_status: TournamentMakerHackingStatusEnum } | null, me: { __typename?: 'MyProfile', id: number, name: string, avatar: string, jobTitle: string | null, twitter: string | null, linkedin: string | null, github: string | null, skills: Array<{ __typename?: 'MakerSkill', id: number, title: string }>, roles: Array<{ __typename?: 'MakerRole', id: number, title: string, icon: string, level: RoleLevelEnum }> } | null }; export type VoteMutationVariables = Exact<{ itemType: Vote_Item_Type; @@ -2281,22 +2300,24 @@ export const GetMakersInTournamentDocument = gql` hasNext hasPrev makers { - id - name - avatar - jobTitle - email - twitter - linkedin - github - roles { + hacking_status + user { id - icon - title - } - skills { - id - title + name + avatar + jobTitle + twitter + linkedin + github + roles { + id + icon + title + } + skills { + id + title + } } } } @@ -2433,13 +2454,19 @@ export type RegisterInTournamentMutationHookResult = ReturnType; export type RegisterInTournamentMutationOptions = Apollo.BaseMutationOptions; export const MeTournamentDocument = gql` - query MeTournament($inTournamentId: Int!) { + query MeTournament($id: Int!) { + tournamentParticipationInfo(tournamentId: $id) { + createdAt + hacking_status + } me { id name avatar jobTitle - in_tournament(id: $inTournamentId) + twitter + linkedin + github ...UserRolesSkills } } @@ -2457,7 +2484,7 @@ export const MeTournamentDocument = gql` * @example * const { data, loading, error } = useMeTournamentQuery({ * variables: { - * inTournamentId: // value for 'inTournamentId' + * id: // value for 'id' * }, * }); */ @@ -2516,16 +2543,24 @@ export const GetTournamentByIdDocument = gql` } getMakersInTournament(tournamentId: $id, take: 4) { makers { - id - avatar + user { + id + avatar + } } } + tournamentParticipationInfo(tournamentId: $id) { + createdAt + hacking_status + } me { id name avatar jobTitle - in_tournament(id: $id) + twitter + linkedin + github ...UserRolesSkills } } diff --git a/src/mocks/handlers.ts b/src/mocks/handlers.ts index b6a8bc4..dc1fe80 100644 --- a/src/mocks/handlers.ts +++ b/src/mocks/handlers.ts @@ -37,6 +37,7 @@ import { GetMakersInTournamentQuery, GetMakersInTournamentQueryVariables, MeTournamentQuery, + TournamentMakerHackingStatusEnum, } from 'src/graphql' const delay = (ms = 1000) => new Promise((res) => setTimeout(res, ms + Math.random() * 1000)) @@ -284,7 +285,12 @@ export const handlers = [ ctx.data({ getTournamentById: getTournamentById(12), getMakersInTournament: getMakersInTournament({ roleId: null, search: null, skip: null, take: 4, tournamentId: 12 }), - me: { ...me() } + me: { ...me() }, + tournamentParticipationInfo: { + hacking_status: TournamentMakerHackingStatusEnum.OpenToConnect, + createdAt: new Date() + } + }) ) }), @@ -294,7 +300,11 @@ export const handlers = [ return res( ctx.data({ - me: { ...me() } + me: { ...me() }, + tournamentParticipationInfo: { + hacking_status: TournamentMakerHackingStatusEnum.OpenToConnect, + createdAt: new Date() + } }) ) }), @@ -304,7 +314,7 @@ export const handlers = [ return res( ctx.data({ - getMakersInTournament: getMakersInTournament(req.variables) + getMakersInTournament: getMakersInTournament(req.variables), }) ) }), diff --git a/src/mocks/resolvers.ts b/src/mocks/resolvers.ts index 74ffc2d..6045106 100644 --- a/src/mocks/resolvers.ts +++ b/src/mocks/resolvers.ts @@ -1,5 +1,5 @@ import { MOCK_DATA } from "./data"; -import { GetMakersInTournamentQueryVariables, MyProfile, Query, QueryGetFeedArgs, QueryGetPostByIdArgs, User } from 'src/graphql' +import { GetMakersInTournamentQueryVariables, MyProfile, Query, QueryGetFeedArgs, QueryGetPostByIdArgs, TournamentMakerHackingStatusEnum, User } from 'src/graphql' import { Chance } from "chance"; import { tags } from "./data/tags"; import { hackathons } from "./data/hackathon"; @@ -114,7 +114,8 @@ export function getMakersInTournament(vars: GetMakersInTournamentQueryVariables) if (!vars.roleId) return true; return u.roles.some(r => r.id === vars.roleId) }) - .slice(offsetStart, offsetEnd + 1) as User[] + .slice(offsetStart, offsetEnd + 1) + .map(u => ({ user: u as User, hacking_status: TournamentMakerHackingStatusEnum.OpenToConnect })) ; return { From 329ecf3b609ee3d7b6d13ffcff74a4d654c7e326 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Fri, 9 Sep 2022 12:14:56 +0300 Subject: [PATCH 35/53] feat: update my hacking_status, filter by hacking status, allow optional fields in inputArgs --- api/functions/graphql/nexus-typegen.ts | 14 +++ api/functions/graphql/schema.graphql | 9 +- api/functions/graphql/types/tournament.js | 75 ++++++++++++++- codegen.yml | 6 +- .../pages/MakersPage/MakerCard/MakerCard.tsx | 37 +++++++- .../ParticipantsSection/MakersList.tsx | 5 +- .../pages/MakersPage/tournamentMakers.graphql | 13 +++ src/graphql/index.tsx | 91 ++++++++++++++++--- src/mocks/handlers.ts | 2 +- 9 files changed, 228 insertions(+), 24 deletions(-) diff --git a/api/functions/graphql/nexus-typegen.ts b/api/functions/graphql/nexus-typegen.ts index 3f35201..364937a 100644 --- a/api/functions/graphql/nexus-typegen.ts +++ b/api/functions/graphql/nexus-typegen.ts @@ -64,6 +64,10 @@ export interface NexusGenInputs { tags: string[]; // [String!]! title: string; // String! } + UpdateTournamentRegistrationInput: { // input type + email?: string | null; // String + hacking_status?: NexusGenEnums['TournamentMakerHackingStatusEnum'] | null; // TournamentMakerHackingStatusEnum + } UserKeyInputType: { // input type key: string; // String! name: string; // String! @@ -194,6 +198,7 @@ export interface NexusGenObjects { } ParticipationInfo: { // root type createdAt: NexusGenScalars['Date']; // Date! + email: string; // String! hacking_status: NexusGenEnums['TournamentMakerHackingStatusEnum']; // TournamentMakerHackingStatusEnum! } PostComment: { // root type @@ -445,6 +450,7 @@ export interface NexusGenFieldTypes { registerInTournament: NexusGenRootTypes['User'] | null; // User updateProfileDetails: NexusGenRootTypes['MyProfile'] | null; // MyProfile updateProfileRoles: NexusGenRootTypes['MyProfile'] | null; // MyProfile + updateTournamentRegistration: NexusGenRootTypes['ParticipationInfo'] | null; // ParticipationInfo updateUserPreferences: NexusGenRootTypes['MyProfile']; // MyProfile! vote: NexusGenRootTypes['Vote']; // Vote! } @@ -475,6 +481,7 @@ export interface NexusGenFieldTypes { } ParticipationInfo: { // field return type createdAt: NexusGenScalars['Date']; // Date! + email: string; // String! hacking_status: NexusGenEnums['TournamentMakerHackingStatusEnum']; // TournamentMakerHackingStatusEnum! } PostComment: { // field return type @@ -798,6 +805,7 @@ export interface NexusGenFieldTypeNames { registerInTournament: 'User' updateProfileDetails: 'MyProfile' updateProfileRoles: 'MyProfile' + updateTournamentRegistration: 'ParticipationInfo' updateUserPreferences: 'MyProfile' vote: 'Vote' } @@ -828,6 +836,7 @@ export interface NexusGenFieldTypeNames { } ParticipationInfo: { // field return type name createdAt: 'Date' + email: 'String' hacking_status: 'TournamentMakerHackingStatusEnum' } PostComment: { // field return type name @@ -1076,6 +1085,10 @@ export interface NexusGenArgTypes { updateProfileRoles: { // args data?: NexusGenInputs['ProfileRolesInput'] | null; // ProfileRolesInput } + updateTournamentRegistration: { // args + data?: NexusGenInputs['UpdateTournamentRegistrationInput'] | null; // UpdateTournamentRegistrationInput + tournament_id: number; // Int! + } updateUserPreferences: { // args userKeys?: NexusGenInputs['UserKeyInputType'][] | null; // [UserKeyInputType!] } @@ -1112,6 +1125,7 @@ export interface NexusGenArgTypes { project_id: number; // Int! } getMakersInTournament: { // args + openToConnect?: boolean | null; // Boolean roleId?: number | null; // Int search?: string | null; // String skip?: number | null; // Int diff --git a/api/functions/graphql/schema.graphql b/api/functions/graphql/schema.graphql index ba9a87e..8d504e7 100644 --- a/api/functions/graphql/schema.graphql +++ b/api/functions/graphql/schema.graphql @@ -152,6 +152,7 @@ type Mutation { registerInTournament(data: RegisterInTournamentInput, tournament_id: Int!): User updateProfileDetails(data: ProfileDetailsInput): MyProfile updateProfileRoles(data: ProfileRolesInput): MyProfile + updateTournamentRegistration(data: UpdateTournamentRegistrationInput, tournament_id: Int!): ParticipationInfo updateUserPreferences(userKeys: [UserKeyInputType!]): MyProfile! vote(amount_in_sat: Int!, item_id: Int!, item_type: VOTE_ITEM_TYPE!): Vote! } @@ -190,6 +191,7 @@ enum POST_TYPE { type ParticipationInfo { createdAt: Date! + email: String! hacking_status: TournamentMakerHackingStatusEnum! } @@ -261,7 +263,7 @@ type Query { getDonationsStats: DonationsStats! getFeed(skip: Int = 0, sortBy: String, tag: Int = 0, take: Int = 10): [Post!]! getLnurlDetailsForProject(project_id: Int!): LnurlDetails! - getMakersInTournament(roleId: Int, search: String, skip: Int = 0, take: Int = 10, tournamentId: Int!): TournamentMakersResponse! + getMakersInTournament(openToConnect: Boolean, roleId: Int, search: String, skip: Int = 0, take: Int = 10, tournamentId: Int!): TournamentMakersResponse! getMyDrafts(type: POST_TYPE!): [Post!]! getPostById(id: Int!, type: POST_TYPE!): Post! getProject(id: Int!): Project! @@ -420,6 +422,11 @@ type TournamentProjectsResponse { projects: [Project!]! } +input UpdateTournamentRegistrationInput { + email: String + hacking_status: TournamentMakerHackingStatusEnum +} + type User implements BaseUser { avatar: String! bio: String diff --git a/api/functions/graphql/types/tournament.js b/api/functions/graphql/types/tournament.js index 121cbb3..f42d335 100644 --- a/api/functions/graphql/types/tournament.js +++ b/api/functions/graphql/types/tournament.js @@ -6,10 +6,11 @@ const { nonNull, enumType, inputObjectType, + booleanArg, } = require('nexus'); const { getUserByPubKey } = require('../../../auth/utils/helperFuncs'); const { prisma } = require('../../../prisma'); -const { paginationArgs } = require('./helpers'); +const { paginationArgs, removeNulls } = require('./helpers'); @@ -196,6 +197,7 @@ const ParticipationInfo = objectType({ name: "ParticipationInfo", definition(t) { t.nonNull.date('createdAt') + t.nonNull.string('email') t.nonNull.field('hacking_status', { type: TournamentMakerHackingStatusEnum }); } @@ -237,6 +239,7 @@ const getMakersInTournament = extendType({ ...paginationArgs({ take: 10 }), search: stringArg(), roleId: intArg(), + openToConnect: booleanArg() }, async resolve(_, args, ctx) { @@ -271,12 +274,33 @@ const getMakersInTournament = extendType({ } }) + if (args.openToConnect) filters.push({ + OR: [ + { + github: { + not: null + } + }, + { + twitter: { + not: null + } + }, + { + linkedin: { + not: null + } + }, + ] + }) + if (user?.id) filters.push({ id: { not: user.id } }) + const makers = (await prisma.tournamentParticipant.findMany({ where: { tournament_id: args.tournamentId, @@ -284,6 +308,9 @@ const getMakersInTournament = extendType({ user: { AND: filters } + }), + ...(args.openToConnect && { + hacking_status: TournamentMakerHackingStatusEnum.value.members.OpenToConnect }) }, orderBy: { @@ -433,6 +460,50 @@ const registerInTournament = extendType({ }, }) +const UpdateTournamentRegistrationInput = inputObjectType({ + name: 'UpdateTournamentRegistrationInput', + definition(t) { + t.string('email') + t.field('hacking_status', { type: TournamentMakerHackingStatusEnum }) + } +}) + +const updateTournamentRegistration = extendType({ + type: 'Mutation', + definition(t) { + t.field('updateTournamentRegistration', { + type: ParticipationInfo, + args: { + data: UpdateTournamentRegistrationInput, + tournament_id: nonNull(intArg()) + }, + async resolve(_root, { tournament_id, data: { email, hacking_status } }, ctx) { + const user = await getUserByPubKey(ctx.userPubKey); + + // Do some validation + // if (!user) + // throw new Error("You have to login"); + + + // Email verification here: + // .... + // .... + + return prisma.tournamentParticipant.update({ + where: { + tournament_id_user_id: { tournament_id, user_id: user.id } + }, + data: removeNulls({ + email, + hacking_status + }), + }); + } + }) + }, +}) + + module.exports = { // Types Tournament, @@ -448,5 +519,5 @@ module.exports = { // Mutations registerInTournament, - + updateTournamentRegistration, } diff --git a/codegen.yml b/codegen.yml index 28cd2dd..b2c805d 100644 --- a/codegen.yml +++ b/codegen.yml @@ -9,4 +9,8 @@ generates: - "typescript-react-apollo" config: withHooks: true - avoidOptionals: true + avoidOptionals: + field: true + inputValue: false + object: true + defaultValue: true diff --git a/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx b/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx index 697418d..0c2f820 100644 --- a/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx +++ b/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx @@ -1,5 +1,5 @@ import Button from "src/Components/Button/Button" -import { GetMakersInTournamentQuery, TournamentMakerHackingStatusEnum, } from "src/graphql"; +import { GetMakersInTournamentQuery, TournamentMakerHackingStatusEnum, useUpdateTournamentRegistrationMutation } from "src/graphql"; import { useAppDispatch, } from "src/utils/hooks"; import Card from 'src/Components/Card/Card'; import Avatar from 'src/features/Profiles/Components/Avatar/Avatar'; @@ -8,6 +8,8 @@ import { createRoute } from 'src/utils/routing'; import { openModal } from "src/redux/features/modals.slice"; import InfoCard from "src/Components/InfoCard/InfoCard"; import { Link } from "react-router-dom"; +import { useState } from "react"; +import { NotificationsService } from "src/services"; type MakerType = GetMakersInTournamentQuery['getMakersInTournament']['makers'][number] @@ -19,8 +21,10 @@ interface Props { export default function MakerCard({ maker, isMe }: Props) { const dispatch = useAppDispatch(); + const [hackingStatus, setHackingStatus] = useState(maker.hacking_status) const contactLinksAvailable = maker.user.github || maker.user.linkedin || maker.user.twitter; + const [udpateInfo, updateInfoMutation] = useUpdateTournamentRegistrationMutation() let actionBtn = <> @@ -32,7 +36,23 @@ export default function MakerCard({ maker, isMe }: Props) { actionBtn = - const missingFields = isMe && getMissingFields(maker) + const missingFields = isMe && getMissingFields(maker); + + const changeHacktingStatus = (value: typeof hackingStatus) => { + setHackingStatus(value); + udpateInfo({ + variables: { + tournamentId: 12, + data: { + hacking_status: value + } + }, + }) + .catch(() => { + setHackingStatus(maker.hacking_status) + NotificationsService.error("A network error happened") + }) + } return ( @@ -76,6 +96,19 @@ export default function MakerCard({ maker, isMe }: Props) {

No skills added

}
+ {isMe &&
+

🚦 Hacking status

+
+ + +
+
}
{actionBtn}
{missingFields && 👾 Complete your profile: make it easy for other makers to find you by adding your {missingFields}. You can add this information in your profile’s Settings ⚙️ menu. diff --git a/src/features/Tournaments/pages/MakersPage/ParticipantsSection/MakersList.tsx b/src/features/Tournaments/pages/MakersPage/ParticipantsSection/MakersList.tsx index b40239c..8b7ee99 100644 --- a/src/features/Tournaments/pages/MakersPage/ParticipantsSection/MakersList.tsx +++ b/src/features/Tournaments/pages/MakersPage/ParticipantsSection/MakersList.tsx @@ -27,6 +27,7 @@ export default function MakersList(props: Props) { search: props.searchFilter ?? null, skip: ITEMS_PER_PAGE * page, take: ITEMS_PER_PAGE, + openToConnect: props.onlyLookingToTeam ?? null }); @@ -40,8 +41,8 @@ export default function MakersList(props: Props) { useEffect(() => { setPage(0); - setQueryFilter(f => ({ ...f, search: props.searchFilter, roleId: props.roleFilter, skip: 0 })) - }, [props.roleFilter, props.searchFilter]); + setQueryFilter(f => ({ ...f, search: props.searchFilter, roleId: props.roleFilter, openToConnect: props.onlyLookingToTeam ?? null, skip: 0 })) + }, [props.onlyLookingToTeam, props.roleFilter, props.searchFilter]); diff --git a/src/features/Tournaments/pages/MakersPage/tournamentMakers.graphql b/src/features/Tournaments/pages/MakersPage/tournamentMakers.graphql index 08448fc..bb38302 100644 --- a/src/features/Tournaments/pages/MakersPage/tournamentMakers.graphql +++ b/src/features/Tournaments/pages/MakersPage/tournamentMakers.graphql @@ -12,6 +12,7 @@ query GetMakersInTournament( $skip: Int $search: String $roleId: Int + $openToConnect: Boolean ) { getMakersInTournament( tournamentId: $tournamentId @@ -19,6 +20,7 @@ query GetMakersInTournament( skip: $skip search: $search roleId: $roleId + openToConnect: $openToConnect ) { hasNext hasPrev @@ -83,3 +85,14 @@ query GetProjectsInTournament( } } } + +mutation UpdateTournamentRegistration( + $tournamentId: Int! + $data: UpdateTournamentRegistrationInput +) { + updateTournamentRegistration(tournament_id: $tournamentId, data: $data) { + createdAt + email + hacking_status + } +} diff --git a/src/graphql/index.tsx b/src/graphql/index.tsx index caced71..e830e51 100644 --- a/src/graphql/index.tsx +++ b/src/graphql/index.tsx @@ -182,6 +182,7 @@ export type Mutation = { registerInTournament: Maybe; updateProfileDetails: Maybe; updateProfileRoles: Maybe; + updateTournamentRegistration: Maybe; updateUserPreferences: MyProfile; vote: Vote; }; @@ -230,6 +231,12 @@ export type MutationUpdateProfileRolesArgs = { }; +export type MutationUpdateTournamentRegistrationArgs = { + data: InputMaybe; + tournament_id: Scalars['Int']; +}; + + export type MutationUpdateUserPreferencesArgs = { userKeys: InputMaybe>; }; @@ -282,6 +289,7 @@ export enum Post_Type { export type ParticipationInfo = { __typename?: 'ParticipationInfo'; createdAt: Scalars['Date']; + email: Scalars['String']; hacking_status: TournamentMakerHackingStatusEnum; }; @@ -309,17 +317,17 @@ export type PostComment = { }; export type ProfileDetailsInput = { - avatar: InputMaybe; - bio: InputMaybe; - email: InputMaybe; - github: InputMaybe; - jobTitle: InputMaybe; - lightning_address: InputMaybe; - linkedin: InputMaybe; - location: InputMaybe; - name: InputMaybe; - twitter: InputMaybe; - website: InputMaybe; + avatar?: InputMaybe; + bio?: InputMaybe; + email?: InputMaybe; + github?: InputMaybe; + jobTitle?: InputMaybe; + lightning_address?: InputMaybe; + linkedin?: InputMaybe; + location?: InputMaybe; + name?: InputMaybe; + twitter?: InputMaybe; + website?: InputMaybe; }; export type ProfileRolesInput = { @@ -407,6 +415,7 @@ export type QueryGetLnurlDetailsForProjectArgs = { export type QueryGetMakersInTournamentArgs = { + openToConnect: InputMaybe; roleId: InputMaybe; search: InputMaybe; skip?: InputMaybe; @@ -533,9 +542,9 @@ export type Story = PostBase & { export type StoryInputType = { body: Scalars['String']; - cover_image: InputMaybe; - id: InputMaybe; - is_published: InputMaybe; + cover_image?: InputMaybe; + id?: InputMaybe; + is_published?: InputMaybe; tags: Array; title: Scalars['String']; }; @@ -636,6 +645,11 @@ export type TournamentProjectsResponse = { projects: Array; }; +export type UpdateTournamentRegistrationInput = { + email?: InputMaybe; + hacking_status?: InputMaybe; +}; + export type User = BaseUser & { __typename?: 'User'; avatar: Scalars['String']; @@ -891,6 +905,7 @@ export type GetMakersInTournamentQueryVariables = Exact<{ skip: InputMaybe; search: InputMaybe; roleId: InputMaybe; + openToConnect: InputMaybe; }>; @@ -907,6 +922,14 @@ export type GetProjectsInTournamentQueryVariables = Exact<{ export type GetProjectsInTournamentQuery = { __typename?: 'Query', getProjectsInTournament: { __typename?: 'TournamentProjectsResponse', hasNext: boolean | null, hasPrev: boolean | null, projects: Array<{ __typename?: 'Project', id: number, title: string, description: string, thumbnail_image: string, category: { __typename?: 'Category', id: number, title: string, icon: string | null }, recruit_roles: Array<{ __typename?: 'MakerRole', id: number, title: string, icon: string, level: RoleLevelEnum }> }> } }; +export type UpdateTournamentRegistrationMutationVariables = Exact<{ + tournamentId: Scalars['Int']; + data: InputMaybe; +}>; + + +export type UpdateTournamentRegistrationMutation = { __typename?: 'Mutation', updateTournamentRegistration: { __typename?: 'ParticipationInfo', createdAt: any, email: string, hacking_status: TournamentMakerHackingStatusEnum } | null }; + export type RegisterInTournamentMutationVariables = Exact<{ tournamentId: Scalars['Int']; data: InputMaybe; @@ -2289,13 +2312,14 @@ export type GetAllRolesQueryHookResult = ReturnType; export type GetAllRolesLazyQueryHookResult = ReturnType; export type GetAllRolesQueryResult = Apollo.QueryResult; export const GetMakersInTournamentDocument = gql` - query GetMakersInTournament($tournamentId: Int!, $take: Int, $skip: Int, $search: String, $roleId: Int) { + query GetMakersInTournament($tournamentId: Int!, $take: Int, $skip: Int, $search: String, $roleId: Int, $openToConnect: Boolean) { getMakersInTournament( tournamentId: $tournamentId take: $take skip: $skip search: $search roleId: $roleId + openToConnect: $openToConnect ) { hasNext hasPrev @@ -2341,6 +2365,7 @@ export const GetMakersInTournamentDocument = gql` * skip: // value for 'skip' * search: // value for 'search' * roleId: // value for 'roleId' + * openToConnect: // value for 'openToConnect' * }, * }); */ @@ -2418,6 +2443,42 @@ export function useGetProjectsInTournamentLazyQuery(baseOptions?: Apollo.LazyQue export type GetProjectsInTournamentQueryHookResult = ReturnType; export type GetProjectsInTournamentLazyQueryHookResult = ReturnType; export type GetProjectsInTournamentQueryResult = Apollo.QueryResult; +export const UpdateTournamentRegistrationDocument = gql` + mutation UpdateTournamentRegistration($tournamentId: Int!, $data: UpdateTournamentRegistrationInput) { + updateTournamentRegistration(tournament_id: $tournamentId, data: $data) { + createdAt + email + hacking_status + } +} + `; +export type UpdateTournamentRegistrationMutationFn = Apollo.MutationFunction; + +/** + * __useUpdateTournamentRegistrationMutation__ + * + * To run a mutation, you first call `useUpdateTournamentRegistrationMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useUpdateTournamentRegistrationMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [updateTournamentRegistrationMutation, { data, loading, error }] = useUpdateTournamentRegistrationMutation({ + * variables: { + * tournamentId: // value for 'tournamentId' + * data: // value for 'data' + * }, + * }); + */ +export function useUpdateTournamentRegistrationMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(UpdateTournamentRegistrationDocument, options); + } +export type UpdateTournamentRegistrationMutationHookResult = ReturnType; +export type UpdateTournamentRegistrationMutationResult = Apollo.MutationResult; +export type UpdateTournamentRegistrationMutationOptions = Apollo.BaseMutationOptions; export const RegisterInTournamentDocument = gql` mutation RegisterInTournament($tournamentId: Int!, $data: RegisterInTournamentInput) { registerInTournament(tournament_id: $tournamentId, data: $data) { diff --git a/src/mocks/handlers.ts b/src/mocks/handlers.ts index dc1fe80..ce88c2b 100644 --- a/src/mocks/handlers.ts +++ b/src/mocks/handlers.ts @@ -284,7 +284,7 @@ export const handlers = [ return res( ctx.data({ getTournamentById: getTournamentById(12), - getMakersInTournament: getMakersInTournament({ roleId: null, search: null, skip: null, take: 4, tournamentId: 12 }), + getMakersInTournament: getMakersInTournament({ roleId: null, search: null, skip: null, take: 4, tournamentId: 12, openToConnect: null }), me: { ...me() }, tournamentParticipationInfo: { hacking_status: TournamentMakerHackingStatusEnum.OpenToConnect, From e1a2e462769afe11f579f724b9dd413869f3087e Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Fri, 9 Sep 2022 20:37:14 +0300 Subject: [PATCH 36/53] feat: extract tournament details to context provider --- .../pages/EventsPage/EventsPage.tsx | 12 ++--- .../pages/MakersPage/MakerCard/MakerCard.tsx | 6 ++- .../pages/MakersPage/MakersPage.tsx | 13 +++-- .../pages/OverviewPage/OverviewPage.tsx | 29 +++++------ .../pages/ProjectsPage/ProjectsPage.tsx | 11 ++--- .../TournamentDetailsPage/Header/Header.tsx | 44 ++++++++--------- .../Navigation/Navigation.tsx | 15 +++--- .../TournamentDetailsContext.tsx | 46 ++++++++++++++++++ .../TournamentDetailsPage.tsx | 48 +++++++------------ 9 files changed, 122 insertions(+), 102 deletions(-) create mode 100644 src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsContext.tsx diff --git a/src/features/Tournaments/pages/EventsPage/EventsPage.tsx b/src/features/Tournaments/pages/EventsPage/EventsPage.tsx index 66cfcb7..c721bd4 100644 --- a/src/features/Tournaments/pages/EventsPage/EventsPage.tsx +++ b/src/features/Tournaments/pages/EventsPage/EventsPage.tsx @@ -1,18 +1,14 @@ import { useState } from 'react' -import { Tournament, TournamentEventTypeEnum } from 'src/graphql' +import { TournamentEventTypeEnum } from 'src/graphql' +import { useTournament } from '../TournamentDetailsPage/TournamentDetailsContext'; import EventCard from './EventCard/EventCard'; import EventsFilters from './EventsFilters/EventsFilters'; -interface Props { - data: Pick -} - -export default function EventsPage({ data: { events, events_count } }: Props) { +export default function EventsPage() { const [searchFilter, setSearchFilter] = useState("") const [eventFilter, setEventFilter] = useState(null) + const { tournamentDetails: { events, events_count } } = useTournament() return (
diff --git a/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx b/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx index 0c2f820..f07737e 100644 --- a/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx +++ b/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx @@ -10,6 +10,7 @@ import InfoCard from "src/Components/InfoCard/InfoCard"; import { Link } from "react-router-dom"; import { useState } from "react"; import { NotificationsService } from "src/services"; +import { useTournament } from "../../TournamentDetailsPage/TournamentDetailsContext"; type MakerType = GetMakersInTournamentQuery['getMakersInTournament']['makers'][number] @@ -23,6 +24,9 @@ export default function MakerCard({ maker, isMe }: Props) { const dispatch = useAppDispatch(); const [hackingStatus, setHackingStatus] = useState(maker.hacking_status) + const { tournamentDetails: { id: tournamentId } } = useTournament() + + const contactLinksAvailable = maker.user.github || maker.user.linkedin || maker.user.twitter; const [udpateInfo, updateInfoMutation] = useUpdateTournamentRegistrationMutation() @@ -42,7 +46,7 @@ export default function MakerCard({ maker, isMe }: Props) { setHackingStatus(value); udpateInfo({ variables: { - tournamentId: 12, + tournamentId, data: { hacking_status: value } diff --git a/src/features/Tournaments/pages/MakersPage/MakersPage.tsx b/src/features/Tournaments/pages/MakersPage/MakersPage.tsx index 4c1b90a..ebdf5d4 100644 --- a/src/features/Tournaments/pages/MakersPage/MakersPage.tsx +++ b/src/features/Tournaments/pages/MakersPage/MakersPage.tsx @@ -1,18 +1,17 @@ -import { Tournament, useMeTournamentQuery, User, } from 'src/graphql' +import { useMeTournamentQuery, User, } from 'src/graphql' +import { useTournament } from '../TournamentDetailsPage/TournamentDetailsContext'; import MakerCard from './MakerCard/MakerCard'; import MakerCardSkeleton from './MakerCard/MakerCard.Skeleton'; import ParticipantsSection from './ParticipantsSection/ParticipantsSection'; -interface Props { - data: Pick -} -export default function MakersPage({ data: { id } }: Props) { +export default function MakersPage() { + + const { tournamentDetails: { id } } = useTournament() const query = useMeTournamentQuery({ - variables: { id: id } + variables: { id } }); return ( diff --git a/src/features/Tournaments/pages/OverviewPage/OverviewPage.tsx b/src/features/Tournaments/pages/OverviewPage/OverviewPage.tsx index 3893659..8a821d8 100644 --- a/src/features/Tournaments/pages/OverviewPage/OverviewPage.tsx +++ b/src/features/Tournaments/pages/OverviewPage/OverviewPage.tsx @@ -2,40 +2,33 @@ import DOMPurify from 'dompurify' import { marked } from 'marked' import Card from 'src/Components/Card/Card' import { Tournament } from 'src/graphql' +import { useTournament } from '../TournamentDetailsPage/TournamentDetailsContext' import FAQsSection from './FAQsSection/FAQsSection' import JudgesSection from './JudgesSection/JudgesSection' import PrizesSection from './PrizesSection/PrizesSection' import RegisterCard from './RegisterCard/RegisterCard' -interface Props { - data: Pick - avatars: string[] - isRegistered: boolean; -} -export default function OverviewPage({ data, avatars, isRegistered }: Props) { + +export default function OverviewPage() { + + const { tournamentDetails, makers, myParticipationInfo } = useTournament() + return (
- + m.user.avatar)} isRegistered={!!myParticipationInfo} />
- - - + + +
) } diff --git a/src/features/Tournaments/pages/ProjectsPage/ProjectsPage.tsx b/src/features/Tournaments/pages/ProjectsPage/ProjectsPage.tsx index 0e7b6b1..4aa109b 100644 --- a/src/features/Tournaments/pages/ProjectsPage/ProjectsPage.tsx +++ b/src/features/Tournaments/pages/ProjectsPage/ProjectsPage.tsx @@ -1,18 +1,17 @@ import { useDebouncedState } from '@react-hookz/web'; import { useState } from 'react' import { FiSearch } from 'react-icons/fi'; -import { Tournament, useGetProjectsInTournamentQuery } from 'src/graphql' +import { useGetProjectsInTournamentQuery } from 'src/graphql' +import { useTournament } from '../TournamentDetailsPage/TournamentDetailsContext'; import ProjectCard from './ProjectCard/ProjectCard'; import ProjectCardSkeleton from './ProjectCard/ProjectCard.Skeleton'; -interface Props { - data: Pick -} -export default function ProjectsPage({ data: { id } }: Props) { +export default function ProjectsPage() { + const { tournamentDetails: { id } } = useTournament() + const [searchFilter, setSearchFilter] = useState(""); const [debouncedsearchFilter, setDebouncedSearchFilter] = useDebouncedState("", 500); diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/Header/Header.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/Header/Header.tsx index 3a02bfb..dbc2bdf 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/Header/Header.tsx +++ b/src/features/Tournaments/pages/TournamentDetailsPage/Header/Header.tsx @@ -1,36 +1,34 @@ import dayjs from 'dayjs' import advancedFormat from 'dayjs/plugin/advancedFormat' import React from 'react' +import { Helmet } from 'react-helmet' import { IoLocationOutline } from 'react-icons/io5' -import { Tournament } from 'src/graphql' -import Navigation from '../Navigation/Navigation' +import { useTournament } from '../TournamentDetailsContext' dayjs.extend(advancedFormat) -interface Props { - data: Pick -} -export default function Header({ data }: Props) { + +export default function Header() { + const { tournamentDetails } = useTournament() return ( -
- -
-
- -
-

TOURNAMENT 🏆

-

{data.title}

-

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

+ <> + + {tournamentDetails.title} Tournament + +
+ +
+
+ +
+

TOURNAMENT 🏆

+

{tournamentDetails.title}

+

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

-

{data.location}

+

{tournamentDetails.location}

+
-
+ ) } diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx index fa910a2..9df9f4e 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx +++ b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx @@ -1,30 +1,29 @@ import { useMemo } from 'react' import { NavLink } from 'react-router-dom' -import { Tournament } from 'src/graphql' import { useCarousel } from 'src/utils/hooks' +import { useTournament } from '../TournamentDetailsContext' -interface Props { - data: Pick -} -export default function Navigation({ data }: Props) { +export default function Navigation() { const { viewportRef, } = useCarousel({ align: 'start', slidesToScroll: 2, containScroll: "trimSnaps", }) + const { tournamentDetails } = useTournament() + const links = useMemo(() => [ { text: "Overview", path: "overview", }, { - text: `Events (${data.events_count})`, + text: `Events (${tournamentDetails.events_count})`, path: "events", }, { - text: `Makers (${data.makers_count})`, + text: `Makers (${tournamentDetails.makers_count})`, path: "makers", }, { @@ -42,7 +41,7 @@ export default function Navigation({ data }: Props) { // path: "resources", // isDisabled: true, // }, - ], [data.events_count, data.makers_count]) + ], [tournamentDetails.events_count, tournamentDetails.makers_count]) return (
diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsContext.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsContext.tsx new file mode 100644 index 0000000..63a71d2 --- /dev/null +++ b/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsContext.tsx @@ -0,0 +1,46 @@ + + +import React, { createContext, PropsWithChildren, useContext } from 'react' +import { useParams } from 'react-router-dom' +import LoadingPage from 'src/Components/LoadingPage/LoadingPage' +import NotFoundPage from 'src/features/Shared/pages/NotFoundPage/NotFoundPage' +import { GetTournamentByIdQuery, useGetTournamentByIdQuery } from 'src/graphql' + +interface ITournamentDetails { + makers: GetTournamentByIdQuery['getMakersInTournament']['makers'] + me: GetTournamentByIdQuery['me'] + tournamentDetails: GetTournamentByIdQuery['getTournamentById'] + myParticipationInfo: GetTournamentByIdQuery['tournamentParticipationInfo'] +} + +const Ctx = createContext(null!) + + +export default function TournamentDetailsContext({ children }: PropsWithChildren<{}>) { + const { id } = useParams() + + const tournaemntQuery = useGetTournamentByIdQuery({ + variables: { + id: Number(id)!, + }, + skip: !id + }) + + + + if (tournaemntQuery.loading) + return + + if (!tournaemntQuery.data?.getTournamentById) + return + + const { getMakersInTournament: makers, me, getTournamentById: tournamentDetails, tournamentParticipationInfo: myParticipationInfo } = tournaemntQuery.data + + return ( + {children} + ) +} + +export const useTournament = () => { + return useContext(Ctx) +} \ No newline at end of file diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx index 366705b..a939343 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx +++ b/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx @@ -7,49 +7,35 @@ import Navigation from './Navigation/Navigation' import EventsPage from '../EventsPage/EventsPage' import MakersPage from '../MakersPage/MakersPage' import ProjectsPage from '../ProjectsPage/ProjectsPage' -import { useGetTournamentByIdQuery, GetTournamentByIdQuery } from 'src/graphql' -import LoadingPage from 'src/Components/LoadingPage/LoadingPage' -import NotFoundPage from 'src/features/Shared/pages/NotFoundPage/NotFoundPage' +import { GetTournamentByIdQuery } from 'src/graphql' +import TournamentDetailsContext from './TournamentDetailsContext' + export type MeTournament = GetTournamentByIdQuery['me'] export default function TournamentDetailsPage() { - const { id } = useParams() - - const tournaemntQuery = useGetTournamentByIdQuery({ - variables: { - id: Number(id)!, - }, - skip: !id - }) - - if (tournaemntQuery.loading) - return - - if (!tournaemntQuery.data?.getTournamentById) - return return (
- - {tournaemntQuery.data.getTournamentById.title} Tournament - -
- -
- - } /> - m.user.avatar)} isRegistered={!!tournaemntQuery.data.tournamentParticipationInfo} />} /> - } /> - } /> - } /> - -
+ +
+ + +
+ + } /> + } /> + } /> + } /> + } /> + +
+
) } From 54874feb4cfc0d0a302bc51ca1c1363213f638dc Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Fri, 9 Sep 2022 20:52:02 +0300 Subject: [PATCH 37/53] perf: better polling optimization in login page/modal --- src/features/Auth/pages/LoginPage/LoginPage.tsx | 14 ++++++++++++-- .../LoginModal/LoginModal.tsx | 17 ++++++++++++++--- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/features/Auth/pages/LoginPage/LoginPage.tsx b/src/features/Auth/pages/LoginPage/LoginPage.tsx index 75ddbbb..a7fd37d 100644 --- a/src/features/Auth/pages/LoginPage/LoginPage.tsx +++ b/src/features/Auth/pages/LoginPage/LoginPage.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useState } from "react" +import { useCallback, useEffect, useRef, useState } from "react" import { Helmet } from "react-helmet"; import { Grid } from "react-loader-spinner"; import { useNavigate, useLocation } from "react-router-dom"; @@ -62,6 +62,7 @@ export default function LoginPage() { const location = useLocation(); const [copied, setCopied] = useState(false); + const canFetchIsLogged = useRef(true) const { loadingLnurl, data: { lnurl, session_token }, error } = useLnurlQuery(); const clipboard = useCopyToClipboard() @@ -96,18 +97,26 @@ export default function LoginPage() { const startPolling = useCallback( () => { const interval = setInterval(() => { + if (canFetchIsLogged.current === false) return; + + canFetchIsLogged.current = false; fetch(CONSTS.apiEndpoint + '/is-logged-in', { credentials: 'include', headers: { session_token } - }).then(data => data.json()) + }) + .then(data => data.json()) .then(data => { if (data.logged_in) { clearInterval(interval) refetch(); } }) + .catch() + .finally(() => { + canFetchIsLogged.current = true; + }) }, 2000); return interval; @@ -123,6 +132,7 @@ export default function LoginPage() { interval = startPolling(); return () => { + canFetchIsLogged.current = true; clearInterval(interval) } }, [lnurl, startPolling]) diff --git a/src/features/Tournaments/pages/OverviewPage/RegisterationModals/LoginModal/LoginModal.tsx b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/LoginModal/LoginModal.tsx index 88cdba8..7c68e50 100644 --- a/src/features/Tournaments/pages/OverviewPage/RegisterationModals/LoginModal/LoginModal.tsx +++ b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/LoginModal/LoginModal.tsx @@ -6,7 +6,7 @@ import { useMeTournamentQuery } from 'src/graphql'; import Button from 'src/Components/Button/Button'; import { QRCodeSVG } from 'qrcode.react'; import { Grid } from 'react-loader-spinner'; -import { useCallback, useEffect, useState } from 'react'; +import { useCallback, useEffect, useRef, useState } from 'react'; import { CONSTS } from 'src/utils'; import useCopyToClipboard from 'src/utils/hooks/useCopyToClipboard'; import { useLnurlQuery } from 'src/features/Auth/pages/LoginPage/LoginPage'; @@ -24,7 +24,9 @@ export default function LinkingAccountModal({ onClose, direction, tournamentId, const [copied, setCopied] = useState(false); const { loadingLnurl, data: { lnurl, session_token }, error } = useLnurlQuery(); - const clipboard = useCopyToClipboard() + const clipboard = useCopyToClipboard(); + + const canFetchIsLogged = useRef(true) const dispatch = useAppDispatch(); @@ -64,18 +66,26 @@ export default function LinkingAccountModal({ onClose, direction, tournamentId, const startPolling = useCallback( () => { const interval = setInterval(() => { + if (canFetchIsLogged.current === false) return; + + canFetchIsLogged.current = false; fetch(CONSTS.apiEndpoint + '/is-logged-in', { credentials: 'include', headers: { session_token } - }).then(data => data.json()) + }) + .then(data => data.json()) .then(data => { if (data.logged_in) { clearInterval(interval) refetch(); } }) + .catch() + .finally(() => { + canFetchIsLogged.current = true; + }) }, 2000); return interval; @@ -91,6 +101,7 @@ export default function LinkingAccountModal({ onClose, direction, tournamentId, interval = startPolling(); return () => { + canFetchIsLogged.current = true; clearInterval(interval) } }, [lnurl, startPolling]) From c44a9ece517a5285d2c92928ba33323c5f64ff32 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Fri, 9 Sep 2022 21:08:51 +0300 Subject: [PATCH 38/53] update: registration links, create route for tournament --- api/functions/graphql/nexus-typegen.ts | 3 +++ api/functions/graphql/schema.graphql | 1 + .../RegistrationDetails/RegistrationDetails.tsx | 5 ++++- .../RegistrationSuccess/RegistrationSuccess.tsx | 7 ++++--- src/utils/routing/routes.ts | 9 +++++++++ 5 files changed, 21 insertions(+), 4 deletions(-) diff --git a/api/functions/graphql/nexus-typegen.ts b/api/functions/graphql/nexus-typegen.ts index 364937a..200fe50 100644 --- a/api/functions/graphql/nexus-typegen.ts +++ b/api/functions/graphql/nexus-typegen.ts @@ -327,6 +327,7 @@ export interface NexusGenObjects { payment_request: string; // String! } WalletKey: { // root type + createdAt: NexusGenScalars['Date']; // Date! is_current: boolean; // Boolean! key: string; // String! name: string; // String! @@ -663,6 +664,7 @@ export interface NexusGenFieldTypes { payment_request: string; // String! } WalletKey: { // field return type + createdAt: NexusGenScalars['Date']; // Date! is_current: boolean; // Boolean! key: string; // String! name: string; // String! @@ -1018,6 +1020,7 @@ export interface NexusGenFieldTypeNames { payment_request: 'String' } WalletKey: { // field return type name + createdAt: 'Date' is_current: 'Boolean' key: 'String' name: 'String' diff --git a/api/functions/graphql/schema.graphql b/api/functions/graphql/schema.graphql index 8d504e7..c3d34e4 100644 --- a/api/functions/graphql/schema.graphql +++ b/api/functions/graphql/schema.graphql @@ -475,6 +475,7 @@ type Vote { } type WalletKey { + createdAt: Date! is_current: Boolean! key: String! name: String! diff --git a/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationDetails/RegistrationDetails.tsx b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationDetails/RegistrationDetails.tsx index 2026ee7..76e8348 100644 --- a/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationDetails/RegistrationDetails.tsx +++ b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationDetails/RegistrationDetails.tsx @@ -82,7 +82,10 @@ export default function RegistrationDetails({ onClose, direction, ...props }: Pr if (data.registerInTournament?.in_tournament) { dispatch(replaceModal({ Modal: "RegisterTournamet_RegistrationSuccess", - direction: Direction.NEXT + direction: Direction.NEXT, + props: { + tournamentId: Number(props.tournamentId) + } })) } diff --git a/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationSuccess/RegistrationSuccess.tsx b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationSuccess/RegistrationSuccess.tsx index e45f8cd..a267c32 100644 --- a/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationSuccess/RegistrationSuccess.tsx +++ b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationSuccess/RegistrationSuccess.tsx @@ -6,10 +6,11 @@ import { useAppSelector } from "src/utils/hooks"; import Button from 'src/Components/Button/Button'; import Confetti from "react-confetti"; import { Portal } from 'src/Components/Portal/Portal'; +import { createRoute } from 'src/utils/routing'; interface Props extends ModalCard { - + tournamentId: number } export default function RegistrationSuccess({ onClose, direction, ...props }: Props) { @@ -60,8 +61,8 @@ export default function RegistrationSuccess({ onClose, direction, ...props }: Pr
- - + +
diff --git a/src/utils/routing/routes.ts b/src/utils/routing/routes.ts index 500aabc..40e8f7e 100644 --- a/src/utils/routing/routes.ts +++ b/src/utils/routing/routes.ts @@ -34,6 +34,11 @@ type RouteOptions = | { type: "edit-profile", } + | { + type: "tournament", + id: string | number + tab: 'overview' | 'events' | 'makers' | 'projects' + } export function createRoute(options: RouteOptions) { @@ -63,6 +68,10 @@ export function createRoute(options: RouteOptions) { if (options.type === 'edit-profile') return '/edit-profile' + + if (options.type === 'tournament') + return `/tournaments/${options.id}/${options.tab}` + return "" } From fdab0fa0d401b52d6d22850cfaf788f2a8379bcf Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Sat, 10 Sep 2022 11:06:52 +0300 Subject: [PATCH 39/53] fix; markdown in faqs, makers filters for contacts --- api/functions/graphql/types/tournament.js | 7 +- prisma/seed/data/tournament.seed.js | 276 ++++++++---------- prisma/seed/index.js | 11 +- .../pages/ExplorePage/Header/Header.tsx | 5 +- .../OverviewPage/FAQsSection/FAQsSection.tsx | 11 +- .../RegisterCard/RegisterCard.tsx | 4 +- .../Navigation/Navigation.tsx | 2 +- src/graphql/index.tsx | 1 + src/mocks/data/users.ts | 24 +- 9 files changed, 175 insertions(+), 166 deletions(-) diff --git a/api/functions/graphql/types/tournament.js b/api/functions/graphql/types/tournament.js index f42d335..c3d1edd 100644 --- a/api/functions/graphql/types/tournament.js +++ b/api/functions/graphql/types/tournament.js @@ -278,17 +278,17 @@ const getMakersInTournament = extendType({ OR: [ { github: { - not: null + not: '' } }, { twitter: { - not: null + not: '' } }, { linkedin: { - not: null + not: '' } }, ] @@ -301,6 +301,7 @@ const getMakersInTournament = extendType({ }) + const makers = (await prisma.tournamentParticipant.findMany({ where: { tournament_id: args.tournamentId, diff --git a/prisma/seed/data/tournament.seed.js b/prisma/seed/data/tournament.seed.js index 162d613..34f7202 100644 --- a/prisma/seed/data/tournament.seed.js +++ b/prisma/seed/data/tournament.seed.js @@ -3,248 +3,228 @@ const tournament = { __typename: "Tournament", id: 12, - title: "The Long Night", - start_date: "2022-09-30T21:00:00.000Z", - end_date: "2022-10-30T22:00:00.000Z", + title: "Legends of Lightning ⚡️", + start_date: "2022-10-12T21:00:00.000Z", + end_date: "2022-11-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: + description: // this field accepts markdown `## Tournament Details -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. +BOLT🔩FUN’s maiden tournament, **Legends of Lightning** ⚡ will be an online global competition for makers to learn, connect, collaborate, and experiment with building innovative applications and tools with bitcoin and lightning. -#### Subtitle1 -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. +Spanning a 2-month period, makers can form teams, hack on projects, and show off their progress, activity, and updates as they compete for up to **$10,000 in bitcoin prizes**. +BOLT🔩FUN has partnered with a number of events, meetups, and hackathons to provide makers the opportunity to brainstorm, design, build, and accelerate their tournament projects over the course of a couple of months. At the end of the tournament, a panel of judges will access and score all submitted projects - announcing the winners in the second week of December! -#### Subtitle2 -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. `, // 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_count: 6, - makers_count: 668, - projects_count: 21, + prizes: [ + { + title: "stw3 champion", + amount: "$ 5k", + image: "https://imagedelivery.net/wyrwp3c-j0gDDUWgnE7lig/39217dcf-c900-46be-153f-169e3a1f0400/public", + }, + { + title: "2nd place", + amount: "$ 2.5k", + image: "https://imagedelivery.net/wyrwp3c-j0gDDUWgnE7lig/39cdb7c8-5fbf-49ff-32cf-fdabc3aa2d00/public", + }, + { + title: "3rd place ", + amount: "$ 1.5k", + 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: [ { - id: 12, - title: "STW3 Round Table #1", - - starts_at: "2022-09-30T21:00:00.000Z", - ends_at: "2022-10-30T22:00:00.000Z", + title: "Tab Conf 22", + starts_at: "2022-10-13T21:00:00.000Z", + ends_at: "2022-10-15T22:00:00.000Z", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", image: 'https://picsum.photos/id/10/400/800', links: [], - location: "Online", - type: 1, - website: "https://event.name" + location: "Atlanta, GA", + type: 1, /** EVent typs encoding + * + Twitter Space: 0, + Workshop: 1, + IRL Meetup: 2, + Online Meetup: 3, + */ + website: "https://2022.tabconf.com/" }, { - id: 13, - title: "STW3 Round Table #2", - starts_at: "2022-09-30T21:00:00.000Z", - ends_at: "2022-10-30T22:00:00.000Z", + title: "Bitcoin Amsterdam", + starts_at: "2022-10-12T21:00:00.000Z", + ends_at: "2022-10-14T22:00:00.000Z", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", image: 'https://picsum.photos/id/10/400/800', links: [], - location: "Online", + location: "Amsterdam, NL", type: 2, - website: "https://event.name" + website: "https://b.tc/conference/amsterdam" }, { - id: 14, - title: "STW3 Round Table #3", - starts_at: "2022-09-30T21:00:00.000Z", - ends_at: "2022-10-30T22:00:00.000Z", + title: "Lugano’s Plan ₿", + starts_at: "2022-10-28T21:00:00.000Z", + ends_at: "2022-11-04T22:00:00.000Z", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", image: 'https://picsum.photos/id/10/400/800', links: [], - location: "Online", + location: "Lugano, CH", type: 3, - website: "https://event.name" + website: "https://planb.lugano.ch/" }, { - id: 44, - title: "Lightning Login", - starts_at: "2022-09-30T21:00:00.000Z", - ends_at: "2022-10-30T22:00:00.000Z", + title: "Adopting Bitcoin 22", + starts_at: "2022-11-15T21:00:00.000Z", + ends_at: "2022-11-17T22:00:00.000Z", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", image: 'https://picsum.photos/id/10/400/800', links: [], - location: "Online", + location: "El Salvador", type: 2, - website: "https://event.name" + website: "https://adoptingbitcoin.org/2022/" }, { - id: 46, - title: "Escrow contracts", - starts_at: "2022-09-30T21:00:00.000Z", - ends_at: "2022-10-30T22:00:00.000Z", + title: "PlebTLV", + starts_at: "2022-10-23T21:00:00.000Z", + ends_at: "2022-10-23T22:00:00.000Z", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", image: 'https://picsum.photos/id/10/400/800', links: [], - location: "Online", + location: "Tel Aviv", type: 2, - website: "https://event.name" + website: "https://plebtlv.com/" }, - { - id: 444, - title: "Lsats - What & Why", - starts_at: "2022-09-30T21:00:00.000Z", - ends_at: "2022-10-30T22:00:00.000Z", + title: "Bitcoin Designathon", + starts_at: "2022-10-12T21:00:00.000Z", + ends_at: "2022-10-16T22:00:00.000Z", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", image: 'https://picsum.photos/id/10/400/800', links: [], location: "Online", type: 2, - website: "https://event.name" + website: "https://bitcoin.design" }, ], judges: [ { - name: "Ben Arc", + name: "Roy Sheinfeld", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - company: "Company", - twitter: "@arcbtc" + company: "Breez", + twitter: "@therealkingonly" }, { - name: "Ben Arc", + name: "John Carvalho", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - company: "Company", - twitter: "@arcbtc" + company: "Synonym", + twitter: "@BitcoinErrorLog" }, { - name: "Ben Arc", + name: "Nifty Nei", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - company: "Company", - twitter: "@arcbtc" + company: "Blockstream", + twitter: "@niftynei" }, { - name: "Ben Arc", + name: "Oleg Mikhalsky", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - company: "Company", - twitter: "@arcbtc" + company: "Fulgur Ventures", + twitter: "@olegmikh1" }, { - name: "Ben Arc", + name: "Alyse Kileen", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - company: "Company", - twitter: "@arcbtc" + company: "Stillmark VC", + twitter: "@AlyseKilleen" }, { - name: "Ben Arc", + name: "Johns Beharry", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - company: "Company", - twitter: "@arcbtc" + company: "Peak Shift", + twitter: "@johnsBeharry" }, { - name: "Ben Arc", + name: "Ben Price", avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - company: "Company", - twitter: "@arcbtc" - }, - { - name: "Ben Arc", - avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - company: "Company", - twitter: "@arcbtc" - }, - { - name: "Ben Arc", - avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - company: "Company", - twitter: "@arcbtc" - }, - { - name: "Ben Arc", - avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - company: "Company", - twitter: "@arcbtc" - }, - { - name: "Ben Arc", - avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - company: "Company", - twitter: "@arcbtc" - }, - { - name: "Ben Arc", - avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - company: "Company", - twitter: "@arcbtc" + company: "The Bitcoin Company", + twitter: "@abitcoinperson" }, ], faqs: [ { - question: "What is Shock the Web?", + question: "When does the tournament start and end?", answer: - `Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there. - -Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.` + `The tournament starts when team and project registrations open on 12th October. The tournament will finish with submissions closing on 30th November, 2022. Judges will then score projects and announce the winners on the 12th December.` }, { - question: "When and where will it take place?", + question: "When and how do we register our projects?", answer: - `Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there. - -Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.` + `Makers can register their projects anytime between 12th October - 30th November. If a project is added on the tournament page, it is automatically registered and it will be judged at the end of the tournament.` }, { - question: "What will we be doing?", + question: "How will projects be judged?", answer: - `Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there. + `Projects will be judged and scored on the following criteria: -Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.` +**1). 🎯 Value Proposition** +Does the project have a product market fit? Does it provide value to the bitcoin ecosystem and beyond? + +**2). 🚨 Innovation** +Is it something we've seen before or does it bring something new and exciting to bitcoin and beyond? + +**3). 👁️ Transparency (#BuildInPublic)** +Encouraging makers to #BuildInPublic. Has the project’s team been transparent throughout their product design and development journey? + +**4). ✅ Execution** +Makers should focus on attention to detail. How well has the project been executed? + +**5). 🍒 UIUX Design** +Design can separate the good from the bad. Taking into account both UI and UX, how well has the application or feature been designed? + +**6). 🔥 Je ne sais quoi** +Does the project have that extra level of pizazz or coolness? Does it raise the bar?` }, { - question: "This is my first time hacking on lightning, will there be help?", + question: "Can I submit a project that I hacked on during another event?", answer: - `Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there. - -Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.` + `Makers can submit their projects from other hackathons, events, and meetups that are registered as events within The Long Night tournament. This allows makers to take advantage of IRL + online meetups, workshops, hackerspaces, inspirational weekend events, and more.` }, { - question: "This is my first time hacking on lightning, will there be help?", + question: "Can I submit multiple projects?", answer: - `Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there. - -Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.` + `Yes, makers can submit multiple projects. However we encourage makers to focus on quality rather than quantity.` }, { - question: "How many members can I have on my team?", + question: "How can I find other makers or projects to team up with?", answer: - `Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there. - -Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.` + `You can see a list of makers who are open to connect in the tournament’s Makers tab. You can also search for projects that are looking to recruit members.` }, { - question: "Who will choose the winners?", + question: "This is my first time hacking on bitcoin, is there any help?", answer: - `Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there. - -Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.` + `We collected some awesome design, development, and project management resources here to get you up and running. You can also watch workshops and tutorials from BOLT🔩FUN’s previous ShockTheWeb⚡hackathons here.` + }, + { + question: "Not sure what to hack on?", + answer: + `Not sure where to get started? Need an idea to hack on? Not to worry, we’ve collected a list of great project ideas for you to look at here.` + }, + { + question: "How can I #BuildInPublic?", + answer: + `Using BOLT🔩FUN Stories ✍️, makers can transparently document their project’s design, development, and management processes. This will help other makers learn from one another, decreasing essential onboarding and learning time, whilst inspiring more great bitcoin apps to be built and innovated on. To see an example of this type of transparent reporting, check out this story here.` }, ], } diff --git a/prisma/seed/index.js b/prisma/seed/index.js index 2e189ab..3c3d084 100644 --- a/prisma/seed/index.js +++ b/prisma/seed/index.js @@ -65,7 +65,7 @@ async function main() { // await createSkills(); - // await createTournament(); + await createTournament(); } @@ -200,6 +200,15 @@ async function createSkills() { async function createTournament() { console.log("Creating Tournament"); + await prisma.tournamentFAQ.createMany({ + + data: tournamentMock.faqs.map(i => ({ + tournament_id: 1, + question: i.question, + answer: i.answer + })) + }) + return const createdTournament = await prisma.tournament.create({ data: { title: tournamentMock.title, diff --git a/src/features/Projects/pages/ExplorePage/Header/Header.tsx b/src/features/Projects/pages/ExplorePage/Header/Header.tsx index 9f67dec..3a08965 100644 --- a/src/features/Projects/pages/ExplorePage/Header/Header.tsx +++ b/src/features/Projects/pages/ExplorePage/Header/Header.tsx @@ -5,18 +5,19 @@ import { MEDIA_QUERIES } from "src/utils/theme/media_queries"; import CustomDot from "./CustomDot/CustomDot"; import useEmblaCarousel from 'embla-carousel-react' import { useCallback, useEffect, useState } from "react"; +import { createRoute } from "src/utils/routing"; const headerLinks = [ { title: <> -

The Long Night tournament is coming!!!

+

Legends of Lightning ⚡️ Tournament

1st Oct - 31st Nov, 2022

, img: "https://imagedelivery.net/wyrwp3c-j0gDDUWgnE7lig/1d5d2c86-fe46-4478-6909-bb3c425c0d00/public", link: { content: "Register Now", - url: "/tournaments/12", + url: createRoute({ type: "tournament", id: 1, tab: 'overview' }), }, }, { diff --git a/src/features/Tournaments/pages/OverviewPage/FAQsSection/FAQsSection.tsx b/src/features/Tournaments/pages/OverviewPage/FAQsSection/FAQsSection.tsx index 2d45895..426037c 100644 --- a/src/features/Tournaments/pages/OverviewPage/FAQsSection/FAQsSection.tsx +++ b/src/features/Tournaments/pages/OverviewPage/FAQsSection/FAQsSection.tsx @@ -1,3 +1,5 @@ +import DOMPurify from 'dompurify'; +import { marked } from 'marked'; import React, { useMemo } from 'react' import Accordion from 'src/Components/Accordion/Accordion'; import { Tournament } from 'src/graphql' @@ -7,6 +9,7 @@ interface Props { } + export default function FAQsSection({ faqs }: Props) { @@ -14,7 +17,13 @@ export default function FAQsSection({ faqs }: Props) {

FAQs

({ heading: faq.question, content:

{faq.answer}

}))} + items={faqs.map(faq => ({ + heading: faq.question, content:
+
+ }))} />
) diff --git a/src/features/Tournaments/pages/OverviewPage/RegisterCard/RegisterCard.tsx b/src/features/Tournaments/pages/OverviewPage/RegisterCard/RegisterCard.tsx index 70cf9d6..cca4022 100644 --- a/src/features/Tournaments/pages/OverviewPage/RegisterCard/RegisterCard.tsx +++ b/src/features/Tournaments/pages/OverviewPage/RegisterCard/RegisterCard.tsx @@ -47,10 +47,10 @@ export default function RegisterCard({ makers_count, start_date, avatars, isRegi return (
-

+ {makers_count > 4 &&

{avatars.map((img, idx) =>

)} + {makers_count} makers -

+

}
diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx index 9df9f4e..bd3cec5 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx +++ b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx @@ -47,7 +47,7 @@ export default function Navigation() {
-
+
{links.map((link) => ({ ...role, level: randomItem(...Object.values(RoleLevelEnum)) })), skills: randomItems(7, ...allMakersSkills), @@ -200,12 +202,14 @@ export const users: (User & MyProfile)[] = [{ { key: "1645h234j2421zxvertw", name: "My Alby wallet key", - is_current: true + is_current: true, + createdAt: new Date(2022, 6, 2).toISOString(), }, { key: "66345134234235", name: "My Phoenix wallet key", - is_current: false + is_current: false, + createdAt: new Date(2022, 6, 2).toISOString() },], roles: randomItems(3, ...allMakersRoles).map(role => ({ ...role, level: randomItem(...Object.values(RoleLevelEnum)) })), skills: randomItems(7, ...allMakersSkills), @@ -235,12 +239,14 @@ export const users: (User & MyProfile)[] = [{ { key: "1645h234j2421zxvertw", name: "My Alby wallet key", - is_current: true + is_current: true, + createdAt: new Date(2022, 6, 2).toISOString(), }, { key: "66345134234235", name: "My Phoenix wallet key", - is_current: false + is_current: false, + createdAt: new Date(2022, 6, 2).toISOString() },], roles: randomItems(3, ...allMakersRoles).map(role => ({ ...role, level: randomItem(...Object.values(RoleLevelEnum)) })), skills: randomItems(7, ...allMakersSkills), @@ -270,12 +276,14 @@ export const users: (User & MyProfile)[] = [{ { key: "1645h234j2421zxvertw", name: "My Alby wallet key", - is_current: true + is_current: true, + createdAt: new Date(2022, 6, 2).toISOString(), }, { key: "66345134234235", name: "My Phoenix wallet key", - is_current: false + is_current: false, + createdAt: new Date(2022, 6, 2).toISOString() },], roles: randomItems(3, ...allMakersRoles).map(role => ({ ...role, level: randomItem(...Object.values(RoleLevelEnum)) })), skills: randomItems(7, ...allMakersSkills), From a39d1ea89139cfb1423653c9eea6e133a4223f5a Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Sat, 10 Sep 2022 11:10:06 +0300 Subject: [PATCH 40/53] fix: make the auto-redirect routes replace type --- src/features/Profiles/pages/EditProfilePage/EditProfilePage.tsx | 2 +- .../pages/TournamentDetailsPage/TournamentDetailsPage.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/features/Profiles/pages/EditProfilePage/EditProfilePage.tsx b/src/features/Profiles/pages/EditProfilePage/EditProfilePage.tsx index 204250b..5f75d91 100644 --- a/src/features/Profiles/pages/EditProfilePage/EditProfilePage.tsx +++ b/src/features/Profiles/pages/EditProfilePage/EditProfilePage.tsx @@ -87,7 +87,7 @@ export default function EditProfilePage() {
- } /> + } /> } /> } /> diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx index a939343..68ac3be 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx +++ b/src/features/Tournaments/pages/TournamentDetailsPage/TournamentDetailsPage.tsx @@ -28,7 +28,7 @@ export default function TournamentDetailsPage() {
- } /> + } /> } /> } /> } /> From 32559a051de1082069d943a5446ae3faba5bef2b Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Sat, 10 Sep 2022 11:21:32 +0300 Subject: [PATCH 41/53] update: change limit to show makers avatars --- .../pages/OverviewPage/RegisterCard/RegisterCard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/Tournaments/pages/OverviewPage/RegisterCard/RegisterCard.tsx b/src/features/Tournaments/pages/OverviewPage/RegisterCard/RegisterCard.tsx index cca4022..9e0c1ce 100644 --- a/src/features/Tournaments/pages/OverviewPage/RegisterCard/RegisterCard.tsx +++ b/src/features/Tournaments/pages/OverviewPage/RegisterCard/RegisterCard.tsx @@ -47,7 +47,7 @@ export default function RegisterCard({ makers_count, start_date, avatars, isRegi return (
- {makers_count > 4 &&

+ {makers_count > 2 &&

{avatars.map((img, idx) =>

)} + {makers_count} makers

} From f55485136299c4f143d97baf96ee7fe70148985d Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Sun, 11 Sep 2022 17:56:31 +0300 Subject: [PATCH 42/53] update: QA fixes --- .../assets/images/logos}/fulgur_logo.svg | 0 src/Components/Ads/Fulgur/Fulgur.tsx | 3 +-- .../Projects/pages/ExplorePage/ExplorePage.tsx | 4 ++-- .../Tournaments/pages/EventsPage/EventsPage.tsx | 6 +++++- .../pages/MakersPage/MakerCard/MakerCard.tsx | 4 ++-- .../pages/OverviewPage/FAQsSection/FAQsSection.tsx | 3 +++ .../OverviewPage/RegisterCard/RegisterCard.tsx | 13 ++++--------- .../ConfirmAccount/ConfirmAccount.tsx | 10 +++++----- .../RegisterationModals/LoginModal/LoginModal.tsx | 6 +++--- .../RegistrationDetails/RegistrationDetails.tsx | 6 +++--- .../RegistrationSuccess/RegistrationSuccess.tsx | 14 +++++++------- .../Navigation/Navigation.tsx | 2 +- src/styles/index.scss | 2 +- src/styles/tw.scss | 2 +- 14 files changed, 38 insertions(+), 37 deletions(-) rename {src/Components/Ads/Fulgur => public/assets/images/logos}/fulgur_logo.svg (100%) diff --git a/src/Components/Ads/Fulgur/fulgur_logo.svg b/public/assets/images/logos/fulgur_logo.svg similarity index 100% rename from src/Components/Ads/Fulgur/fulgur_logo.svg rename to public/assets/images/logos/fulgur_logo.svg diff --git a/src/Components/Ads/Fulgur/Fulgur.tsx b/src/Components/Ads/Fulgur/Fulgur.tsx index 10ae079..5328196 100644 --- a/src/Components/Ads/Fulgur/Fulgur.tsx +++ b/src/Components/Ads/Fulgur/Fulgur.tsx @@ -1,5 +1,4 @@ import Button from 'src/Components/Button/Button' -import Logo from './fulgur_logo.svg' import Lines from './lines-h.png' @@ -8,7 +7,7 @@ export default function Fulgur() {
- Fulgur Ventures Logo + Fulgur Ventures Logo

Turn your hackathon project into a startup

Schedule an office hour with Fulgur Ventures

diff --git a/src/features/Projects/pages/ExplorePage/ExplorePage.tsx b/src/features/Projects/pages/ExplorePage/ExplorePage.tsx index 27053cd..ec3d04c 100644 --- a/src/features/Projects/pages/ExplorePage/ExplorePage.tsx +++ b/src/features/Projects/pages/ExplorePage/ExplorePage.tsx @@ -6,7 +6,7 @@ import Categories from "./Categories/Categories"; export default function ExplorePage() { return ( - <> +
{`Explore Lightning Products`} @@ -22,6 +22,6 @@ export default function ExplorePage() {
- +
) } diff --git a/src/features/Tournaments/pages/EventsPage/EventsPage.tsx b/src/features/Tournaments/pages/EventsPage/EventsPage.tsx index c721bd4..95977ff 100644 --- a/src/features/Tournaments/pages/EventsPage/EventsPage.tsx +++ b/src/features/Tournaments/pages/EventsPage/EventsPage.tsx @@ -1,4 +1,5 @@ import { useState } from 'react' +import Button from 'src/Components/Button/Button'; import { TournamentEventTypeEnum } from 'src/graphql' import { useTournament } from '../TournamentDetailsPage/TournamentDetailsContext'; import EventCard from './EventCard/EventCard'; @@ -12,7 +13,10 @@ export default function EventsPage() { return (
-

Events 📆 ({events_count})

+
+

Events 📆 ({events_count})

+ +
🚦 Hacking status

diff --git a/src/features/Tournaments/pages/OverviewPage/FAQsSection/FAQsSection.tsx b/src/features/Tournaments/pages/OverviewPage/FAQsSection/FAQsSection.tsx index 426037c..8807968 100644 --- a/src/features/Tournaments/pages/OverviewPage/FAQsSection/FAQsSection.tsx +++ b/src/features/Tournaments/pages/OverviewPage/FAQsSection/FAQsSection.tsx @@ -17,6 +17,9 @@ export default function FAQsSection({ faqs }: Props) {

FAQs

({ heading: faq.question, content:
+
{makers_count > 2 &&

{avatars.map((img, idx) =>

)} + {makers_count} makers

} - +
{counter.isExpired ? @@ -77,14 +77,9 @@ export default function RegisterCard({ makers_count, start_date, avatars, isRegi

- Sponsors + Sponsored by

-
- - - - -
+ Fulgur Ventures Logo
) diff --git a/src/features/Tournaments/pages/OverviewPage/RegisterationModals/ConfirmAccount/ConfirmAccount.tsx b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/ConfirmAccount/ConfirmAccount.tsx index 9ea7762..6fbd69b 100644 --- a/src/features/Tournaments/pages/OverviewPage/RegisterationModals/ConfirmAccount/ConfirmAccount.tsx +++ b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/ConfirmAccount/ConfirmAccount.tsx @@ -40,15 +40,15 @@ export default function ConfirmAccount({ onClose, direction, tournamentId, ...pr exit='exit' className="modal-card max-w-[442px] rounded-xl relative" > -
- +
+

Register for tournament


-
+
-
-

{me.name}

+
+

{me.name}

{me.jobTitle}

diff --git a/src/features/Tournaments/pages/OverviewPage/RegisterationModals/LoginModal/LoginModal.tsx b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/LoginModal/LoginModal.tsx index 7c68e50..71bf657 100644 --- a/src/features/Tournaments/pages/OverviewPage/RegisterationModals/LoginModal/LoginModal.tsx +++ b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/LoginModal/LoginModal.tsx @@ -171,12 +171,12 @@ export default function LinkingAccountModal({ onClose, direction, tournamentId, exit='exit' className="modal-card max-w-[442px] rounded-xl relative" > -
- +
+

Connect ⚡️ your maker profile


-
+
{content}
diff --git a/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationDetails/RegistrationDetails.tsx b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationDetails/RegistrationDetails.tsx index 76e8348..6ee6298 100644 --- a/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationDetails/RegistrationDetails.tsx +++ b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationDetails/RegistrationDetails.tsx @@ -113,12 +113,12 @@ export default function RegistrationDetails({ onClose, direction, ...props }: Pr exit='exit' className="modal-card max-w-[442px] rounded-xl relative " > -
- +
+

Register for tournament


-
+

Please provide us with some additional details below.

diff --git a/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationSuccess/RegistrationSuccess.tsx b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationSuccess/RegistrationSuccess.tsx index a267c32..ed74936 100644 --- a/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationSuccess/RegistrationSuccess.tsx +++ b/src/features/Tournaments/pages/OverviewPage/RegisterationModals/RegistrationSuccess/RegistrationSuccess.tsx @@ -30,15 +30,15 @@ export default function RegistrationSuccess({ onClose, direction, ...props }: Pr exit='exit' className="modal-card max-w-[442px] rounded-xl relative" > -
- +
+

Registration succeeded!! ✅


-
+
-
-

{me.name}

+
+

{me.name}

{me.jobTitle}

@@ -61,8 +61,8 @@ export default function RegistrationSuccess({ onClose, direction, ...props }: Pr
- - + +
diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx index bd3cec5..ce8e79d 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx +++ b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx @@ -44,7 +44,7 @@ export default function Navigation() { ], [tournamentDetails.events_count, tournamentDetails.makers_count]) return ( -
+
diff --git a/src/styles/index.scss b/src/styles/index.scss index 74fe6ac..a2439b5 100644 --- a/src/styles/index.scss +++ b/src/styles/index.scss @@ -12,7 +12,7 @@ html { body { overflow-x: hidden; - background-color: #ffffff; + background-color: #f9fafb; } .content-container, diff --git a/src/styles/tw.scss b/src/styles/tw.scss index 18b2141..896cb1b 100644 --- a/src/styles/tw.scss +++ b/src/styles/tw.scss @@ -16,7 +16,7 @@ } .input-wrapper { - @apply relative w-full border border-gray-300 rounded-12 flex focus-within:outline-primary-400 focus-within:border-primary-300 focus-within:ring focus-within:ring-primary-200 focus-within:ring-opacity-50; + @apply relative w-full border bg-white border-gray-300 rounded-12 flex focus-within:outline-primary-400 focus-within:border-primary-300 focus-within:ring focus-within:ring-primary-200 focus-within:ring-opacity-50; } .input-text { From 4518ab0ae7a312b6de8cb2597e58cd44c8ad687e Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Sun, 11 Sep 2022 20:55:56 +0300 Subject: [PATCH 43/53] fix: tournament event starts_at, ends_at format --- .../migration.sql | 10 ++++++++++ prisma/schema.prisma | 10 +++++----- .../pages/EventsPage/EventCard/EventCard.tsx | 2 +- 3 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 prisma/migrations/20220911174549_remove_only_date_constraints/migration.sql diff --git a/prisma/migrations/20220911174549_remove_only_date_constraints/migration.sql b/prisma/migrations/20220911174549_remove_only_date_constraints/migration.sql new file mode 100644 index 0000000..b5dd52e --- /dev/null +++ b/prisma/migrations/20220911174549_remove_only_date_constraints/migration.sql @@ -0,0 +1,10 @@ +-- AlterTable +ALTER TABLE "Donation" ALTER COLUMN "createdAt" SET DATA TYPE TIMESTAMP(3); + +-- AlterTable +ALTER TABLE "Tournament" ALTER COLUMN "start_date" SET DATA TYPE TIMESTAMP(3), +ALTER COLUMN "end_date" SET DATA TYPE TIMESTAMP(3); + +-- AlterTable +ALTER TABLE "TournamentEvent" ALTER COLUMN "ends_at" SET DATA TYPE TIMESTAMP(3), +ALTER COLUMN "starts_at" SET DATA TYPE TIMESTAMP(3); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index c1602ec..783d13f 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -249,7 +249,7 @@ model Hackathon { model Donation { id Int @id @default(autoincrement()) amount Int - createdAt DateTime @default(now()) @db.Date + createdAt DateTime @default(now()) payment_request String? payment_hash String? preimage String? @@ -287,8 +287,8 @@ model Tournament { description String thumbnail_image String cover_image String - start_date DateTime @db.Date - end_date DateTime @db.Date + start_date DateTime + end_date DateTime location String website String votes_count Int @default(0) @@ -336,8 +336,8 @@ model TournamentEvent { title String image String description String - starts_at DateTime @db.Date - ends_at DateTime @db.Date + starts_at DateTime + ends_at DateTime location String website String type Int diff --git a/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx b/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx index 26b60f1..be99f15 100644 --- a/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx +++ b/src/features/Tournaments/pages/EventsPage/EventCard/EventCard.tsx @@ -49,7 +49,7 @@ export default function EventCard({ event }: Props) {

- {`${dayjs(event.starts_at).format('H:mm')} - ${dayjs(event.starts_at).format('H:mm, Do MMM')}`} + {`${dayjs(event.starts_at).format('H:mm')} - ${dayjs(event.ends_at).format('H:mm, Do MMM')}`}

From f3f885086f7544b2c42e1995537f266f88abe126 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Sun, 11 Sep 2022 21:52:06 +0300 Subject: [PATCH 44/53] fix: tournament overview bg on mobile, hackathons page redesign --- src/Components/Navbar/NavDesktop.tsx | 358 +++++++++--------- .../pages/HackathonsPage/HackathonsPage.tsx | 38 +- .../pages/OverviewPage/OverviewPage.tsx | 2 +- 3 files changed, 213 insertions(+), 185 deletions(-) diff --git a/src/Components/Navbar/NavDesktop.tsx b/src/Components/Navbar/NavDesktop.tsx index 5bbc318..038c76d 100644 --- a/src/Components/Navbar/NavDesktop.tsx +++ b/src/Components/Navbar/NavDesktop.tsx @@ -39,113 +39,115 @@ export default function NavDesktop() { return (

diff --git a/src/features/Hackathons/pages/HackathonsPage/HackathonsPage.tsx b/src/features/Hackathons/pages/HackathonsPage/HackathonsPage.tsx index 83b99f0..b194a9a 100644 --- a/src/features/Hackathons/pages/HackathonsPage/HackathonsPage.tsx +++ b/src/features/Hackathons/pages/HackathonsPage/HackathonsPage.tsx @@ -7,6 +7,9 @@ import SortByFilter from '../../Components/SortByFilter/SortByFilter' import styles from './styles.module.scss' import { Helmet } from 'react-helmet' import { Fulgur } from 'src/Components/Ads/Fulgur' +import { IoLocationOutline } from 'react-icons/io5' +import { Link } from 'react-router-dom' +import { createRoute } from 'src/utils/routing' export default function HackathonsPage() { @@ -28,17 +31,38 @@ export default function HackathonsPage() {
-
- + */}
+
Date: Sun, 11 Sep 2022 21:56:30 +0300 Subject: [PATCH 45/53] fix: make hackathons cards skeletons 4 --- .../Hackathons/Components/HackathonsList/HackathonsList.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/features/Hackathons/Components/HackathonsList/HackathonsList.tsx b/src/features/Hackathons/Components/HackathonsList/HackathonsList.tsx index c51889d..27c6832 100644 --- a/src/features/Hackathons/Components/HackathonsList/HackathonsList.tsx +++ b/src/features/Hackathons/Components/HackathonsList/HackathonsList.tsx @@ -19,6 +19,7 @@ export default function HackathonsList(props: Props) { + }
From 6375656ac9e69ff0f07789874cebd26d04578cc2 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Mon, 12 Sep 2022 09:19:16 +0300 Subject: [PATCH 46/53] update: "list an event" btn style --- src/Components/Button/Button.tsx | 7 ++++--- src/features/Tournaments/pages/EventsPage/EventsPage.tsx | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Components/Button/Button.tsx b/src/Components/Button/Button.tsx index 8d4c378..e01b929 100644 --- a/src/Components/Button/Button.tsx +++ b/src/Components/Button/Button.tsx @@ -5,7 +5,7 @@ import { TailSpin } from 'react-loader-spinner'; type Props = { color?: 'primary' | 'red' | 'white' | 'gray' | "black" | 'none', - variant?: 'fill' | 'outline' + variant?: 'fill' | 'outline' | 'text' size?: 'sm' | 'md' | 'lg' children: ReactNode; href?: string; @@ -40,7 +40,7 @@ const loadingColor: UnionToObjectKeys = { const btnStylesOutline: UnionToObjectKeys = { none: "", primary: "text-primary-600", - gray: 'text-gray-700', + gray: 'text-gray-600', white: 'text-gray-900', black: 'text-black', red: "text-red-500", @@ -48,7 +48,8 @@ const btnStylesOutline: UnionToObjectKeys = { const baseBtnStyles: UnionToObjectKeys = { fill: "transition-transform active:scale-95", - outline: "transition-transform bg-gray-900 bg-opacity-0 hover:bg-opacity-5 active:bg-opacity-10 border border-gray-200 active:scale-95 " + outline: "transition-transform bg-gray-900 bg-opacity-0 hover:bg-opacity-5 active:bg-opacity-10 border border-gray-200 active:scale-95 ", + text: "transition-transform active:scale-95 hover:bg-gray-100 active:bg-gray-50" } diff --git a/src/features/Tournaments/pages/EventsPage/EventsPage.tsx b/src/features/Tournaments/pages/EventsPage/EventsPage.tsx index 95977ff..25adc96 100644 --- a/src/features/Tournaments/pages/EventsPage/EventsPage.tsx +++ b/src/features/Tournaments/pages/EventsPage/EventsPage.tsx @@ -15,7 +15,7 @@ export default function EventsPage() {

Events 📆 ({events_count})

- +
Date: Mon, 12 Sep 2022 10:27:56 +0300 Subject: [PATCH 47/53] fix: small visual improvements --- src/Components/Card/Card.tsx | 4 +-- .../pages/HackathonsPage/HackathonsPage.tsx | 2 +- .../PopularTagsFilter/PopularTagsFilter.tsx | 1 - .../pages/EditProfilePage/EditProfilePage.tsx | 32 ++++++++++--------- .../TournamentDetailsPage/Header/Header.tsx | 2 +- .../Navigation/Navigation.tsx | 28 ++++++++-------- src/styles/index.scss | 8 ++--- 7 files changed, 40 insertions(+), 37 deletions(-) diff --git a/src/Components/Card/Card.tsx b/src/Components/Card/Card.tsx index e9727e7..edc6123 100644 --- a/src/Components/Card/Card.tsx +++ b/src/Components/Card/Card.tsx @@ -21,8 +21,8 @@ const Card = React.forwardRef>(({ ref={ref} className={` ${onlyMd ? - `md:bg-white md:rounded-16 md:outline outline-2 outline-gray-200 ${defaultPadding && "md:p-24"}` : - `bg-white rounded-12 md:rounded-16 outline outline-2 outline-gray-200 ${defaultPadding && "p-16 md:p-24"}` + `md:bg-white md:rounded-16 md:border-2 border-gray-200 ${defaultPadding && "md:p-24"}` : + `bg-white rounded-12 md:rounded-16 border-2 border-gray-200 ${defaultPadding && "p-16 md:p-24"}` } ${className} `} diff --git a/src/features/Hackathons/pages/HackathonsPage/HackathonsPage.tsx b/src/features/Hackathons/pages/HackathonsPage/HackathonsPage.tsx index d91b25b..7b0914c 100644 --- a/src/features/Hackathons/pages/HackathonsPage/HackathonsPage.tsx +++ b/src/features/Hackathons/pages/HackathonsPage/HackathonsPage.tsx @@ -33,7 +33,7 @@ export default function HackathonsPage() {
-
+
{isMdScreen ? -

Popular Tags

    {tagsQuery.loading ? diff --git a/src/features/Profiles/pages/EditProfilePage/EditProfilePage.tsx b/src/features/Profiles/pages/EditProfilePage/EditProfilePage.tsx index d5daaf7..0b0dcb8 100644 --- a/src/features/Profiles/pages/EditProfilePage/EditProfilePage.tsx +++ b/src/features/Profiles/pages/EditProfilePage/EditProfilePage.tsx @@ -67,22 +67,24 @@ export default function EditProfilePage() {
: -
- - {links.map((link, idx) => - +
+ + {links.map((link, idx) => + ({ - boxShadow: isActive ? '0px 2px var(--primary)' : 'none' - })} - > - {link.text} - - )} - + style={({ isActive }) => ({ + boxShadow: isActive ? '0px 3px 1px -1px var(--primary)' : 'none' + })} + > + {link.text} + + )} + +
} diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/Header/Header.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/Header/Header.tsx index dbc2bdf..ce486e3 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/Header/Header.tsx +++ b/src/features/Tournaments/pages/TournamentDetailsPage/Header/Header.tsx @@ -15,7 +15,7 @@ export default function Header() { {tournamentDetails.title} Tournament -
+
diff --git a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx index ce8e79d..5c980ae 100644 --- a/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx +++ b/src/features/Tournaments/pages/TournamentDetailsPage/Navigation/Navigation.tsx @@ -45,31 +45,33 @@ export default function Navigation() { return (
-
-
-
- {links.map((link) => ` +
+
+
+
+ {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'} ${link.isDisabled && "pointer-events-none opacity-60"} `} - role='button' - > - {link.text} - )} + role='button' + > + {link.text} + )} +
-
- {/* */} +
) diff --git a/src/styles/index.scss b/src/styles/index.scss index ff88772..9abd516 100644 --- a/src/styles/index.scss +++ b/src/styles/index.scss @@ -28,10 +28,10 @@ body { } display: grid; - grid-template-columns: minmax(var(--padding), 1fr) minmax(auto, 1440px) minmax( - var(--padding), - 1fr - ); + grid-template-columns: minmax(var(--padding), 1fr) minmax( + auto, + var(--maxPageWidth, 1440px) + ) minmax(var(--padding), 1fr); > * { grid-column: 2/3; From c25e1016477c3362d1f791d46e585f99a56a3438 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Mon, 12 Sep 2022 10:58:48 +0300 Subject: [PATCH 48/53] fix: add new breakpoint util --- .../StoryPageContent/StoryPageContent.tsx | 2 +- .../PostDetailsPage.skeleton.tsx | 50 ++++++++++--------- .../pages/PostDetailsPage/PostDetailsPage.tsx | 4 +- .../pages/OverviewPage/OverviewPage.tsx | 2 +- src/styles/index.scss | 9 ++-- src/styles/tw.scss | 6 +++ tailwind.config.js | 3 ++ 7 files changed, 43 insertions(+), 33 deletions(-) diff --git a/src/features/Posts/pages/PostDetailsPage/Components/StoryPageContent/StoryPageContent.tsx b/src/features/Posts/pages/PostDetailsPage/Components/StoryPageContent/StoryPageContent.tsx index 810bd82..7a563fc 100644 --- a/src/features/Posts/pages/PostDetailsPage/Components/StoryPageContent/StoryPageContent.tsx +++ b/src/features/Posts/pages/PostDetailsPage/Components/StoryPageContent/StoryPageContent.tsx @@ -28,7 +28,7 @@ export default function StoryPageContent({ story }: Props) { return ( <>
- + {story.cover_image && - +
+
+ - - + + +
) } diff --git a/src/features/Posts/pages/PostDetailsPage/PostDetailsPage.tsx b/src/features/Posts/pages/PostDetailsPage/PostDetailsPage.tsx index 42b7f54..2994964 100644 --- a/src/features/Posts/pages/PostDetailsPage/PostDetailsPage.tsx +++ b/src/features/Posts/pages/PostDetailsPage/PostDetailsPage.tsx @@ -45,10 +45,10 @@ export default function PostDetailsPage() {
-