From 9e8d302c31194765b81ffae3d03620c82fdba7c5 Mon Sep 17 00:00:00 2001 From: Zeke Abshire Date: Tue, 18 Apr 2023 20:18:46 -0500 Subject: [PATCH] Put meaningful data on each page --- prisma/schema.prisma | 138 +++++++++--------- .../projects/DisplayProjectCard.tsx | 15 ++ src/components/projects/EditProjectCard.tsx | 18 +++ src/components/projects/ProjectCard.tsx | 17 --- src/pages/auth/sign-in/index.tsx | 11 +- src/pages/discover/archive/index.tsx | 4 +- src/pages/discover/index.tsx | 2 +- src/pages/discover/proposals/index.tsx | 4 +- src/pages/discover/revisions/index.tsx | 12 +- src/pages/profile/[username].tsx | 24 ++- src/pages/projects/[projectId].tsx | 24 +++ src/pages/projects/index.tsx | 17 +++ src/server/api/routers/profiles.ts | 1 + src/server/api/routers/projects.ts | 19 ++- src/utils/filters.ts | 7 + 15 files changed, 204 insertions(+), 109 deletions(-) create mode 100644 src/components/projects/DisplayProjectCard.tsx create mode 100644 src/components/projects/EditProjectCard.tsx delete mode 100644 src/components/projects/ProjectCard.tsx create mode 100644 src/pages/projects/[projectId].tsx diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 70f525a..da26048 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -1,100 +1,102 @@ generator client { - provider = "prisma-client-js" + provider = "prisma-client-js" } datasource db { - provider = "mysql" - url = env("DATABASE_URL") - relationMode = "prisma" + provider = "mysql" + url = env("DATABASE_URL") + relationMode = "prisma" } model Account { - id String @id @default(cuid()) - userId String - type String - provider String - providerAccountId String - refresh_token String? @db.Text - access_token String? @db.Text - expires_at Int? - token_type String? - scope String? - id_token String? @db.Text - session_state String? - user User @relation(fields: [userId], references: [id], onDelete: Cascade) + id String @id @default(cuid()) + userId String + type String + provider String + providerAccountId String + refresh_token String? @db.Text + access_token String? @db.Text + expires_at Int? + token_type String? + scope String? + id_token String? @db.Text + session_state String? + user User @relation(fields: [userId], references: [id], onDelete: Cascade) - @@unique([provider, providerAccountId]) - @@index([userId]) + @@unique([provider, providerAccountId]) + @@index([userId]) } model Session { - id String @id @default(cuid()) - sessionToken String @unique - userId String - expires DateTime - user User @relation(fields: [userId], references: [id], onDelete: Cascade) + id String @id @default(cuid()) + sessionToken String @unique + userId String + expires DateTime + user User @relation(fields: [userId], references: [id], onDelete: Cascade) - @@index([userId]) + @@index([userId]) } model VerificationToken { - identifier String - token String @unique - expires DateTime + identifier String + token String @unique + expires DateTime - @@unique([identifier, token]) + @@unique([identifier, token]) } model User { - id String @id @default(cuid()) - - email String @unique - emailVerified DateTime? - username String? @unique - name String? - bio String? - image String? - - accounts Account[] - sessions Session[] - - authoredProjects Project[] @relation("author") - projects Project[] @relation("members") + id String @id @default(cuid()) + username String? @unique + name String? + email String @unique + emailVerified DateTime? + image String? + bio String? + accounts Account[] + sessions Session[] + authoredProjects Project[] @relation("author") + projects Project[] @relation("members") } model Project { - id String @id @default(cuid()) - createdAt DateTime @default(now()) + id String @id @default(cuid()) + createdAt DateTime @default(now()) + title String + description String + authorId String + bannerImageUrl String? + state ProjectLifecycle @default(PROPOSAL) + author User @relation("author", fields: [authorId], references: [id]) + members User[] @relation("members") + previews ProjectPreview[] - title String - description String - bannerImageUrl String? - - authorId String - author User @relation("author", fields: [authorId], references: [id]) - members User[] @relation("members") - - state ProjectLifecycle @default(PROPOSAL) - previews ProjectPreview[] - - @@index([authorId]) + @@index([authorId]) } model ProjectPreview { - projectState ProjectLifecycle - projectId String - project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) + projectState ProjectLifecycle + projectId String + title String? + description String? + cardImageUrl String? + project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) - title String? - description String? - cardImageUrl String? + @@unique([projectId, projectState]) +} - @@unique([projectId, projectState]) +model members { + A String + B String + + @@unique([A, B], map: "_members_AB_unique") + @@index([B], map: "_members_B_index") + @@map("_members") } enum ProjectLifecycle { - PROPOSAL - IN_PROGRESS - REVISION - COMPLETE + PROPOSAL + IN_PROGRESS + REVISION + COMPLETE } diff --git a/src/components/projects/DisplayProjectCard.tsx b/src/components/projects/DisplayProjectCard.tsx new file mode 100644 index 0000000..9d878f4 --- /dev/null +++ b/src/components/projects/DisplayProjectCard.tsx @@ -0,0 +1,15 @@ +import type { Project } from "@prisma/client"; +import { formatDate } from "@utils/filters"; + +export const DisplayProjectCard: React.FC<{ project: Project }> = ({ + project, +}) => { + return ( +
+

{project.title}

+

{formatDate(project.createdAt)}

+

{project.state}

+

{project.description}

+
+ ); +}; diff --git a/src/components/projects/EditProjectCard.tsx b/src/components/projects/EditProjectCard.tsx new file mode 100644 index 0000000..4da84af --- /dev/null +++ b/src/components/projects/EditProjectCard.tsx @@ -0,0 +1,18 @@ +import type { Project } from "@prisma/client"; +import { formatDate } from "@utils/filters"; +import Link from "next/link"; + +export const EditProjectCard: React.FC<{ project: Project }> = ({ + project, +}) => { + return ( + +
+

{project.title}

+

{formatDate(project.createdAt)}

+

{project.state}

+

{project.description}

+
+ + ); +}; diff --git a/src/components/projects/ProjectCard.tsx b/src/components/projects/ProjectCard.tsx deleted file mode 100644 index 0366cd8..0000000 --- a/src/components/projects/ProjectCard.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import Button from "@components/Button"; -import type { Project } from "@prisma/client"; -import dayjs from "dayjs"; -import relativeTime from "dayjs/plugin/relativeTime"; - -dayjs.extend(relativeTime); - -export const ProjectCard: React.FC<{ project: Project }> = ({ project }) => { - return ( -
-

{project.title}

-

{dayjs(project.createdAt).fromNow()}

-

{project.state}

-

{project.description}

-
- ); -}; diff --git a/src/pages/auth/sign-in/index.tsx b/src/pages/auth/sign-in/index.tsx index c0f82da..adcab07 100644 --- a/src/pages/auth/sign-in/index.tsx +++ b/src/pages/auth/sign-in/index.tsx @@ -80,7 +80,16 @@ export async function getServerSideProps(ctx: GetServerSidePropsContext) { const session = await getServerAuthSession(ctx); if (!session) { - const providers = await getProviders(); + // const providers = await getProviders(); + const providers = { + google: { + id: "google", + name: "Google", + type: "oauth", + signinUrl: "http://localhost:3000/api/auth/signin/google", + callbackUrl: "http://localhost:3000/api/auth/callback/google", + }, + }; return { props: { providers, diff --git a/src/pages/discover/archive/index.tsx b/src/pages/discover/archive/index.tsx index eb66d22..00d8f02 100644 --- a/src/pages/discover/archive/index.tsx +++ b/src/pages/discover/archive/index.tsx @@ -1,7 +1,7 @@ import { DiscoverLayout } from "@components/layouts"; import { api } from "@utils/api"; import type { InferGetServerSidePropsType, NextPage } from "next"; -import { ProjectCard } from "@components/projects/ProjectCard"; +import { DisplayProjectCard } from "@components/projects/DisplayProjectCard"; import { requireAuth } from "@components/HOC/requireAuth"; const Discover: NextPage< @@ -18,7 +18,7 @@ const Discover: NextPage<

Loading ...

) : ( data?.map((project) => ( - + )) )} diff --git a/src/pages/discover/index.tsx b/src/pages/discover/index.tsx index ff7bbb3..aa5e7fe 100644 --- a/src/pages/discover/index.tsx +++ b/src/pages/discover/index.tsx @@ -7,7 +7,7 @@ import type { InferGetServerSidePropsType, NextPage, } from "next"; -import { ProjectCard } from "@components/projects/ProjectCard"; +import { ProjectCard } from "@components/projects/DisplayProjectCard"; import { requireAuth } from "@components/HOC/requireAuth"; const Discover: NextPage< diff --git a/src/pages/discover/proposals/index.tsx b/src/pages/discover/proposals/index.tsx index b151e07..dc470ef 100644 --- a/src/pages/discover/proposals/index.tsx +++ b/src/pages/discover/proposals/index.tsx @@ -1,7 +1,7 @@ import { DiscoverLayout } from "@components/layouts"; import { api } from "@utils/api"; import type { InferGetServerSidePropsType, NextPage } from "next"; -import { ProjectCard } from "@components/projects/ProjectCard"; +import { DisplayProjectCard } from "@components/projects/DisplayProjectCard"; import { requireAuth } from "@components/HOC/requireAuth"; const Discover: NextPage< @@ -18,7 +18,7 @@ const Discover: NextPage<

