mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 20:41:09 +02:00
feat(todo): add task metadata fields and mana page
- Add storyPoints, effectiveDuration, funRating to TaskMetadata - Add UI controls in TaskEditModal for new metadata fields - Add columns/kanban icon to shared-ui PillNavigation - Add Mana subscription page to todo app - Update TASK_METADATA.md documentation 🤖 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
3e35e6a2f4
commit
0c2434bd1d
5 changed files with 131 additions and 2 deletions
|
|
@ -23,10 +23,21 @@ export interface Subtask {
|
||||||
order: number;
|
order: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type DurationUnit = 'minutes' | 'hours' | 'days';
|
||||||
|
|
||||||
|
export interface EffectiveDuration {
|
||||||
|
value: number;
|
||||||
|
unit: DurationUnit;
|
||||||
|
}
|
||||||
|
|
||||||
export interface TaskMetadata {
|
export interface TaskMetadata {
|
||||||
notes?: string;
|
notes?: string;
|
||||||
attachments?: string[];
|
attachments?: string[];
|
||||||
linkedCalendarEventId?: string | null;
|
linkedCalendarEventId?: string | null;
|
||||||
|
// Agile/Productivity metadata
|
||||||
|
storyPoints?: number | null; // Fibonacci: 1, 2, 3, 5, 8, 13, 21
|
||||||
|
effectiveDuration?: EffectiveDuration | null; // Actual time spent
|
||||||
|
funRating?: number | null; // 1-10 scale
|
||||||
}
|
}
|
||||||
|
|
||||||
export const tasks = pgTable(
|
export const tasks = pgTable(
|
||||||
|
|
|
||||||
39
apps/todo/apps/web/src/routes/(app)/mana/+page.svelte
Normal file
39
apps/todo/apps/web/src/routes/(app)/mana/+page.svelte
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { SubscriptionPage } from '@manacore/shared-subscription-ui';
|
||||||
|
|
||||||
|
function handleSubscribe(planId: string) {
|
||||||
|
console.log('Subscribe to plan:', planId);
|
||||||
|
alert(`Abo "${planId}" ausgewählt. Bezahlsystem wird noch integriert.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleBuyPackage(packageId: string) {
|
||||||
|
console.log('Buy package:', packageId);
|
||||||
|
alert(`Paket "${packageId}" ausgewählt. Bezahlsystem wird noch integriert.`);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<title>Mana - Todo</title>
|
||||||
|
</svelte:head>
|
||||||
|
|
||||||
|
<div class="mana-page">
|
||||||
|
<SubscriptionPage
|
||||||
|
appName="Todo"
|
||||||
|
onSubscribe={handleSubscribe}
|
||||||
|
onBuyPackage={handleBuyPackage}
|
||||||
|
currentPlanId="free"
|
||||||
|
pageTitle="Wähle dein Abo"
|
||||||
|
subscriptionsTitle="Abonnements"
|
||||||
|
packagesTitle="Einmal-Pakete"
|
||||||
|
yearlyDiscount="2 Monate gratis"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.mana-page {
|
||||||
|
min-height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
overflow-x: hidden;
|
||||||
|
background-color: hsl(var(--background));
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -141,6 +141,44 @@ Das `metadata`-Objekt enthält erweiterte Informationen.
|
||||||
| `metadata.notes` | `string` | Zusätzliche Notizen |
|
| `metadata.notes` | `string` | Zusätzliche Notizen |
|
||||||
| `metadata.attachments` | `string[]` | URLs zu Dateianhängen |
|
| `metadata.attachments` | `string[]` | URLs zu Dateianhängen |
|
||||||
| `metadata.linkedCalendarEventId` | `string \| null` | ID eines verknüpften Kalender-Events |
|
| `metadata.linkedCalendarEventId` | `string \| null` | ID eines verknüpften Kalender-Events |
|
||||||
|
| `metadata.storyPoints` | `number \| null` | Storypoints (Fibonacci: 1, 2, 3, 5, 8, 13, 21) |
|
||||||
|
| `metadata.effectiveDuration` | `EffectiveDuration \| null` | Effektive Dauer der Aufgabe |
|
||||||
|
| `metadata.funRating` | `number \| null` | Spaß-Faktor (Skala 1-10) |
|
||||||
|
|
||||||
|
### EffectiveDuration-Struktur
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface EffectiveDuration {
|
||||||
|
value: number; // Numerischer Wert
|
||||||
|
unit: DurationUnit; // 'minutes' | 'hours' | 'days'
|
||||||
|
}
|
||||||
|
|
||||||
|
type DurationUnit = 'minutes' | 'hours' | 'days';
|
||||||
|
```
|
||||||
|
|
||||||
|
### Storypoints
|
||||||
|
|
||||||
|
Storypoints verwenden die Fibonacci-Sequenz zur Aufwandsschätzung:
|
||||||
|
|
||||||
|
| Wert | Typischer Aufwand |
|
||||||
|
|------|-------------------|
|
||||||
|
| 1 | Sehr klein, wenige Minuten |
|
||||||
|
| 2 | Klein, unter einer Stunde |
|
||||||
|
| 3 | Mittel, ein paar Stunden |
|
||||||
|
| 5 | Größer, halber Tag |
|
||||||
|
| 8 | Groß, ganzer Tag |
|
||||||
|
| 13 | Sehr groß, mehrere Tage |
|
||||||
|
| 21 | Epic, aufteilen empfohlen |
|
||||||
|
|
||||||
|
### Spaß-Faktor
|
||||||
|
|
||||||
|
Der Spaß-Faktor ist eine Skala von 1-10:
|
||||||
|
|
||||||
|
| Bereich | Bedeutung | Farbe |
|
||||||
|
|---------|-----------|-------|
|
||||||
|
| 1-3 | Unangenehm | Rot (#ef4444) |
|
||||||
|
| 4-6 | Neutral | Gelb (#eab308) |
|
||||||
|
| 7-10 | Macht Spaß | Grün (#22c55e) |
|
||||||
|
|
||||||
### Beispiel
|
### Beispiel
|
||||||
```typescript
|
```typescript
|
||||||
|
|
@ -151,7 +189,13 @@ Das `metadata`-Objekt enthält erweiterte Informationen.
|
||||||
"https://storage.example.com/file1.pdf",
|
"https://storage.example.com/file1.pdf",
|
||||||
"https://storage.example.com/image.png"
|
"https://storage.example.com/image.png"
|
||||||
],
|
],
|
||||||
linkedCalendarEventId: "cal-event-123"
|
linkedCalendarEventId: "cal-event-123",
|
||||||
|
storyPoints: 5,
|
||||||
|
effectiveDuration: {
|
||||||
|
value: 2,
|
||||||
|
unit: "hours"
|
||||||
|
},
|
||||||
|
funRating: 7
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
@ -223,7 +267,10 @@ const task: Task = {
|
||||||
metadata: {
|
metadata: {
|
||||||
notes: "Design-Specs sind im Anhang",
|
notes: "Design-Specs sind im Anhang",
|
||||||
attachments: ["https://storage.example.com/design-specs.pdf"],
|
attachments: ["https://storage.example.com/design-specs.pdf"],
|
||||||
linkedCalendarEventId: "cal-123"
|
linkedCalendarEventId: "cal-123",
|
||||||
|
storyPoints: 8,
|
||||||
|
effectiveDuration: { value: 4, unit: "hours" },
|
||||||
|
funRating: 6
|
||||||
},
|
},
|
||||||
|
|
||||||
// Timestamps
|
// Timestamps
|
||||||
|
|
@ -240,6 +287,20 @@ const task: Task = {
|
||||||
- `priority` - Priorität-Picker (Niedrig, Mittel, Hoch, Dringend)
|
- `priority` - Priorität-Picker (Niedrig, Mittel, Hoch, Dringend)
|
||||||
- `projectId` - Projekt-Picker
|
- `projectId` - Projekt-Picker
|
||||||
|
|
||||||
|
### Im TaskEditModal implementiert
|
||||||
|
- Alle QuickAdd-Felder
|
||||||
|
- `description` - Textarea
|
||||||
|
- `dueTime` - Zeit-Picker
|
||||||
|
- `startDate` - Datum-Picker
|
||||||
|
- `status` - Select (Ausstehend, In Bearbeitung, Abgeschlossen, Abgebrochen)
|
||||||
|
- `labels` - Multi-Select Dropdown
|
||||||
|
- `subtasks` - Drag-and-Drop Liste
|
||||||
|
- `recurrenceRule` - Select (Täglich, Wöchentlich, etc.)
|
||||||
|
- `metadata.notes` - Textarea
|
||||||
|
- `metadata.storyPoints` - Fibonacci-Buttons (1, 2, 3, 5, 8, 13, 21)
|
||||||
|
- `metadata.effectiveDuration` - Quick-Select Chips + benutzerdefinierte Eingabe
|
||||||
|
- `metadata.funRating` - 10-Punkte-Skala mit Farbverlauf
|
||||||
|
|
||||||
### Noch nicht im QuickAdd
|
### Noch nicht im QuickAdd
|
||||||
- Labels
|
- Labels
|
||||||
- Erinnerungen/Reminders
|
- Erinnerungen/Reminders
|
||||||
|
|
@ -248,3 +309,6 @@ const task: Task = {
|
||||||
- Beschreibung
|
- Beschreibung
|
||||||
- Startdatum
|
- Startdatum
|
||||||
- Uhrzeit
|
- Uhrzeit
|
||||||
|
- Storypoints
|
||||||
|
- Effektive Dauer
|
||||||
|
- Spaß-Faktor
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,21 @@ export interface Subtask {
|
||||||
order: number;
|
order: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type DurationUnit = 'minutes' | 'hours' | 'days';
|
||||||
|
|
||||||
|
export interface EffectiveDuration {
|
||||||
|
value: number;
|
||||||
|
unit: DurationUnit;
|
||||||
|
}
|
||||||
|
|
||||||
export interface TaskMetadata {
|
export interface TaskMetadata {
|
||||||
notes?: string;
|
notes?: string;
|
||||||
attachments?: string[];
|
attachments?: string[];
|
||||||
linkedCalendarEventId?: string | null;
|
linkedCalendarEventId?: string | null;
|
||||||
|
// Agile/Productivity metadata
|
||||||
|
storyPoints?: number | null; // Fibonacci: 1, 2, 3, 5, 8, 13, 21
|
||||||
|
effectiveDuration?: EffectiveDuration | null; // Actual time spent
|
||||||
|
funRating?: number | null; // 1-10 scale
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Task {
|
export interface Task {
|
||||||
|
|
|
||||||
|
|
@ -275,6 +275,10 @@
|
||||||
check: 'M5 13l4 4L19 7',
|
check: 'M5 13l4 4L19 7',
|
||||||
checkCircle: 'M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z',
|
checkCircle: 'M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z',
|
||||||
plus: 'M12 4v16m8-8H4',
|
plus: 'M12 4v16m8-8H4',
|
||||||
|
columns:
|
||||||
|
'M9 4H5a1 1 0 00-1 1v14a1 1 0 001 1h4a1 1 0 001-1V5a1 1 0 00-1-1zM19 4h-4a1 1 0 00-1 1v14a1 1 0 001 1h4a1 1 0 001-1V5a1 1 0 00-1-1z',
|
||||||
|
kanban:
|
||||||
|
'M9 4H5a1 1 0 00-1 1v14a1 1 0 001 1h4a1 1 0 001-1V5a1 1 0 00-1-1zM19 4h-4a1 1 0 00-1 1v14a1 1 0 001 1h4a1 1 0 001-1V5a1 1 0 00-1-1z',
|
||||||
// Original icons
|
// Original icons
|
||||||
mic: 'M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 01-3-3V5a3 3 0 116 0v6a3 3 0 01-3 3z',
|
mic: 'M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 01-3-3V5a3 3 0 116 0v6a3 3 0 01-3 3z',
|
||||||
calendar:
|
calendar:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue