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