feat(writing): register Writing as a Workbench card

Writing is now pickable from the Workbench AppPagePicker and can run
side-by-side with the other module cards. Previously only reachable via
direct navigation to /writing.

- app-registry: registerApp({ id: 'writing', icon: NotePencil, color:
  '#0ea5e9', list: ListView }) with a "Neuer Draft" context-menu action
  that dispatches mana:quick-action (same convention as library/notes/
  quiz — the event channel is the standard cross-card hook).
- writing ListView: onMount listener for the mana:quick-action event
  flips showCreate=true when { app:'writing', action:'new' } fires, so
  the kebab menu → "Neuer Draft" opens the inline BriefingForm instead
  of being a no-op.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-04-24 17:15:25 +02:00
parent 92bee0d71a
commit c1d643ffb5
2 changed files with 43 additions and 2 deletions

View file

@ -1,3 +1,4 @@
import { formatDate } from '$lib/i18n/format';
/**
* Unified App Registrations All app descriptors in one file.
*
@ -79,6 +80,7 @@ import {
Exam,
Globe,
CoatHanger,
NotePencil,
} from '@mana/shared-icons';
// ── Apps with entity capabilities ───────────────────────────
@ -119,7 +121,7 @@ registerApp({
},
getDisplayData: (item) => ({
title: (item.title as string) || 'Aufgabe',
subtitle: item.dueDate ? new Date(item.dueDate as string).toLocaleDateString('de') : undefined,
subtitle: item.dueDate ? formatDate(new Date(item.dueDate as string)) : undefined,
}),
createItem: async (data) => {
const { tasksStore } = await import('$lib/modules/todo/stores/tasks.svelte');
@ -180,7 +182,7 @@ registerApp({
getDisplayData: (item) => ({
title: (item.title as string) || 'Termin',
subtitle: item.startDate
? new Date(item.startDate as string).toLocaleDateString('de', {
? formatDate(new Date(item.startDate as string), {
day: '2-digit',
month: '2-digit',
hour: '2-digit',
@ -1330,6 +1332,29 @@ registerApp({
],
});
registerApp({
id: 'writing',
name: 'Writing',
color: '#0ea5e9',
icon: NotePencil,
views: {
// Detail view (/writing/draft/[id]) uses goto() from the list view,
// same pattern as library. Workbench detail-slot not wired yet.
list: { load: () => import('$lib/modules/writing/ListView.svelte') },
},
contextMenuActions: [
{
id: 'new-draft',
label: 'Neuer Draft',
icon: Plus,
action: () =>
window.dispatchEvent(
new CustomEvent('mana:quick-action', { detail: { app: 'writing', action: 'new' } })
),
},
],
});
registerApp({
id: 'spaces',
name: 'Spaces',

View file

@ -6,6 +6,7 @@
unstarted draft.
-->
<script lang="ts">
import { onMount } from 'svelte';
import { goto } from '$app/navigation';
import KindTabs from '../components/KindTabs.svelte';
import StatusFilter from '../components/StatusFilter.svelte';
@ -86,6 +87,21 @@
showCreate = false;
openDraft(d);
}
// Workbench "Neuer Draft" context-menu action. Uses the shared
// mana:quick-action event channel that the app-registry dispatches
// from the card's kebab menu. Also fires when the user picks the
// action from the command palette once that's wired up globally.
onMount(() => {
function handleQuickAction(ev: Event) {
const detail = (ev as CustomEvent<{ app?: string; action?: string }>).detail;
if (detail?.app === 'writing' && detail?.action === 'new') {
showCreate = true;
}
}
window.addEventListener('mana:quick-action', handleQuickAction);
return () => window.removeEventListener('mana:quick-action', handleQuickAction);
});
</script>
<div class="writing-shell">