Put meaningful data on each page

This commit is contained in:
2023-04-18 20:18:46 -05:00
parent dc1e9c6947
commit 9e8d302c31
15 changed files with 204 additions and 109 deletions

View File

@@ -47,17 +47,14 @@ model VerificationToken {
model User {
id String @id @default(cuid())
email String @unique
emailVerified DateTime?
username String? @unique
name String?
bio String?
email String @unique
emailVerified DateTime?
image String?
bio String?
accounts Account[]
sessions Session[]
authoredProjects Project[] @relation("author")
projects Project[] @relation("members")
}
@@ -65,16 +62,13 @@ model User {
model Project {
id String @id @default(cuid())
createdAt DateTime @default(now())
title String
description String
bannerImageUrl String?
authorId String
bannerImageUrl String?
state ProjectLifecycle @default(PROPOSAL)
author User @relation("author", fields: [authorId], references: [id])
members User[] @relation("members")
state ProjectLifecycle @default(PROPOSAL)
previews ProjectPreview[]
@@index([authorId])
@@ -83,15 +77,23 @@ model Project {
model ProjectPreview {
projectState ProjectLifecycle
projectId String
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
title String?
description String?
cardImageUrl String?
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
@@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

View File

@@ -0,0 +1,15 @@
import type { Project } from "@prisma/client";
import { formatDate } from "@utils/filters";
export const DisplayProjectCard: React.FC<{ project: Project }> = ({
project,
}) => {
return (
<div key={project.id} className="mb-10">
<h4 className="text-r-2xl font-medium">{project.title}</h4>
<p className="text-r-sm">{formatDate(project.createdAt)}</p>
<p className="text-r-sm">{project.state}</p>
<p className="text-r-lg">{project.description}</p>
</div>
);
};

View File

@@ -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 (
<Link href={`/projects/${project.id}`}>
<div className="mb-10 rounded border-[6px] border-fg py-2 px-3">
<h4 className="text-r-2xl font-medium">{project.title}</h4>
<p className="text-r-sm">{formatDate(project.createdAt)}</p>
<p className="text-r-sm">{project.state}</p>
<p className="text-r-lg">{project.description}</p>
</div>
</Link>
);
};

View File

@@ -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 (
<div key={project.id} className="mb-10">
<h4 className="text-r-2xl font-medium">{project.title}</h4>
<p className="text-r-sm">{dayjs(project.createdAt).fromNow()}</p>
<p className="text-r-sm">{project.state}</p>
<p className="text-r-lg">{project.description}</p>
</div>
);
};

View File

@@ -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,

View File

@@ -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<
<p>Loading ...</p>
) : (
data?.map((project) => (
<ProjectCard key={project.id} project={project} />
<DisplayProjectCard key={project.id} project={project} />
))
)}
</DiscoverLayout>

View File

@@ -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<

View File

@@ -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<
<p>Loading ...</p>
) : (
data?.map((project) => (
<ProjectCard key={project.id} project={project} />
<DisplayProjectCard key={project.id} project={project} />
))
)}
</DiscoverLayout>

View File

@@ -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<
<p>Loading ...</p>
) : (
data?.map((project) => (
<ProjectCard key={project.id} project={project} />
<DisplayProjectCard key={project.id} project={project} />
))
)}
</DiscoverLayout>

View File

@@ -16,16 +16,24 @@ const Profile: NextPage<
<h1 className="text-r-5xl font-bold text-primary">Profile</h1>
{data && (
<>
<h2 className="text-r-4xl">{data.name}</h2>
<p>{data.username}</p>
<p>{data.name}</p>
<p>{data.bio}</p>
<p>
<h3 className="text-r-3xl">My Projects</h3>
{data.authoredProjects.map((m) => (
<>
<p>{m.title}</p>
<p>{m.description}</p>
</>
))}
<h3 className="text-r-3xl">Projects I{"'"}ve Worked On</h3>
{data.projects.map((m) => (
<>
<p>{m.title}</p>
<p>{m.description}</p>
</>
))}
</p>
</>
)}
</MainLayout>

View File

@@ -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<typeof getServerSideProps>
> = ({ projectId }) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const { data } = api.projects.getProjectById.useQuery({ projectId });
return (
<MainLayout>
<p>{data?.id}</p>
</MainLayout>
);
};
export default SpecificProject;
// eslint-disable-next-line @typescript-eslint/require-await
export const getServerSideProps = requireAuth(async (ctx) => {
return { props: { projectId: ctx.params?.projectId } };
});

View File

@@ -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 (
<MainLayout>
<h1 className="text-r-5xl font-bold text-primary">Projects</h1>
{sortedProjects.map((p) => (
<EditProjectCard key={p.id} project={p} />
))}
</MainLayout>
);
};

View File

@@ -13,6 +13,7 @@ export const profileRouter = createTRPCRouter({
name: true,
bio: true,
image: true,
authoredProjects: true,
projects: true,
},
});

View File

@@ -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 }) => {

View File

@@ -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