diff --git a/scheduler_app/app/(routes)/[business]/[meetingEventId]/page.js b/scheduler_app/app/(routes)/[business]/[meetingEventId]/page.js new file mode 100644 index 0000000..61e5ef4 --- /dev/null +++ b/scheduler_app/app/(routes)/[business]/[meetingEventId]/page.js @@ -0,0 +1,41 @@ +"use client" +import React, { useEffect, useState } from 'react' +import MeetingEventSelection from '../_components/MeetingEventSelection' +import { collection, doc, getDoc, getDocs, getFirestore, query, where } from 'firebase/firestore' +import { app } from '@/config/FirebaseConfig' + +const ShareMeetingEvent = ({params}) => { + const [businessInfo, setBusinessInfo] = useState(); + const [meetingEventInfo, setMeetingEventInfo] = useState(); + const [loading, setLoading] = useState(false); + + const db = getFirestore(app); + + //get information + const getMeetingEventDetail = async () => { + setLoading(true) + const q = query(collection(db, 'Business'), where('businessName', '==', params.business)); + const docSnap = await getDocs(q); + docSnap.forEach((doc) => { + setBusinessInfo(doc.data()) + }); + + const docRef = doc(db, 'MeetingEvent', params.meetingEventId); + const result = await getDoc(docRef); + setMeetingEventInfo(result.data()); + setLoading(false) + } + + useEffect(() => { + params && getMeetingEventDetail(); + }, [params]) + + + return ( +
+ +
+ ) +} + +export default ShareMeetingEvent \ No newline at end of file diff --git a/scheduler_app/app/(routes)/[business]/_components/MeetingEventSelection.js b/scheduler_app/app/(routes)/[business]/_components/MeetingEventSelection.js new file mode 100644 index 0000000..f98d6fa --- /dev/null +++ b/scheduler_app/app/(routes)/[business]/_components/MeetingEventSelection.js @@ -0,0 +1,60 @@ +import { GoClock } from "react-icons/go"; +import { PiMapPinLight, PiInfo } from "react-icons/pi"; +import { Calendar } from "@/components/ui/calendar" +import React, { useEffect, useState } from 'react' +import Link from "next/link"; + +const MeetingEventSelection = ({meetingEventInfo, businessInfo}) => { + const [date, setDate] = useState(new Date()); + const [timeSlots, setTimeSlots] = useState(); + + useEffect(() => { + meetingEventInfo?.timeDuration && createTimeSlot(meetingEventInfo?.timeDuration) + }, [meetingEventInfo]) + //create time slot + const createTimeSlot = (interval) => { + const startTime = 8 * 60; + const endTime = 22 * 60; + const totalSlots = (endTime - startTime) / interval; + const slots = Array.from({length: totalSlots}, (_, i) => { + const totalMinutes = startTime + i * interval; + const hours = Math.floor(totalMinutes / 60); + const minutes = totalMinutes % 60; + const formattedHours = hours > 12 ? hours - 12: hours; + const period = hours >= 12? 'PM' : 'AM'; + return `${String(formattedHours).padStart(2, '0')} : ${String(minutes).padStart(2, '0')} ${period}` + }); + setTimeSlots(slots); + } + + + return ( +
+

Schedule.Me

+
+
+

{businessInfo?.businessName}

+

{meetingEventInfo?.eventName?meetingEventInfo?.eventName:'Meeting/Event Name'}

+
+

{meetingEventInfo?.timeDuration} minutes

+

{meetingEventInfo?.locationMeeting}

+ {meetingEventInfo?.urlMeeting} +
+
+
+
+

Select your meeting date & time

+ date < new Date()} mode="single" selected={date} onSelect={setDate} className="rounded-md border mt-5"/> +
+
+ {timeSlots?.map((time, index) => ( + + ))} +
+
+
+
+ ) +} + +export default MeetingEventSelection \ No newline at end of file diff --git a/scheduler_app/app/(routes)/dashboard/availability/page.js b/scheduler_app/app/(routes)/dashboard/availability/page.js index cfc0a98..b666de1 100644 --- a/scheduler_app/app/(routes)/dashboard/availability/page.js +++ b/scheduler_app/app/(routes)/dashboard/availability/page.js @@ -1,35 +1,84 @@ +"use client" import DaysList from '@/app/_utils/DaysList' -import React from 'react' +import React, { useEffect, useState } from 'react' import { Checkbox } from "@/components/ui/checkbox" import { Input } from '@/components/ui/input' import { Button } from '@/components/ui/button' +import { doc, getDoc, getFirestore, updateDoc } from 'firebase/firestore' +import { app } from '@/config/FirebaseConfig' +import { useKindeBrowserClient } from '@kinde-oss/kinde-auth-nextjs' +import { toast } from 'sonner' const Availability = () => { + const [availableDays, setAvailableDays] = useState({Sunday: false}, {Monday: false}, {Tuesday:false}, {Wednesday: false}, {Thuesday:false}, {Friday: false}, {Saturday: false}); + const [startTime, setStartTime] = useState(); + const [endTime, setEndTime] = useState(); + const {user} = useKindeBrowserClient(); + const db = getFirestore(app); + + //available days functionality + const handleChange = (day, value) => { + setAvailableDays({ + ...availableDays, [day]: value + }) + console.log(availableDays) + } + + const handleSave = async () => { + console.log(availableDays, startTime, endTime); + const docRef = doc(db, 'Business', user?.email) + await updateDoc(docRef, { + availableDays: availableDays, + startTime: startTime, + endTime: endTime + }).then(res => { + toast('Available days and time are updated.') + }) + } + + //get information after save + const getInfo = async () => { + const docRef = doc(db, 'Business', user?.email); + const docSnap = await getDoc(docRef); + const result = docSnap.data(); + setAvailableDays(result.availableDays); + setStartTime(result.startTime); + setEndTime(result.endTime); + } + + useEffect(() => { + user && getInfo(); + }, [user]) + + return (

Availability


Available days & time

-
+
{DaysList.map((item, index) => ( -
-

{item.day}

-
-
-

Start time

-

-

-
-
-

End time

- -
-
+
+

+ handleChange(item.day, e)} + checked={availableDays[item.day] ?availableDays[item.day] : false}/>{item.day} +

))}
+
+
+

