From 5dea9526dea21978451060e3897365d4fe73e360 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Wed, 31 Aug 2022 11:36:10 +0300 Subject: [PATCH 001/123] 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 002/123] 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 003/123] 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 004/123] 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 005/123] 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 006/123] 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 007/123] 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 008/123] 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 009/123] 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 010/123] 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 011/123] 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 012/123] 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 013/123] 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 014/123] 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 015/123] 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 016/123] 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 017/123] 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 018/123] 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 019/123] 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 6fe859ff8529c0c1f6fc1149e8b0f8e246037eb9 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Mon, 5 Sep 2022 16:04:45 +0300 Subject: [PATCH 020/123] fix: avatar image cover --- src/features/Auth/pages/LoginPage/LoginPage.tsx | 6 +++--- src/features/Profiles/Components/Avatar/Avatar.tsx | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/features/Auth/pages/LoginPage/LoginPage.tsx b/src/features/Auth/pages/LoginPage/LoginPage.tsx index 6fb0d75..d874171 100644 --- a/src/features/Auth/pages/LoginPage/LoginPage.tsx +++ b/src/features/Auth/pages/LoginPage/LoginPage.tsx @@ -9,7 +9,7 @@ import { IoRocketOutline } from "react-icons/io5"; import Button from "src/Components/Button/Button"; import { FiCopy } from "react-icons/fi"; import useCopyToClipboard from "src/utils/hooks/useCopyToClipboard"; -import { getPropertyFromUnknown, } from "src/utils/helperFunctions"; +import { getPropertyFromUnknown, trimText, } from "src/utils/helperFunctions"; @@ -147,9 +147,9 @@ export default function LoginPage() { else if (isLoggedIn) content =

- Hello: @{meQuery.data?.me?.name.slice(0, 10)}... + Hello: @{trimText(meQuery.data?.me?.name, 10)}

- +
else diff --git a/src/features/Profiles/Components/Avatar/Avatar.tsx b/src/features/Profiles/Components/Avatar/Avatar.tsx index 48d6995..a30aa4d 100644 --- a/src/features/Profiles/Components/Avatar/Avatar.tsx +++ b/src/features/Profiles/Components/Avatar/Avatar.tsx @@ -7,7 +7,7 @@ interface Props { export default function Avatar({ src, alt, width = 40 }: Props) { return ( - {alt From 939832a7ac1cc5c91f2a5966921cdd11253ecea9 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Mon, 5 Sep 2022 16:11:11 +0300 Subject: [PATCH 021/123] 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 022/123] 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 8c77b1be4f91cf3d482c8daa4dceab75ebf584cc Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Tue, 6 Sep 2022 11:41:09 +0300 Subject: [PATCH 023/123] feat: add recruit_roles to project DB modal/api --- api/functions/graphql/nexus-typegen.ts | 2 ++ api/functions/graphql/schema.graphql | 1 + api/functions/graphql/types/project.js | 23 +++++++++++++++++++ api/functions/graphql/types/users.js | 1 + .../migration.sql | 14 +++++++++++ prisma/schema.prisma | 22 ++++++++++++++---- 6 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 prisma/migrations/20220906083327_add_project_recruit_roles_tabel/migration.sql diff --git a/api/functions/graphql/nexus-typegen.ts b/api/functions/graphql/nexus-typegen.ts index 0137828..21ab32b 100644 --- a/api/functions/graphql/nexus-typegen.ts +++ b/api/functions/graphql/nexus-typegen.ts @@ -436,6 +436,7 @@ export interface NexusGenFieldTypes { id: number; // Int! lightning_address: string | null; // String lnurl_callback_url: string | null; // String + recruit_roles: NexusGenRootTypes['MakerRole'][]; // [MakerRole!]! screenshots: string[]; // [String!]! tags: NexusGenRootTypes['Tag'][]; // [Tag!]! thumbnail_image: string; // String! @@ -728,6 +729,7 @@ export interface NexusGenFieldTypeNames { id: 'Int' lightning_address: 'String' lnurl_callback_url: 'String' + recruit_roles: 'MakerRole' screenshots: 'String' tags: 'Tag' thumbnail_image: 'String' diff --git a/api/functions/graphql/schema.graphql b/api/functions/graphql/schema.graphql index 75e6573..995093b 100644 --- a/api/functions/graphql/schema.graphql +++ b/api/functions/graphql/schema.graphql @@ -234,6 +234,7 @@ type Project { id: Int! lightning_address: String lnurl_callback_url: String + recruit_roles: [MakerRole!]! screenshots: [String!]! tags: [Tag!]! thumbnail_image: String! diff --git a/api/functions/graphql/types/project.js b/api/functions/graphql/types/project.js index a9fed49..cc663bb 100644 --- a/api/functions/graphql/types/project.js +++ b/api/functions/graphql/types/project.js @@ -8,6 +8,7 @@ const { const { prisma } = require('../../../prisma'); const { paginationArgs, getLnurlDetails, lightningAddressToLnurl } = require('./helpers'); +const { MakerRole } = require('./users'); const Project = objectType({ @@ -44,6 +45,28 @@ const Project = objectType({ return prisma.project.findUnique({ where: { id: parent.id } }).tags(); } }) + + t.nonNull.list.nonNull.field('recruit_roles', { + type: MakerRole, + resolve: async (parent) => { + const data = await prisma.project.findUnique({ + where: { + id: parent.id + }, + select: { + recruit_roles: { + select: { + role: true, + level: true + } + }, + } + }) + return data.recruit_roles.map(data => { + return ({ ...data.role, level: data.level }) + }) + } + }) } }) diff --git a/api/functions/graphql/types/users.js b/api/functions/graphql/types/users.js index 8b9cd1c..7bdb310 100644 --- a/api/functions/graphql/types/users.js +++ b/api/functions/graphql/types/users.js @@ -451,6 +451,7 @@ module.exports = { User, MyProfile, WalletKey, + MakerRole, // Queries me, profile, diff --git a/prisma/migrations/20220906083327_add_project_recruit_roles_tabel/migration.sql b/prisma/migrations/20220906083327_add_project_recruit_roles_tabel/migration.sql new file mode 100644 index 0000000..54a0f2f --- /dev/null +++ b/prisma/migrations/20220906083327_add_project_recruit_roles_tabel/migration.sql @@ -0,0 +1,14 @@ +-- CreateTable +CREATE TABLE "ProjectRecruitRoles" ( + "projectId" INTEGER NOT NULL, + "roleId" INTEGER NOT NULL, + "level" INTEGER NOT NULL, + + CONSTRAINT "ProjectRecruitRoles_pkey" PRIMARY KEY ("projectId","roleId") +); + +-- AddForeignKey +ALTER TABLE "ProjectRecruitRoles" ADD CONSTRAINT "ProjectRecruitRoles_roleId_fkey" FOREIGN KEY ("roleId") REFERENCES "WorkRole"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ProjectRecruitRoles" ADD CONSTRAINT "ProjectRecruitRoles_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 1a5b903..c7c5c26 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -89,10 +89,11 @@ model UsersOnWorkRoles { } model WorkRole { - id Int @id @default(autoincrement()) - title String @unique - icon String - users UsersOnWorkRoles[] + id Int @id @default(autoincrement()) + title String @unique + icon String + users UsersOnWorkRoles[] + projects ProjectRecruitRoles[] } model Skill { @@ -133,6 +134,19 @@ model Project { awards Award[] tags Tag[] + + recruit_roles ProjectRecruitRoles[] +} + +model ProjectRecruitRoles { + project Project @relation(fields: [projectId], references: [id]) + projectId Int + role WorkRole @relation(fields: [roleId], references: [id]) + roleId Int + + level Int + + @@id([projectId, roleId]) } model Award { From da769384d56e081dc59b5530655593417cb2d835 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Tue, 6 Sep 2022 12:30:14 +0300 Subject: [PATCH 024/123] 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 70acc142e8341afadee332a1d8973d3f583c7dd0 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Tue, 6 Sep 2022 12:57:07 +0300 Subject: [PATCH 025/123] fix: page jump after closing project modal --- .../Components/ProjectCardMini/ProjectCardMini.tsx | 12 +++--------- .../ExplorePage/ProjectsSection/ProjectsSection.tsx | 5 ++++- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/features/Projects/Components/ProjectCardMini/ProjectCardMini.tsx b/src/features/Projects/Components/ProjectCardMini/ProjectCardMini.tsx index 619c65e..70bf777 100644 --- a/src/features/Projects/Components/ProjectCardMini/ProjectCardMini.tsx +++ b/src/features/Projects/Components/ProjectCardMini/ProjectCardMini.tsx @@ -12,25 +12,19 @@ interface Props { } export default function ProjectCardMini({ project, onClick }: Props) { - const { vote } = useVote({ - itemId: project.id, - itemType: Vote_Item_Type.Project - }); - return (
{ - console.log(e.key); e.key !== 'Enter' || onClick(project.id) }} + onClick={(e) => { e.currentTarget.focus(); onClick(project.id) }} tabIndex={0} + role='button' > - {project.title} onClick(project.id)} draggable="false" className="flex-shrink-0 w-64 h-64 bg-gray-200 border-0 rounded-full hover:cursor-pointer"> + {project.title}
onClick(project.id)} - role='button' >

{project.title}

{project.category.title}

diff --git a/src/features/Projects/pages/ExplorePage/ProjectsSection/ProjectsSection.tsx b/src/features/Projects/pages/ExplorePage/ProjectsSection/ProjectsSection.tsx index 0013633..3fb873d 100644 --- a/src/features/Projects/pages/ExplorePage/ProjectsSection/ProjectsSection.tsx +++ b/src/features/Projects/pages/ExplorePage/ProjectsSection/ProjectsSection.tsx @@ -3,9 +3,10 @@ import ProjectsRow from "../ProjectsRow/ProjectsRow"; import ProjectsRowSkeleton from "../ProjectsRow/ProjectsRow.Skeleton"; import { MdLocalFireDepartment } from "react-icons/md"; import { useExploreProjectsQuery } from "src/graphql"; +import React from "react"; -export default function ProjectsSection() { +function ProjectsSection() { const { data, loading } = useExploreProjectsQuery(); @@ -42,3 +43,5 @@ export default function ProjectsSection() {
) } + +export default React.memo(ProjectsSection) \ No newline at end of file From 58ca7fdd160b2a564ce551aa307d9dcdbb40cfd0 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Tue, 6 Sep 2022 13:30:22 +0300 Subject: [PATCH 026/123] 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 b9359bf0b27ea305883dfa8547357deabffd9f49 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Tue, 6 Sep 2022 13:39:28 +0300 Subject: [PATCH 027/123] update: add "email" field to profile --- .../BasicProfileInfoTab.tsx | 19 +++++++++++++++++-- .../pages/ProfilePage/AboutCard/AboutCard.tsx | 9 ++++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/features/Profiles/pages/EditProfilePage/BasicProfileInfoTab/BasicProfileInfoTab.tsx b/src/features/Profiles/pages/EditProfilePage/BasicProfileInfoTab/BasicProfileInfoTab.tsx index 0d31d32..5b5e277 100644 --- a/src/features/Profiles/pages/EditProfilePage/BasicProfileInfoTab/BasicProfileInfoTab.tsx +++ b/src/features/Profiles/pages/EditProfilePage/BasicProfileInfoTab/BasicProfileInfoTab.tsx @@ -206,6 +206,21 @@ export default function BasicProfileInfoTab() { {errors.location &&

{errors.location.message}

} +

+ Email +

+
+ +
+ {errors.website &&

+ {errors.website.message} +

}

Website

@@ -222,7 +237,7 @@ export default function BasicProfileInfoTab() { {errors.website.message}

}

- Twitter + Twitter handle

}

- Github + Github username

Date: Tue, 6 Sep 2022 13:41:42 +0300 Subject: [PATCH 028/123] update: email text --- .../ConnectToMakerModal.tsx | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 src/features/Tournaments/pages/MakersPage/ConnectToMakerModal/ConnectToMakerModal.tsx 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..ff10ea2 --- /dev/null +++ b/src/features/Tournaments/pages/MakersPage/ConnectToMakerModal/ConnectToMakerModal.tsx @@ -0,0 +1,88 @@ +import { motion } from 'framer-motion' +import { ModalCard, modalCardVariants } from 'src/Components/Modals/ModalsContainer/ModalsContainer' +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'; +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.email, + text: maker.email?.replace(/(^\w+:|^)\/\//, '').replace(/\/$/, ""), + icon: FiMail, + colors: "bg-violet-100 text-violet-900", + 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), + } + ]; + + + 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) => + + + )} +
+
+
+ ) +} + + + From ed21e21359bce17fd6adaea1b3baefdae5dc3d14 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Tue, 6 Sep 2022 13:42:10 +0300 Subject: [PATCH 029/123] update: email regex --- src/features/Profiles/pages/ProfilePage/AboutCard/AboutCard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/Profiles/pages/ProfilePage/AboutCard/AboutCard.tsx b/src/features/Profiles/pages/ProfilePage/AboutCard/AboutCard.tsx index 6f87f17..70fbc0d 100644 --- a/src/features/Profiles/pages/ProfilePage/AboutCard/AboutCard.tsx +++ b/src/features/Profiles/pages/ProfilePage/AboutCard/AboutCard.tsx @@ -27,7 +27,7 @@ export default function AboutCard({ user, isOwner }: Props) { const links = [ { hasValue: user.email, - text: user.email?.replace(/(^\w+:|^)\/\//, '').replace(/\/$/, ""), + text: user.email, icon: FiMail, colors: "bg-violet-100 text-violet-900", url: user.email && `mailto:${user.email}` From fbb8d1cf6d85731f9a50ba29a3a64ccd98a60707 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Tue, 6 Sep 2022 13:59:56 +0300 Subject: [PATCH 030/123] 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 c16c353ec8d469bd2ffdeeb866a0279063ac1139 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Tue, 6 Sep 2022 14:14:02 +0300 Subject: [PATCH 031/123] fix: remove extra card --- .../ConnectToMakerModal.tsx | 88 ------------------- 1 file changed, 88 deletions(-) delete mode 100644 src/features/Tournaments/pages/MakersPage/ConnectToMakerModal/ConnectToMakerModal.tsx diff --git a/src/features/Tournaments/pages/MakersPage/ConnectToMakerModal/ConnectToMakerModal.tsx b/src/features/Tournaments/pages/MakersPage/ConnectToMakerModal/ConnectToMakerModal.tsx deleted file mode 100644 index ff10ea2..0000000 --- a/src/features/Tournaments/pages/MakersPage/ConnectToMakerModal/ConnectToMakerModal.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import { motion } from 'framer-motion' -import { ModalCard, modalCardVariants } from 'src/Components/Modals/ModalsContainer/ModalsContainer' -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'; -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.email, - text: maker.email?.replace(/(^\w+:|^)\/\//, '').replace(/\/$/, ""), - icon: FiMail, - colors: "bg-violet-100 text-violet-900", - 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), - } - ]; - - - return ( - -
- -

Send team request 🤝

-
-
-
- - ) -} - - - From 3f71e854048791b11565445701124cf1387561aa Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Wed, 7 Sep 2022 10:04:01 +0300 Subject: [PATCH 032/123] 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 ba0cbff046721d7b677909f38a96e69d985a9c40 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Wed, 7 Sep 2022 10:06:00 +0300 Subject: [PATCH 033/123] update: add tailwind plugins --- package-lock.json | 57 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 2 ++ tailwind.config.js | 2 ++ 3 files changed, 61 insertions(+) diff --git a/package-lock.json b/package-lock.json index 1638ed0..b289b87 100644 --- a/package-lock.json +++ b/package-lock.json @@ -113,6 +113,8 @@ "@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", "@types/fslightbox-react": "^1.4.2", @@ -15322,6 +15324,30 @@ "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1" } }, + "node_modules/@tailwindcss/line-clamp": { + "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" + } + }, + "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", @@ -31588,6 +31614,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", @@ -82371,6 +82403,25 @@ "mini-svg-data-uri": "^1.2.3" } }, + "@tailwindcss/line-clamp": { + "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": { + "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", @@ -95121,6 +95172,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 f78d0a4..5bb2074 100644 --- a/package.json +++ b/package.json @@ -165,6 +165,8 @@ "@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", "@types/fslightbox-react": "^1.4.2", diff --git a/tailwind.config.js b/tailwind.config.js index 094c3c8..e5a3fba 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -99,5 +99,7 @@ module.exports = { }, plugins: [ require('@tailwindcss/forms'), + require('@tailwindcss/line-clamp'), + require('@tailwindcss/typography'), ], } From 5cd6b129519d68338c1ed2780ef656e03d5bf082 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Wed, 7 Sep 2022 10:17:39 +0300 Subject: [PATCH 034/123] 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 035/123] 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 1a92252ea0a32a575fb62523622590fee7e22040 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Wed, 7 Sep 2022 11:19:05 +0300 Subject: [PATCH 036/123] update: added tournament modals to db schema --- .../migration.sql | 102 ++++++++++++++++++ prisma/schema.prisma | 87 +++++++++++++++ 2 files changed, 189 insertions(+) create mode 100644 prisma/migrations/20220907081831_create_tournament_tables/migration.sql diff --git a/prisma/migrations/20220907081831_create_tournament_tables/migration.sql b/prisma/migrations/20220907081831_create_tournament_tables/migration.sql new file mode 100644 index 0000000..9b417f2 --- /dev/null +++ b/prisma/migrations/20220907081831_create_tournament_tables/migration.sql @@ -0,0 +1,102 @@ +-- CreateTable +CREATE TABLE "Tournament" ( + "id" SERIAL NOT NULL, + "title" TEXT NOT NULL, + "description" TEXT NOT NULL, + "thumbnail_image" TEXT NOT NULL, + "cover_image" TEXT NOT NULL, + "start_date" DATE NOT NULL, + "end_date" DATE NOT NULL, + "location" TEXT NOT NULL, + "website" TEXT NOT NULL, + "votes_count" INTEGER NOT NULL DEFAULT 0, + + CONSTRAINT "Tournament_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "TournamentPrize" ( + "id" SERIAL NOT NULL, + "title" TEXT NOT NULL, + "amount" TEXT NOT NULL, + "image" TEXT NOT NULL, + "tournament_id" INTEGER NOT NULL, + + CONSTRAINT "TournamentPrize_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "TournamentJudge" ( + "id" SERIAL NOT NULL, + "name" TEXT NOT NULL, + "company" TEXT NOT NULL, + "twitter" TEXT, + "tournament_id" INTEGER NOT NULL, + + CONSTRAINT "TournamentJudge_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "TournamentFAQ" ( + "id" SERIAL NOT NULL, + "question" TEXT NOT NULL, + "answer" TEXT NOT NULL, + "tournament_id" INTEGER NOT NULL, + + CONSTRAINT "TournamentFAQ_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "TournamentEvent" ( + "id" SERIAL NOT NULL, + "title" TEXT NOT NULL, + "image" TEXT NOT NULL, + "description" TEXT NOT NULL, + "date" DATE NOT NULL, + "location" TEXT NOT NULL, + "website" TEXT NOT NULL, + "type" INTEGER NOT NULL, + "tournament_id" INTEGER NOT NULL, + + CONSTRAINT "TournamentEvent_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "TournamentParticipant" ( + "tournament_id" INTEGER NOT NULL, + "user_id" INTEGER NOT NULL, + + CONSTRAINT "TournamentParticipant_pkey" PRIMARY KEY ("tournament_id","user_id") +); + +-- CreateTable +CREATE TABLE "TournamentProject" ( + "tournament_id" INTEGER NOT NULL, + "project_id" INTEGER NOT NULL, + + CONSTRAINT "TournamentProject_pkey" PRIMARY KEY ("tournament_id","project_id") +); + +-- AddForeignKey +ALTER TABLE "TournamentPrize" ADD CONSTRAINT "TournamentPrize_tournament_id_fkey" FOREIGN KEY ("tournament_id") REFERENCES "Tournament"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "TournamentJudge" ADD CONSTRAINT "TournamentJudge_tournament_id_fkey" FOREIGN KEY ("tournament_id") REFERENCES "Tournament"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "TournamentFAQ" ADD CONSTRAINT "TournamentFAQ_tournament_id_fkey" FOREIGN KEY ("tournament_id") REFERENCES "Tournament"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "TournamentEvent" ADD CONSTRAINT "TournamentEvent_tournament_id_fkey" FOREIGN KEY ("tournament_id") REFERENCES "Tournament"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "TournamentParticipant" ADD CONSTRAINT "TournamentParticipant_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "TournamentParticipant" ADD CONSTRAINT "TournamentParticipant_tournament_id_fkey" FOREIGN KEY ("tournament_id") REFERENCES "Tournament"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "TournamentProject" ADD CONSTRAINT "TournamentProject_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "Project"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "TournamentProject" ADD CONSTRAINT "TournamentProject_tournament_id_fkey" FOREIGN KEY ("tournament_id") REFERENCES "Tournament"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index c7c5c26..87b4d2a 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -67,6 +67,8 @@ model User { userKeys UserKey[] skills Skill[] roles UsersOnWorkRoles[] + + tournaments TournamentParticipant[] } model UserKey { @@ -136,6 +138,7 @@ model Project { tags Tag[] recruit_roles ProjectRecruitRoles[] + tournaments TournamentProject[] } model ProjectRecruitRoles { @@ -272,3 +275,87 @@ model HostedImage { createdAt DateTime @default(now()) is_used Boolean @default(false) } + +// ----------------- +// Tournament +// ----------------- +model Tournament { + id Int @id @default(autoincrement()) + title String + description String + thumbnail_image String + cover_image String + start_date DateTime @db.Date + end_date DateTime @db.Date + location String + website String + votes_count Int @default(0) + + prizes TournamentPrize[] + judges TournamentJudge[] + faqs TournamentFAQ[] + events TournamentEvent[] + participants TournamentParticipant[] + projects TournamentProject[] +} + +model TournamentPrize { + id Int @id @default(autoincrement()) + title String + amount String + image String + + tournament Tournament @relation(fields: [tournament_id], references: [id]) + tournament_id Int +} + +model TournamentJudge { + id Int @id @default(autoincrement()) + name String + company String + twitter String? + + tournament Tournament @relation(fields: [tournament_id], references: [id]) + tournament_id Int +} + +model TournamentFAQ { + id Int @id @default(autoincrement()) + question String + answer String + + tournament Tournament @relation(fields: [tournament_id], references: [id]) + tournament_id Int +} + +model TournamentEvent { + id Int @id @default(autoincrement()) + title String + image String + description String + date DateTime @db.Date + location String + website String + type Int + + tournament Tournament @relation(fields: [tournament_id], references: [id]) + tournament_id Int +} + +model TournamentParticipant { + tournament Tournament @relation(fields: [tournament_id], references: [id]) + tournament_id Int + user User @relation(fields: [user_id], references: [id]) + user_id Int + + @@id([tournament_id, user_id]) +} + +model TournamentProject { + tournament Tournament @relation(fields: [tournament_id], references: [id]) + tournament_id Int + project Project @relation(fields: [project_id], references: [id]) + project_id Int + + @@id([tournament_id, project_id]) +} From a7203e94f2bb1bf12a57837890b545fc4e55b1ca Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Wed, 7 Sep 2022 11:34:14 +0300 Subject: [PATCH 037/123] 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 9062e040ffede070331801d95352b07a9df20e91 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Wed, 7 Sep 2022 11:35:13 +0300 Subject: [PATCH 038/123] update: tournament date field type --- .../migration.sql | 12 ++++++++++++ prisma/schema.prisma | 3 ++- 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 prisma/migrations/20220907083457_update_tournament_event_date_field/migration.sql diff --git a/prisma/migrations/20220907083457_update_tournament_event_date_field/migration.sql b/prisma/migrations/20220907083457_update_tournament_event_date_field/migration.sql new file mode 100644 index 0000000..777faca --- /dev/null +++ b/prisma/migrations/20220907083457_update_tournament_event_date_field/migration.sql @@ -0,0 +1,12 @@ +/* + Warnings: + + - You are about to drop the column `date` on the `TournamentEvent` table. All the data in the column will be lost. + - Added the required column `ends_at` to the `TournamentEvent` table without a default value. This is not possible if the table is not empty. + - Added the required column `starts_at` to the `TournamentEvent` table without a default value. This is not possible if the table is not empty. + +*/ +-- AlterTable +ALTER TABLE "TournamentEvent" DROP COLUMN "date", +ADD COLUMN "ends_at" DATE NOT NULL, +ADD COLUMN "starts_at" DATE NOT NULL; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 87b4d2a..0eeec07 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -333,7 +333,8 @@ model TournamentEvent { title String image String description String - date DateTime @db.Date + starts_at DateTime @db.Date + ends_at DateTime @db.Date location String website String type Int From be0a752fb0df72e85ee5283055bba8b8a8b15b12 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Wed, 7 Sep 2022 11:52:05 +0300 Subject: [PATCH 039/123] 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 15e7583fb6b83ea225f5c2009c25e020e1ad3b11 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Wed, 7 Sep 2022 11:53:30 +0300 Subject: [PATCH 040/123] update: db schema --- .../migration.sql | 8 ++++++++ prisma/schema.prisma | 1 + 2 files changed, 9 insertions(+) create mode 100644 prisma/migrations/20220907085319_add_avatar_to_tournament_judge/migration.sql diff --git a/prisma/migrations/20220907085319_add_avatar_to_tournament_judge/migration.sql b/prisma/migrations/20220907085319_add_avatar_to_tournament_judge/migration.sql new file mode 100644 index 0000000..64ce7a1 --- /dev/null +++ b/prisma/migrations/20220907085319_add_avatar_to_tournament_judge/migration.sql @@ -0,0 +1,8 @@ +/* + Warnings: + + - Added the required column `avatar` to the `TournamentJudge` table without a default value. This is not possible if the table is not empty. + +*/ +-- AlterTable +ALTER TABLE "TournamentJudge" ADD COLUMN "avatar" TEXT NOT NULL; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 0eeec07..ae9d461 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -312,6 +312,7 @@ model TournamentPrize { model TournamentJudge { id Int @id @default(autoincrement()) name String + avatar String company String twitter String? From 36636b5f0d7eab4fa2ab87ff2af2c6e5e9f91c8e Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Wed, 7 Sep 2022 12:00:40 +0300 Subject: [PATCH 041/123] 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 042/123] 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 043/123] 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 f7d86633b37d7efb96de1dc4d2f2c55c5609e7a2 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Thu, 8 Sep 2022 09:54:34 +0300 Subject: [PATCH 044/123] feat: update db schema --- .../migration.sql | 10 ++++++++++ prisma/schema.prisma | 3 +++ 2 files changed, 13 insertions(+) create mode 100644 prisma/migrations/20220908065418_add_email_and_hackingstatus_to_tournament_participant/migration.sql diff --git a/prisma/migrations/20220908065418_add_email_and_hackingstatus_to_tournament_participant/migration.sql b/prisma/migrations/20220908065418_add_email_and_hackingstatus_to_tournament_participant/migration.sql new file mode 100644 index 0000000..2b563a1 --- /dev/null +++ b/prisma/migrations/20220908065418_add_email_and_hackingstatus_to_tournament_participant/migration.sql @@ -0,0 +1,10 @@ +/* + Warnings: + + - Added the required column `email` to the `TournamentParticipant` table without a default value. This is not possible if the table is not empty. + - Added the required column `hacking_status` to the `TournamentParticipant` table without a default value. This is not possible if the table is not empty. + +*/ +-- AlterTable +ALTER TABLE "TournamentParticipant" ADD COLUMN "email" TEXT NOT NULL, +ADD COLUMN "hacking_status" INTEGER NOT NULL; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index ae9d461..974fc53 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -350,6 +350,9 @@ model TournamentParticipant { user User @relation(fields: [user_id], references: [id]) user_id Int + email String + hacking_status Int + @@id([tournament_id, user_id]) } From a0f09aaa33033632ae9b7f6077ca03d158bbd26a Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Thu, 8 Sep 2022 14:53:08 +0300 Subject: [PATCH 045/123] 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 764c6b662281e1daae22622b4e51e627dfb7ea47 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Fri, 9 Sep 2022 07:50:36 +0300 Subject: [PATCH 046/123] feat: add createdAt to userKeys, tour participations --- api/functions/graphql/types/users.js | 14 +++++++++++--- .../migration.sql | 5 +++++ prisma/schema.prisma | 6 ++++-- 3 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 prisma/migrations/20220909043627_add_created_at_to_keys_and_participations/migration.sql diff --git a/api/functions/graphql/types/users.js b/api/functions/graphql/types/users.js index 7bdb310..b1f6cf8 100644 --- a/api/functions/graphql/types/users.js +++ b/api/functions/graphql/types/users.js @@ -171,9 +171,16 @@ const MyProfile = objectType({ t.nonNull.list.nonNull.field('walletsKeys', { type: "WalletKey", - resolve: async (parent, _, context) => { - const userKeys = await prisma.user.findUnique({ where: { id: parent.id } }).userKeys(); - return userKeys.map(k => ({ ...k, is_current: k.key === context.userPubKey })) + resolve: (parent, _, context) => { + return prisma.userKey.findMany({ + where: { + user_id: parent.id, + }, + orderBy: { + createdAt: "asc" + } + }) + .then(keys => keys.map(k => ({ ...k, is_current: k.key === context.userPubKey }))) } }); } @@ -283,6 +290,7 @@ const WalletKey = objectType({ definition(t) { t.nonNull.string('key'); t.nonNull.string('name'); + t.nonNull.date('createdAt'); t.nonNull.boolean('is_current') } }) diff --git a/prisma/migrations/20220909043627_add_created_at_to_keys_and_participations/migration.sql b/prisma/migrations/20220909043627_add_created_at_to_keys_and_participations/migration.sql new file mode 100644 index 0000000..4bb777b --- /dev/null +++ b/prisma/migrations/20220909043627_add_created_at_to_keys_and_participations/migration.sql @@ -0,0 +1,5 @@ +-- AlterTable +ALTER TABLE "TournamentParticipant" ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP; + +-- AlterTable +ALTER TABLE "UserKey" ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 974fc53..1f3c9a7 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -72,8 +72,9 @@ model User { } model UserKey { - key String @id - name String @default("My new wallet key") + key String @id + name String @default("My new wallet key") + createdAt DateTime @default(now()) user User? @relation(fields: [user_id], references: [id]) user_id Int? @@ -349,6 +350,7 @@ model TournamentParticipant { tournament_id Int user User @relation(fields: [user_id], references: [id]) user_id Int + createdAt DateTime @default(now()) email String hacking_status Int From 64d8263ae6b613a2a694cb6f91fcba235aa7a8c3 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Fri, 9 Sep 2022 09:46:18 +0300 Subject: [PATCH 047/123] 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 f23e6f271b6df75e1c8d35ab740bf025553e09c8 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Fri, 9 Sep 2022 09:48:57 +0300 Subject: [PATCH 048/123] update: add discord to user's table --- .../20220909064845_add_discord_to_user_table/migration.sql | 2 ++ prisma/schema.prisma | 1 + 2 files changed, 3 insertions(+) create mode 100644 prisma/migrations/20220909064845_add_discord_to_user_table/migration.sql diff --git a/prisma/migrations/20220909064845_add_discord_to_user_table/migration.sql b/prisma/migrations/20220909064845_add_discord_to_user_table/migration.sql new file mode 100644 index 0000000..3834a6f --- /dev/null +++ b/prisma/migrations/20220909064845_add_discord_to_user_table/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "User" ADD COLUMN "discord" TEXT; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 1f3c9a7..c1602ec 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -52,6 +52,7 @@ model User { website String? twitter String? github String? + discord String? linkedin String? bio String? location String? From 329ecf3b609ee3d7b6d13ffcff74a4d654c7e326 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Fri, 9 Sep 2022 12:14:56 +0300 Subject: [PATCH 049/123] 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 050/123] 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 051/123] 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 052/123] 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 053/123] 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 054/123] 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 055/123] 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 056/123] 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 057/123] 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 f10a20757a9bfca8b4e3626b9e7946ad92ab17be Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Sun, 11 Sep 2022 20:56:47 +0300 Subject: [PATCH 058/123] update: db schema --- .../migration.sql | 10 ++++++++++ prisma/schema.prisma | 10 +++++----- 2 files changed, 15 insertions(+), 5 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 From f3f885086f7544b2c42e1995537f266f88abe126 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Sun, 11 Sep 2022 21:52:06 +0300 Subject: [PATCH 059/123] 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 060/123] 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 061/123] 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 09:41:19 +0300 Subject: [PATCH 062/123] refactor: page-container class structure --- src/Components/Navbar/NavDesktop.tsx | 356 +++++++++--------- src/Components/Navbar/NavMobile.tsx | 120 +++--- .../pages/HackathonsPage/HackathonsPage.tsx | 54 +-- .../Posts/pages/FeedPage/FeedPage.tsx | 136 +++---- .../pages/PostDetailsPage/PostDetailsPage.tsx | 40 +- .../pages/EditProfilePage/EditProfilePage.tsx | 88 ++--- .../pages/ProfilePage/ProfilePage.tsx | 7 +- .../pages/ExplorePage/ExplorePage.tsx | 4 +- src/styles/index.scss | 24 +- 9 files changed, 423 insertions(+), 406 deletions(-) diff --git a/src/Components/Navbar/NavDesktop.tsx b/src/Components/Navbar/NavDesktop.tsx index 5bbc318..88c3ce6 100644 --- a/src/Components/Navbar/NavDesktop.tsx +++ b/src/Components/Navbar/NavDesktop.tsx @@ -39,113 +39,114 @@ export default function NavDesktop() { return ( diff --git a/src/Components/Navbar/NavMobile.tsx b/src/Components/Navbar/NavMobile.tsx index 08fadad..15a214a 100644 --- a/src/Components/Navbar/NavMobile.tsx +++ b/src/Components/Navbar/NavMobile.tsx @@ -73,68 +73,70 @@ export default function NavMobile() { return (
diff --git a/src/features/Hackathons/pages/HackathonsPage/HackathonsPage.tsx b/src/features/Hackathons/pages/HackathonsPage/HackathonsPage.tsx index 83b99f0..a96e64f 100644 --- a/src/features/Hackathons/pages/HackathonsPage/HackathonsPage.tsx +++ b/src/features/Hackathons/pages/HackathonsPage/HackathonsPage.tsx @@ -28,36 +28,38 @@ export default function HackathonsPage() {
- +
+ +
+
) } diff --git a/src/features/Posts/pages/FeedPage/FeedPage.tsx b/src/features/Posts/pages/FeedPage/FeedPage.tsx index a4257cb..8a4ada7 100644 --- a/src/features/Posts/pages/FeedPage/FeedPage.tsx +++ b/src/features/Posts/pages/FeedPage/FeedPage.tsx @@ -43,78 +43,80 @@ export default function FeedPage() {
-
- {tagFilter &&

- setTagFilter(null)}>Stories - - {tagFilter.title} -

} -

{ - tagFilter ? - <>{tagFilter.icon} {capitalize(tagFilter.title)} - : - "Stories ✍🏼" - }

-
-
- -
-
- -
- - + +
) diff --git a/src/features/Posts/pages/PostDetailsPage/PostDetailsPage.tsx b/src/features/Posts/pages/PostDetailsPage/PostDetailsPage.tsx index 345774f..42b7f54 100644 --- a/src/features/Posts/pages/PostDetailsPage/PostDetailsPage.tsx +++ b/src/features/Posts/pages/PostDetailsPage/PostDetailsPage.tsx @@ -45,29 +45,31 @@ export default function PostDetailsPage() {
- +
+ - - -
-
- }> - - -
diff --git a/src/features/Profiles/pages/EditProfilePage/EditProfilePage.tsx b/src/features/Profiles/pages/EditProfilePage/EditProfilePage.tsx index 204250b..2d87707 100644 --- a/src/features/Profiles/pages/EditProfilePage/EditProfilePage.tsx +++ b/src/features/Profiles/pages/EditProfilePage/EditProfilePage.tsx @@ -45,55 +45,57 @@ export default function EditProfilePage() { Settings -
- -
- - } /> - } /> - } /> - - } /> - -
+ )} + +
+ } + +
+ + } /> + } /> + } /> + + } /> + +
+
) diff --git a/src/features/Profiles/pages/ProfilePage/ProfilePage.tsx b/src/features/Profiles/pages/ProfilePage/ProfilePage.tsx index 92142be..e358d88 100644 --- a/src/features/Profiles/pages/ProfilePage/ProfilePage.tsx +++ b/src/features/Profiles/pages/ProfilePage/ProfilePage.tsx @@ -48,9 +48,10 @@ export default function ProfilePage() { } -
- {isMediumScreen ? +
{isMediumScreen ? <>
- } + }
) diff --git a/src/features/Projects/pages/ExplorePage/ExplorePage.tsx b/src/features/Projects/pages/ExplorePage/ExplorePage.tsx index 27053cd..88f3fb7 100644 --- a/src/features/Projects/pages/ExplorePage/ExplorePage.tsx +++ b/src/features/Projects/pages/ExplorePage/ExplorePage.tsx @@ -11,10 +11,8 @@ export default function ExplorePage() { {`Explore Lightning Products`} -
- +
-
diff --git a/src/styles/index.scss b/src/styles/index.scss index 96fdc2e..b94d9f1 100644 --- a/src/styles/index.scss +++ b/src/styles/index.scss @@ -26,21 +26,27 @@ body { @include gt-md { --padding: 32px; } - width: calc(min(100% - 2 * var(--padding), 1440px)); - margin: 0 auto; + + display: grid; + grid-template-columns: minmax(var(--padding), 1fr) minmax(auto, 1440px) minmax( + var(--padding), + 1fr + ); + + > * { + grid-column: 2/3; + min-width: 0; + } + + > .full-width { + grid-column: 1/-1; + } } .page-container { padding: 32px 0; } -// @media screen and (min-width: 780px) { -// .page-container { -// width: calc(min(100% - 64px, 1440px)); -// margin: 0 auto; -// } -// } - svg { display: inline-block; } From c30c45ac4441489a6e869a0a4260aca9f0a8ce27 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Mon, 12 Sep 2022 10:27:56 +0300 Subject: [PATCH 063/123] 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 064/123] 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() {
-