feat(calendar): add default calendars and event indicators

- Create 4 default calendars for new users: Persönlich, Beruf, Familie, Freizeit
- Add event count dots below dates in DateStrip (max 5 dots)
- Show blue dots for events, white dots on today

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Till-JS 2025-12-12 03:51:53 +01:00
parent c6677a8a1b
commit 7ff8213bd6
2 changed files with 80 additions and 6 deletions

View file

@ -113,12 +113,56 @@ export class CalendarService {
return updated;
}
// Create a new default calendar
return this.create(userId, {
name: 'Mein Kalender',
isDefault: true,
color: '#3B82F6',
});
// Create default calendars for new user
await this.createDefaultCalendars(userId);
// Return the default one
const defaultCal = await this.db
.select()
.from(calendars)
.where(and(eq(calendars.userId, userId), eq(calendars.isDefault, true)));
return defaultCal[0];
}
/**
* Create default calendars for a new user
*/
async createDefaultCalendars(userId: string): Promise<Calendar[]> {
const defaultCalendars = [
{
name: 'Persönlich',
color: '#3B82F6', // Blue
isDefault: true,
description: 'Private Termine',
},
{
name: 'Beruf',
color: '#10B981', // Green
isDefault: false,
description: 'Arbeit, Meetings, Projekte',
},
{
name: 'Familie',
color: '#F97316', // Orange
isDefault: false,
description: 'Familientermine, Geburtstage',
},
{
name: 'Freizeit',
color: '#8B5CF6', // Violet
isDefault: false,
description: 'Hobbies, Sport, Events',
},
];
const created: Calendar[] = [];
for (const cal of defaultCalendars) {
const calendar = await this.create(userId, cal);
created.push(calendar);
}
return created;
}
private async clearDefaultCalendar(userId: string): Promise<void> {

View file

@ -1,5 +1,6 @@
<script lang="ts">
import { viewStore } from '$lib/stores/view.svelte';
import { eventsStore } from '$lib/stores/events.svelte';
import {
format,
isToday,
@ -13,6 +14,12 @@
import { onMount, tick } from 'svelte';
import SunCalc from 'suncalc';
// Get event count for a day (max 5 dots displayed)
function getEventCount(date: Date): number {
const events = eventsStore.getEventsForDay(date, false);
return Math.min(events.length, 5); // Cap at 5 dots
}
// Moon phase emojis (8 phases)
const MOON_EMOJIS = ['🌑', '🌒', '🌓', '🌔', '🌕', '🌖', '🌗', '🌘'];
@ -223,6 +230,7 @@
{@const dayIsRangeEnd = isSameDay(day, viewRange.end)}
{@const isFirstOfMonth = day.getDate() === 1}
{@const moonPhase = isSignificantMoonPhase(day)}
{@const eventCount = getEventCount(day)}
{#if isFirstOfMonth}
<div class="month-divider"></div>
{/if}
@ -249,6 +257,13 @@
<span class="day-number" style={dayIsToday ? 'color: white;' : ''}
>{format(day, 'd')}</span
>
{#if eventCount > 0}
<div class="event-dots" style={dayIsToday ? 'opacity: 0.9;' : ''}>
{#each Array(eventCount) as _, i}
<span class="event-dot" style={dayIsToday ? 'background: white;' : ''}></span>
{/each}
</div>
{/if}
</button>
{/each}
</div>
@ -371,6 +386,21 @@
line-height: 1;
}
.event-dots {
display: flex;
gap: 2px;
justify-content: center;
margin-top: 2px;
}
.event-dot {
width: 4px;
height: 4px;
border-radius: 50%;
background: #3b82f6;
opacity: 0.7;
}
.day-item:hover {
background: var(--color-muted, #f3f4f6);
}