Start time

+

setStartTime(e.target.value)} defaultValue={startTime}/> -

+
+
+

End time

+ setEndTime(e.target.value)} defaultValue={endTime}/> +
+
- +
) } diff --git a/scheduler_app/app/(routes)/dashboard/meeting/_components/MeetingEventList.js b/scheduler_app/app/(routes)/dashboard/meeting/_components/MeetingEventList.js index e12af31..2c1f7b0 100644 --- a/scheduler_app/app/(routes)/dashboard/meeting/_components/MeetingEventList.js +++ b/scheduler_app/app/(routes)/dashboard/meeting/_components/MeetingEventList.js @@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react' import { app } from '@/config/FirebaseConfig' import { useKindeBrowserClient } from '@kinde-oss/kinde-auth-nextjs' -import { collection, deleteDoc, doc, getDocs, getFirestore, orderBy, query, where } from 'firebase/firestore' +import { collection, deleteDoc, doc, getDoc, getDocs, getFirestore, orderBy, query, where } from 'firebase/firestore' import { GoClock } from "react-icons/go"; import { PiMapPinLight, PiCopyLight, PiShareFatLight } from 'react-icons/pi' import { IoSettingsOutline } from "react-icons/io5"; @@ -12,6 +12,7 @@ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigge const MeetingEventList = () => { const [eventList, setEventList] = useState([]); + const [businessInfo, setBusinessInfo] = useState() const db = getFirestore(app); const {user} = useKindeBrowserClient(); @@ -33,8 +34,23 @@ const MeetingEventList = () => { }) } + //grab information and pass to copy link + const BusinessInfo = async () => { + const docRef = doc(db, 'Business', user.email); + const docSnap = await getDoc(docRef) + setBusinessInfo(docSnap.data()); + } + + const onCopyHandle = (event) => { + const meetingEventUrl = process.env.NEXT_PUBLIC_BASE_URL+'/'+businessInfo.businessName+'/'+event.id + navigator.clipboard.writeText(meetingEventUrl); + toast('Copied') + } + useEffect(() => { - user && getEventList() + user && getEventList(); + user && BusinessInfo(); + }, [user]) @@ -50,7 +66,7 @@ const MeetingEventList = () => {
- +