This commit is contained in:
beo3000 2026-02-22 21:51:01 +01:00
parent d281b1babc
commit 92a077009e
9 changed files with 226 additions and 86 deletions

View File

@ -1 +1 @@
1.1.2 1.1.5

View File

@ -74,13 +74,13 @@
{#if showModeSwitch} {#if showModeSwitch}
<div class="flex gap-1 rounded-full bg-[#333] p-1"> <div class="flex gap-1 rounded-full bg-[#333] p-1">
<button <button
class="rounded-full border-none px-4 py-2 font-bold transition-all {mode === 'prep' ? 'bg-accent text-white shadow-md' : 'bg-transparent text-[#aaa] cursor-pointer'}" class="rounded-full border-none px-3 py-1.5 text-sm font-bold transition-all {mode === 'prep' ? 'bg-accent text-white shadow-md' : 'bg-transparent text-[#aaa] cursor-pointer'}"
onclick={() => onmodechange?.('prep')} onclick={() => onmodechange?.('prep')}
> >
Vorbereitung Vorbereitung
</button> </button>
<button <button
class="rounded-full border-none px-4 py-2 font-bold transition-all {mode === 'meeting' ? 'bg-warning text-[#222] shadow-md' : 'bg-transparent text-[#aaa] cursor-pointer'}" class="rounded-full border-none px-3 py-1.5 text-sm font-bold transition-all {mode === 'meeting' ? 'bg-warning text-[#222] shadow-md' : 'bg-transparent text-[#aaa] cursor-pointer'}"
onclick={() => onmodechange?.('meeting')} onclick={() => onmodechange?.('meeting')}
> >
Meeting Meeting
@ -90,12 +90,12 @@
{#if showScopeSwitch} {#if showScopeSwitch}
<div class="flex gap-1 rounded-full bg-[#333] p-1"> <div class="flex gap-1 rounded-full bg-[#333] p-1">
<button <button
class="rounded-full border-none px-4 py-2 font-bold transition-all {journalScope === 'business' ? 'text-white shadow-md' : 'bg-transparent text-[#aaa] cursor-pointer'}" class="rounded-full border-none px-3 py-1.5 text-sm font-bold transition-all {journalScope === 'business' ? 'text-white shadow-md' : 'bg-transparent text-[#aaa] cursor-pointer'}"
style={journalScope === 'business' ? `background-color: ${$scopeSettings.businessColor}` : ''} style={journalScope === 'business' ? `background-color: ${$scopeSettings.businessColor}` : ''}
onclick={() => onjournalscopechange?.('business')} onclick={() => onjournalscopechange?.('business')}
>Firma</button> >Firma</button>
<button <button
class="rounded-full border-none px-4 py-2 font-bold transition-all {journalScope === 'private' ? 'text-white shadow-md' : 'bg-transparent text-[#aaa] cursor-pointer'}" class="rounded-full border-none px-3 py-1.5 text-sm font-bold transition-all {journalScope === 'private' ? 'text-white shadow-md' : 'bg-transparent text-[#aaa] cursor-pointer'}"
style={journalScope === 'private' ? `background-color: ${$scopeSettings.privateColor}` : ''} style={journalScope === 'private' ? `background-color: ${$scopeSettings.privateColor}` : ''}
onclick={() => onjournalscopechange?.('private')} onclick={() => onjournalscopechange?.('private')}
>Privat</button> >Privat</button>

View File

@ -2,9 +2,28 @@
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { liveQuery } from 'dexie'; import { liveQuery } from 'dexie';
import { db } from '$lib/db/schema'; import { db } from '$lib/db/schema';
import { softDeleteContext, toggleFavorite } from '$lib/db/repositories'; import { softDeleteContext, toggleFavorite, upsertContext } from '$lib/db/repositories';
import { newId } from '$lib/db/helpers';
import ConfirmDialog from '$lib/components/ConfirmDialog.svelte'; import ConfirmDialog from '$lib/components/ConfirmDialog.svelte';
let creating = $state(false);
let newName = $state('');
async function create() {
const name = newName.trim();
if (!name) return;
const id = newId();
await upsertContext({ id, name: `Firma ${name}`, type: 'company' });
newName = '';
creating = false;
goto(`/context/${id}`);
}
function onKeydown(e: KeyboardEvent) {
if (e.key === 'Enter') { e.preventDefault(); create(); }
else if (e.key === 'Escape') { creating = false; newName = ''; }
}
const allCompanies = liveQuery(() => const allCompanies = liveQuery(() =>
db.contexts.filter(c => !c.deletedAt && c.type === 'company').sortBy('sortOrder') db.contexts.filter(c => !c.deletedAt && c.type === 'company').sortBy('sortOrder')
); );
@ -30,7 +49,21 @@
</script> </script>
<div class="mx-auto max-w-3xl p-6"> <div class="mx-auto max-w-3xl p-6">
<h1 class="mb-6 text-2xl font-bold text-white">Alle Firmen</h1> <div class="mb-6 flex items-center gap-3">
<h1 class="flex-1 text-2xl font-bold text-white">Alle Firmen</h1>
<button class="rounded bg-accent px-3 py-1.5 text-sm font-medium text-white hover:bg-accent/80" onclick={() => creating = true}>+ Neu</button>
</div>
{#if creating}
<input
class="mb-4 w-full rounded bg-white/10 px-3 py-2 text-sm text-white outline-none placeholder:text-muted"
placeholder="Firmenname..."
bind:value={newName}
onkeydown={onKeydown}
onblur={() => setTimeout(() => { creating = false; newName = ''; }, 150)}
autofocus
/>
{/if}
{#if companies.length > 0} {#if companies.length > 0}
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">

View File

@ -2,9 +2,28 @@
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { liveQuery } from 'dexie'; import { liveQuery } from 'dexie';
import { db } from '$lib/db/schema'; import { db } from '$lib/db/schema';
import { softDeleteContext, toggleFavorite } from '$lib/db/repositories'; import { softDeleteContext, toggleFavorite, upsertContext } from '$lib/db/repositories';
import { newId } from '$lib/db/helpers';
import ConfirmDialog from '$lib/components/ConfirmDialog.svelte'; import ConfirmDialog from '$lib/components/ConfirmDialog.svelte';
let creating = $state(false);
let newName = $state('');
async function create() {
const name = newName.trim();
if (!name) return;
const id = newId();
await upsertContext({ id, name, type: 'meeting' });
newName = '';
creating = false;
goto(`/context/${id}`);
}
function onKeydown(e: KeyboardEvent) {
if (e.key === 'Enter') { e.preventDefault(); create(); }
else if (e.key === 'Escape') { creating = false; newName = ''; }
}
const allMeetings = liveQuery(() => const allMeetings = liveQuery(() =>
db.contexts.filter(c => !c.deletedAt && c.type === 'meeting' && c.id !== 'daily-log').sortBy('sortOrder') db.contexts.filter(c => !c.deletedAt && c.type === 'meeting' && c.id !== 'daily-log').sortBy('sortOrder')
); );
@ -26,7 +45,21 @@
</script> </script>
<div class="mx-auto max-w-3xl p-6"> <div class="mx-auto max-w-3xl p-6">
<h1 class="mb-6 text-2xl font-bold text-white">Alle Jour Fixes</h1> <div class="mb-6 flex items-center gap-3">
<h1 class="flex-1 text-2xl font-bold text-white">Alle Jour Fixes</h1>
<button class="rounded bg-accent px-3 py-1.5 text-sm font-medium text-white hover:bg-accent/80" onclick={() => creating = true}>+ Neu</button>
</div>
{#if creating}
<input
class="mb-4 w-full rounded bg-white/10 px-3 py-2 text-sm text-white outline-none placeholder:text-muted"
placeholder="Name des Jour Fix..."
bind:value={newName}
onkeydown={onKeydown}
onblur={() => setTimeout(() => { creating = false; newName = ''; }, 150)}
autofocus
/>
{/if}
{#if meetings.length > 0} {#if meetings.length > 0}
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">

View File

@ -1,6 +1,9 @@
<script lang="ts"> <script lang="ts">
import { goto } from '$app/navigation';
import { liveQuery } from 'dexie'; import { liveQuery } from 'dexie';
import { db } from '$lib/db/schema'; import { db } from '$lib/db/schema';
import { upsertContext } from '$lib/db/repositories';
import { newId } from '$lib/db/helpers';
import PersonList from '$lib/components/PersonList.svelte'; import PersonList from '$lib/components/PersonList.svelte';
const allPersons = liveQuery(() => const allPersons = liveQuery(() =>
@ -8,9 +11,42 @@
); );
const persons = $derived($allPersons ?? []); const persons = $derived($allPersons ?? []);
let creating = $state(false);
let newName = $state('');
async function create() {
const name = newName.trim();
if (!name) return;
const id = newId();
await upsertContext({ id, name: `Person ${name}`, type: 'person' });
newName = '';
creating = false;
goto(`/context/${id}`);
}
function onKeydown(e: KeyboardEvent) {
if (e.key === 'Enter') { e.preventDefault(); create(); }
else if (e.key === 'Escape') { creating = false; newName = ''; }
}
</script> </script>
<div class="mx-auto max-w-3xl p-6"> <div class="mx-auto max-w-3xl p-6">
<h1 class="mb-6 text-2xl font-bold text-white">Alle Personen</h1> <div class="mb-6 flex items-center gap-3">
<h1 class="flex-1 text-2xl font-bold text-white">Alle Personen</h1>
<button class="rounded bg-accent px-3 py-1.5 text-sm font-medium text-white hover:bg-accent/80" onclick={() => creating = true}>+ Neu</button>
</div>
{#if creating}
<input
class="mb-4 w-full rounded bg-white/10 px-3 py-2 text-sm text-white outline-none placeholder:text-muted"
placeholder="Name der Person..."
bind:value={newName}
onkeydown={onKeydown}
onblur={() => setTimeout(() => { creating = false; newName = ''; }, 150)}
autofocus
/>
{/if}
<PersonList {persons} /> <PersonList {persons} />
</div> </div>

View File

@ -2,10 +2,29 @@
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { liveQuery } from 'dexie'; import { liveQuery } from 'dexie';
import { db } from '$lib/db/schema'; import { db } from '$lib/db/schema';
import { softDeleteContext, toggleFavorite } from '$lib/db/repositories'; import { softDeleteContext, toggleFavorite, upsertContext } from '$lib/db/repositories';
import { newId } from '$lib/db/helpers';
import ConfirmDialog from '$lib/components/ConfirmDialog.svelte'; import ConfirmDialog from '$lib/components/ConfirmDialog.svelte';
import type { AgendaContext, ProjectMeta } from '@ka-note/shared'; import type { AgendaContext, ProjectMeta } from '@ka-note/shared';
let creating = $state(false);
let newName = $state('');
async function create() {
const name = newName.trim();
if (!name) return;
const id = newId();
await upsertContext({ id, name: `Project ${name}`, type: 'project' });
newName = '';
creating = false;
goto(`/context/${id}`);
}
function onKeydown(e: KeyboardEvent) {
if (e.key === 'Enter') { e.preventDefault(); create(); }
else if (e.key === 'Escape') { creating = false; newName = ''; }
}
const allProjects = liveQuery(() => const allProjects = liveQuery(() =>
db.contexts.filter(c => !c.deletedAt && c.type === 'project').sortBy('sortOrder') db.contexts.filter(c => !c.deletedAt && c.type === 'project').sortBy('sortOrder')
); );
@ -36,7 +55,21 @@
</script> </script>
<div class="mx-auto max-w-3xl p-6"> <div class="mx-auto max-w-3xl p-6">
<h1 class="mb-6 text-2xl font-bold text-white">Alle Projekte</h1> <div class="mb-6 flex items-center gap-3">
<h1 class="flex-1 text-2xl font-bold text-white">Alle Projekte</h1>
<button class="rounded bg-accent px-3 py-1.5 text-sm font-medium text-white hover:bg-accent/80" onclick={() => creating = true}>+ Neu</button>
</div>
{#if creating}
<input
class="mb-4 w-full rounded bg-white/10 px-3 py-2 text-sm text-white outline-none placeholder:text-muted"
placeholder="Projektname..."
bind:value={newName}
onkeydown={onKeydown}
onblur={() => setTimeout(() => { creating = false; newName = ''; }, 150)}
autofocus
/>
{/if}
{#if activeProjects.length > 0} {#if activeProjects.length > 0}
<h2 class="mb-3 text-sm font-bold uppercase text-[#aaa]">Aktiv</h2> <h2 class="mb-3 text-sm font-bold uppercase text-[#aaa]">Aktiv</h2>

View File

@ -98,48 +98,51 @@
{#if currentPage} {#if currentPage}
<div class="space-y-4"> <div class="space-y-4">
<!-- Header --> <!-- Header -->
<h1 class="flex items-center gap-3 border-b-2 pb-2.5" style="border-color: var(--scope-color)"> <div class="border-b-2 pb-2.5 space-y-2" style="border-color: var(--scope-color)">
{#if editing} <!-- Row 1: title + scope toggle -->
<input <div class="flex items-center gap-3">
class="flex-1 bg-transparent text-2xl font-bold text-white outline-none placeholder:text-muted" {#if editing}
bind:value={titleInput} <input
onblur={saveTitle} class="flex-1 bg-transparent text-2xl font-bold text-white outline-none placeholder:text-muted"
onkeydown={(e) => e.key === 'Enter' && (e.preventDefault(), saveTitle())} bind:value={titleInput}
placeholder="Seitentitel..." onblur={saveTitle}
/> onkeydown={(e) => e.key === 'Enter' && (e.preventDefault(), saveTitle())}
{:else} placeholder="Seitentitel..."
<span class="flex-1 text-2xl font-bold">{currentPage.title}</span> />
{/if} {:else}
<span class="flex-1 text-2xl font-bold">{currentPage.title}</span>
{/if}
<!-- Read/Edit toggle --> <!-- Privat/Firma toggle -->
<button <div class="flex gap-1 rounded-full bg-[#333] p-1 shrink-0">
class="shrink-0 rounded px-3 py-1.5 text-sm font-medium transition-colors <button
{editing ? 'bg-accent text-white hover:bg-accent/80' : 'bg-white/10 text-[#ccc] hover:bg-white/20 hover:text-white'}" class="rounded-full border-none px-3 py-1.5 text-sm font-bold transition-all {scope === 'business' ? 'text-white shadow-md' : 'bg-transparent text-[#aaa] cursor-pointer'}"
onclick={() => editing ? switchToRead() : (editing = true)} style={scope === 'business' ? `background-color: ${$scopeSettings.businessColor}` : ''}
title={editing ? 'Leseansicht' : 'Bearbeiten'} onclick={() => handleScopeChange('business')}
> >Firma</button>
{editing ? '✓ Fertig' : '✎ Bearbeiten'} <button
</button> class="rounded-full border-none px-3 py-1.5 text-sm font-bold transition-all {scope === 'private' ? 'text-white shadow-md' : 'bg-transparent text-[#aaa] cursor-pointer'}"
style={scope === 'private' ? `background-color: ${$scopeSettings.privateColor}` : ''}
<!-- Privat/Firma toggle --> onclick={() => handleScopeChange('private')}
<div class="flex gap-1 rounded-full bg-[#333] p-1 shrink-0"> >Privat</button>
<button </div>
class="rounded-full border-none px-3 py-1.5 text-sm font-bold transition-all {scope === 'business' ? 'text-white shadow-md' : 'bg-transparent text-[#aaa] cursor-pointer'}"
style={scope === 'business' ? `background-color: ${$scopeSettings.businessColor}` : ''}
onclick={() => handleScopeChange('business')}
>Firma</button>
<button
class="rounded-full border-none px-3 py-1.5 text-sm font-bold transition-all {scope === 'private' ? 'text-white shadow-md' : 'bg-transparent text-[#aaa] cursor-pointer'}"
style={scope === 'private' ? `background-color: ${$scopeSettings.privateColor}` : ''}
onclick={() => handleScopeChange('private')}
>Privat</button>
</div> </div>
<button <!-- Row 2: actions -->
class="shrink-0 text-sm text-muted hover:text-danger" <div class="flex items-center gap-2">
onclick={() => confirmDelete = true} <button
>Löschen</button> class="rounded px-3 py-1.5 text-sm font-medium transition-colors
</h1> {editing ? 'bg-accent text-white hover:bg-accent/80' : 'bg-white/10 text-[#ccc] hover:bg-white/20 hover:text-white'}"
onclick={() => editing ? switchToRead() : (editing = true)}
>
{editing ? '✓ Fertig' : '✎ Bearbeiten'}
</button>
<button
class="rounded px-2 py-1.5 text-xs text-muted hover:bg-danger/20 hover:text-danger ml-auto"
onclick={() => confirmDelete = true}
>Löschen</button>
</div>
</div>
<!-- Notebook badges + assigner (always visible) --> <!-- Notebook badges + assigner (always visible) -->
<div class="flex flex-wrap items-center gap-2"> <div class="flex flex-wrap items-center gap-2">

View File

@ -46,54 +46,56 @@
{#if $notebook$} {#if $notebook$}
<div class="space-y-4"> <div class="space-y-4">
<h1 class="flex items-center gap-3 border-b-2 pb-2.5 text-2xl font-bold" style="border-color: var(--scope-color)"> <div class="border-b-2 pb-2.5 space-y-2" style="border-color: var(--scope-color)">
<button class="text-base text-muted hover:text-white" onclick={() => goto('/wiki')}>&larr;</button> <!-- Row 1: back + title + scope toggle -->
<div class="flex items-center gap-3">
<button class="text-base text-muted hover:text-white shrink-0" onclick={() => goto('/wiki')}>&larr;</button>
{#if editingName} {#if editingName}
<input <input
class="flex-1 bg-transparent border-b-2 border-accent outline-none text-inherit" class="flex-1 bg-transparent text-2xl font-bold border-b-2 border-accent outline-none text-inherit"
bind:value={nameInput} bind:value={nameInput}
onkeydown={(e) => { if (e.key === 'Enter') { e.preventDefault(); saveRename(); } else if (e.key === 'Escape') editingName = false; }} onkeydown={(e) => { if (e.key === 'Enter') { e.preventDefault(); saveRename(); } else if (e.key === 'Escape') editingName = false; }}
onblur={saveRename} onblur={saveRename}
autofocus autofocus
/> />
{:else} {:else}
<span class="flex-1">{$notebook$.name}</span> <span class="flex-1 text-2xl font-bold">{$notebook$.name}</span>
<button class="text-base text-muted hover:text-white" onclick={startRename} title="Umbenennen"></button> <button class="text-base text-muted hover:text-white shrink-0" onclick={startRename} title="Umbenennen"></button>
{/if} {/if}
<!-- Favoriten-Stern --> <!-- Privat/Firma toggle -->
<button <div class="flex gap-1 rounded-full bg-[#333] p-1 shrink-0">
class="text-xl {$notebook$.isFavorite ? 'text-warning' : 'text-muted hover:text-warning'}" <button
onclick={() => toggleNotebookFavorite(notebookId)} class="rounded-full border-none px-3 py-1.5 text-sm font-bold transition-all {!$notebook$.isPrivate ? 'text-white shadow-md' : 'bg-transparent text-[#aaa] cursor-pointer'}"
title={$notebook$.isFavorite ? 'Aus Sidebar entfernen' : 'In Sidebar anzeigen'} style={!$notebook$.isPrivate ? `background-color: ${$scopeSettings.businessColor}` : ''}
>★</button> onclick={() => upsertNotebook({ id: notebookId, isPrivate: false })}
>Firma</button>
<!-- Privat/Firma toggle --> <button
<div class="flex gap-1 rounded-full bg-[#333] p-1"> class="rounded-full border-none px-3 py-1.5 text-sm font-bold transition-all {$notebook$.isPrivate ? 'text-white shadow-md' : 'bg-transparent text-[#aaa] cursor-pointer'}"
<button style={$notebook$.isPrivate ? `background-color: ${$scopeSettings.privateColor}` : ''}
class="rounded-full border-none px-2.5 py-1 text-xs font-bold transition-all {!$notebook$.isPrivate ? 'text-white shadow-md' : 'bg-transparent text-[#aaa] cursor-pointer'}" onclick={() => upsertNotebook({ id: notebookId, isPrivate: true })}
style={!$notebook$.isPrivate ? `background-color: ${$scopeSettings.businessColor}` : ''} >Privat</button>
onclick={() => upsertNotebook({ id: notebookId, isPrivate: false })} </div>
>Firma</button>
<button
class="rounded-full border-none px-2.5 py-1 text-xs font-bold transition-all {$notebook$.isPrivate ? 'text-white shadow-md' : 'bg-transparent text-[#aaa] cursor-pointer'}"
style={$notebook$.isPrivate ? `background-color: ${$scopeSettings.privateColor}` : ''}
onclick={() => upsertNotebook({ id: notebookId, isPrivate: true })}
>Privat</button>
</div> </div>
<div class="ml-auto flex items-center gap-2"> <!-- Row 2: actions -->
<div class="flex items-center gap-2">
<button <button
class="rounded bg-accent px-3 py-1.5 text-sm font-medium text-white hover:bg-accent/80" class="rounded bg-accent px-3 py-1.5 text-sm font-medium text-white hover:bg-accent/80"
onclick={addPage} onclick={addPage}
>+ Neue Seite</button> >+ Neue Seite</button>
<button <button
class="rounded px-2 py-1.5 text-xs text-muted hover:bg-danger/20 hover:text-danger" class="rounded px-2 py-1.5 text-xs text-muted hover:bg-danger/20 hover:text-danger"
onclick={() => toggleNotebookFavorite(notebookId)}
title={$notebook$.isFavorite ? 'Aus Sidebar entfernen' : 'In Sidebar anzeigen'}
>{$notebook$.isFavorite ? '★ Sidebar' : '☆ Sidebar'}</button>
<button
class="rounded px-2 py-1.5 text-xs text-muted hover:bg-danger/20 hover:text-danger ml-auto"
onclick={() => confirmDelete = true} onclick={() => confirmDelete = true}
>Löschen</button> >Löschen</button>
</div> </div>
</h1> </div>
<div class="space-y-1"> <div class="space-y-1">
{#each ($pages$ ?? []) as p (p.id)} {#each ($pages$ ?? []) as p (p.id)}

Binary file not shown.