Skip to content

Commit

Permalink
fix(nextjs): create projects now works
Browse files Browse the repository at this point in the history
  • Loading branch information
not-ani committed Oct 28, 2024
1 parent 582455a commit e5f131c
Show file tree
Hide file tree
Showing 14 changed files with 167 additions and 139 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import React, { useState } from "react";
import { revalidateTag } from "next/cache";
import { useParams, useRouter } from "next/navigation";
import { useParams } from "next/navigation";
import { zodResolver } from "@hookform/resolvers/zod";
import { CheckIcon } from "lucide-react";
import { useForm } from "react-hook-form";
Expand Down
7 changes: 7 additions & 0 deletions apps/nextjs/src/app/(home)/_components/all-projects.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { findAllProjects } from "../_queries";
import ProjectGrid from "./project-grid";

export default async function AllProjects() {
const allProjects = await findAllProjects();
return <ProjectGrid projects={allProjects} />;
}
17 changes: 9 additions & 8 deletions apps/nextjs/src/app/(home)/_components/create-project-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import type { z } from "zod";
import React, { useState } from "react";
import { useRouter } from "next/navigation";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
Expand Down Expand Up @@ -33,6 +34,7 @@ import { api } from "~/trpc/react";

export function CreateProject() {
const [isOpen, setIsOpen] = useState(false);
const router = useRouter();

const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
Expand All @@ -43,22 +45,21 @@ export function CreateProject() {
},
});

const utils = api.useUtils();
const createProject = api.projects.create.useMutation({
onSuccess: () => {
toast.success("Project created");
form.reset();
void utils.projects.invalidate();
setIsOpen(false);
router.refresh();
},
onError: (error) => {
console.error(error);
toast.error("something went wrong");
},
});