Loading ...

) : ( data?.map((project) => ( - + )) )} diff --git a/src/pages/discover/revisions/index.tsx b/src/pages/discover/revisions/index.tsx index a5b37f3..77758ff 100644 --- a/src/pages/discover/revisions/index.tsx +++ b/src/pages/discover/revisions/index.tsx @@ -1,13 +1,7 @@ import { DiscoverLayout } from "@components/layouts"; -import { getServerAuthSession } from "@server/auth"; import { api } from "@utils/api"; -import type { - GetServerSideProps, - GetServerSidePropsContext, - InferGetServerSidePropsType, - NextPage, -} from "next"; -import { ProjectCard } from "@components/projects/ProjectCard"; +import type { InferGetServerSidePropsType, NextPage } from "next"; +import { DisplayProjectCard } from "@components/projects/DisplayProjectCard"; import { requireAuth } from "@components/HOC/requireAuth"; const Discover: NextPage< @@ -24,7 +18,7 @@ const Discover: NextPage<

Loading ...

) : ( data?.map((project) => ( - + )) )} diff --git a/src/pages/profile/[username].tsx b/src/pages/profile/[username].tsx index 689ce18..2602698 100644 --- a/src/pages/profile/[username].tsx +++ b/src/pages/profile/[username].tsx @@ -16,16 +16,24 @@ const Profile: NextPage<

