mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 19:01:08 +02:00
fix(timeblocks): type errors from recurrence migration
- calendar/types: replace duplicate recurrenceRule with recurrenceDate on CalendarEvent; map it in timeBlockToCalendarEvent - recurrence: drop stale Record casts now that LocalTimeBlock types isRecurrenceException and recurrenceDate - todo: route recurrenceRule through TimeBlock in createTask/updateTask, load it from block in useTaskForm; accept labelIds via metadata; remove stale projectId casts - calendar/events: include linkedBlockId/parentBlockId/recurrenceDate in createDraftEvent - habits: drop unused db / LocalTimeBlock imports - eslint-config: disable consistent-type-imports (parser conflict with .svelte.ts files) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
af9b1f9369
commit
ce04f43248
8 changed files with 26 additions and 11 deletions
|
|
@ -195,7 +195,7 @@ export async function cleanupFutureInstances(templateBlockId: string): Promise<v
|
||||||
|
|
||||||
for (const instance of instances) {
|
for (const instance of instances) {
|
||||||
if (instance.deletedAt) continue;
|
if (instance.deletedAt) continue;
|
||||||
if ((instance as Record<string, unknown>).isRecurrenceException) continue;
|
if (instance.isRecurrenceException) continue;
|
||||||
if (instance.recurrenceDate && instance.recurrenceDate >= today) {
|
if (instance.recurrenceDate && instance.recurrenceDate >= today) {
|
||||||
await deleteBlock(instance.id);
|
await deleteBlock(instance.id);
|
||||||
}
|
}
|
||||||
|
|
@ -255,7 +255,7 @@ export function expandTemplatesVirtually(
|
||||||
const existingKeys = new Set(
|
const existingKeys = new Set(
|
||||||
existingBlocks
|
existingBlocks
|
||||||
.filter((b) => b.parentBlockId)
|
.filter((b) => b.parentBlockId)
|
||||||
.map((b) => `${b.parentBlockId}|${(b as Record<string, unknown>).recurrenceDate}`)
|
.map((b) => `${b.parentBlockId}|${b.recurrenceDate}`)
|
||||||
);
|
);
|
||||||
|
|
||||||
const virtuals: VirtualTimeBlock[] = [];
|
const virtuals: VirtualTimeBlock[] = [];
|
||||||
|
|
|
||||||
|
|
@ -377,6 +377,9 @@ export const eventsStore = {
|
||||||
icon: null,
|
icon: null,
|
||||||
isLive: false,
|
isLive: false,
|
||||||
projectId: null,
|
projectId: null,
|
||||||
|
linkedBlockId: null,
|
||||||
|
parentBlockId: null,
|
||||||
|
recurrenceDate: null,
|
||||||
};
|
};
|
||||||
return draftEvent;
|
return draftEvent;
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ export interface CalendarEvent {
|
||||||
projectId: string | null;
|
projectId: string | null;
|
||||||
linkedBlockId: string | null;
|
linkedBlockId: string | null;
|
||||||
parentBlockId: string | null;
|
parentBlockId: string | null;
|
||||||
recurrenceRule: string | null;
|
recurrenceDate: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Calendar {
|
export interface Calendar {
|
||||||
|
|
@ -107,5 +107,6 @@ export function timeBlockToCalendarEvent(
|
||||||
projectId: block.projectId,
|
projectId: block.projectId,
|
||||||
linkedBlockId: block.linkedBlockId,
|
linkedBlockId: block.linkedBlockId,
|
||||||
parentBlockId: block.parentBlockId,
|
parentBlockId: block.parentBlockId,
|
||||||
|
recurrenceDate: block.recurrenceDate,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,6 @@ import {
|
||||||
materializeRecurringBlocks,
|
materializeRecurringBlocks,
|
||||||
regenerateForBlock,
|
regenerateForBlock,
|
||||||
} from '$lib/data/time-blocks/recurrence';
|
} from '$lib/data/time-blocks/recurrence';
|
||||||
import { db } from '$lib/data/database';
|
|
||||||
import type { LocalTimeBlock } from '$lib/data/time-blocks/types';
|
|
||||||
import type { LocalHabit, LocalHabitLog, HabitSchedule } from '../types';
|
import type { LocalHabit, LocalHabitLog, HabitSchedule } from '../types';
|
||||||
|
|
||||||
export const habitsStore = {
|
export const habitsStore = {
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,8 @@ export function useTaskForm() {
|
||||||
title = task.title;
|
title = task.title;
|
||||||
description = task.description ?? '';
|
description = task.description ?? '';
|
||||||
dueDate = task.dueDate ? task.dueDate.split('T')[0] : '';
|
dueDate = task.dueDate ? task.dueDate.split('T')[0] : '';
|
||||||
// Load scheduled time from TimeBlock if scheduled
|
// Load scheduled time + recurrence from TimeBlock if scheduled
|
||||||
|
recurrenceRule = '';
|
||||||
if (task.scheduledBlockId) {
|
if (task.scheduledBlockId) {
|
||||||
const block = await getBlock(task.scheduledBlockId);
|
const block = await getBlock(task.scheduledBlockId);
|
||||||
if (block) {
|
if (block) {
|
||||||
|
|
@ -55,6 +56,7 @@ export function useTaskForm() {
|
||||||
dueTime = block.startDate.includes('T')
|
dueTime = block.startDate.includes('T')
|
||||||
? block.startDate.split('T')[1]?.substring(0, 5)
|
? block.startDate.split('T')[1]?.substring(0, 5)
|
||||||
: '';
|
: '';
|
||||||
|
recurrenceRule = block.recurrenceRule ?? '';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dueTime = '';
|
dueTime = '';
|
||||||
|
|
@ -63,7 +65,6 @@ export function useTaskForm() {
|
||||||
priority = task.priority;
|
priority = task.priority;
|
||||||
status = task.status;
|
status = task.status;
|
||||||
subtasks = task.subtasks ? [...task.subtasks] : [];
|
subtasks = task.subtasks ? [...task.subtasks] : [];
|
||||||
recurrenceRule = task.recurrenceRule ?? '';
|
|
||||||
effectiveDuration = task.estimatedDuration ?? null;
|
effectiveDuration = task.estimatedDuration ?? null;
|
||||||
showDeleteConfirm = false;
|
showDeleteConfirm = false;
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ import type {
|
||||||
export function toTask(local: LocalTask): Task {
|
export function toTask(local: LocalTask): Task {
|
||||||
return {
|
return {
|
||||||
id: local.id,
|
id: local.id,
|
||||||
projectId: (local as Record<string, unknown>).projectId as string | null | undefined,
|
projectId: local.projectId,
|
||||||
title: local.title,
|
title: local.title,
|
||||||
description: local.description,
|
description: local.description,
|
||||||
dueDate: local.dueDate,
|
dueDate: local.dueDate,
|
||||||
|
|
@ -30,7 +30,6 @@ export function toTask(local: LocalTask): Task {
|
||||||
isCompleted: local.isCompleted,
|
isCompleted: local.isCompleted,
|
||||||
completedAt: local.completedAt,
|
completedAt: local.completedAt,
|
||||||
order: local.order,
|
order: local.order,
|
||||||
recurrenceRule: local.recurrenceRule,
|
|
||||||
subtasks: local.subtasks ?? null,
|
subtasks: local.subtasks ?? null,
|
||||||
metadata: local.metadata ?? null,
|
metadata: local.metadata ?? null,
|
||||||
createdAt: local.createdAt ?? new Date().toISOString(),
|
createdAt: local.createdAt ?? new Date().toISOString(),
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ export const tasksStore = {
|
||||||
subtasks?: Subtask[];
|
subtasks?: Subtask[];
|
||||||
recurrenceRule?: string;
|
recurrenceRule?: string;
|
||||||
estimatedDuration?: number;
|
estimatedDuration?: number;
|
||||||
|
labelIds?: string[];
|
||||||
// Optional: schedule on calendar
|
// Optional: schedule on calendar
|
||||||
scheduleStartDate?: string; // YYYY-MM-DD
|
scheduleStartDate?: string; // YYYY-MM-DD
|
||||||
scheduleStartTime?: string; // HH:mm
|
scheduleStartTime?: string; // HH:mm
|
||||||
|
|
@ -49,6 +50,7 @@ export const tasksStore = {
|
||||||
sourceId: taskId,
|
sourceId: taskId,
|
||||||
title: data.title,
|
title: data.title,
|
||||||
projectId: data.projectId ?? null,
|
projectId: data.projectId ?? null,
|
||||||
|
recurrenceRule: data.recurrenceRule ?? null,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -62,12 +64,12 @@ export const tasksStore = {
|
||||||
scheduledBlockId,
|
scheduledBlockId,
|
||||||
estimatedDuration: data.estimatedDuration ?? null,
|
estimatedDuration: data.estimatedDuration ?? null,
|
||||||
order: count,
|
order: count,
|
||||||
recurrenceRule: data.recurrenceRule ?? null,
|
|
||||||
subtasks: data.subtasks,
|
subtasks: data.subtasks,
|
||||||
|
metadata: data.labelIds && data.labelIds.length > 0 ? { labelIds: data.labelIds } : undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (data.projectId !== undefined) {
|
if (data.projectId !== undefined) {
|
||||||
(newLocal as Record<string, unknown>).projectId = data.projectId;
|
newLocal.projectId = data.projectId;
|
||||||
}
|
}
|
||||||
|
|
||||||
await taskTable.add(newLocal);
|
await taskTable.add(newLocal);
|
||||||
|
|
@ -82,8 +84,11 @@ export const tasksStore = {
|
||||||
// Handle schedule changes via TimeBlock
|
// Handle schedule changes via TimeBlock
|
||||||
const schedStartDate = data._scheduleStartDate as string | null | undefined;
|
const schedStartDate = data._scheduleStartDate as string | null | undefined;
|
||||||
const schedStartTime = data._scheduleStartTime as string | null | undefined;
|
const schedStartTime = data._scheduleStartTime as string | null | undefined;
|
||||||
|
const recurrenceRule = data.recurrenceRule as string | null | undefined;
|
||||||
delete data._scheduleStartDate;
|
delete data._scheduleStartDate;
|
||||||
delete data._scheduleStartTime;
|
delete data._scheduleStartTime;
|
||||||
|
// recurrenceRule lives on the TimeBlock — never on the task row
|
||||||
|
delete data.recurrenceRule;
|
||||||
|
|
||||||
if (schedStartDate !== undefined) {
|
if (schedStartDate !== undefined) {
|
||||||
if (schedStartDate) {
|
if (schedStartDate) {
|
||||||
|
|
@ -103,6 +108,7 @@ export const tasksStore = {
|
||||||
endDate: endISO,
|
endDate: endISO,
|
||||||
allDay: !schedStartTime,
|
allDay: !schedStartTime,
|
||||||
title: (data.title as string) ?? task.title,
|
title: (data.title as string) ?? task.title,
|
||||||
|
...(recurrenceRule !== undefined ? { recurrenceRule } : {}),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Create new block
|
// Create new block
|
||||||
|
|
@ -116,6 +122,7 @@ export const tasksStore = {
|
||||||
sourceId: id,
|
sourceId: id,
|
||||||
title: (data.title as string) ?? task.title,
|
title: (data.title as string) ?? task.title,
|
||||||
projectId: (data.projectId as string) ?? task.projectId ?? null,
|
projectId: (data.projectId as string) ?? task.projectId ?? null,
|
||||||
|
recurrenceRule: recurrenceRule ?? null,
|
||||||
});
|
});
|
||||||
data.scheduledBlockId = blockId;
|
data.scheduledBlockId = blockId;
|
||||||
}
|
}
|
||||||
|
|
@ -133,6 +140,11 @@ export const tasksStore = {
|
||||||
await updateBlock(task.scheduledBlockId, { title: data.title as string });
|
await updateBlock(task.scheduledBlockId, { title: data.title as string });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update recurrence on existing TimeBlock when not also rescheduling
|
||||||
|
if (recurrenceRule !== undefined && schedStartDate === undefined && task.scheduledBlockId) {
|
||||||
|
await updateBlock(task.scheduledBlockId, { recurrenceRule });
|
||||||
|
}
|
||||||
|
|
||||||
await taskTable.update(id, {
|
await taskTable.update(id, {
|
||||||
...data,
|
...data,
|
||||||
updatedAt: new Date().toISOString(),
|
updatedAt: new Date().toISOString(),
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ export const typescriptConfig = [
|
||||||
ecmaVersion: 2022,
|
ecmaVersion: 2022,
|
||||||
sourceType: 'module',
|
sourceType: 'module',
|
||||||
projectService: true,
|
projectService: true,
|
||||||
|
tsconfigRootDir: import.meta.dirname,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: {
|
plugins: {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue