Skip to content

Instantly share code, notes, and snippets.

@keegandonley
Created November 12, 2021 19:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save keegandonley/cf2a5bcc04bd9e540e87351fc1ca2163 to your computer and use it in GitHub Desktop.
Save keegandonley/cf2a5bcc04bd9e540e87351fc1ca2163 to your computer and use it in GitHub Desktop.
Calendar Demo
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