mirror of
https://github.com/Sosokker/B2D-Ventures.git
synced 2025-12-18 13:34:06 +01:00
feat: add page to view schedule meeting for business
This commit is contained in:
parent
bf1226a704
commit
af351aa481
101
src/app/calendar/manage/ManageMeetDialog.tsx
Normal file
101
src/app/calendar/manage/ManageMeetDialog.tsx
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogClose,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
import { Table, TableBody, TableCell, TableFooter, TableHead, TableHeader, TableRow } from "@/components/ui/table";
|
||||||
|
import { Clock } from "lucide-react";
|
||||||
|
import { createSupabaseClient } from "@/lib/supabase/clientComponentClient";
|
||||||
|
|
||||||
|
import getMeetingLog from "./actions";
|
||||||
|
import { useQuery } from "@supabase-cache-helpers/postgrest-react-query";
|
||||||
|
import { LegacyLoader } from "@/components/loading/LegacyLoader";
|
||||||
|
|
||||||
|
interface DialogProps {
|
||||||
|
children?: React.ReactNode;
|
||||||
|
open?: boolean;
|
||||||
|
defaultOpen?: boolean;
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
onOpenChange?(open: boolean): void;
|
||||||
|
modal?: boolean;
|
||||||
|
projectId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ManageMeetDialog(props: DialogProps) {
|
||||||
|
const supabase = createSupabaseClient();
|
||||||
|
const {
|
||||||
|
data: meetingLog,
|
||||||
|
error: meetingLogError,
|
||||||
|
isLoading: isLoadingMeetingLog,
|
||||||
|
} = useQuery(getMeetingLog(supabase, props.projectId), {
|
||||||
|
enabled: !!props.projectId,
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog {...props}>
|
||||||
|
<DialogContent className="sm:max-w-md overflow-y-auto h-[80%]">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle className="flex gap-2 items-center">
|
||||||
|
<Clock />
|
||||||
|
Meeting Request
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogDescription>List of meeting you need to attend.</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
|
||||||
|
{meetingLogError ? (
|
||||||
|
<div>Error Loading data</div>
|
||||||
|
) : isLoadingMeetingLog ? (
|
||||||
|
<LegacyLoader />
|
||||||
|
) : meetingLog && meetingLog.length > 0 ? (
|
||||||
|
<Table>
|
||||||
|
<TableHeader>
|
||||||
|
<TableRow>
|
||||||
|
<TableHead className="w-[100px]">Date</TableHead>
|
||||||
|
<TableHead>Start Time</TableHead>
|
||||||
|
<TableHead>End Time</TableHead>
|
||||||
|
<TableHead>User</TableHead>
|
||||||
|
<TableHead>Note</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
{meetingLog.map((log) => (
|
||||||
|
<TableRow key={log.id}>
|
||||||
|
<TableCell className="font-medium">{log.meet_date}</TableCell>
|
||||||
|
<TableCell>{log.start_time}</TableCell>
|
||||||
|
<TableCell>{log.end_time}</TableCell>
|
||||||
|
<TableCell>{log.user_id}</TableCell>
|
||||||
|
<TableCell>{log.note || "No note provided"}</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
<TableFooter>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell colSpan={5} className="text-right">
|
||||||
|
Total Meetings: {meetingLog.length}
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableFooter>
|
||||||
|
</Table>
|
||||||
|
) : (
|
||||||
|
<div>No meeting logs available</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<DialogFooter className="sm:justify-start mt-4">
|
||||||
|
<DialogClose asChild>
|
||||||
|
<Button type="button" variant="secondary">
|
||||||
|
Close
|
||||||
|
</Button>
|
||||||
|
</DialogClose>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
63
src/app/calendar/manage/ProjectCardSection.tsx
Normal file
63
src/app/calendar/manage/ProjectCardSection.tsx
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Separator } from "@/components/ui/separator";
|
||||||
|
import { Card, CardContent, CardDescription, CardTitle, CardHeader, CardFooter } from "@/components/ui/card";
|
||||||
|
import { Tooltip, TooltipProvider, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
||||||
|
import { ManageMeetDialog } from "./ManageMeetDialog";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
|
||||||
|
type ProjectCardSectionProps = {
|
||||||
|
id: number;
|
||||||
|
project_name: string;
|
||||||
|
project_short_description: string;
|
||||||
|
business_id: {
|
||||||
|
user_id: string;
|
||||||
|
};
|
||||||
|
dataroom_id: number | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ProjectCardCalendarManageSectionProps = {
|
||||||
|
projectData: ProjectCardSectionProps[] | null;
|
||||||
|
};
|
||||||
|
export default function ProjectCardCalendarManageSection({ projectData }: ProjectCardCalendarManageSectionProps) {
|
||||||
|
const [showMeetModal, setShowMeetModal] = useState<boolean>(false);
|
||||||
|
const [currentProjectId, setCurrentProjectId] = useState<number | undefined>(undefined);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div id="content" className="grid grid-cols-2 space-x-2">
|
||||||
|
{projectData != null ? (
|
||||||
|
projectData.map((project) => (
|
||||||
|
<Card key={project.id} className="mb-3">
|
||||||
|
<CardHeader className="h-[55%]">
|
||||||
|
<CardTitle>{project.project_name}</CardTitle>
|
||||||
|
<TooltipProvider>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<CardDescription className="line-clamp-1">{project.project_short_description}</CardDescription>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>{project.project_short_description}</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
</CardHeader>
|
||||||
|
<Separator className="mb-3" />
|
||||||
|
<CardContent>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
setCurrentProjectId(project.id);
|
||||||
|
setTimeout(() => setShowMeetModal(true), 0);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Meeting List
|
||||||
|
</Button>
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter></CardFooter>
|
||||||
|
</Card>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<div>No data</div>
|
||||||
|
)}
|
||||||
|
<ManageMeetDialog open={showMeetModal} onOpenChange={setShowMeetModal} projectId={currentProjectId!} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
20
src/app/calendar/manage/actions.ts
Normal file
20
src/app/calendar/manage/actions.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { Database } from "@/types/database.types";
|
||||||
|
import { SupabaseClient } from "@supabase/supabase-js";
|
||||||
|
|
||||||
|
export default function getMeetingLog(client: SupabaseClient<Database>, projectId: number) {
|
||||||
|
return client
|
||||||
|
.from("meeting_log")
|
||||||
|
.select(
|
||||||
|
`
|
||||||
|
id,
|
||||||
|
meet_date,
|
||||||
|
start_time,
|
||||||
|
end_time,
|
||||||
|
note,
|
||||||
|
user_id,
|
||||||
|
project_id,
|
||||||
|
created_at
|
||||||
|
`
|
||||||
|
)
|
||||||
|
.eq("project_id", projectId);
|
||||||
|
}
|
||||||
62
src/app/calendar/manage/page.tsx
Normal file
62
src/app/calendar/manage/page.tsx
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import { Separator } from "@/components/ui/separator";
|
||||||
|
import { Clock } from "lucide-react";
|
||||||
|
import { createSupabaseClient } from "@/lib/supabase/serverComponentClient";
|
||||||
|
import { getProjectByUserId } from "@/lib/data/projectQuery";
|
||||||
|
import { Suspense } from "react";
|
||||||
|
import { LegacyLoader } from "@/components/loading/LegacyLoader";
|
||||||
|
import { getUserRole } from "@/lib/data/userQuery";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import Link from "next/link";
|
||||||
|
import ProjectCardCalendarManageSection from "./ProjectCardSection";
|
||||||
|
|
||||||
|
export default async function ManageMeetingPage() {
|
||||||
|
const supabase = createSupabaseClient();
|
||||||
|
const { data: user, error: userError } = await supabase.auth.getUser();
|
||||||
|
|
||||||
|
if (userError) {
|
||||||
|
throw "Can't get user data!";
|
||||||
|
}
|
||||||
|
|
||||||
|
const userId = user.user?.id;
|
||||||
|
|
||||||
|
const { data: roleData, error: roleDataError } = await getUserRole(supabase, userId);
|
||||||
|
|
||||||
|
if (roleDataError) {
|
||||||
|
throw "Error fetching user data";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!roleData || roleData.role != "business") {
|
||||||
|
return (
|
||||||
|
<div className="container max-w-screen-xl">
|
||||||
|
<span className="flex gap-2 items-center mt-4">
|
||||||
|
<Clock />
|
||||||
|
<p className="text-2xl font-bold">Manage Meeting Request</p>
|
||||||
|
</span>
|
||||||
|
<Separator className="my-3" />
|
||||||
|
<div className="mb-3 mt-2">Please apply for business first to access functionalities of busienss account</div>
|
||||||
|
<Link href="/business/apply">
|
||||||
|
<Button>Apply for business</Button>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: projectData, error: projectDataError } = await getProjectByUserId(supabase, userId);
|
||||||
|
|
||||||
|
if (projectDataError) {
|
||||||
|
throw "Can't get project data";
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="container max-w-screen-xl">
|
||||||
|
<span className="flex gap-2 items-center mt-4">
|
||||||
|
<Clock />
|
||||||
|
<p className="text-2xl font-bold">Manage Meeting Request</p>
|
||||||
|
</span>
|
||||||
|
<Separator className="my-3" />
|
||||||
|
<Suspense fallback={<LegacyLoader />}>
|
||||||
|
<ProjectCardCalendarManageSection projectData={projectData} />
|
||||||
|
</Suspense>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user