diff --git a/src/app/admin/project/[businessId]/ProjectAction.tsx b/src/app/admin/project/[businessId]/ProjectAction.tsx new file mode 100644 index 0000000..47aaabd --- /dev/null +++ b/src/app/admin/project/[businessId]/ProjectAction.tsx @@ -0,0 +1,104 @@ +"use client"; + +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; +import { Button } from "@/components/ui/button"; +import { Check, X } from "lucide-react"; +import { useState } from "react"; +import { createSupabaseClient } from "@/lib/supabase/clientComponentClient"; +import { approveProject, rejectBusiness } from "@/lib/data/applicationMutate"; +import toast from "react-hot-toast"; + +interface ProjectActionsProps { + projectId: number; +} + +export default function ProjectActions({ projectId }: ProjectActionsProps) { + const [isRejectLoading, setIsRejectLoading] = useState(false); + const [isApproveLoading, setIsApproveLoading] = useState(false); + const [isRejectOpen, setIsRejectOpen] = useState(false); + const [isApproveOpen, setIsApproveOpen] = useState(false); + + const onRejectProject = async () => { + try { + setIsRejectLoading(true); + const client = createSupabaseClient(); + + const { error } = await rejectBusiness(client, projectId); + if (error) throw error; + + toast.success("Project rejected successfully"); + window.location.reload(); + } catch (error) { + toast.error("Failed to reject project"); + console.error("Failed to reject project:", error); + } finally { + setIsRejectLoading(false); + setIsRejectOpen(false); + } + }; + + const onApproveProject = async () => { + try { + setIsApproveLoading(true); + const client = createSupabaseClient(); + + const { error } = await approveProject(client, projectId); + if (error) throw error; + + toast.success("Project approved successfully"); + window.location.reload(); + } catch (error) { + toast.error("Failed to approve project"); + console.error("Failed to approve project:", error); + } finally { + setIsApproveLoading(false); + setIsApproveOpen(false); + } + }; + + return ( +
+ + + + + + + Approve this Project + Are you sure you want to approve this project? + + + + + + + + + + + + + + Reject this Project + Are you sure you want to reject this project? + + + + + + +
+ ); +} diff --git a/src/app/admin/project/[businessId]/page.tsx b/src/app/admin/project/[businessId]/page.tsx new file mode 100644 index 0000000..5f0f71b --- /dev/null +++ b/src/app/admin/project/[businessId]/page.tsx @@ -0,0 +1,139 @@ +import { createSupabaseClient } from "@/lib/supabase/serverComponentClient"; +import { getAllProjectApplicationByBusinessQuery } from "@/lib/data/applicationQuery"; +import Link from "next/link"; +import Image from "next/image"; +import ProjectActions from "./ProjectAction"; +import { Table, TableBody, TableCaption, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; + +interface ProjectApplicationData { + id: number; + created_at: string; + deadline: string; + status: string; + project_name: string; + business_id: number; + business_name: string; + user_id: number; + project_type_id: number; + project_type_value: string; + short_description: string; + pitch_deck_url: string | null; + project_logo: string | null; + min_investment: number; + target_investment: number; + project_photos: string[] | null; +} + +interface ProjectApplicationTableProps { + projects: ProjectApplicationData[]; +} + +function ProjectApplicationTable({ projects }: ProjectApplicationTableProps) { + if (!projects || projects.length === 0) { + return ( + + + No project applications found + + + ); + } + + return ( + <> + {projects.map((project) => ( + + {project.project_name} + {project.project_type_value} + + {project.project_logo && ( + {`${project.project_name} + )} + + {project.short_description} + + {project.pitch_deck_url && ( + + Pitch Deck + + )} + + {project.min_investment} + {project.target_investment} + {new Date(project.created_at).toLocaleDateString()} + {new Date(project.deadline).toLocaleDateString()} + + {project.project_photos ? ( + project.project_photos.length > 0 && ( +
+ {project.project_photos.map((photoUrl, index) => ( + {`Project + ))} +
+ ) + ) : ( +

No images available

+ )} +
+ + + +
+ ))} + + ); +} + +export default async function ProjectAdminPage({ params }: { params: { businessId: string } }) { + const client = createSupabaseClient(); + const { data: projectApplicationData, error: projectApplicationError } = + await getAllProjectApplicationByBusinessQuery(client, Number(params.businessId)); + + if (projectApplicationError) { + console.log(projectApplicationError); + return
Error loading project applications
; + } + + return ( +
+

+ {projectApplicationData?.[0]?.business_name || "Business Projects"} +

+ + + Project Applications for Business + + + Project Name + Project Type + Logo + Description + Pitch Deck + Min Investment + Target Investment + Created At + Deadline + Photos + Actions + + + + + +
+
+ ); +} diff --git a/src/lib/data/applicationMutate.ts b/src/lib/data/applicationMutate.ts index fb879fa..81b2c2d 100644 --- a/src/lib/data/applicationMutate.ts +++ b/src/lib/data/applicationMutate.ts @@ -1,23 +1,37 @@ import { SupabaseClient } from "@supabase/supabase-js"; -export async function rejectBusiness( - client: SupabaseClient, - businessApplicationId: Number, -) { - return client.from("business_application") - .update({ - status: "reject", - }) - .eq("id", businessApplicationId); +export async function rejectBusiness(client: SupabaseClient, businessApplicationId: Number) { + return client + .from("business_application") + .update({ + status: "reject", + }) + .eq("id", businessApplicationId); } -export async function approveBusiness( - client: SupabaseClient, - businessApplicationId: Number, -) { - return client.from("business_application") - .update({ - status: "approve", - }) - .eq("id", businessApplicationId); +export async function approveBusiness(client: SupabaseClient, businessApplicationId: Number) { + return client + .from("business_application") + .update({ + status: "approve", + }) + .eq("id", businessApplicationId); +} + +export async function rejectProject(client: SupabaseClient, projectApplicationId: Number) { + return client + .from("project_application") + .update({ + status: "reject", + }) + .eq("id", projectApplicationId); +} + +export async function approveProject(client: SupabaseClient, projectApplicationId: Number) { + return client + .from("project_application") + .update({ + status: "approve", + }) + .eq("id", projectApplicationId); } diff --git a/src/lib/data/applicationQuery.ts b/src/lib/data/applicationQuery.ts index 99e614b..6910ec1 100644 --- a/src/lib/data/applicationQuery.ts +++ b/src/lib/data/applicationQuery.ts @@ -26,3 +26,34 @@ export const getAllBusinessApplicationQuery = (client: SupabaseClient) => { ` ); }; + +export const getAllProjectApplicationByBusinessQuery = (client: SupabaseClient, businessId: number) => { + return client + .from("project_application") + .select( + ` + id, + created_at, + deadline, + status, + project_name, + ...business_id ( + business_id:id, + business_name, + user_id + ), + ...project_type_id!inner ( + project_type_id:id, + project_type_value:value + ), + short_description, + pitch_deck_url, + project_logo, + min_investment, + target_investment, + user_id, + project_photos + ` + ) + .eq("business_id", businessId); +};