const onSubmit = async (values: CreateProjectSchema) => {
try {
await createProject.mutateAsync(values);
} catch (error) {
toast.error("Error creating project");
}
const onSubmit = (values: CreateProjectSchema) => {
createProject.mutate(values);
};

return (
Expand Down
36 changes: 36 additions & 0 deletions apps/nextjs/src/app/(home)/_components/project-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { memo } from "react";
import Image from "next/image";
import Link from "next/link";

import { Card, CardContent, CardFooter } from "@amaxa/ui/card";

interface ProjectCardProps {
project: {
id: string;
name: string;
image: string | null;
};
}

const ProjectCard = memo(function ProjectCard({ project }: ProjectCardProps) {
return (
<Link href={`/project/${project.id}`} className="block w-full">
<Card className="h-[300px] w-full overflow-hidden transition-transform duration-200 hover:bg-muted/40">
<CardContent className="relative h-[220px] p-0">
<Image
src={project.image ?? "/placeholder.svg"}
alt={project.name}
fill
className="object-cover"
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
/>
</CardContent>
<CardFooter className="h-[80px] items-center justify-center text-center">
<h3 className="line-clamp-2 text-lg font-semibold">{project.name}</h3>
</CardFooter>
</Card>
</Link>
);
});

export default ProjectCard;
23 changes: 23 additions & 0 deletions apps/nextjs/src/app/(home)/_components/project-grid.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { memo } from "react";

import ProjectCard from "./project-card";

const ProjectGrid = memo(function ProjectGrid({
projects,
}: {
projects: {
id: string;
name: string;
image: string | null;
}[];
}) {
return (
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
{projects.map((project) => (
<ProjectCard key={project.id} project={project} />
))}
</div>
);
});

export default ProjectGrid;
26 changes: 26 additions & 0 deletions apps/nextjs/src/app/(home)/_components/user-projects.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { getUserProjects } from "~/components/navbar/switcher";
import ProjectGrid from "./project-grid";

export default async function UserProjects({
userId,
userStatus,
}: {
userId: string;
userStatus: string;
}) {
const usersProjects = await getUserProjects(userId);

if (userStatus === "Pending" || userStatus === "Unverified") {
return (
<div className="col-span-1 row-span-1 flex h-[300px] w-[300px] flex-col items-center justify-center border-dashed bg-secondary/10">
<p>
{userStatus === "Pending"
? "Your account is pending approval, please wait for the admin to approve your account"
: "Your account is unverified, please wait till we verify your account to access the platform"}
</p>
</div>
);
}

return <ProjectGrid projects={usersProjects} />;
}
10 changes: 1 addition & 9 deletions apps/nextjs/src/app/(home)/_queries/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
import { db } from "@amaxa/db/client";

import { next_cache } from "~/lib/cache";

export const findAllProjects = next_cache(
async () => await db.query.Projects.findMany({}),
["findAllProjects"],
{
revalidate: 60 * 60 * 10,
},
);
export const findAllProjects = () => db.query.Projects.findMany({});
18 changes: 2 additions & 16 deletions apps/nextjs/src/app/(home)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,21 @@ import { isAdmin } from "@amaxa/api";

import { AppHeader } from "~/components/app-header";
import { AppNav } from "~/components/layout-tabs";
import { checkAuth } from "~/lib/auth";

export default async function Layout({
export default function Layout({
children,
modal,
}: {
children: React.ReactNode;
modal: React.ReactNode;
}) {
const auth = await checkAuth();
const links = [
{ href: "/", label: "Projects" },
{ href: "/events", label: "Events" },
{ href: "/guides/action-guides", label: "Guides" },
isAdmin(auth)
? { href: "/admin", label: "Admin" }
: {
href: "",
label: "",
},
];

return (
<div>
<div className="flex flex-col">
<div className="">
<Suspense fallback={<div>loading..</div>}>
<AppHeader />
<AppNav links={links} className="bg-secondary/40 " />
<AppNav className="bg-secondary/40 " />
</Suspense>
</div>
<main className="">{children}</main>
Expand Down
119 changes: 31 additions & 88 deletions apps/nextjs/src/app/(home)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,102 +1,45 @@
import React from "react";
import Image from "next/image";
import Link from "next/link";
import { Suspense } from "react";
import dynamic from "next/dynamic";

import { Card, CardContent, CardFooter, CardHeader } from "@amaxa/ui/card";

import { getUserProjects } from "~/components/navbar/switcher";
import { checkAuth } from "~/lib/auth";
import { CreateProject } from "./_components/create-project-dialog";
import { findAllProjects } from "./_queries";
import AllProjects from "./_components/all-projects";
import UserProjects from "./_components/user-projects";

const CreateProject = dynamic(
() =>
import("./_components/create-project-dialog").then(
(mod) => mod.CreateProject,
),
{
loading: () => <p>Loading...</p>,
},
);

export default async function Page() {
const session = await checkAuth();
const [usersProjects, allProjects] = await Promise.all([
getUserProjects(session.user.id),
findAllProjects(),
]);

return (
<div className="min-h-screen p-4 sm:p-6 lg:p-8">
<div className="">
<div className="flex w-full flex-col gap-5">
<div className="flex flex-col gap-6">
<div className="flex flex-row justify-between gap-6">
<h3 className="text-4xl font-semibold">Your Project</h3>
{session.user.role === "Admin" ? <CreateProject /> : null}
</div>
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3 ">
{session.user.status == "Pending" ? (
<Card className="col-span-1 row-span-1 flex h-[300px] w-[300px] flex-col items-center justify-center border-dashed bg-secondary/10 transition-transform duration-200">
<CardHeader>
Your account is pending approval, please wait for the admin
to approve your account
</CardHeader>
</Card>
) : session.user.status == "Unverified" ? (
<Card className="col-span-1 row-span-1 flex h-[300px] w-[300px] flex-col items-center justify-center border-dashed bg-secondary/10 transition-transform duration-200">
<CardHeader>
Your account is unverified, please wait till we verify your
account to access the platform
</CardHeader>
</Card>
) : (
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3 ">
{usersProjects.map((project) => {
return (
<Link
key={project.id}
href={`/project/${project.id}`}
className="col-span-1 row-span-1 bg-secondary/10 transition-transform duration-200"
>
<Card className="col-span-1 row-span-1 bg-secondary/10 transition-transform duration-200">
<CardContent className="py-5">
<Image
src={project.image ?? ""}
width={1000}
height={500}
alt={String(project.id)}
/>
</CardContent>
<CardFooter className="justify-center text-center font-bold md:text-2xl">
{project.name}
</CardFooter>
</Card>
</Link>
);
})}
</div>
)}
</div>
</div>
<div className="flex flex-col gap-6">
<h3 className="text-4xl font-semibold">Explore Projects</h3>
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3 ">
{allProjects.map((project) => {
return (
<Link key={project.id} href={`/project/${project.id}`}>
<Card className="col-span-1 row-span-1 bg-secondary/10 transition-transform duration-200">
<CardContent className="py-5">
<Image
src={project.image ?? ""}
width={1000}
height={500}
alt={String(project.id)}
/>
</CardContent>
<CardFooter className="justify-center text-center font-bold md:text-2xl">
{project.name}
</CardFooter>
</Card>
</Link>
);
})}
</div>
<div className="flex w-full flex-col gap-5">
<div className="flex flex-col gap-6">
<div className="flex flex-row justify-between gap-6">
<h3 className="text-4xl font-semibold">Your Projects</h3>
{session.user.role === "Admin" && <CreateProject />}
</div>
<Suspense fallback={<div>Loading your projects...</div>}>
<UserProjects
userId={session.user.id}
userStatus={session.user.status}
/>
</Suspense>
</div>
<div className="flex flex-col gap-6">
<h3 className="text-4xl font-semibold">Explore Projects</h3>
<Suspense fallback={<div>Loading all projects...</div>}>
<AllProjects />
</Suspense>
</div>
</div>
</div>
);
}

export const dynamic = "force-dynamic";
8 changes: 7 additions & 1 deletion apps/nextjs/src/app/_components/flow-provider.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"use client";
import { SessionProvider } from 'next-auth/react'

import React from "react";
import { ReactFlowProvider } from "@xyflow/react";
Expand All @@ -11,7 +12,12 @@ import "reactflow/dist/style.css";
function FlowProvider({ children }: { children: React.ReactNode }) {
return (
<TooltipProvider>
<ReactFlowProvider>{children}</ReactFlowProvider>
<ReactFlowProvider>
<SessionProvider>
{children}

</SessionProvider>
</ReactFlowProvider>
</TooltipProvider>
);
}
Expand Down
25 changes: 18 additions & 7 deletions apps/nextjs/src/components/layout-tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,32 @@ import Link from "next/link";
import { usePathname } from "next/navigation";
import * as TabsPrimitive from "@radix-ui/react-tabs";
import { motion } from "framer-motion";
import { useSession } from "next-auth/react";

import { cn } from "@amaxa/ui";

interface TabLink {
href: string;
label: string;
}

interface VercelTabsProps {
links?: TabLink[];
className?: string;
}

export function AppNav({ links, className }: VercelTabsProps) {
export function AppNav({ className }: VercelTabsProps) {
const pathname = usePathname();
const session = useSession();

const links = [
{ href: "/", label: "Projects" },
{ href: "/events", label: "Events" },
{ href: "/guides/action-guides", label: "Guides" },
session?.data?.user.role === "Admin"
? {
href: "/admin",
label: "Admin",
}
: {
href: "/",
label: "",
},
];

if (!links || links.length === 0) {
return null;
Expand Down
Loading

0 comments on commit e5f131c

Please sign in to comment.