feature: store meeting log and check for submitting state in calendar

This commit is contained in:
Sosokker 2024-11-14 11:22:19 +07:00
parent b84dde1044
commit 4ed90281ce
7 changed files with 1243 additions and 52 deletions

1
.prettierignore Normal file
View File

@ -0,0 +1 @@
/tailwind.config.ts

1147
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,10 @@
"dependencies": {
"@hookform/resolvers": "^3.9.0",
"@mdxeditor/editor": "^3.15.0",
"@nextui-org/calendar": "^2.0.12",
"@nextui-org/date-input": "^2.1.4",
"@nextui-org/system": "^2.2.6",
"@nextui-org/theme": "^2.2.11",
"@radix-ui/react-alert-dialog": "^1.1.2",
"@radix-ui/react-avatar": "^1.1.0",
"@radix-ui/react-checkbox": "^1.1.2",
@ -34,6 +38,7 @@
"@supabase-cache-helpers/postgrest-react-query": "^1.10.1",
"@supabase/ssr": "^0.4.1",
"@supabase/supabase-js": "^2.46.1",
"@tailwindcss/line-clamp": "^0.4.4",
"@tanstack/react-query": "^5.59.0",
"@tanstack/react-query-devtools": "^5.59.0",
"b2d-ventures": "file:",
@ -41,16 +46,17 @@
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"cmdk": "1.0.0",
"date-fns": "^4.1.0",
"date-fns": "^3.0.0",
"dotenv": "^16.4.5",
"embla-carousel-react": "^8.2.0",
"framer-motion": "^11.11.15",
"lucide-react": "^0.428.0",
"next": "^14.2.15",
"next-themes": "^0.3.0",
"react": "^18.3.1",
"react-chartjs-2": "^5.2.0",
"react-countup": "^6.5.3",
"react-day-picker": "^9",
"react-day-picker": "^8.10.1",
"react-dom": "^18",
"react-file-icon": "^1.5.0",
"react-hook-form": "^7.53.0",

View File

@ -1,6 +1,6 @@
"use client";
import React, { useState } from "react";
import React, { useState, useEffect } from "react";
import { Button } from "@/components/ui/button";
import {
Dialog,
@ -13,10 +13,15 @@ import {
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Clock } from "lucide-react";
import { DateTimePicker, TimePicker } from "@/components/ui/datetime-picker";
import { Label } from "@/components/ui/label";
import { createCalendarEvent } from "./actions";
import { createCalendarEvent, createMeetingLog } from "./actions";
import { Session } from "@supabase/supabase-js";
import { createSupabaseClient } from "@/lib/supabase/clientComponentClient";
import { TimeInput } from "@nextui-org/date-input";
import { Calendar } from "@nextui-org/calendar";
import { TimeValue } from "@react-types/datepicker";
import { CalendarDate, getLocalTimeZone, today } from "@internationalized/date";
import toast from "react-hot-toast";
interface DialogProps {
children?: React.ReactNode;
@ -27,37 +32,75 @@ interface DialogProps {
modal?: boolean;
session: Session;
projectName: string;
projectId?: number;
}
export function MeetEventDialog(props: DialogProps) {
const [eventDate, setEventDate] = useState<Date | undefined>(undefined);
const [startTime, setStartTime] = useState<Date | undefined>(undefined);
const [endTime, setEndTime] = useState<Date | undefined>(undefined);
const supabase = createSupabaseClient();
const timezone = getLocalTimeZone();
const [eventDate, setEventDate] = useState<CalendarDate | undefined>(undefined);
const [startTime, setStartTime] = useState<TimeValue | undefined>(undefined);
const [endTime, setEndTime] = useState<TimeValue | undefined>(undefined);
const [eventName, setEventName] = useState(`Meet with ${props.projectName}`);
const [eventDescription, setEventDescription] = useState(
"Meet and gather more information on business in B2DVentures"
);
const [isSubmitting, setIsSubmitting] = useState<boolean>(false);
const [noteToBusiness, setNoteToBusiness] = useState<string>("");
const session = props.session;
useEffect(() => {
if (props.projectName) {
setEventName(`Meet with ${props.projectName}`);
}
}, [props.projectName]);
const handleCreateEvent = async () => {
if (!session || !eventDate || !startTime || !endTime || !eventName) {
alert("Please fill in all event details.");
toast.error("Please fill in all event details.");
return;
}
const startDate = new Date(eventDate);
startDate.setHours(startTime.getHours(), startTime.getMinutes());
setIsSubmitting(true);
try {
const startDate = eventDate.toDate(timezone);
startDate.setHours(startTime.hour, startTime.minute);
const endDate = eventDate.toDate(timezone);
endDate.setHours(endTime.hour, startTime.minute);
const endDate = new Date(eventDate);
endDate.setHours(endTime.getHours(), endTime.getMinutes());
await createCalendarEvent(session, startDate, endDate, eventName, eventDescription);
const { status, error } = await createMeetingLog({
client: supabase,
meet_date: eventDate.toString().split("T")[0],
start_time: startTime.toString(),
end_time: endTime.toString(),
note: noteToBusiness,
userId: session.user.id,
projectId: props.projectId!,
});
if (!status) {
console.error("Meeting log error:", error);
toast.error("Failed to log the meeting. Please try again.");
return;
}
toast.success("Meeting event created successfully!");
props.onOpenChange?.(false);
} catch (error) {
console.error("Error creating event:", error);
toast.error("There was an error creating the event. Please try again.");
} finally {
setIsSubmitting(false);
}
};
return (
<Dialog {...props}>
<DialogContent className="sm:max-w-md">
<DialogContent className="sm:max-w-md overflow-y-auto h-[80%]">
<DialogHeader>
<DialogTitle className="flex gap-2 items-center">
<Clock />
@ -98,23 +141,23 @@ export function MeetEventDialog(props: DialogProps) {
</div>
<div>
<Label>Date</Label>
<DateTimePicker granularity="day" hourCycle={24} value={eventDate} onChange={setEventDate} />
<Calendar value={eventDate} onChange={setEventDate} minValue={today(getLocalTimeZone())} />
</div>
<div>
<div>
<Label>Start Time</Label>
<TimePicker date={startTime} onChange={setStartTime} />
<TimeInput label="Start Time" value={startTime} onChange={setStartTime} />
</div>
<div>
<Label>End Time</Label>
<TimePicker date={endTime} onChange={setEndTime} />
<TimeInput label="End Time" value={endTime} onChange={setEndTime} />
</div>
</div>
</div>
<DialogFooter className="sm:justify-start mt-4">
<Button type="button" onClick={handleCreateEvent} className="mr-2">
Create Event
<Button type="button" onClick={handleCreateEvent} className="mr-2" disabled={isSubmitting}>
{isSubmitting ? "Creating..." : "Create Event"}
</Button>
<DialogClose asChild>
<Button type="button" variant="secondary">

View File

@ -1,4 +1,4 @@
import { Session } from "@supabase/supabase-js";
import { Session, SupabaseClient } from "@supabase/supabase-js";
export async function createCalendarEvent(
session: Session,
@ -33,9 +33,40 @@ export async function createCalendarEvent(
const data = await response.json();
console.log(data);
alert("Event created, check your Google Calendar!");
} catch (error) {
console.error("Error creating calendar event:", error);
alert("Failed to create the event.");
}
}
interface CreateMeetingLogProps {
client: SupabaseClient;
userId: string;
projectId: number;
meet_date: string;
start_time: string;
end_time: string;
note: string;
}
export async function createMeetingLog({
client,
userId,
projectId,
meet_date,
start_time,
end_time,
note,
}: CreateMeetingLogProps) {
const { error } = await client.from("meeting_log").insert([
{
meet_date: meet_date, // Format date as YYYY-MM-DD
start_time: start_time, // Format time as HH:MM:SS
end_time: end_time, // Format time as HH:MM:SS
note: note, // Text for meeting notes
user_id: userId, // Replace with a valid UUID
project_id: projectId,
},
]);
return error ? { status: false, error } : { status: true, error: null };
}

View File

@ -37,6 +37,7 @@ const DatetimePickerHourCycle = () => {
const supabase = createSupabaseClient();
const [showModal, setShowModal] = useState<boolean>(false);
const [currentProjectName, setCurrentProjectName] = useState<string>("");
const [currentProjectId, setCurrentProjectId] = useState<number | undefined>(undefined);
const { session, loading } = useSession();
const {
@ -125,7 +126,8 @@ const DatetimePickerHourCycle = () => {
<Button
onClick={() => {
setCurrentProjectName(projectInvestments[0].project_name);
setShowModal(true);
setCurrentProjectId(projectInvestments[0].project_id);
setTimeout(() => setShowModal(true), 0);
}}
>
Schedule Meeting
@ -139,6 +141,7 @@ const DatetimePickerHourCycle = () => {
onOpenChange={setShowModal}
session={session}
projectName={currentProjectName}
projectId={currentProjectId}
/>
</div>
);

View File

@ -1,12 +1,14 @@
import {nextui} from '@nextui-org/theme';
import type { Config } from "tailwindcss"
const config = {
darkMode: ["class"],
content: [
'./pages/**/*.{ts,tsx}',
'./components/**/*.{ts,tsx}',
'./app/**/*.{ts,tsx}',
'./src/**/*.{ts,tsx}',
"./pages/**/*.{ts,tsx}",
"./components/**/*.{ts,tsx}",
"./app/**/*.{ts,tsx}",
"./src/**/*.{ts,tsx}",
"./node_modules/@nextui-org/theme/dist/components/(calendar|date-input|button|ripple|spinner).js"
],
prefix: "",
theme: {
@ -74,7 +76,7 @@ const config = {
},
},
},
plugins: [require("tailwindcss-animate"), require('@tailwindcss/typography'),],
plugins: [require('tailwindcss-animate'),require('@tailwindcss/typography'),nextui()],
} satisfies Config
export default config