Files
cutt/frontend/src/Calendar.tsx

206 lines
5.4 KiB
TypeScript

import { JSX, useEffect, useState } from "react";
import { apiAuth } from "./api";
import { useSession } from "./Session";
interface Datum {
[id: number]: string;
}
interface Events {
[key: string]: Datum;
}
const Calendar = ({ playerId }: { playerId: number }) => {
const [selectedDate, setSelectedDate] = useState(new Date());
const [events, setEvents] = useState<Events>();
const { teams, players } = useSession();
async function loadSubmissionDates() {
if (teams?.activeTeam) {
const data = await apiAuth(`analysis/times/${teams?.activeTeam}`, null);
if (data.detail) {
console.log(data.detail);
} else {
setEvents(data as Events);
}
}
}
useEffect(() => {
loadSubmissionDates();
}, [players]);
const getEventsForDay = (date: Date) => {
return events && events[date.toISOString().split("T")[0]];
};
// Handle day click
const handleDayClick = (date: Date) => {
setSelectedDate(date);
};
// Navigate to previous month
const handlePrevMonth = () => {
const date = new Date(selectedDate);
date.setMonth(date.getMonth() - 1);
setSelectedDate(date);
};
// Navigate to next month
const handleNextMonth = () => {
const date = new Date(selectedDate);
date.setMonth(date.getMonth() + 1);
setSelectedDate(date);
};
// Render month navigation
const renderMonthNavigation = () => {
return (
<div className="field has-addons">
<p className="control">
<button
className="button is-light is-size-7-mobile"
onClick={handlePrevMonth}
>
&lt;
</button>
</p>
<p className="control">
<button
className="button is-light is-size-7-mobile"
onClick={() => setSelectedDate(new Date())}
>
📅{" "}
{selectedDate.toLocaleString("default", {
month: "long",
year: "numeric",
})}
</button>
</p>
<p className="control">
<button
className="button is-light is-size-7-mobile"
onClick={handleNextMonth}
>
&gt;
</button>
</p>
</div>
);
};
// Render the calendar
const renderCalendar = () => {
const firstDayOfMonth = new Date(
selectedDate.getFullYear(),
selectedDate.getMonth(),
0
).getDay();
const lastDateOfMonth = new Date(
selectedDate.getFullYear(),
selectedDate.getMonth() + 1,
0
).getDate();
let days: JSX.Element[] = [];
let day = 1;
for (let i = 0; i < 7; i++) {
const date = new Date(0);
date.setDate(i + 5);
days.push(
<button
key={"weekday_" + i}
className="button is-size-7-mobile is-white is-static"
>
{date.toLocaleString("default", {
weekday: "narrow",
})}
</button>
);
}
// Add empty cells for the first week
for (let i = 0; i < firstDayOfMonth; i++) {
days.push(<div key={"prev" + i} className="empty"></div>);
}
// Render each day of the month
while (day <= lastDateOfMonth) {
const date = new Date(selectedDate);
date.setDate(day);
const todaysEvents = getEventsForDay(date);
days.push(
<button
key={date.getDate()}
className={
"cell button is-size-7-mobile" +
(date.toDateString() === selectedDate.toDateString()
? " is-focused is-active is-primary is-light"
: " is-white") +
(date.toDateString() === new Date().toDateString()
? " is-danger has-text-weight-extrabold"
: "") +
(todaysEvents ? " is-warning is-light" : "") +
(todaysEvents && playerId in todaysEvents
? " is-hovered has-text-weight-semibold"
: "")
}
onClick={() => handleDayClick(date)}
>
{day}
</button>
);
day++;
}
return (
<div className="fixed-grid has-7-cols">
<div className="grid is-gap-0.5">{days}</div>
</div>
);
};
// Render events for the selected day
const renderEvents = () => {
const eventsForDay = getEventsForDay(selectedDate);
return (
<div className="events">
{eventsForDay &&
Object.entries(eventsForDay).map(([id, sub]) => {
const name = players?.find((p) => p.id === Number(id));
return (
<p className="field">
<div className="control" key={id}>
<div className="tags are-medium has-addons">
<span className="tag is-warning is-size-7-mobile">
{name !== undefined ? name.display_name : ""}
</span>
<span className="tag is-primary is-light is-size-7-mobile">
{sub}
</span>
</div>
</div>
</p>
);
})}
</div>
);
};
return (
<div className="block is-size-7-mobile">
<h2 className="title is-4">Latest Submissions</h2>
<div className="columns is-6">
<div className="column" style={{ maxWidth: 600 }}>
{renderMonthNavigation()}
{renderCalendar()}
</div>
<div className="column is-narrow">{renderEvents()}</div>
</div>
</div>
);
};
export default Calendar;