updated avialable page and creted meeting id route
This commit is contained in:
parent
8d3dc33e21
commit
66513ddd2f
4 changed files with 184 additions and 18 deletions
|
@ -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
|
|
@ -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
|
|
@ -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 (
|
||||
<div className='px-5'>
|
||||
<p className='font-semibold text-xl'>Availability</p><hr className='my-5'/>
|
||||
<div>
|
||||
<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) => (
|
||||
<div key={index} className='grid grid-cols-3 border-b mb-2'>
|
||||
<p className='flex items-center gap-2 text-sm sm:text-base'><Checkbox />{item.day}</p>
|
||||
<div className='flex gap-2 mb-2'>
|
||||
<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'/> - </p>
|
||||
</div>
|
||||
<div>
|
||||
<p className='mb-1 text-xs font-semibold text-gray-700'>End time</p>
|
||||
<Input type="time"/>
|
||||
</div>
|
||||
</div>
|
||||
<div key={index} className='grid grid-cols-3 mb-2'>
|
||||
<p className='flex items-center gap-2 text-sm sm:text-base'>
|
||||
<Checkbox onCheckedChange={(e) => handleChange(item.day, e)}
|
||||
checked={availableDays[item.day] ?availableDays[item.day] : false}/>{item.day}
|
||||
</p>
|
||||
</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>
|
||||
<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>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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 = () => {
|
|||
<hr/>
|
||||
<div className='flex justify-between'>
|
||||
<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>
|
||||
</div>
|
||||
<div className='flex'>
|
||||
|
|
Loading…
Add table
Reference in a new issue