Ka-Note/ka-note/client/src/lib/components/ContextHeader.svelte

112 lines
3.9 KiB
Svelte

<script lang="ts">
import type { AgendaContext } from '@ka-note/shared';
import { upsertContext } from '$lib/db/repositories';
import { scopeSettings } from '$lib/stores/scopeContext';
interface Props {
context: AgendaContext;
mode?: 'prep' | 'meeting';
onmodechange?: (mode: 'prep' | 'meeting') => void;
journalScope?: 'business' | 'private';
onjournalscopechange?: (scope: 'business' | 'private') => void;
}
let { context, mode, onmodechange, journalScope, onjournalscopechange }: Props = $props();
const showModeSwitch = $derived(!!onmodechange && context.type === 'meeting' && context.id !== 'daily-log');
const showScopeSwitch = $derived(!!onjournalscopechange && context.id === 'daily-log');
const canRename = $derived(context.id !== 'daily-log');
let editing = $state(false);
let nameInput = $state('');
function editableName(): string {
return context.name.replace(/^(Person |Project |Firma )/, '');
}
function fullName(input: string): string {
if (context.type === 'person') return 'Person ' + input;
if (context.type === 'project') return 'Project ' + input;
if (context.type === 'company') return 'Firma ' + input;
return input;
}
function startEdit() {
nameInput = editableName();
editing = true;
}
async function saveEdit() {
editing = false;
const trimmed = nameInput.trim();
if (!trimmed || trimmed === editableName()) return;
await upsertContext({ id: context.id, name: fullName(trimmed) });
}
function onKeydown(e: KeyboardEvent) {
if (e.key === 'Enter') {
e.preventDefault();
(e.target as HTMLInputElement).blur();
} else if (e.key === 'Escape') {
editing = false;
}
}
const headerColor = $derived(
showScopeSwitch
? (journalScope === 'private' ? $scopeSettings.privateColor : $scopeSettings.businessColor)
: $scopeSettings.businessColor
);
</script>
<h1 class="flex items-center justify-between border-b-2 pb-2.5 mb-5" style="border-color: {headerColor}">
{#if editing}
<input
class="text-2xl font-bold bg-transparent border-b-2 text-inherit outline-none w-full mr-4"
style="border-color: {headerColor}"
bind:value={nameInput}
onkeydown={onKeydown}
onblur={saveEdit}
autofocus
/>
{:else}
<span class="text-2xl font-bold">{context.name}</span>
{#if canRename}
<button
class="ml-2 text-[#888] hover:text-white bg-transparent border-none cursor-pointer text-base"
onclick={startEdit}
title="Rename"
></button>
{/if}
{/if}
{#if showModeSwitch}
<div class="flex gap-1 rounded-full bg-[#333] p-1">
<button
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')}
>
Vorbereitung
</button>
<button
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')}
>
Meeting
</button>
</div>
{/if}
{#if showScopeSwitch}
<div class="flex gap-1 rounded-full bg-[#333] p-1">
<button
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}` : ''}
onclick={() => onjournalscopechange?.('business')}
>Firma</button>
<button
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}` : ''}
onclick={() => onjournalscopechange?.('private')}
>Privat</button>
</div>
{/if}
</h1>