Profile

{data && ( <> +

{data.name}

{data.username}

-

{data.name}

{data.bio}

-

- {data.projects.map((m) => ( - <> -

{m.title}

- - ))} -

+ +

My Projects

+ {data.authoredProjects.map((m) => ( + <> +

{m.title}

+

{m.description}

+ + ))} +

Projects I{"'"}ve Worked On

+ {data.projects.map((m) => ( + <> +

{m.title}

+

{m.description}

+ + ))} )} diff --git a/src/pages/projects/[projectId].tsx b/src/pages/projects/[projectId].tsx new file mode 100644 index 0000000..df779cf --- /dev/null +++ b/src/pages/projects/[projectId].tsx @@ -0,0 +1,24 @@ +import { requireAuth } from "@components/HOC/requireAuth"; +import { MainLayout } from "@components/layouts"; +import { api } from "@utils/api"; +import type { InferGetServerSidePropsType, NextPage } from "next"; + +const SpecificProject: NextPage< + InferGetServerSidePropsType +> = ({ projectId }) => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const { data } = api.projects.getProjectById.useQuery({ projectId }); + + return ( + +

{data?.id}

+
+ ); +}; + +export default SpecificProject; + +// eslint-disable-next-line @typescript-eslint/require-await +export const getServerSideProps = requireAuth(async (ctx) => { + return { props: { projectId: ctx.params?.projectId } }; +}); diff --git a/src/pages/projects/index.tsx b/src/pages/projects/index.tsx index 517f30a..4363969 100644 --- a/src/pages/projects/index.tsx +++ b/src/pages/projects/index.tsx @@ -1,11 +1,28 @@ import type { NextPage } from "next"; import { MainLayout } from "@components/layouts"; import { requireAuth } from "@components/HOC/requireAuth"; +import { api } from "@utils/api"; +import { useMemo } from "react"; +import { EditProjectCard } from "@components/projects/EditProjectCard"; const Projects: NextPage = () => { + const { data } = api.projects.getAllByCurrentUser.useQuery(); + + const sortedProjects = useMemo(() => { + if (!data) return []; + + const projects = data.projects.concat(data.authoredProjects); + return projects.sort( + (a, b) => b.createdAt.getTime() - a.createdAt.getTime() + ); + }, [data]); + return (

