mirror of
https://github.com/Sosokker/B2D-Ventures.git
synced 2025-12-18 13:34:06 +01:00
feature: store meeting log and check for submitting state in calendar
This commit is contained in:
parent
b84dde1044
commit
4ed90281ce
1
.prettierignore
Normal file
1
.prettierignore
Normal file
@ -0,0 +1 @@
|
||||
/tailwind.config.ts
|
||||
1147
package-lock.json
generated
1147
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
10
package.json
10
package.json
@ -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",
|
||||
|
||||
@ -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">
|
||||
|
||||
@ -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 };
|
||||
}
|
||||
|
||||
@ -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>
|
||||
);
|
||||
|
||||
@ -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
|
||||
Loading…
Reference in New Issue
Block a user