This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
export function canCompleteTask(dueDate: number): boolean {
|
||||
if (dueDate === 0) return true;
|
||||
const now = new Date();
|
||||
const endOfToday = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 23, 59, 59, 999).getTime();
|
||||
return dueDate <= endOfToday;
|
||||
}
|
||||
|
||||
export const categoryCreateSchema = z.object({
|
||||
name: z.string().min(1).max(50),
|
||||
color: z.string().regex(/^#[0-9A-Fa-f]{6}$/),
|
||||
order: z.number().int().min(0).optional(),
|
||||
});
|
||||
|
||||
export const categoryUpdateSchema = z.object({
|
||||
name: z.string().min(1).max(50).optional(),
|
||||
color: z.string().regex(/^#[0-9A-Fa-f]{6}$/).optional(),
|
||||
order: z.number().int().min(0).optional(),
|
||||
});
|
||||
|
||||
export const repeatSchema = z.enum(['none', 'daily', 'weekly', 'monthly', 'custom']);
|
||||
|
||||
export const taskCreateSchema = z.object({
|
||||
title: z.string().min(1).max(100),
|
||||
description: z.string().max(1000).optional(),
|
||||
categoryId: z.string().min(1),
|
||||
priority: z.enum(['none', 'low', 'medium', 'high', 'critical']).optional(),
|
||||
dueDate: z.number().int().min(0).optional(),
|
||||
dueTime: z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().or(z.literal('')).transform(v => v ?? ''),
|
||||
endTime: z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().or(z.literal('')),
|
||||
allDay: z.boolean().optional(),
|
||||
repeat: repeatSchema.optional(),
|
||||
repeatInterval: z.number().int().min(1).max(30).optional(),
|
||||
repeatDays: z.string().max(20).optional(),
|
||||
seriesId: z.string().max(50).optional(),
|
||||
reminder: z.enum(['none', 'at_time', '15', '30', '60', '120', '1440']).optional(),
|
||||
reminders: z.string().max(100).optional(),
|
||||
assigneeId: z.string().nullable().optional(),
|
||||
subtasks: z.array(z.object({ title: z.string().min(1).max(100) })).optional(),
|
||||
});
|
||||
|
||||
export const taskUpdateSchema = z.object({
|
||||
title: z.string().min(1).max(100).optional(),
|
||||
description: z.string().max(1000).optional(),
|
||||
categoryId: z.string().min(1).optional(),
|
||||
priority: z.enum(['none', 'low', 'medium', 'high', 'critical']).optional(),
|
||||
completed: z.boolean().optional(),
|
||||
dueDate: z.number().int().min(0).optional(),
|
||||
dueTime: z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().or(z.literal('')).transform(v => v === '' ? undefined : v),
|
||||
endTime: z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional(),
|
||||
reminders: z.string().max(100).optional(),
|
||||
assigneeId: z.string().nullable().optional(),
|
||||
});
|
||||
|
||||
export const subtaskCreateSchema = z.object({
|
||||
title: z.string().min(1).max(100),
|
||||
description: z.string().max(1000).optional(),
|
||||
priority: z.enum(['none', 'low', 'medium', 'high', 'critical']).optional(),
|
||||
dueDate: z.number().int().min(0).optional(),
|
||||
dueTime: z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().or(z.literal('')).transform(v => v ?? ''),
|
||||
endTime: z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().or(z.literal('')),
|
||||
allDay: z.boolean().optional(),
|
||||
repeat: repeatSchema.optional(),
|
||||
repeatInterval: z.number().int().min(1).max(30).optional(),
|
||||
repeatDays: z.string().max(20).optional(),
|
||||
seriesId: z.string().max(50).optional(),
|
||||
reminder: z.enum(['none', 'at_time', '15', '30', '60', '120', '1440']).optional(),
|
||||
reminders: z.string().max(100).optional(),
|
||||
assigneeId: z.string().nullable().optional(),
|
||||
order: z.number().int().min(0).optional(),
|
||||
});
|
||||
|
||||
export const subtaskUpdateSchema = z.object({
|
||||
title: z.string().min(1).max(100).optional(),
|
||||
description: z.string().max(1000).optional(),
|
||||
priority: z.enum(['none', 'low', 'medium', 'high', 'critical']).optional(),
|
||||
completed: z.boolean().optional(),
|
||||
dueDate: z.number().int().min(0).optional(),
|
||||
dueTime: z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().or(z.literal('')).transform(v => v === '' ? undefined : v),
|
||||
endTime: z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional(),
|
||||
allDay: z.boolean().optional(),
|
||||
repeat: repeatSchema.optional(),
|
||||
repeatInterval: z.number().int().min(1).max(30).optional(),
|
||||
repeatDays: z.string().max(20).optional(),
|
||||
seriesId: z.string().max(50).optional(),
|
||||
reminder: z.enum(['none', 'at_time', '15', '30', '60', '120', '1440']).optional(),
|
||||
reminders: z.string().max(100).optional(),
|
||||
assigneeId: z.string().nullable().optional(),
|
||||
order: z.number().int().min(0).optional(),
|
||||
});
|
||||
|
||||
export const userSettingsSchema = z.object({
|
||||
darkMode: z.boolean().optional(),
|
||||
notifications: z.boolean().optional(),
|
||||
reminderTime: z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional(),
|
||||
defaultCategory: z.string().optional().nullable(),
|
||||
sortBy: z.enum(['dueDate', 'priority', 'title', 'createdAt']).optional(),
|
||||
sortOrder: z.enum(['asc', 'desc']).optional(),
|
||||
});
|
||||
|
||||
export const repeatProfileSchema = z.object({
|
||||
name: z.string().min(1).max(50),
|
||||
repeat: repeatSchema,
|
||||
repeatInterval: z.number().int().min(1).max(30),
|
||||
repeatDays: z.string().max(20),
|
||||
});
|
||||
|
||||
export const repeatProfileUpdateSchema = z.object({
|
||||
name: z.string().min(1).max(50).optional(),
|
||||
repeat: repeatSchema.optional(),
|
||||
repeatInterval: z.number().int().min(1).max(30).optional(),
|
||||
repeatDays: z.string().max(20).optional(),
|
||||
});
|
||||
|
||||
export const searchQuerySchema = z.object({
|
||||
q: z.string().min(1).max(50),
|
||||
});
|
||||
|
||||
export const friendRequestSchema = z.object({
|
||||
username: z.string().min(1).max(50),
|
||||
});
|
||||
|
||||
export const friendshipSchema = z.object({
|
||||
id: z.string(),
|
||||
userId: z.string(),
|
||||
friendId: z.string(),
|
||||
status: z.enum(['pending', 'accepted']),
|
||||
createdAt: z.number(),
|
||||
updatedAt: z.number(),
|
||||
});
|
||||
|
||||
export const pushChangesSchema = z.object({
|
||||
changes: z.object({
|
||||
categories: z.array(categoryCreateSchema.extend({ id: z.string(), createdAt: z.number(), updatedAt: z.number() })).optional(),
|
||||
tasks: z.array(taskCreateSchema.extend({ id: z.string(), completed: z.boolean(), createdAt: z.number(), updatedAt: z.number() })).optional(),
|
||||
subtasks: z.array(subtaskCreateSchema.extend({ id: z.string(), taskId: z.string(), completed: z.boolean(), createdAt: z.number(), updatedAt: z.number() })).optional(),
|
||||
repeatProfiles: z.array(repeatProfileSchema.extend({ id: z.string(), createdAt: z.number(), updatedAt: z.number() })).optional(),
|
||||
friendships: z.array(friendshipSchema).optional(),
|
||||
}),
|
||||
lastPulledAt: z.number().int().min(0),
|
||||
});
|
||||
|
||||
export const syncQuerySchema = z.object({
|
||||
since: z.string().transform(Number).pipe(z.number().int().min(0)),
|
||||
});
|
||||
|
||||
export const taskQuerySchema = z.object({
|
||||
categoryId: z.string().optional(),
|
||||
completed: z.string().transform(v => v === 'true').optional(),
|
||||
dueBefore: z.string().transform(Number).pipe(z.number().int().min(0)).optional(),
|
||||
dueAfter: z.string().transform(Number).pipe(z.number().int().min(0)).optional(),
|
||||
priority: z.enum(['none', 'low', 'medium', 'high', 'critical']).optional(),
|
||||
sortBy: z.enum(['dueDate', 'priority', 'createdAt', 'title']).optional(),
|
||||
sortOrder: z.enum(['asc', 'desc']).optional(),
|
||||
limit: z.string().transform(Number).pipe(z.number().int().min(1).max(100)).optional(),
|
||||
offset: z.string().transform(Number).pipe(z.number().int().min(0)).optional(),
|
||||
});
|
||||
Reference in New Issue
Block a user