Add entry image backgrounds and indicators to calendar !

This commit is contained in:
2026-02-03 16:33:24 +13:00
parent 5fff9a0359
commit ca3fc60ee1
2 changed files with 93 additions and 19 deletions

View File

@@ -1,7 +1,15 @@
<script lang="ts"> <script lang="ts">
interface Entry {
date: string;
id: string;
image?: string;
content: string;
}
let { let {
year = $bindable('2026'), year = $bindable('2026'),
month = $bindable('0') month = $bindable('0'),
entries
} = $props() } = $props()
var headers = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]; var headers = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
@@ -10,6 +18,16 @@
let currentYear = $state(parseInt(year)); let currentYear = $state(parseInt(year));
let currentMonth = $state(parseInt(month)); let currentMonth = $state(parseInt(month));
// Helper function to find entry for a specific day
function getEntryForDay(year: number, month: number, date: number): Entry | undefined {
if (!entries) return undefined;
const dateStr = new Date(year, month, date).toISOString().split('T')[0];
return entries.find(entry => {
const entryDate = entry.date.split('T')[0];
return entryDate === dateStr;
});
}
// Get current week when in week view // Get current week when in week view
function getCurrentWeek() { function getCurrentWeek() {
const today = new Date(); const today = new Date();
@@ -23,13 +41,15 @@
for (let i = 0; i < 7; i++) { for (let i = 0; i < 7; i++) {
const day = new Date(monday); const day = new Date(monday);
day.setDate(monday.getDate() + i); day.setDate(monday.getDate() + i);
const entry = getEntryForDay(day.getFullYear(), day.getMonth(), day.getDate());
week.push({ week.push({
date: day.getDate(), date: day.getDate(),
month: day.getMonth(), month: day.getMonth(),
year: day.getFullYear(), year: day.getFullYear(),
dayName: headers[i], dayName: headers[i],
isCurrentMonth: day.getMonth() === today.getMonth(), isCurrentMonth: day.getMonth() === today.getMonth(),
isToday: day.toDateString() === today.toDateString() isToday: day.toDateString() === today.toDateString(),
entry
}); });
} }
return week; return week;
@@ -51,13 +71,18 @@
const prevMonthLastDay = new Date(year, month, 0).getDate(); const prevMonthLastDay = new Date(year, month, 0).getDate();
for (let i = startDay - 1; i >= 0; i--) { for (let i = startDay - 1; i >= 0; i--) {
const dayIndex = days.length % 7; const dayIndex = days.length % 7;
const dayDate = prevMonthLastDay - i;
const dayMonth = month - 1;
const dayYear = month === 0 ? year - 1 : year;
const entry = getEntryForDay(dayYear, dayMonth, dayDate);
days.push({ days.push({
date: prevMonthLastDay - i, date: dayDate,
month: month - 1, month: dayMonth,
year: month === 0 ? year - 1 : year, year: dayYear,
dayName: headers[dayIndex], dayName: headers[dayIndex],
isCurrentMonth: false, isCurrentMonth: false,
isToday: false isToday: false,
entry
}); });
} }
@@ -68,13 +93,15 @@
today.getMonth() === month && today.getMonth() === month &&
today.getFullYear() === year; today.getFullYear() === year;
const dayIndex = days.length % 7; const dayIndex = days.length % 7;
const entry = getEntryForDay(year, month, i);
days.push({ days.push({
date: i, date: i,
month: month, month: month,
year: year, year: year,
dayName: headers[dayIndex], dayName: headers[dayIndex],
isCurrentMonth: true, isCurrentMonth: true,
isToday isToday,
entry
}); });
} }
@@ -82,13 +109,17 @@
const remaining = 42 - days.length; // 6 rows * 7 days const remaining = 42 - days.length; // 6 rows * 7 days
for (let i = 1; i <= remaining; i++) { for (let i = 1; i <= remaining; i++) {
const dayIndex = days.length % 7; const dayIndex = days.length % 7;
const dayMonth = month + 1;
const dayYear = month === 11 ? year + 1 : year;
const entry = getEntryForDay(dayYear, dayMonth, i);
days.push({ days.push({
date: i, date: i,
month: month + 1, month: dayMonth,
year: month === 11 ? year + 1 : year, year: dayYear,
dayName: headers[dayIndex], dayName: headers[dayIndex],
isCurrentMonth: false, isCurrentMonth: false,
isToday: false isToday: false,
entry
}); });
} }
@@ -155,12 +186,24 @@
<div class="calendar"> <div class="calendar">
{#each days as day, index} {#each days as day, index}
<div class="day" class:other-month={!day.isCurrentMonth} class:today={day.isToday}> <div
class="day"
class:other-month={!day.isCurrentMonth}
class:today={day.isToday}
class:has-image={day.entry?.image}
style={day.entry?.image ? `background-image: url(${day.entry.image}); background-size: cover; background-position: center;` : ''}
>
{#if day.entry?.image}
<div class="image-overlay"></div>
{/if}
<div class="day-header"> <div class="day-header">
{#if index < 7} {#if index < 7}
<span class="day-name">{day.dayName}</span> <span class="day-name">{day.dayName}</span>
{/if} {/if}
<span class="date">{day.date}</span> <span class="date">{day.date}</span>
{#if day.entry}
<span class="entry-indicator"></span>
{/if}
</div> </div>
</div> </div>
{/each} {/each}
@@ -187,7 +230,7 @@
height: 36px; height: 36px;
border: 1px solid rgba(166, 168, 179, 0.2); border: 1px solid rgba(166, 168, 179, 0.2);
background: transparent; background: transparent;
color: #e9a1a7; color: #009FB7;
font-size: 24px; font-size: 24px;
cursor: pointer; cursor: pointer;
border-radius: 4px; border-radius: 4px;
@@ -199,7 +242,7 @@
.expand-btn:hover { .expand-btn:hover {
background: rgba(233, 161, 167, 0.1); background: rgba(233, 161, 167, 0.1);
border-color: #e9a1a7; border-color: #009FB7;
} }
.nav-btn { .nav-btn {
@@ -207,7 +250,7 @@
height: 32px; height: 32px;
border: 1px solid rgba(166, 168, 179, 0.2); border: 1px solid rgba(166, 168, 179, 0.2);
background: transparent; background: transparent;
color: #e9a1a7; color: #009FB7;
font-size: 20px; font-size: 20px;
cursor: pointer; cursor: pointer;
border-radius: 4px; border-radius: 4px;
@@ -219,13 +262,13 @@
.nav-btn:hover { .nav-btn:hover {
background: rgba(233, 161, 167, 0.1); background: rgba(233, 161, 167, 0.1);
border-color: #e9a1a7; border-color: #009FB7;
} }
.month-year { .month-year {
font-size: 18px; font-size: 18px;
font-weight: 600; font-weight: 600;
color: #e9a1a7; color: #009FB7;
flex: 1; flex: 1;
text-align: center; text-align: center;
} }
@@ -248,17 +291,33 @@
z-index: 1; z-index: 1;
} }
.day.has-image {
background-color: transparent;
}
.image-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.3);
z-index: 1;
}
.day-header { .day-header {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
margin-bottom: 8px; margin-bottom: 8px;
position: relative;
z-index: 2;
} }
.day-name { .day-name {
font-size: 12px; font-size: 12px;
text-transform: uppercase; text-transform: uppercase;
color: #e9a1a7; color: #009FB7;
font-weight: 500; font-weight: 500;
} }
@@ -268,6 +327,21 @@
letter-spacing: 1px; letter-spacing: 1px;
} }
.entry-indicator {
width: 8px;
height: 8px;
border-radius: 50%;
background-color: #4a9eff;
display: inline-block;
margin-left: 8px;
}
.day.has-image .day-name,
.day.has-image .date {
color: white;
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8);
}
.day.other-month { .day.other-month {
opacity: 0.3; opacity: 0.3;
} }
@@ -277,7 +351,7 @@
} }
.day.today .date { .day.today .date {
color: #e9a1a7; color: #009FB7;
font-weight: 700; font-weight: 700;
} }

View File

@@ -17,7 +17,7 @@
} }
</script> </script>
<Calendar /> <Calendar entries={data.all} />
<div class="flex flex-col md:flex-row space-y-4 w-full mt-6"> <div class="flex flex-col md:flex-row space-y-4 w-full mt-6">