Untitled
javascript
2 months ago
7.5 kB
2
Indexable
Never
'use client'; import { useEffect, useState } from "react"; import data from './data.json'; export default function Page() { return ( <MainComponent> <HeaderComponent/> <TableComponent/> </MainComponent> ) } function MainComponent({children}:{children:React.ReactNode}){ return ( <div className="flex flex-col items-center"> {children} </div> ) } function HeaderComponent(){ return ( <div className="bg-[#F45B69] flex h-12 w-full justify-around "> <div className="flex flex-row child:flex-1 items-center w-full divide-x divide-slate-600 text-white"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="w-6 h-6"> <path strokeLinecap="round" strokeLinejoin="round" d="M12 10.5v6m3-3H9m4.06-7.19l-2.12-2.12a1.5 1.5 0 00-1.061-.44H4.5A2.25 2.25 0 002.25 6v12a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9a2.25 2.25 0 00-2.25-2.25h-5.379a1.5 1.5 0 01-1.06-.44z" /> </svg> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="w-6 h-6"> <path strokeLinecap="round" strokeLinejoin="round" d="M15.75 19.5L8.25 12l7.5-7.5" /> </svg> <div className=" text-center ">Prev</div> <div className=" text-center ">Current</div> <div className=" text-center ">Next</div> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="w-6 h-6"> <path strokeLinecap="round" strokeLinejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5" /> </svg> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="w-6 h-6"> <path strokeLinecap="round" strokeLinejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281z" /> <path strokeLinecap="round" strokeLinejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" /> </svg> </div> </div> ) } function TableComponent(){ const hours = [8,9,10,11,12,13,14,15,16,17,18,19,20,21,22]; return ( <div className="bg-[#2e3f45] text-white w-full p-5 pb-3"> <div className="flex flex-col"> <div className="flex flex-row "> <div className="w-10 flex-none"></div> <div className="flex flex-row w-full"> { data.map(day => <div key={day.id} className="flex-1 text-center font-bold"> <div className="">{day["day"].slice(0, 3)}</div> <div className="mx-5 rounded-full border-2 ">{day["date"]}</div> <div className="h-3 border-l-0.1"></div> </div> ) } </div> </div> <div className="flex flex-row"> <div className="flex flex-col"> {hours.map(hour => <div key={hour} className="flex flex-row h-12"> <div className="w-8 text-right pr-1 relative bottom-3 text-sm">{hour}u</div> <div className="w-2 border-t-0.1"></div> </div> )} </div> <div className="flex flex-row w-full"> { data.map(day => <div key={day.id} className="flex-1 grid grid-cols-1"> {hours .filter(hour => !day.timeslots.some(timeslot => timeslot.start < hour && hour < timeslot.end )) .map((hour, i, arr) => <div key={hour} className={`border-t-0.1 border-l-0.1 h-full ${rowspan(arr[i+1] - hour)}`}> {day.timeslots.filter(timeslot => (timeslot.start == hour)).map(timeslot => <TimeslotComponent key={timeslot.id} title={timeslot.title} names={timeslot.names}/> )} </div>) } </div> ) } </div> </div> </div> </div> ) } function TimeslotComponent({title, names}:{title:string, names:string[]}){ const myName = "Saba" const [available, setAvailable] = useState(!!names.includes(myName)); const [show, setShow] = useState(false); useEffect(() => { if (available) { if (!names.includes(myName)){ names.push(myName) } }else { names.splice(names.findIndex(name => name == myName), 1) } }, [available]) return ( <div className="relative z-1 h-full"> <div className="absolute right-0 left-0 top-0 p-0.5 bg-zinc-50 m-0.5"> <div className=" pt-0 p-1 lg:text-sm text-xs font-mono rounded-lg rounded-bl-none rounded-tr-none rounded-tl-none min-h-full w-full bg-[#7c4145]" onMouseEnter={() => setShow(true)} onMouseLeave={() => setShow(false)} > <div className="lg:flex justify-between"> <div className="font-white font-semibold capitalize lg:underline underline-offset-4 decoration-pink-500 decoration-2 lg:mt-1">{title}</div> <IsAvailableButton available={available} setAvailable={setAvailable}/> </div> {show && <div className=" capitalize">{names.map(name => <div className="block">{name}</div>)}</div>} </div> </div> <div className="bg-[#3F565F] w-1 ml-0.5 h-full z-0"> </div> </div> ) } function IsAvailableButton({available, setAvailable}:{available:boolean, setAvailable:React.Dispatch<React.SetStateAction<boolean>>}){ if (available) { return <button className="bg-green-500 border-transparent text-white font-semibold px-1 lg:mt-1 border rounded hover:border-green-500 hover:bg-transparent hover:text-green-700" onClick={() => setAvailable(false)}>Free</button> }else{ return <button className="bg-red-500 border-transparent text-white font-semibold px-1 lg:mt-1 border rounded hover:border-red-500 hover:bg-transparent hover:text-red-700" onClick={() => setAvailable(true)}>Busy</button> } } function rowspan(i:number){ const rowspans = [ 'row-span-1','row-span-2','row-span-3','row-span-4','row-span-5','row-span-6','row-span-7','row-span-8', 'row-span-9','row-span-10','row-span-11','row-span-12','row-span-13','row-span-14','row-span-15','row-span-16', 'row-span-17','row-span-18','row-span-19','row-span-20','row-span-21','row-span-22','row-span-23','row-span-24' ]; return rowspans[i-1]; }