Projects

+ {sortedProjects.map((p) => ( + + ))}
); }; diff --git a/src/server/api/routers/profiles.ts b/src/server/api/routers/profiles.ts index 0a8a7db..bed740f 100644 --- a/src/server/api/routers/profiles.ts +++ b/src/server/api/routers/profiles.ts @@ -13,6 +13,7 @@ export const profileRouter = createTRPCRouter({ name: true, bio: true, image: true, + authoredProjects: true, projects: true, }, }); diff --git a/src/server/api/routers/projects.ts b/src/server/api/routers/projects.ts index 1741c9d..1515dcf 100644 --- a/src/server/api/routers/projects.ts +++ b/src/server/api/routers/projects.ts @@ -1,5 +1,5 @@ import { proposalSchema } from "@utils/constants/schema/project"; -import { Project, ProjectLifecycle } from "@prisma/client"; +import { ProjectLifecycle } from "@prisma/client"; import { z } from "zod"; import { createTRPCRouter, publicProcedure, protectedProcedure } from "../trpc"; @@ -11,6 +11,12 @@ export const projectsRouter = createTRPCRouter({ orderBy: [{ createdAt: "desc" }], }); }), + getAllByCurrentUser: protectedProcedure.query(({ ctx }) => { + return ctx.prisma.user.findUnique({ + where: { id: ctx.session.user.id }, + select: { authoredProjects: true, projects: true }, + }); + }), getAllByUserId: publicProcedure .input( z.object({ @@ -36,6 +42,17 @@ export const projectsRouter = createTRPCRouter({ orderBy: [{ createdAt: "desc" }], }); }), + getProjectById: publicProcedure + .input( + z.object({ + projectId: z.string(), + }) + ) + .query(({ ctx, input }) => { + return ctx.prisma.project.findUnique({ + where: { id: input.projectId }, + }); + }), createProposal: protectedProcedure .input(proposalSchema) .mutation(async ({ ctx, input }) => { diff --git a/src/utils/filters.ts b/src/utils/filters.ts index d38f818..b9a3697 100644 --- a/src/utils/filters.ts +++ b/src/utils/filters.ts @@ -1,3 +1,10 @@ +import dayjs from "dayjs"; +import relativeTime from "dayjs/plugin/relativeTime"; + +dayjs.extend(relativeTime); + +export const formatDate = (date: Date) => dayjs(date).fromNow(); + export const getQueryOrDefault = ( value: string | string[] | undefined, fallback: string