From c2fcc294916d4fd27c8140d81fad49980cbc851e Mon Sep 17 00:00:00 2001 From: Gram Liu Date: Mon, 4 Dec 2023 20:14:55 -0800 Subject: [PATCH] Create projects table --- apps/web/app/page.tsx | 27 ++++- apps/web/package.json | 3 + apps/web/src/components/header.tsx | 6 +- apps/web/src/components/projects-table.tsx | 48 +++++++++ packages/database/package.json | 4 +- packages/database/prisma/schema.prisma | 3 +- packages/ui/src/components/ui/index.tsx | 1 + packages/ui/src/components/ui/table.tsx | 117 +++++++++++++++++++++ pnpm-lock.yaml | 51 +++++---- 9 files changed, 232 insertions(+), 28 deletions(-) create mode 100644 apps/web/src/components/projects-table.tsx create mode 100644 packages/ui/src/components/ui/table.tsx diff --git a/apps/web/app/page.tsx b/apps/web/app/page.tsx index 01beb43..5f7f6a4 100644 --- a/apps/web/app/page.tsx +++ b/apps/web/app/page.tsx @@ -1,15 +1,32 @@ -"use client"; -import "@tldraw/tldraw/tldraw.css"; -import { Toaster } from "@ui/components"; +import { auth } from "@clerk/nextjs"; +import { SkeletonPlaceholder, Toaster } from "@ui/components"; +import { prisma } from "database"; +import { Suspense } from "react"; import Header from "~/components/header"; +import ProjectsTable from "~/components/projects-table"; + +export default async function IndexPage() { + const { userId } = auth(); + + const projects = await prisma.project.findMany({ + where: { + userId: userId, + }, + include: { + repository: true, + }, + }); -export default function IndexPage() { return (

Projects

-
+
+ }> + + +
); diff --git a/apps/web/package.json b/apps/web/package.json index 702cd30..7bc3ed8 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -14,7 +14,9 @@ "@tldraw/tldraw": "2.0.0-canary.699502d8c479", "axios": "^1.5.1", "clsx": "^2.0.0", + "database": "workspace:*", "lucide-react": "^0.293.0", + "luxon": "^3.4.4", "million": "^2.6.4", "next": "^14.0.3", "react": "^18.2.0", @@ -24,6 +26,7 @@ "zod": "^3.22.4" }, "devDependencies": { + "@types/luxon": "^3.3.7", "@types/node": "^17.0.12", "@types/react": "^18.0.22", "@types/react-dom": "^18.0.7", diff --git a/apps/web/src/components/header.tsx b/apps/web/src/components/header.tsx index 205e670..b219183 100644 --- a/apps/web/src/components/header.tsx +++ b/apps/web/src/components/header.tsx @@ -10,7 +10,7 @@ import { DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, - DropdownMenuTrigger + DropdownMenuTrigger, } from "@ui/components"; import { User } from "lucide-react"; import HomeIcon from "./home-icon"; @@ -49,7 +49,9 @@ export default function Header({ children }: Props) { {user?.fullName ?? "My Profile"} - {user?.primaryEmailAddress.emailAddress ?? ""} + + {user?.primaryEmailAddress.emailAddress ?? ""} + diff --git a/apps/web/src/components/projects-table.tsx b/apps/web/src/components/projects-table.tsx new file mode 100644 index 0000000..cca2bf1 --- /dev/null +++ b/apps/web/src/components/projects-table.tsx @@ -0,0 +1,48 @@ +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@ui/components"; +import { Project, Repository } from "database"; +import { DateTime } from "luxon"; + +type ProjectWithRepository = Project & { + repository: Repository; +}; + +interface Props { + projects: ProjectWithRepository[]; +} + +/** + * Table for displaying the current user's projects + */ +export default function ProjectsTable({ projects }: Props) { + return ( + + + + Name + GitHub + Branch + Created + + + + {projects.map((project) => { + return ( + + {project.name} + {project.repository.fullName} + {project.branch} + {DateTime.fromJSDate(project.createdAt).toFormat("dd MMM yyyy")} + + ); + })} + +
+ ); +} diff --git a/packages/database/package.json b/packages/database/package.json index 41a67a6..73e1b3f 100644 --- a/packages/database/package.json +++ b/packages/database/package.json @@ -25,7 +25,7 @@ }, "dependencies": { "@paralleldrive/cuid2": "^2.2.2", - "@prisma/client": "^5.5.2", + "@prisma/client": "^5.6.0", "@t3-oss/env-core": "^0.7.1", "core": "link:@t3-oss/env/core", "zod": "^3.22.4" @@ -34,7 +34,7 @@ "@types/node": "^17.0.12", "config": "workspace:*", "eslint": "^8.12.0", - "prisma": "^5.5.2", + "prisma": "^5.6.0", "rimraf": "^3.0.2", "tsconfig": "workspace:*", "tsup": "^5.11.13", diff --git a/packages/database/prisma/schema.prisma b/packages/database/prisma/schema.prisma index 8af24ef..2d391b5 100644 --- a/packages/database/prisma/schema.prisma +++ b/packages/database/prisma/schema.prisma @@ -1,6 +1,5 @@ generator client { provider = "prisma-client-js" - binaryTargets = ["native", "debian-openssl-1.1.x", "linux-musl-openssl-3.0.x"] } datasource db { @@ -46,6 +45,8 @@ model Project { id String @id @map("_id") userId String + name String + repositoryId String @unique repository Repository @relation(fields: [repositoryId], references: [id]) branch String diff --git a/packages/ui/src/components/ui/index.tsx b/packages/ui/src/components/ui/index.tsx index 6ddf99f..5c8b276 100644 --- a/packages/ui/src/components/ui/index.tsx +++ b/packages/ui/src/components/ui/index.tsx @@ -6,6 +6,7 @@ export * from "./dialog"; export * from "./dropdown-menu"; export * from "./popover"; export * from "./skeleton"; +export * from "./table"; export * from "./tabs"; export * from "./toast"; export * from "./toaster"; diff --git a/packages/ui/src/components/ui/table.tsx b/packages/ui/src/components/ui/table.tsx new file mode 100644 index 0000000..0e554b6 --- /dev/null +++ b/packages/ui/src/components/ui/table.tsx @@ -0,0 +1,117 @@ +import * as React from "react" + +import { cn } from "@ui/lib/utils" + +const Table = React.forwardRef< + HTMLTableElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+ + +)) +Table.displayName = "Table" + +const TableHeader = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableHeader.displayName = "TableHeader" + +const TableBody = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableBody.displayName = "TableBody" + +const TableFooter = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + tr]:last:border-b-0", + className + )} + {...props} + /> +)) +TableFooter.displayName = "TableFooter" + +const TableRow = React.forwardRef< + HTMLTableRowElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableRow.displayName = "TableRow" + +const TableHead = React.forwardRef< + HTMLTableCellElement, + React.ThHTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +TableHead.displayName = "TableHead" + +const TableCell = React.forwardRef< + HTMLTableCellElement, + React.TdHTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableCell.displayName = "TableCell" + +const TableCaption = React.forwardRef< + HTMLTableCaptionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +TableCaption.displayName = "TableCaption" + +export { + Table, + TableHeader, + TableBody, + TableFooter, + TableHead, + TableRow, + TableCell, + TableCaption, +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f623643..880934b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -141,9 +141,15 @@ importers: clsx: specifier: ^2.0.0 version: 2.0.0 + database: + specifier: workspace:* + version: link:../../packages/database lucide-react: specifier: ^0.293.0 version: 0.293.0(react@18.2.0) + luxon: + specifier: ^3.4.4 + version: 3.4.4 million: specifier: ^2.6.4 version: 2.6.4 @@ -166,6 +172,9 @@ importers: specifier: ^3.22.4 version: 3.22.4 devDependencies: + '@types/luxon': + specifier: ^3.3.7 + version: 3.3.7 '@types/node': specifier: ^17.0.12 version: 17.0.45 @@ -181,9 +190,6 @@ importers: config: specifier: workspace:* version: link:../../packages/config - database: - specifier: workspace:* - version: link:../../packages/database eslint: specifier: ^7.32.0 version: 7.32.0 @@ -225,8 +231,8 @@ importers: specifier: ^2.2.2 version: 2.2.2 '@prisma/client': - specifier: ^5.5.2 - version: 5.5.2(prisma@5.5.2) + specifier: ^5.6.0 + version: 5.6.0(prisma@5.6.0) '@t3-oss/env-core': specifier: ^0.7.1 version: 0.7.1(typescript@4.9.5)(zod@3.22.4) @@ -247,8 +253,8 @@ importers: specifier: ^8.12.0 version: 8.52.0 prisma: - specifier: ^5.5.2 - version: 5.5.2 + specifier: ^5.6.0 + version: 5.6.0 rimraf: specifier: ^3.0.2 version: 3.0.2 @@ -2238,8 +2244,8 @@ packages: webcrypto-core: 1.7.7 dev: false - /@prisma/client@5.5.2(prisma@5.5.2): - resolution: {integrity: sha512-54XkqR8M+fxbzYqe+bIXimYnkkcGqgOh0dn0yWtIk6CQT4IUCAvNFNcQZwk2KqaLU+/1PHTSWrcHtx4XjluR5w==} + /@prisma/client@5.6.0(prisma@5.6.0): + resolution: {integrity: sha512-mUDefQFa1wWqk4+JhKPYq8BdVoFk9NFMBXUI8jAkBfQTtgx8WPx02U2HB/XbAz3GSUJpeJOKJQtNvaAIDs6sug==} engines: {node: '>=16.13'} requiresBuild: true peerDependencies: @@ -2248,16 +2254,16 @@ packages: prisma: optional: true dependencies: - '@prisma/engines-version': 5.5.1-1.aebc046ce8b88ebbcb45efe31cbe7d06fd6abc0a - prisma: 5.5.2 + '@prisma/engines-version': 5.6.0-32.e95e739751f42d8ca026f6b910f5a2dc5adeaeee + prisma: 5.6.0 dev: false - /@prisma/engines-version@5.5.1-1.aebc046ce8b88ebbcb45efe31cbe7d06fd6abc0a: - resolution: {integrity: sha512-O+qHFnZvAyOFk1tUco2/VdiqS0ym42a3+6CYLScllmnpbyiTplgyLt2rK/B9BTjYkSHjrgMhkG47S0oqzdIckA==} + /@prisma/engines-version@5.6.0-32.e95e739751f42d8ca026f6b910f5a2dc5adeaeee: + resolution: {integrity: sha512-UoFgbV1awGL/3wXuUK3GDaX2SolqczeeJ5b4FVec9tzeGbSWJboPSbT0psSrmgYAKiKnkOPFSLlH6+b+IyOwAw==} dev: false - /@prisma/engines@5.5.2: - resolution: {integrity: sha512-Be5hoNF8k+lkB3uEMiCHbhbfF6aj1GnrTBnn5iYFT7GEr3TsOEp1soviEcBR0tYCgHbxjcIxJMhdbvxALJhAqg==} + /@prisma/engines@5.6.0: + resolution: {integrity: sha512-Mt2q+GNJpU2vFn6kif24oRSBQv1KOkYaterQsi0k2/lA+dLvhRX6Lm26gon6PYHwUM8/h8KRgXIUMU0PCLB6bw==} requiresBuild: true /@protobufjs/aspromise@1.1.2: @@ -4126,6 +4132,10 @@ packages: '@types/koa': 2.13.10 dev: true + /@types/luxon@3.3.7: + resolution: {integrity: sha512-gKc9P2d4g5uYwmy4s/MO/yOVPmvHyvzka1YH6i5dM03UrFofHSmgc0D0ymbDRStFWHusk6cwwF6nhLm/ckBbbQ==} + dev: true + /@types/mime@1.3.4: resolution: {integrity: sha512-1Gjee59G25MrQGk8bsNvC6fxNiRgUlGn2wlhGf95a59DrprnnHk80FIMMFG9XHMdrfsuA119ht06QPDXA1Z7tw==} @@ -7700,6 +7710,11 @@ packages: react: 18.2.0 dev: false + /luxon@3.4.4: + resolution: {integrity: sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==} + engines: {node: '>=12'} + dev: false + /lz-string@1.5.0: resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true @@ -8439,13 +8454,13 @@ packages: hasBin: true dev: true - /prisma@5.5.2: - resolution: {integrity: sha512-WQtG6fevOL053yoPl6dbHV+IWgKo25IRN4/pwAGqcWmg7CrtoCzvbDbN9fXUc7QS2KK0LimHIqLsaCOX/vHl8w==} + /prisma@5.6.0: + resolution: {integrity: sha512-EEaccku4ZGshdr2cthYHhf7iyvCcXqwJDvnoQRAJg5ge2Tzpv0e2BaMCp+CbbDUwoVTzwgOap9Zp+d4jFa2O9A==} engines: {node: '>=16.13'} hasBin: true requiresBuild: true dependencies: - '@prisma/engines': 5.5.2 + '@prisma/engines': 5.6.0 /prismjs@1.27.0: resolution: {integrity: sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==}