diff --git a/package-lock.json b/package-lock.json index 999fc08..c7767a2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "@next-auth/prisma-adapter": "^1.0.5", "@next/font": "^13.1.6", "@prisma/client": "^4.9.0", - "@radix-ui/react-avatar": "^1.0.2", + "@radix-ui/react-avatar": "^1.0.3", "@radix-ui/react-dialog": "^1.0.3", "@radix-ui/react-dropdown-menu": "^2.0.4", "@radix-ui/react-hover-card": "^1.0.5", @@ -701,19 +701,138 @@ } }, "node_modules/@radix-ui/react-avatar": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.0.2.tgz", - "integrity": "sha512-XRL8z2l9V7hRLCPjHWg/34RBPZUGpmOjmsRSNvIh2DI28GyIWDChbcsDUVc63MzOItk6Q83Ob2KK8k2FUlXlGA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.0.3.tgz", + "integrity": "sha512-9ToF7YNex3Ste45LrAeTlKtONI9yVRt/zOS158iilIkW5K/Apeyb/TUQlcEFTEFvWr8Kzdi2ZYrm1/suiXPajQ==", "dependencies": { "@babel/runtime": "^7.13.10", - "@radix-ui/react-context": "1.0.0", - "@radix-ui/react-primitive": "1.0.2", - "@radix-ui/react-use-callback-ref": "1.0.0", - "@radix-ui/react-use-layout-effect": "1.0.0" + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1" }, "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0", "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-compose-refs": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz", + "integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-context": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.0.1.tgz", + "integrity": "sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-primitive": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz", + "integrity": "sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-slot": "1.0.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-slot": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz", + "integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz", + "integrity": "sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz", + "integrity": "sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, "node_modules/@radix-ui/react-collection": { @@ -2702,7 +2821,7 @@ "version": "18.0.10", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.10.tgz", "integrity": "sha512-E42GW/JA4Qv15wQdqJq8DL4JhNpB3prJgjgapN3qJT9K2zO5IIAQh4VXvCEDupoqAwnz0cY4RlXeC/ajX5SFHg==", - "dev": true, + "devOptional": true, "dependencies": { "@types/react": "*" } @@ -9108,15 +9227,67 @@ } }, "@radix-ui/react-avatar": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.0.2.tgz", - "integrity": "sha512-XRL8z2l9V7hRLCPjHWg/34RBPZUGpmOjmsRSNvIh2DI28GyIWDChbcsDUVc63MzOItk6Q83Ob2KK8k2FUlXlGA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.0.3.tgz", + "integrity": "sha512-9ToF7YNex3Ste45LrAeTlKtONI9yVRt/zOS158iilIkW5K/Apeyb/TUQlcEFTEFvWr8Kzdi2ZYrm1/suiXPajQ==", "requires": { "@babel/runtime": "^7.13.10", - "@radix-ui/react-context": "1.0.0", - "@radix-ui/react-primitive": "1.0.2", - "@radix-ui/react-use-callback-ref": "1.0.0", - "@radix-ui/react-use-layout-effect": "1.0.0" + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1" + }, + "dependencies": { + "@radix-ui/react-compose-refs": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz", + "integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==", + "requires": { + "@babel/runtime": "^7.13.10" + } + }, + "@radix-ui/react-context": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.0.1.tgz", + "integrity": "sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==", + "requires": { + "@babel/runtime": "^7.13.10" + } + }, + "@radix-ui/react-primitive": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz", + "integrity": "sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==", + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-slot": "1.0.2" + } + }, + "@radix-ui/react-slot": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz", + "integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==", + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1" + } + }, + "@radix-ui/react-use-callback-ref": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz", + "integrity": "sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==", + "requires": { + "@babel/runtime": "^7.13.10" + } + }, + "@radix-ui/react-use-layout-effect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz", + "integrity": "sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==", + "requires": { + "@babel/runtime": "^7.13.10" + } + } } }, "@radix-ui/react-collection": { @@ -10696,7 +10867,7 @@ "version": "18.0.10", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.10.tgz", "integrity": "sha512-E42GW/JA4Qv15wQdqJq8DL4JhNpB3prJgjgapN3qJT9K2zO5IIAQh4VXvCEDupoqAwnz0cY4RlXeC/ajX5SFHg==", - "dev": true, + "devOptional": true, "requires": { "@types/react": "*" } diff --git a/package.json b/package.json index f933493..7fa4dba 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "@next-auth/prisma-adapter": "^1.0.5", "@next/font": "^13.1.6", "@prisma/client": "^4.9.0", - "@radix-ui/react-avatar": "^1.0.2", + "@radix-ui/react-avatar": "^1.0.3", "@radix-ui/react-dialog": "^1.0.3", "@radix-ui/react-dropdown-menu": "^2.0.4", "@radix-ui/react-hover-card": "^1.0.5", diff --git a/src/components/projects/ProjectCards.tsx b/src/components/projects/ProjectCards.tsx index f1abf77..0a13f3f 100644 --- a/src/components/projects/ProjectCards.tsx +++ b/src/components/projects/ProjectCards.tsx @@ -145,7 +145,7 @@ const ProjectLifecycleIndicator: React.FC<{ state: ProjectLifecycle }> = ({ {lifecycleTooltips[state]} {/* */} diff --git a/src/pages/projects/[projectId].tsx b/src/pages/projects/[projectId].tsx index 399659a..dca5e72 100644 --- a/src/pages/projects/[projectId].tsx +++ b/src/pages/projects/[projectId].tsx @@ -1,5 +1,10 @@ import { MainLayout } from "@components/layouts"; -import { ProjectLifecycle } from "@prisma/client"; +import { + Project, + ProjectLifecycle, + ProjectPreview, + User, +} from "@prisma/client"; import { api } from "@utils/api"; import type { GetServerSidePropsContext, @@ -16,12 +21,35 @@ import { createProxySSGHelpers } from "@trpc/react-query/ssg"; import { MDX } from "@components/MDX"; import Image from "next/image"; import { FiEdit3 } from "react-icons/fi"; +import { MDXRemoteSerializeResult } from "next-mdx-remote"; +import React, { useState } from "react"; +import * as Avatar from "@radix-ui/react-avatar"; + +enum PageMode { + visitor, + member, + editor, + preview, +} + +type FetchedProjectAsProps = { + project: + | (Project & { + author: User; + members: User[]; + previews: ProjectPreview[]; + }) + | null + | undefined; +}; const StateOrder: ProjectLifecycle[] = Object.values(ProjectLifecycle); const SpecificProject: NextPage< InferGetServerSidePropsType > = ({ projectId, description }) => { + const [mode, setMode] = useState(PageMode.visitor); + const ctx = api.useContext(); const { data, isRefetching } = api.projects.getProjectById.useQuery( @@ -34,49 +62,83 @@ const SpecificProject: NextPage< } ); // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const { mutate, isLoading: isUpdatingState } = - api.projects.updateState.useMutation({ - onSuccess: () => { - void ctx.projects.getProjectById.invalidate(); - }, - }); + // const { mutate, isLoading: isUpdatingState } = + // api.projects.updateState.useMutation({ + // onSuccess: () => { + // void ctx.projects.getProjectById.invalidate(); + // }, + // }); - const changeState = (diff: -1 | 1) => { - if (!data) return; + // const changeState = (diff: -1 | 1) => { + // if (!data) return; - const newState = - StateOrder[ - StateOrder.findIndex((state) => state === data.state) + diff - ] ?? data.state; + // const newState = + // StateOrder[ + // StateOrder.findIndex((state) => state === data.state) + diff + // ] ?? data.state; - if (newState !== data.state) { - mutate({ - projectId: data.id, - state: newState, - }); - } + // if (newState !== data.state) { + // mutate({ + // projectId: data.id, + // state: newState, + // }); + // } + // }; + + // TODO: Make edit mode do something + const componentsByMode = { + [PageMode.visitor]: ( + + ), + [PageMode.member]: ( + + ), + [PageMode.editor]: ( + + ), + [PageMode.preview]: ( + + ), }; return ( -
- -
-
-

{data?.title}

- -
- -
+
+ + {/* Right side panel */} +
+
+ +
- {/* Right side panel */} ); }; @@ -122,22 +184,88 @@ export const getServerSideProps = async (ctx: GetServerSidePropsContext) => { return { props: { projectId, description: mdxSource } }; }; -const BannerImage: React.FC<{ bannerImageUrl: string }> = ({ - bannerImageUrl, -}) => { - // TODO: On hover, show edit button + popup for a new image picker +interface ProfilePictureProps { + name: string | undefined | null; + image: string | undefined | null; +} + +const ProfilePicture: React.FC = ({ name, image }) => { return ( - + + {name?.charAt(0)} + + ); }; -const ProjectDetails: React.FC<{ title: string }> = ({ title }) => { - return <>; +interface ProjectProgressProps { + progress: ProjectLifecycle | undefined | null; +} + +const ProjectProgress: React.FC = ({ progress }) => { + const stateIndex = StateOrder.findIndex((state) => state === progress) ?? -1; + + return ( +
+ {/* TODO: Fix shadows */} +
+ {["bg-disabled", "bg-warning", "bg-error", "bg-success"].map((bg, i) => { + return ( +
+ {i <= stateIndex && ( +
+ )} +
+ ); + })} +
+ ); +}; + +interface DisplayProjectProps extends FetchedProjectAsProps { + description: MDXRemoteSerializeResult< + Record, + Record + >; +} + +const DisplayProject: React.FC = ({ + project, + description, +}) => { + return ( +
+
+ project banner +
+
+
+

+ {project?.title} +

+ +
+ +
+
+ ); }; diff --git a/src/server/api/routers/projects.ts b/src/server/api/routers/projects.ts index 1c1399c..f2005a4 100644 --- a/src/server/api/routers/projects.ts +++ b/src/server/api/routers/projects.ts @@ -77,6 +77,7 @@ export const projectsRouter = createTRPCRouter({ .query(({ ctx, input }) => { return ctx.prisma.project.findUnique({ where: { id: input.projectId }, + include: { author: true, members: true, previews: true }, }); }), createProposal: protectedProcedure