-
-
Save keegandonley/cf2a5bcc04bd9e540e87351fc1ca2163 to your computer and use it in GitHub Desktop.
Calendar Demo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Fragment, useMemo, useState } from 'react'; | |
import { | |
faChevronLeft, | |
faChevronRight, | |
} from '@fortawesome/pro-duotone-svg-icons'; | |
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; | |
import { DateTime } from 'luxon'; | |
const days = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; | |
const names = [ | |
'January', | |
'February', | |
'March', | |
'April', | |
'May', | |
'June', | |
'July', | |
'August', | |
'September', | |
'October', | |
'November', | |
'December', | |
]; | |
const weekDays = [ | |
'Sunday', | |
'Monday', | |
'Tuesday', | |
'Wednesday', | |
'Thursday', | |
'Friday', | |
'Saturday', | |
]; | |
const CalendarDemo = () => { | |
const [monthOffset, setMonthOffset] = useState(0); | |
const date = useMemo( | |
() => DateTime.local().startOf('month').minus({ months: monthOffset }), | |
[monthOffset] | |
); | |
const today = useMemo( | |
() => DateTime.local().startOf('day').minus({ days: 0 }), | |
[] | |
); | |
const month = useMemo(() => { | |
const monthIndex = date.month - 1; | |
const startingIndex = date.weekday === 7 ? 0 : date.weekday; | |
const daysInMonth = days[monthIndex]; | |
const res: (null | number)[][] = [ | |
[null, null, null, null, null, null, null], | |
[null, null, null, null, null, null, null], | |
[null, null, null, null, null, null, null], | |
[null, null, null, null, null, null, null], | |
[null, null, null, null, null, null, null], | |
[null, null, null, null, null, null, null], | |
]; | |
let usedDaysThisWeek = startingIndex; | |
let weeksUsed = 0; | |
let day = 1; | |
while (day <= daysInMonth) { | |
res[weeksUsed][usedDaysThisWeek] = day; | |
day += 1; | |
if (usedDaysThisWeek === 6) { | |
usedDaysThisWeek = 0; | |
weeksUsed += 1; | |
} else { | |
usedDaysThisWeek += 1; | |
} | |
} | |
return res; | |
}, [date]); | |
return ( | |
<div className="p-6"> | |
<div className="text-center mb-4 text-lg"> | |
<FontAwesomeIcon | |
icon={faChevronLeft} | |
className="mr-4 cursor-pointer text-gray-400 hover:text-black" | |
onClick={() => setMonthOffset((m) => m + 1)} | |
/> | |
<span className="font-semibold"> | |
{names[date.month - 1]} {date.year} | |
</span> | |
<FontAwesomeIcon | |
icon={faChevronRight} | |
className="ml-4 cursor-pointer text-gray-400 hover:text-black" | |
onClick={() => setMonthOffset((m) => m - 1)} | |
/> | |
</div> | |
<div className="overflow-x-auto"> | |
<div> | |
<div className="flex"> | |
{weekDays.map((day, _index) => { | |
return ( | |
<div | |
key={day} | |
className={`min-w-[200px] border-solid border-transparent border-l flex-grow text-gray-600 text-center mb-1 text-sm cursor-pointer`} | |
> | |
{day} | |
</div> | |
); | |
})} | |
</div> | |
</div> | |
<div className="flex flex-col flex-grow min-h-[700px] mb-12"> | |
{month.map((week, weekIndex) => { | |
return week.every((x) => x === null) ? ( | |
<Fragment key={JSON.stringify(week)} /> | |
) : ( | |
<div key={JSON.stringify(week)} className="flex flex-grow"> | |
{week.map((day, dayIndex) => { | |
const isToday = | |
day === today.day && | |
date.month === today.month && | |
date.year === today.year; | |
return ( | |
<div | |
key={`${JSON.stringify(week)}-${day}-${dayIndex}`} | |
className={`min-w-[200px] min-h-[100px] ${ | |
day ? 'bg-gray-100' : '' | |
} ${isToday ? 'bg-blue-200' : ''} ${ | |
weekIndex === 0 ? 'border-t' : '' | |
} border-solid border-b w-full flex flex-col border-r border-gray-200 ${ | |
dayIndex === 0 ? 'border-l' : '' | |
}`} | |
> | |
<div className="relative h-4"> | |
<div className="absolute text-xs left-1 top-1 text-gray-500"> | |
{day} | |
</div> | |
</div> | |
</div> | |
); | |
})} | |
</div> | |
); | |
})} | |
</div> | |
</div> | |
</div> | |
); | |
}; | |
export default CalendarDemo; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment