updated avialable page and creted meeting id route

This commit is contained in:
Juthatip McDevitt 2024-04-29 13:01:15 -05:00
parent 8d3dc33e21
commit 66513ddd2f
4 changed files with 184 additions and 18 deletions

View file

@ -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 (
<div>
<MeetingEventSelection meetingEventInfo={meetingEventInfo} businessInfo={businessInfo}/>
</div>
)
}
export default ShareMeetingEvent

View file

@ -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 (
<div className='px-5 py-10 shadow-md m-4 border-t-8 mx-10 md:mx-20 lg:mx-40 my-10 lg:my-20' style={{borderTopColor: meetingEventInfo?.themeColor}}>
<p className='text-xl uppercase font-semibold tracking-wide'>Schedule.Me</p>
<div className='grid grid-cols-1 lg:grid-cols-3 mt-5'>
<div className='border-r'>
<p className='font-semibold mb-5 text-xl'>{businessInfo?.businessName}</p>
<p className="font-normal flex items-center gap-1"><PiInfo/> {meetingEventInfo?.eventName?meetingEventInfo?.eventName:'Meeting/Event Name'}</p>
<div className='mt-2 flex flex-col gap-2'>
<p className='flex gap-1 items-center'><GoClock/>{meetingEventInfo?.timeDuration} minutes</p>
<p className='flex gap-1 items-center'><PiMapPinLight/>{meetingEventInfo?.locationMeeting}</p>
<Link href={meetingEventInfo?.urlMeeting?meetingEventInfo?.urlMeeting:''} className="text-gray-500 underline text-sm">{meetingEventInfo?.urlMeeting}</Link>
</div>
</div>
<div className='grid px-2 md:px-5 lg:col-span-2 min-[480px]:flex'>
<div className="flex flex-col">
<p className="font-semibold mt-5 lg:mt-0">Select your meeting date & time</p>
<Calendar disabled={(date) => date < new Date()} mode="single" selected={date} onSelect={setDate} className="rounded-md border mt-5"/>
</div>
<div className="w-full flex flex-col overflow-auto gap-2 p-2 md:p-5" style={{maxHeight: '350px'}}>
{timeSlots?.map((time, index) => (
<button key={index} className='text-xs p-2 border rounded-md hover:bg-gray-100'>{time}</button>
))}
</div>
</div>
</div>
</div>
)
}
export default MeetingEventSelection

View file

@ -1,35 +1,84 @@
"use client"
import DaysList from '@/app/_utils/DaysList' import DaysList from '@/app/_utils/DaysList'
import React from 'react' import React, { useEffect, useState } from 'react'
import { Checkbox } from "@/components/ui/checkbox" import { Checkbox } from "@/components/ui/checkbox"
import { Input } from '@/components/ui/input' import { Input } from '@/components/ui/input'
import { Button } from '@/components/ui/button' 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 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 ( return (
<div className='px-5'> <div className='px-5'>
<p className='font-semibold text-xl'>Availability</p><hr className='my-5'/> <p className='font-semibold text-xl'>Availability</p><hr className='my-5'/>
<div> <div>
<p className='my-5 font-semibold'>Available days & time</p> <p className='my-5 font-semibold'>Available days & time</p>
<div className='flex flex-col'> <div className='grid grid-cols-2 md:grid-cols-4 gap-5'>
{DaysList.map((item, index) => ( {DaysList.map((item, index) => (
<div key={index} className='grid grid-cols-3 border-b mb-2'> <div key={index} className='grid grid-cols-3 mb-2'>
<p className='flex items-center gap-2 text-sm sm:text-base'><Checkbox />{item.day}</p> <p className='flex items-center gap-2 text-sm sm:text-base'>
<div className='flex gap-2 mb-2'> <Checkbox onCheckedChange={(e) => handleChange(item.day, e)}
<div> checked={availableDays[item.day] ?availableDays[item.day] : false}/>{item.day}
<p className='mb-1 text-xs font-semibold text-gray-700'>Start time</p> </p>
<p className='flex gap-1 sm:gap-2 items-center'><Input type='time'/> - </p>
</div>
<div>
<p className='mb-1 text-xs font-semibold text-gray-700'>End time</p>
<Input type="time"/>
</div>
</div>
</div> </div>
))} ))}
</div> </div>
<div className='flex gap-2 mb-2 mt-5'>
<div>
<p className='mb-1 text-xs font-semibold text-gray-700'>Start time</p>
<p className='flex gap-1 sm:gap-2 items-center'><Input type='time' onChange={(e) => setStartTime(e.target.value)} defaultValue={startTime}/> - </p>
</div> </div>
<Button className="mt-5">Save</Button> <div>
<p className='mb-1 text-xs font-semibold text-gray-700'>End time</p>
<Input type="time" onChange={(e) => setEndTime(e.target.value)} defaultValue={endTime}/>
</div>
</div>
</div>
<Button onClick={handleSave} className="mt-5">Save</Button>
</div> </div>
) )
} }

View file

@ -2,7 +2,7 @@
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { app } from '@/config/FirebaseConfig' import { app } from '@/config/FirebaseConfig'
import { useKindeBrowserClient } from '@kinde-oss/kinde-auth-nextjs' 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 { GoClock } from "react-icons/go";
import { PiMapPinLight, PiCopyLight, PiShareFatLight } from 'react-icons/pi' import { PiMapPinLight, PiCopyLight, PiShareFatLight } from 'react-icons/pi'
import { IoSettingsOutline } from "react-icons/io5"; import { IoSettingsOutline } from "react-icons/io5";
@ -12,6 +12,7 @@ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigge
const MeetingEventList = () => { const MeetingEventList = () => {
const [eventList, setEventList] = useState([]); const [eventList, setEventList] = useState([]);
const [businessInfo, setBusinessInfo] = useState()
const db = getFirestore(app); const db = getFirestore(app);
const {user} = useKindeBrowserClient(); 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(() => { useEffect(() => {
user && getEventList() user && getEventList();
user && BusinessInfo();
}, [user]) }, [user])
@ -50,7 +66,7 @@ const MeetingEventList = () => {
<hr/> <hr/>
<div className='flex justify-between'> <div className='flex justify-between'>
<div className='flex gap-2'> <div className='flex gap-2'>
<button onClick={() => {navigator.clipboard.writeText(event.urlMeeting), toast('Copied')}} className='text-lg'><PiCopyLight/></button> <button onClick={() => {onCopyHandle(event)}} className='text-lg'><PiCopyLight/></button>
<button className="text-lg"><PiShareFatLight/></button> <button className="text-lg"><PiShareFatLight/></button>
</div> </div>
<div className='flex'> <div className='flex'>