175 lines
4.4 KiB
TypeScript
175 lines
4.4 KiB
TypeScript
import { 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="month-navigation">
|
|
<button onClick={handlePrevMonth}><</button>
|
|
<span>
|
|
<button onClick={() => setSelectedDate(new Date())}>📅</button>
|
|
{selectedDate.toLocaleString("default", {
|
|
month: "long",
|
|
year: "numeric",
|
|
})}
|
|
</span>
|
|
<button onClick={handleNextMonth}>></button>
|
|
</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(
|
|
<div key={"weekday_" + i} className="weekday">
|
|
{date.toLocaleString("default", {
|
|
weekday: "narrow",
|
|
})}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// 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(
|
|
<div
|
|
key={date.getDate()}
|
|
className={
|
|
"day" +
|
|
(date.toDateString() === selectedDate.toDateString()
|
|
? " selected-day"
|
|
: "")
|
|
}
|
|
onClick={() => handleDayClick(date)}
|
|
>
|
|
<div
|
|
className={
|
|
"day-circle" +
|
|
(date.toDateString() === new Date().toDateString()
|
|
? " today"
|
|
: "") +
|
|
(todaysEvents ? " has-event" : "") +
|
|
(todaysEvents && playerId in todaysEvents ? " active-player" : "")
|
|
}
|
|
>
|
|
{day}
|
|
</div>
|
|
</div>
|
|
);
|
|
day++;
|
|
}
|
|
|
|
return <div className="calendar">{days}</div>;
|
|
};
|
|
|
|
// Render events for the selected day
|
|
const renderEvents = () => {
|
|
const eventsForDay = getEventsForDay(selectedDate);
|
|
return (
|
|
<div className="events">
|
|
{eventsForDay && (
|
|
<ul>
|
|
{Object.entries(eventsForDay).map(([id, sub]) => {
|
|
const name = players?.find((p) => p.id === Number(id));
|
|
return (
|
|
<li key={id}>
|
|
{name !== undefined ? name.display_name : ""}:{" "}
|
|
<span style={{ letterSpacing: 8 }}>{sub}</span>
|
|
</li>
|
|
);
|
|
})}
|
|
</ul>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
return (
|
|
<div className="calendar-container">
|
|
<h2>Latest Submissions</h2>
|
|
{renderMonthNavigation()}
|
|
{renderCalendar()}
|
|
{renderEvents()}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default Calendar;
|