Files
Memento/src/lib/components/calendar.svelte

68 lines
2.1 KiB
Svelte

<script lang="ts">
import Calendar from "$lib/components/ui/calendar/calendar.svelte";
import CalendarDay from "$lib/components/ui/calendar/calendar-day.svelte";
import { CalendarDate, type DateValue } from "@internationalized/date";
let {
value = $bindable<CalendarDate | undefined>(
new CalendarDate(2026, 2, 1),
),
} = $props();
let placeholder = $state<CalendarDate | undefined>(undefined);
let imageMap = $state<Map<string, string>>(new Map());
let displayedMonth = $derived(placeholder ?? value);
$effect(() => {
if (displayedMonth) {
const month = `${displayedMonth.year}-${String(displayedMonth.month).padStart(2, "0")}`;
fetchMonthImages(month);
}
});
async function fetchMonthImages(month: string) {
try {
const res = await fetch(`/api/entry?month=${month}`);
const entries = await res.json();
const newMap = new Map<string, string>();
for (const entry of entries) {
if (entry.image) {
const d = new Date(entry.date);
const key = `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}`;
newMap.set(key, entry.image);
}
}
imageMap = newMap;
} catch (err) {
console.error("Failed to fetch month images:", err);
}
}
function getImageForDate(day: DateValue): string | null {
const key = `${day.year}-${day.month}-${day.day}`;
return imageMap.get(key) ?? null;
}
</script>
<Calendar
type="single"
bind:value
bind:placeholder
class="rounded-lg border shadow-sm [--cell-size:--spacing(11)] md:[--cell-size:--spacing(12)]"
>
{#snippet day({ day })}
<CalendarDay>
{day.day}
{@const img = getImageForDate(day)}
{#if img}
<img
src={img}
alt=""
class="h-4 w-full rounded-sm object-cover"
/>
{/if}
</CalendarDay>
{/snippet}
</Calendar>