2026-04-18 11:55:01 +00:00
|
|
|
import "./monthGrid.css";
|
|
|
|
|
import { ViewController } from "../viewController";
|
2026-09-23 00:09:09 +02:00
|
|
|
import * as React from "../../react";
|
2024-07-26 03:14:55 +02:00
|
|
|
import TaskViewModel from "../../ViewModel/Pages/taskViewModel";
|
2026-04-09 16:48:22 +00:00
|
|
|
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
2026-04-18 11:55:01 +00:00
|
|
|
import { localeCompare } from "../../Model/Utility/utility";
|
|
|
|
|
import { MonthGrid } from "../../Model/Files/calendarModel";
|
2024-07-26 03:14:55 +02:00
|
|
|
|
2024-07-26 03:38:46 +02:00
|
|
|
export function MonthGrid<T>(
|
2026-04-09 16:48:22 +00:00
|
|
|
coreViewModel: CoreViewModel,
|
2026-04-01 08:29:39 +00:00
|
|
|
monthGrid: MonthGrid<React.MapState<T>>,
|
|
|
|
|
selectedDate: React.State<number>,
|
|
|
|
|
handleDrop: (date: string) => void,
|
2024-07-26 03:38:46 +02:00
|
|
|
) {
|
2026-04-01 08:29:39 +00:00
|
|
|
const dayLabels: HTMLElement[] = [];
|
|
|
|
|
let currentWeekday = monthGrid.firstDayOfWeek;
|
|
|
|
|
while (dayLabels.length < 7) {
|
|
|
|
|
dayLabels.push(
|
|
|
|
|
<span class="secondary">
|
2026-04-09 16:48:22 +00:00
|
|
|
{
|
|
|
|
|
coreViewModel.translations.regional.weekdays.abbreviated[
|
|
|
|
|
currentWeekday
|
|
|
|
|
]
|
|
|
|
|
}
|
2026-04-01 08:29:39 +00:00
|
|
|
</span>,
|
|
|
|
|
);
|
|
|
|
|
currentWeekday++;
|
|
|
|
|
if (currentWeekday == 7) currentWeekday = 0;
|
|
|
|
|
}
|
2024-07-26 03:29:07 +02:00
|
|
|
|
2026-04-01 08:29:39 +00:00
|
|
|
const offsetElements: HTMLElement[] = [];
|
|
|
|
|
for (let i = 0; i < monthGrid.offset; i++) {
|
|
|
|
|
offsetElements.push(<div></div>);
|
|
|
|
|
}
|
2024-07-26 03:14:55 +02:00
|
|
|
|
2026-04-01 08:29:39 +00:00
|
|
|
const converter: React.StateItemConverter<TaskViewModel> = (
|
|
|
|
|
taskViewModel,
|
|
|
|
|
) => {
|
|
|
|
|
const view = (
|
|
|
|
|
<span class="ellipsis secondary">{taskViewModel.task.name}</span>
|
|
|
|
|
);
|
2024-07-26 06:20:16 +02:00
|
|
|
|
2026-04-01 08:29:39 +00:00
|
|
|
taskViewModel.index.subscribe((newIndex) => {
|
|
|
|
|
view.style.order = newIndex;
|
|
|
|
|
});
|
2024-07-26 06:20:16 +02:00
|
|
|
|
2026-04-01 08:29:39 +00:00
|
|
|
return view;
|
|
|
|
|
};
|
2024-07-26 03:14:55 +02:00
|
|
|
|
2026-04-01 08:29:39 +00:00
|
|
|
return (
|
|
|
|
|
<div class="month-grid-wrapper">
|
|
|
|
|
<div class="day-labels">{...dayLabels}</div>
|
|
|
|
|
<div class="month-grid">
|
|
|
|
|
{...offsetElements}
|
|
|
|
|
{...Object.entries(monthGrid.days)
|
|
|
|
|
.sort((a, b) => localeCompare(a[0], b[0]))
|
|
|
|
|
.map((entry) => {
|
|
|
|
|
const [date, mapState] = entry;
|
2024-07-26 03:14:55 +02:00
|
|
|
|
2026-04-01 08:29:39 +00:00
|
|
|
const isSelected = React.createProxyState(
|
|
|
|
|
[selectedDate],
|
|
|
|
|
() => selectedDate.value == parseInt(date),
|
|
|
|
|
);
|
2024-07-26 03:38:46 +02:00
|
|
|
|
2026-04-16 11:56:42 +00:00
|
|
|
const isToday = React.createProxyState(
|
|
|
|
|
[coreViewModel.todayDate],
|
|
|
|
|
() => {
|
|
|
|
|
return (
|
|
|
|
|
monthGrid.isCurrentMonth == true &&
|
|
|
|
|
date ==
|
2026-04-18 11:55:01 +00:00
|
|
|
coreViewModel.unwrappedTodayDate
|
|
|
|
|
.getDate()
|
|
|
|
|
.toString()
|
2026-05-03 14:25:03 +00:00
|
|
|
.padStart(2, "0")
|
2026-04-16 11:56:42 +00:00
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
);
|
2024-07-26 05:32:07 +02:00
|
|
|
|
2026-04-01 08:29:39 +00:00
|
|
|
const eventCount: React.State<number> =
|
|
|
|
|
React.createProxyState(
|
|
|
|
|
[mapState],
|
|
|
|
|
() => mapState.value.size,
|
|
|
|
|
);
|
2024-08-27 09:58:28 -07:00
|
|
|
|
2026-04-01 08:29:39 +00:00
|
|
|
const hasEvents: React.State<boolean> =
|
|
|
|
|
React.createProxyState(
|
|
|
|
|
[eventCount],
|
|
|
|
|
() => eventCount.value != 0,
|
|
|
|
|
);
|
2024-08-27 09:58:28 -07:00
|
|
|
|
2026-04-01 08:29:39 +00:00
|
|
|
function select() {
|
|
|
|
|
selectedDate.value = parseInt(date);
|
|
|
|
|
}
|
2024-07-26 03:38:46 +02:00
|
|
|
|
2026-04-01 08:29:39 +00:00
|
|
|
function drop() {
|
|
|
|
|
handleDrop(date);
|
|
|
|
|
}
|
2024-07-26 07:07:07 +02:00
|
|
|
|
2026-04-01 08:29:39 +00:00
|
|
|
return (
|
|
|
|
|
<button
|
|
|
|
|
class="tile"
|
|
|
|
|
on:click={select}
|
|
|
|
|
toggle:selected={isSelected}
|
|
|
|
|
toggle:today={isToday}
|
2026-04-15 12:47:10 +00:00
|
|
|
on:dragover={ViewController.allowDrop}
|
2026-04-01 08:29:39 +00:00
|
|
|
on:drop={drop}
|
|
|
|
|
>
|
|
|
|
|
<div>
|
|
|
|
|
<b>{date}</b>
|
|
|
|
|
<span
|
|
|
|
|
class="event-count"
|
|
|
|
|
toggle:has-events={hasEvents}
|
|
|
|
|
subscribe:innerText={eventCount}
|
|
|
|
|
></span>
|
|
|
|
|
<div
|
|
|
|
|
class="event-list"
|
|
|
|
|
children:append={[mapState, converter]}
|
|
|
|
|
></div>
|
|
|
|
|
</div>
|
|
|
|
|
</button>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
2024-07-26 03:14:55 +02:00
|
|
|
}
|