mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-22 18:26:42 +02:00
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:
parent
c6677a8a1b
commit
7ff8213bd6
2 changed files with 80 additions and 6 deletions
|
|
@ -113,12 +113,56 @@ export class CalendarService {
|
||||||
return updated;
|
return updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new default calendar
|
// Create default calendars for new user
|
||||||
return this.create(userId, {
|
await this.createDefaultCalendars(userId);
|
||||||
name: 'Mein Kalender',
|
|
||||||
isDefault: true,
|
// Return the default one
|
||||||
color: '#3B82F6',
|
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> {
|
private async clearDefaultCalendar(userId: string): Promise<void> {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { viewStore } from '$lib/stores/view.svelte';
|
import { viewStore } from '$lib/stores/view.svelte';
|
||||||
|
import { eventsStore } from '$lib/stores/events.svelte';
|
||||||
import {
|
import {
|
||||||
format,
|
format,
|
||||||
isToday,
|
isToday,
|
||||||
|
|
@ -13,6 +14,12 @@
|
||||||
import { onMount, tick } from 'svelte';
|
import { onMount, tick } from 'svelte';
|
||||||
import SunCalc from 'suncalc';
|
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)
|
// Moon phase emojis (8 phases)
|
||||||
const MOON_EMOJIS = ['🌑', '🌒', '🌓', '🌔', '🌕', '🌖', '🌗', '🌘'];
|
const MOON_EMOJIS = ['🌑', '🌒', '🌓', '🌔', '🌕', '🌖', '🌗', '🌘'];
|
||||||
|
|
||||||
|
|
@ -223,6 +230,7 @@
|
||||||
{@const dayIsRangeEnd = isSameDay(day, viewRange.end)}
|
{@const dayIsRangeEnd = isSameDay(day, viewRange.end)}
|
||||||
{@const isFirstOfMonth = day.getDate() === 1}
|
{@const isFirstOfMonth = day.getDate() === 1}
|
||||||
{@const moonPhase = isSignificantMoonPhase(day)}
|
{@const moonPhase = isSignificantMoonPhase(day)}
|
||||||
|
{@const eventCount = getEventCount(day)}
|
||||||
{#if isFirstOfMonth}
|
{#if isFirstOfMonth}
|
||||||
<div class="month-divider"></div>
|
<div class="month-divider"></div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
@ -249,6 +257,13 @@
|
||||||
<span class="day-number" style={dayIsToday ? 'color: white;' : ''}
|
<span class="day-number" style={dayIsToday ? 'color: white;' : ''}
|
||||||
>{format(day, 'd')}</span
|
>{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>
|
</button>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -371,6 +386,21 @@
|
||||||
line-height: 1;
|
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 {
|
.day-item:hover {
|
||||||
background: var(--color-muted, #f3f4f6);
|
background: var(--color-muted, #f3f4f6);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue