export type Priority = 'low' | 'medium' | 'high' // Status is now an admin-editable pipeline (see AppStatus below), not a fixed // enum — the string is whatever `statuses.value` the admin has configured. export type Status = string export type RecurRule = 'daily' | 'weekdays' | 'weekly' | 'monthly' export const PRIORITIES: Priority[] = ['low', 'medium', 'high'] export const PRIORITY_LABELS: Record = { low: 'Low', medium: 'Medium', high: 'High' } export const RECUR_RULES: RecurRule[] = ['daily', 'weekdays', 'weekly', 'monthly'] export const RECUR_LABELS: Record = { daily: 'Every day', weekdays: 'Every weekday', weekly: 'Every week', monthly: 'Every month', } // Preset list colours (user data, not design-system chrome). export const LIST_COLOURS = ['#c9a84c', '#0d9488', '#2563eb', '#7c3aed', '#dc2626', '#d97706', '#16a34a', '#64748b'] export interface List { id: number owner_id: string name: string colour: string icon: string sort_order: number is_archived: boolean open_count: number total_count: number created_at: string } export interface Task { id: number list_id: number | null owner_id: string created_by: string assigned_to: string | null category_id: number | null project_id: number | null title: string notes: string | null status: Status priority: Priority due_at: string | null remind_at: string | null reminded_at: string | null recur_rule: RecurRule | null completed_at: string | null sort_order: number created_at: string updated_at: string // joined / derived list_name?: string list_colour?: string status_label?: string is_done?: boolean is_hold?: boolean category_name?: string category_colour?: string project_name?: string project_colour?: string item_count?: number item_done?: number } export interface AppStatus { id: number label: string value: string position: number is_done: boolean is_hold: boolean } export interface Category { id: number name: string colour: string sort_order: number created_at: string } export interface Project { id: number created_by: string name: string description: string | null colour: string is_archived: boolean sort_order: number created_at: string task_count?: number done_count?: number } export interface ProjectDetail extends Project { tasks: Task[] } export interface TaskTagEntry { user_email: string tagged_by: string created_at: string } export interface TaskItem { id: number task_id: number label: string is_done: boolean sort_order: number } export interface TaskComment { id: number task_id: number author_email: string | null author_name: string | null body: string created_at: string } export interface TaskDetail extends Task { items: TaskItem[] comments: TaskComment[] tags: TaskTagEntry[] } export interface AppConfig { remind_by_push: boolean remind_by_email: boolean } export interface User { user_id: number name: string email: string is_admin: boolean caps: string[] // bare slugs — verify?app=tasks strips the prefix } // Users with access to this app, served by the central auth service. export interface AuthUser { id: number email: string name: string } export function can(user: User, cap: string): boolean { return user.is_admin || user.caps.includes(cap) }