opt side panel

This commit is contained in:
beo3000 2026-02-24 19:06:18 +01:00
parent 53b20cf492
commit e5a37bd7ed
4 changed files with 116 additions and 209 deletions

View File

@ -1 +1 @@
1.1.52
1.1.54

View File

@ -14,34 +14,77 @@
<div class="flex flex-wrap gap-2.5 mt-4 pt-4 border-t border-[#444]">
{#if isDailyLog}
<button class="flex-1 rounded bg-success px-4 py-2 font-bold text-white text-sm flex items-center justify-center gap-1" onclick={onnote}>
<button
class="flex-1 rounded bg-accent px-4 py-2 font-bold text-white text-sm flex items-center justify-center gap-1 hover:brightness-110 transition-all"
onclick={onnote}
>
Notieren
</button>
<button class="flex-1 rounded bg-accent px-4 py-2 font-bold text-white text-sm flex items-center justify-center gap-1" onclick={ondone}>
Erledigt
</button>
<button class="flex-1 rounded bg-warning px-4 py-2 font-bold text-[#222] text-sm flex items-center justify-center gap-1" onclick={onsnooze}>
Später
</button>
<div class="flex gap-1.5">
<button
class="rounded border border-[#444] bg-transparent px-3 py-2 text-xs text-[#777] hover:border-warning hover:text-warning transition-all flex flex-col items-center gap-0.5 min-w-[4rem]"
onclick={onsnooze}
title="Später"
>
<span class="text-base leading-none"></span>
<span>Später</span>
</button>
<button
class="rounded border border-[#444] bg-transparent px-3 py-2 text-xs text-[#777] hover:border-success hover:text-success transition-all flex flex-col items-center gap-0.5 min-w-[4rem]"
onclick={ondone}
title="Erledigt"
>
<span class="text-base leading-none"></span>
<span>Erledigt</span>
</button>
</div>
{:else if isMeetingMode && !isProcessed}
<button class="flex-1 rounded bg-success px-4 py-2 font-bold text-white text-sm flex items-center justify-center gap-1" onclick={onnote}>
<button
class="flex-1 rounded bg-accent px-4 py-2 font-bold text-white text-sm flex items-center justify-center gap-1 hover:brightness-110 transition-all"
onclick={onnote}
>
Notieren & Offen
</button>
<button class="flex-1 rounded bg-warning px-4 py-2 font-bold text-[#222] text-sm flex items-center justify-center gap-1" onclick={onsnooze}>
Verschieben
</button>
<button class="flex-1 rounded bg-info px-4 py-2 font-bold text-[#222] text-sm flex items-center justify-center gap-1" onclick={() => onskip?.()}>
Überspringen
</button>
<button class="flex-1 rounded bg-danger px-4 py-2 font-bold text-white text-sm flex items-center justify-center gap-1" onclick={ondone}>
Erledigt
</button>
<div class="flex gap-1.5">
<button
class="rounded border border-[#444] bg-transparent px-3 py-2 text-xs text-[#777] hover:border-warning hover:text-warning transition-all flex flex-col items-center gap-0.5 min-w-[4rem]"
onclick={onsnooze}
title="Verschieben"
>
<span class="text-base leading-none"></span>
<span>Verschieben</span>
</button>
<button
class="rounded border border-[#444] bg-transparent px-3 py-2 text-xs text-[#777] hover:border-info hover:text-info transition-all flex flex-col items-center gap-0.5 min-w-[4rem]"
onclick={() => onskip?.()}
title="Überspringen"
>
<span class="text-base leading-none"></span>
<span>Überspringen</span>
</button>
<button
class="rounded border border-[#444] bg-transparent px-3 py-2 text-xs text-[#777] hover:border-success hover:text-success transition-all flex flex-col items-center gap-0.5 min-w-[4rem]"
onclick={ondone}
title="Erledigt"
>
<span class="text-base leading-none"></span>
<span>Erledigt</span>
</button>
</div>
{:else}
<button class="flex-1 rounded bg-success px-4 py-2 font-bold text-white text-sm flex items-center justify-center gap-1" onclick={onnote}>
<button
class="flex-1 rounded bg-accent px-4 py-2 font-bold text-white text-sm flex items-center justify-center gap-1 hover:brightness-110 transition-all"
onclick={onnote}
>
Speichern
</button>
<button class="ml-auto rounded bg-danger px-4 py-2 font-bold text-white text-sm flex items-center justify-center gap-1" onclick={ondone}>
Archivieren
<button
class="rounded border border-[#444] bg-transparent px-3 py-2 text-xs text-[#777] hover:border-success hover:text-success transition-all flex flex-col items-center gap-0.5 min-w-[4rem]"
onclick={ondone}
title="Erledigt"
>
<span class="text-base leading-none"></span>
<span>Erledigt</span>
</button>
{/if}
</div>

View File

@ -5,10 +5,8 @@
import { liveQuery } from 'dexie';
import { db } from '$lib/db/schema';
import { resetAndReseed } from '$lib/db/seed';
import { upsertContext } from '$lib/db/repositories';
import { newId } from '$lib/db/helpers';
import type { AgendaContext, ContextType } from '@ka-note/shared';
import { account, logout, login } from '$lib/auth/authStore.js';
import type { AgendaContext } from '@ka-note/shared';
import { account, logout } from '$lib/auth/authStore.js';
import { syncStatus, lastSyncAt, fullSync } from '$lib/sync/syncService';
import { deletedItemCount } from '$lib/stores/agenda';
import { favoriteNotebooks } from '$lib/stores/wiki';
@ -42,9 +40,6 @@
collapsed[key] = !collapsed[key];
}
let creatingType: ContextType | null = $state(null);
let newName = $state('');
function navigate(id: string) {
goto(`/context/${id}`);
onnavigate?.();
@ -57,46 +52,17 @@
return ctx.name;
}
function startCreating(type: ContextType) {
creatingType = type;
newName = '';
// Active nav item style: subtle left border indicator
function navItem(active: boolean) {
return active
? 'mb-1 w-full rounded-r px-2.5 py-2 text-left text-sm border-l-2 border-accent bg-white/8 font-semibold text-white'
: 'mb-1 w-full rounded px-2.5 py-2 text-left text-sm border-l-2 border-transparent text-[#aaa] hover:bg-white/5 hover:text-white transition-colors';
}
function cancelCreating() {
creatingType = null;
newName = '';
}
async function createNewContext() {
const name = newName.trim();
if (!name || !creatingType) return;
const type = creatingType;
const slug = name.toLowerCase().replace(/\s+/g, '-');
const id = type === 'company' ? `f-${slug}` : type === 'person' ? `u-${slug}` : type === 'project' ? `p-${slug}` : newId();
const fullName = type === 'company' ? `Firma ${name}` : type === 'project' ? `Project ${name}` : type === 'person' ? `Person ${name}` : name;
const existing = ($contexts ?? []).filter((c: AgendaContext) => c.type === type);
const sortOrder = existing.length;
const meta = type === 'person' ? { fullName: '', email: '', phone: '', duSince: '', personSubType: 'contact' as const } : undefined;
await upsertContext({ id, name: fullName, type, sortOrder, ...(meta ? { meta } : {}) });
cancelCreating();
navigate(id);
}
function handleInputKeydown(e: KeyboardEvent) {
if (e.key === 'Enter') {
e.preventDefault();
createNewContext();
} else if (e.key === 'Escape') {
cancelCreating();
}
}
function autofocus(node: HTMLElement) {
node.focus();
}
// Section header: ▼ toggle (small) + label (navigates to overview)
const sectionHeader = 'flex items-center gap-2 mt-6 mb-1 pl-1 pr-1';
const sectionToggle = 'text-[10px] text-muted hover:text-white transition-colors flex-shrink-0 px-1 py-1';
const sectionLabel = 'text-xs uppercase text-muted hover:text-white flex items-center gap-1.5 transition-colors flex-1 text-left font-medium tracking-wide';
</script>
{#if !hideLogo}
@ -108,244 +74,142 @@
{/if}
<!-- General -->
<div class="mb-1 mt-6 pl-1 text-xs uppercase text-muted">General</div>
<div class="mb-1 mt-6 pl-1 text-xs uppercase text-muted flex items-center gap-1.5 font-medium tracking-wide"><span>🏠</span> General</div>
<ul class="m-0 list-none p-0">
{#if dailyLog}
<li>
<button
class="mb-1 w-full rounded px-2.5 py-2.5 text-left text-sm transition-colors {currentId === 'daily-log' ? 'bg-accent font-bold text-white' : 'text-[#ccc] hover:bg-white/5 hover:text-white'}"
onclick={() => navigate('daily-log')}
>
<button class={navItem(currentId === 'daily-log')} onclick={() => navigate('daily-log')}>
{dailyLog.name}
</button>
</li>
{/if}
</ul>
<!-- Archive -->
<ul class="m-0 list-none p-0">
<li>
<button
class="mb-1 w-full rounded px-2.5 py-2.5 text-left text-sm transition-colors {page.url.pathname.startsWith('/journal/archive') ? 'bg-accent font-bold text-white' : 'text-[#ccc] hover:bg-white/5 hover:text-white'}"
class={navItem(page.url.pathname.startsWith('/journal/archive'))}
onclick={() => { goto('/journal/archive'); onnavigate?.(); }}
>
📅 Archiv
Archiv
</button>
</li>
</ul>
<!-- Jour Fixes -->
<div class="mb-1 mt-6 flex items-center justify-between pl-1 pr-1">
<button class="text-xs uppercase text-muted hover:text-white flex items-center gap-1" onclick={() => toggleSection('meetings')}>
<span class="inline-block text-[10px] transition-transform {collapsed['meetings'] ? '-rotate-90' : ''}">{@html '&#9660;'}</span>
Jour Fixes
<div class={sectionHeader}>
<button class={sectionToggle} onclick={() => toggleSection('meetings')} title="Auf-/Zuklappen">
<span class="inline-block transition-transform {collapsed['meetings'] ? '-rotate-90' : ''}">{@html '&#9660;'}</span>
</button>
<button class={sectionLabel} onclick={() => { goto('/meetings'); onnavigate?.(); }}>
<span>💬</span> Jour Fixes
</button>
<button class="text-muted hover:text-white text-sm leading-none" onclick={() => startCreating('meeting')}>+</button>
</div>
{#if !collapsed['meetings']}
<ul class="m-0 list-none p-0">
{#each meetings as ctx}
<li>
<button
class="mb-1 w-full rounded px-2.5 py-2.5 text-left text-sm transition-colors {currentId === ctx.id ? 'bg-accent font-bold text-white' : 'text-[#ccc] hover:bg-white/5 hover:text-white'}"
onclick={() => navigate(ctx.id)}
>
<button class={navItem(currentId === ctx.id)} onclick={() => navigate(ctx.id)}>
{ctx.name}
</button>
</li>
{/each}
{#if creatingType === 'meeting'}
<li>
<input
class="mb-1 w-full rounded bg-white/10 px-2.5 py-2 text-sm text-white outline-none placeholder:text-muted"
placeholder="Name..."
bind:value={newName}
onkeydown={handleInputKeydown}
onblur={cancelCreating}
use:autofocus
/>
</li>
{/if}
<li>
<button
class="mb-1 w-full rounded px-2.5 py-2.5 text-left text-xs text-[#666] transition-colors hover:bg-white/5 hover:text-[#aaa]"
onclick={() => { goto('/meetings'); onnavigate?.(); }}
>
Alle Jour Fixes &rarr;
</button>
</li>
</ul>
{/if}
<!-- Projects -->
<div class="mb-1 mt-6 flex items-center justify-between pl-1 pr-1">
<button class="text-xs uppercase text-muted hover:text-white flex items-center gap-1" onclick={() => toggleSection('projects')}>
<span class="inline-block text-[10px] transition-transform {collapsed['projects'] ? '-rotate-90' : ''}">{@html '&#9660;'}</span>
Projects
<div class={sectionHeader}>
<button class={sectionToggle} onclick={() => toggleSection('projects')} title="Auf-/Zuklappen">
<span class="inline-block transition-transform {collapsed['projects'] ? '-rotate-90' : ''}">{@html '&#9660;'}</span>
</button>
<button class={sectionLabel} onclick={() => { goto('/projects'); onnavigate?.(); }}>
<span>📁</span> Projects
</button>
<button class="text-muted hover:text-white text-sm leading-none" onclick={() => startCreating('project')}>+</button>
</div>
{#if !collapsed['projects']}
<ul class="m-0 list-none p-0">
{#each projects as ctx}
<li>
<button
class="mb-1 w-full rounded px-2.5 py-2.5 text-left text-sm transition-colors {currentId === ctx.id ? 'bg-accent font-bold text-white' : 'text-[#ccc] hover:bg-white/5 hover:text-white'}"
onclick={() => navigate(ctx.id)}
>
<button class={navItem(currentId === ctx.id)} onclick={() => navigate(ctx.id)}>
{displayName(ctx)}
</button>
</li>
{/each}
{#if creatingType === 'project'}
<li>
<input
class="mb-1 w-full rounded bg-white/10 px-2.5 py-2 text-sm text-white outline-none placeholder:text-muted"
placeholder="Name..."
bind:value={newName}
onkeydown={handleInputKeydown}
onblur={cancelCreating}
use:autofocus
/>
</li>
{/if}
<li>
<button
class="mb-1 w-full rounded px-2.5 py-2.5 text-left text-xs text-[#666] transition-colors hover:bg-white/5 hover:text-[#aaa]"
onclick={() => { goto('/projects'); onnavigate?.(); }}
>
Alle Projekte &rarr;
</button>
</li>
</ul>
{/if}
<!-- Companies -->
<div class="mb-1 mt-6 flex items-center justify-between pl-1 pr-1">
<button class="text-xs uppercase text-muted hover:text-white flex items-center gap-1" onclick={() => toggleSection('companies')}>
<span class="inline-block text-[10px] transition-transform {collapsed['companies'] ? '-rotate-90' : ''}">{@html '&#9660;'}</span>
Firmen
<div class={sectionHeader}>
<button class={sectionToggle} onclick={() => toggleSection('companies')} title="Auf-/Zuklappen">
<span class="inline-block transition-transform {collapsed['companies'] ? '-rotate-90' : ''}">{@html '&#9660;'}</span>
</button>
<button class={sectionLabel} onclick={() => { goto('/companies'); onnavigate?.(); }}>
<span>🏢</span> Firmen
</button>
<button class="text-muted hover:text-white text-sm leading-none" onclick={() => startCreating('company')}>+</button>
</div>
{#if !collapsed['companies']}
<ul class="m-0 list-none p-0">
{#each companies as ctx}
<li>
<button
class="mb-1 w-full rounded px-2.5 py-2.5 text-left text-sm transition-colors {currentId === ctx.id ? 'bg-accent font-bold text-white' : 'text-[#ccc] hover:bg-white/5 hover:text-white'}"
onclick={() => navigate(ctx.id)}
>
<button class={navItem(currentId === ctx.id)} onclick={() => navigate(ctx.id)}>
{displayName(ctx)}
</button>
</li>
{/each}
{#if creatingType === 'company'}
<li>
<input
class="mb-1 w-full rounded bg-white/10 px-2.5 py-2 text-sm text-white outline-none placeholder:text-muted"
placeholder="Name..."
bind:value={newName}
onkeydown={handleInputKeydown}
onblur={cancelCreating}
use:autofocus
/>
</li>
{/if}
<li>
<button
class="mb-1 w-full rounded px-2.5 py-2.5 text-left text-xs text-[#666] transition-colors hover:bg-white/5 hover:text-[#aaa]"
onclick={() => { goto('/companies'); onnavigate?.(); }}
>
Alle Firmen &rarr;
</button>
</li>
</ul>
{/if}
<!-- People -->
<div class="mb-1 mt-6 flex items-center justify-between pl-1 pr-1">
<button class="text-xs uppercase text-muted hover:text-white flex items-center gap-1" onclick={() => toggleSection('people')}>
<span class="inline-block text-[10px] transition-transform {collapsed['people'] ? '-rotate-90' : ''}">{@html '&#9660;'}</span>
People
<div class={sectionHeader}>
<button class={sectionToggle} onclick={() => toggleSection('people')} title="Auf-/Zuklappen">
<span class="inline-block transition-transform {collapsed['people'] ? '-rotate-90' : ''}">{@html '&#9660;'}</span>
</button>
<button class={sectionLabel} onclick={() => { goto('/persons'); onnavigate?.(); }}>
<span>👤</span> People
</button>
<button class="text-muted hover:text-white text-sm leading-none" onclick={() => startCreating('person')}>+</button>
</div>
{#if !collapsed['people']}
<ul class="m-0 list-none p-0">
{#each people as ctx}
<li>
<button
class="mb-1 w-full rounded px-2.5 py-2.5 text-left text-sm transition-colors {currentId === ctx.id ? 'bg-accent font-bold text-white' : 'text-[#ccc] hover:bg-white/5 hover:text-white'}"
onclick={() => navigate(ctx.id)}
>
<button class={navItem(currentId === ctx.id)} onclick={() => navigate(ctx.id)}>
{displayName(ctx)}
</button>
</li>
{/each}
{#if creatingType === 'person'}
<li>
<input
class="mb-1 w-full rounded bg-white/10 px-2.5 py-2 text-sm text-white outline-none placeholder:text-muted"
placeholder="Name..."
bind:value={newName}
onkeydown={handleInputKeydown}
onblur={cancelCreating}
use:autofocus
/>
</li>
{/if}
<li>
<button
class="mb-1 w-full rounded px-2.5 py-2.5 text-left text-xs text-[#666] transition-colors hover:bg-white/5 hover:text-[#aaa]"
onclick={() => { goto('/persons'); onnavigate?.(); }}
>
Alle Personen &rarr;
</button>
</li>
</ul>
{/if}
<!-- Wiki -->
<div class="mb-1 mt-6 flex items-center justify-between pl-1 pr-1">
<button class="text-xs uppercase text-muted hover:text-white flex items-center gap-1" onclick={() => toggleSection('wiki')}>
<span class="inline-block text-[10px] transition-transform {collapsed['wiki'] ? '-rotate-90' : ''}">{@html '&#9660;'}</span>
Wiki
<div class={sectionHeader}>
<button class={sectionToggle} onclick={() => toggleSection('wiki')} title="Auf-/Zuklappen">
<span class="inline-block transition-transform {collapsed['wiki'] ? '-rotate-90' : ''}">{@html '&#9660;'}</span>
</button>
<button class={sectionLabel} onclick={() => { goto('/wiki'); onnavigate?.(); }}>
<span>📖</span> Wiki
</button>
<button class="text-muted hover:text-white text-sm leading-none" onclick={() => { goto('/wiki'); onnavigate?.(); }}>↗</button>
</div>
{#if !collapsed['wiki']}
<ul class="m-0 list-none p-0">
{#each ($wikiNotebooks$ ?? []) as nb}
<li>
<button
class="mb-1 w-full rounded px-2.5 py-2.5 text-left text-sm transition-colors text-[#ccc] hover:bg-white/5 hover:text-white"
class={navItem(page.url.pathname === `/wiki/notebook/${nb.id}`)}
onclick={() => { goto(`/wiki/notebook/${nb.id}`); onnavigate?.(); }}
>
{nb.name}
</button>
</li>
{/each}
<li>
<button
class="mb-1 w-full rounded px-2.5 py-2.5 text-left text-xs text-[#666] transition-colors hover:bg-white/5 hover:text-[#aaa]"
onclick={() => { goto('/wiki'); onnavigate?.(); }}
>
Alle Notizbücher &rarr;
</button>
</li>
</ul>
{/if}
<div class="mt-4">
<button
class="mb-1 w-full rounded px-2.5 py-2.5 text-left text-sm transition-colors flex items-center gap-2 text-[#ccc] hover:bg-white/5 hover:text-white"
class={navItem(page.url.pathname === '/trash') + ' flex items-center gap-2'}
onclick={() => { goto('/trash'); onnavigate?.(); }}
>
<span>🗑</span>
<span>Papierkorb</span>
{#if ($trashCount$ ?? 0) > 0}
<span class="ml-auto rounded-full bg-danger/70 px-1.5 py-0.5 text-xs text-white leading-none">{$trashCount$}</span>
<span class="ml-auto rounded-full bg-white/15 px-1.5 py-0.5 text-xs text-[#888] leading-none">{$trashCount$}</span>
{/if}
</button>
</div>

Binary file not shown.