From 80b7053f88825cb0685eb59205e2d08a596749a2 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Sun, 21 Aug 2022 13:44:35 +0300 Subject: [PATCH 01/10] feat: profile roles, skills, tournaments, similar makers cards/stories/schemas --- api/functions/graphql/nexus-typegen.ts | 92 ++++++++++++++ api/functions/graphql/schema.graphql | 45 +++++++ api/functions/graphql/types/tournaments.js | 55 +++++++++ api/functions/graphql/types/users.js | 91 +++++++++++++- .../Components/TrendingCard/TrendingCard.tsx | 2 +- .../CommentsSettingsCard.stories.tsx | 5 +- .../LinkedAccountsCard.stories.tsx | 6 +- .../pages/ProfilePage/AboutCard/AboutCard.tsx | 44 ++++--- .../pages/ProfilePage/ProfilePage.tsx | 46 +++++-- .../RolesCard/RolesCard.stories.tsx | 31 +++++ .../pages/ProfilePage/RolesCard/RolesCard.tsx | 58 +++++++++ .../SimilarMakersCard.stories.tsx | 22 ++++ .../SimilarMakersCard/SimilarMakersCard.tsx | 38 ++++++ .../SkillsCard/SkillsCard.stories.tsx | 31 +++++ .../ProfilePage/SkillsCard/SkillsCard.tsx | 29 +++++ .../TournamentsCard.stories.tsx | 31 +++++ .../TournamentsCard/TournamentsCard.tsx | 45 +++++++ .../pages/ProfilePage/profile.graphql | 23 ++++ .../pages/ProfilePage/styles.module.scss | 9 ++ src/graphql/index.tsx | 78 +++++++++++- src/mocks/data/users.ts | 113 +++++++++++++++++- 21 files changed, 856 insertions(+), 38 deletions(-) create mode 100644 api/functions/graphql/types/tournaments.js create mode 100644 src/features/Profiles/pages/ProfilePage/RolesCard/RolesCard.stories.tsx create mode 100644 src/features/Profiles/pages/ProfilePage/RolesCard/RolesCard.tsx create mode 100644 src/features/Profiles/pages/ProfilePage/SimilarMakersCard/SimilarMakersCard.stories.tsx create mode 100644 src/features/Profiles/pages/ProfilePage/SimilarMakersCard/SimilarMakersCard.tsx create mode 100644 src/features/Profiles/pages/ProfilePage/SkillsCard/SkillsCard.stories.tsx create mode 100644 src/features/Profiles/pages/ProfilePage/SkillsCard/SkillsCard.tsx create mode 100644 src/features/Profiles/pages/ProfilePage/TournamentsCard/TournamentsCard.stories.tsx create mode 100644 src/features/Profiles/pages/ProfilePage/TournamentsCard/TournamentsCard.tsx diff --git a/api/functions/graphql/nexus-typegen.ts b/api/functions/graphql/nexus-typegen.ts index bd8c67e..4c8413f 100644 --- a/api/functions/graphql/nexus-typegen.ts +++ b/api/functions/graphql/nexus-typegen.ts @@ -57,6 +57,7 @@ export interface NexusGenInputs { export interface NexusGenEnums { POST_TYPE: "Bounty" | "Question" | "Story" + RoleLevelEnum: 3 | 0 | 1 | 2 | 4 VOTE_ITEM_TYPE: "Bounty" | "PostComment" | "Project" | "Question" | "Story" | "User" } @@ -208,6 +209,16 @@ 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! + id: number; // Int! + start_date: NexusGenScalars['Date']; // Date! + thumbnail_image: string; // String! + title: string; // String! + website: string; // String! + } User: { // root type avatar: string; // String! bio?: string | null; // String @@ -224,6 +235,16 @@ export interface NexusGenObjects { twitter?: string | null; // String website?: string | null; // String } + UserRole: { // root type + icon: string; // String! + id: number; // Int! + level: NexusGenEnums['RoleLevelEnum']; // RoleLevelEnum! + title: string; // String! + } + UserSkill: { // root type + id: number; // Int! + title: string; // String! + } Vote: { // root type amount_in_sat: number; // Int! id: number; // Int! @@ -357,7 +378,11 @@ export interface NexusGenFieldTypes { nostr_prv_key: string | null; // String nostr_pub_key: string | null; // String role: string | null; // String + roles: NexusGenRootTypes['UserRole'][]; // [UserRole!]! + similar_makers: NexusGenRootTypes['User'][]; // [User!]! + skills: NexusGenRootTypes['UserSkill'][]; // [UserSkill!]! stories: NexusGenRootTypes['Story'][]; // [Story!]! + tournaments: NexusGenRootTypes['Tournament'][]; // [Tournament!]! twitter: string | null; // String walletsKeys: NexusGenRootTypes['WalletKey'][]; // [WalletKey!]! website: string | null; // String @@ -405,6 +430,7 @@ export interface NexusGenFieldTypes { profile: NexusGenRootTypes['User'] | null; // User projectsByCategory: NexusGenRootTypes['Project'][]; // [Project!]! searchProjects: NexusGenRootTypes['Project'][]; // [Project!]! + similarMakers: NexusGenRootTypes['User'][]; // [User!]! } Question: { // field return type author: NexusGenRootTypes['Author']; // Author! @@ -442,6 +468,17 @@ 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! + id: number; // Int! + start_date: NexusGenScalars['Date']; // Date! + tags: NexusGenRootTypes['Tag'][]; // [Tag!]! + thumbnail_image: string; // String! + title: string; // String! + website: string; // String! + } User: { // field return type avatar: string; // String! bio: string | null; // String @@ -455,10 +492,24 @@ export interface NexusGenFieldTypes { location: string | null; // String name: string; // String! role: string | null; // String + roles: NexusGenRootTypes['UserRole'][]; // [UserRole!]! + similar_makers: NexusGenRootTypes['User'][]; // [User!]! + skills: NexusGenRootTypes['UserSkill'][]; // [UserSkill!]! stories: NexusGenRootTypes['Story'][]; // [Story!]! + tournaments: NexusGenRootTypes['Tournament'][]; // [Tournament!]! twitter: string | null; // String website: string | null; // String } + UserRole: { // field return type + icon: string; // String! + id: number; // Int! + level: NexusGenEnums['RoleLevelEnum']; // RoleLevelEnum! + title: string; // String! + } + UserSkill: { // field return type + id: number; // Int! + title: string; // String! + } Vote: { // field return type amount_in_sat: number; // Int! id: number; // Int! @@ -485,7 +536,11 @@ export interface NexusGenFieldTypes { location: string | null; // String name: string; // String! role: string | null; // String + roles: NexusGenRootTypes['UserRole'][]; // [UserRole!]! + similar_makers: NexusGenRootTypes['User'][]; // [User!]! + skills: NexusGenRootTypes['UserSkill'][]; // [UserSkill!]! stories: NexusGenRootTypes['Story'][]; // [Story!]! + tournaments: NexusGenRootTypes['Tournament'][]; // [Tournament!]! twitter: string | null; // String website: string | null; // String } @@ -606,7 +661,11 @@ export interface NexusGenFieldTypeNames { nostr_prv_key: 'String' nostr_pub_key: 'String' role: 'String' + roles: 'UserRole' + similar_makers: 'User' + skills: 'UserSkill' stories: 'Story' + tournaments: 'Tournament' twitter: 'String' walletsKeys: 'WalletKey' website: 'String' @@ -654,6 +713,7 @@ export interface NexusGenFieldTypeNames { profile: 'User' projectsByCategory: 'Project' searchProjects: 'Project' + similarMakers: 'User' } Question: { // field return type name author: 'Author' @@ -691,6 +751,17 @@ export interface NexusGenFieldTypeNames { isOfficial: 'Boolean' title: 'String' } + Tournament: { // field return type name + cover_image: 'String' + description: 'String' + end_date: 'Date' + id: 'Int' + start_date: 'Date' + tags: 'Tag' + thumbnail_image: 'String' + title: 'String' + website: 'String' + } User: { // field return type name avatar: 'String' bio: 'String' @@ -704,10 +775,24 @@ export interface NexusGenFieldTypeNames { location: 'String' name: 'String' role: 'String' + roles: 'UserRole' + similar_makers: 'User' + skills: 'UserSkill' stories: 'Story' + tournaments: 'Tournament' twitter: 'String' website: 'String' } + UserRole: { // field return type name + icon: 'String' + id: 'Int' + level: 'RoleLevelEnum' + title: 'String' + } + UserSkill: { // field return type name + id: 'Int' + title: 'String' + } Vote: { // field return type name amount_in_sat: 'Int' id: 'Int' @@ -734,7 +819,11 @@ export interface NexusGenFieldTypeNames { location: 'String' name: 'String' role: 'String' + roles: 'UserRole' + similar_makers: 'User' + skills: 'UserSkill' stories: 'Story' + tournaments: 'Tournament' twitter: 'String' website: 'String' } @@ -833,6 +922,9 @@ export interface NexusGenArgTypes { skip?: number | null; // Int take: number | null; // Int } + similarMakers: { // args + id: number; // Int! + } } } diff --git a/api/functions/graphql/schema.graphql b/api/functions/graphql/schema.graphql index 8a3947c..f6f89f6 100644 --- a/api/functions/graphql/schema.graphql +++ b/api/functions/graphql/schema.graphql @@ -31,7 +31,11 @@ interface BaseUser { location: String name: String! role: String + roles: [UserRole!]! + similar_makers: [User!]! + skills: [UserSkill!]! stories: [Story!]! + tournaments: [Tournament!]! twitter: String website: String } @@ -137,7 +141,11 @@ type MyProfile implements BaseUser { nostr_prv_key: String nostr_pub_key: String role: String + roles: [UserRole!]! + similar_makers: [User!]! + skills: [UserSkill!]! stories: [Story!]! + tournaments: [Tournament!]! twitter: String walletsKeys: [WalletKey!]! website: String @@ -221,6 +229,7 @@ type Query { profile(id: Int!): User 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!]! } type Question implements PostBase { @@ -237,6 +246,14 @@ type Question implements PostBase { votes_count: Int! } +enum RoleLevelEnum { + Advanced + Beginner + Hobbyist + Intermediate + Pro +} + type Story implements PostBase { author: Author! body: String! @@ -271,6 +288,18 @@ type Tag { title: String! } +type Tournament { + cover_image: String! + description: String! + end_date: Date! + id: Int! + start_date: Date! + tags: [Tag!]! + thumbnail_image: String! + title: String! + website: String! +} + type User implements BaseUser { avatar: String! bio: String @@ -284,7 +313,11 @@ type User implements BaseUser { location: String name: String! role: String + roles: [UserRole!]! + similar_makers: [User!]! + skills: [UserSkill!]! stories: [Story!]! + tournaments: [Tournament!]! twitter: String website: String } @@ -294,6 +327,18 @@ input UserKeyInputType { name: String! } +type UserRole { + icon: String! + id: Int! + level: RoleLevelEnum! + title: String! +} + +type UserSkill { + id: Int! + title: String! +} + enum VOTE_ITEM_TYPE { Bounty PostComment diff --git a/api/functions/graphql/types/tournaments.js b/api/functions/graphql/types/tournaments.js new file mode 100644 index 0000000..9f04081 --- /dev/null +++ b/api/functions/graphql/types/tournaments.js @@ -0,0 +1,55 @@ +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 b633464..3d4d06b 100644 --- a/api/functions/graphql/types/users.js +++ b/api/functions/graphql/types/users.js @@ -1,8 +1,9 @@ const { prisma } = require('../../../prisma'); -const { objectType, extendType, intArg, nonNull, inputObjectType, interfaceType, list } = require("nexus"); +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'); @@ -24,6 +25,39 @@ const BaseUser = interfaceType({ t.string('linkedin') t.string('bio') t.string('location') + t.nonNull.list.nonNull.field('roles', { + type: UserRole, + resolve: (parent) => { + return [] + } + }) + t.nonNull.list.nonNull.field('skills', { + type: UserSkill, + resolve: (parent) => { + return [] + } + }) + t.nonNull.list.nonNull.field('tournaments', { + type: Tournament, + resolve: (parent) => { + return [] + } + }) + t.nonNull.list.nonNull.field('similar_makers', { + type: "User", + resolve(parent,) { + return prisma.user.findMany({ + where: { + AND: { + id: { + not: parent.id + } + } + }, + take: 3, + }) + } + }) t.nonNull.list.nonNull.field('stories', { @@ -40,6 +74,35 @@ const BaseUser = interfaceType({ }, }) +const RoleLevelEnum = enumType({ + name: 'RoleLevelEnum', + members: { + Beginner: 0, + Hobbyist: 1, + Intermediate: 2, + Advanced: 3, + Pro: 4, + }, +}); + +const UserRole = objectType({ + name: 'UserRole', + definition(t) { + t.nonNull.int('id'); + t.nonNull.string('title'); + t.nonNull.string('icon'); + t.nonNull.field('level', { type: RoleLevelEnum }) + } +}) + +const UserSkill = objectType({ + name: 'UserSkill', + definition(t) { + t.nonNull.int('id'); + t.nonNull.string('title'); + } +}) + const User = objectType({ name: 'User', definition(t) { @@ -93,6 +156,30 @@ const profile = extendType({ } }) +const similarMakers = extendType({ + type: "Query", + definition(t) { + t.nonNull.list.nonNull.field('similarMakers', { + type: "User", + args: { + id: nonNull(intArg()) + }, + async resolve(parent, { id }, ctx) { + return prisma.user.findMany({ + where: { + AND: { + id: { + not: id + } + } + }, + take: 3, + }) + } + }) + } +}) + const ProfileDetailsInput = inputObjectType({ name: 'ProfileDetailsInput', definition(t) { @@ -228,6 +315,7 @@ const updateUserPreferences = extendType({ module.exports = { // Types + BaseUser, User, MyProfile, @@ -235,6 +323,7 @@ module.exports = { // Queries me, profile, + similarMakers, // Mutations updateProfileDetails, updateUserPreferences, diff --git a/src/features/Posts/Components/TrendingCard/TrendingCard.tsx b/src/features/Posts/Components/TrendingCard/TrendingCard.tsx index 99f5cfd..8404bf5 100644 --- a/src/features/Posts/Components/TrendingCard/TrendingCard.tsx +++ b/src/features/Posts/Components/TrendingCard/TrendingCard.tsx @@ -14,7 +14,7 @@ export default function TrendingCard() { return ( -

Trending on BOLT.FUN

+

Trending on BOLT🔩FUN