mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-16 13:03:31 +08:00
- Add 7 frequency modes (every N min/hours, daily, weekdays, specific days, monthly, custom cron) with progressive disclosure UI - Add "Run Now" button with confirmation popover and fire-and-forget API - Add execution logs panel (TaskRunsPanel) with auto-polling and accordion behavior - Add task edit mode with cron reverse-parsing (parseCron) to populate form - Add server-side extractAssistantText to store meaningful AI responses instead of raw NDJSON - Fix session linking: pass --session-id to CLI subprocess so "View conversation" navigates to actual content - Fix MACRO undefined error by adding --preload to Bun.spawn - Add confirmation popovers for all destructive actions (run/disable/delete) - Add DayOfWeekPicker component for specific-days scheduling - Add cronDescribe utility with i18n support and unit tests - Display task creation time and last run time - Add ~50 i18n keys (en/zh) for all new UI elements Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
69 lines
1.7 KiB
TypeScript
69 lines
1.7 KiB
TypeScript
import { create } from 'zustand'
|
|
import { tasksApi } from '../api/tasks'
|
|
import type { CronTask, CreateTaskInput, TaskRun } from '../types/task'
|
|
|
|
type TaskStore = {
|
|
tasks: CronTask[]
|
|
recentRuns: TaskRun[]
|
|
isLoading: boolean
|
|
error: string | null
|
|
|
|
fetchTasks: () => Promise<void>
|
|
createTask: (input: CreateTaskInput) => Promise<void>
|
|
updateTask: (id: string, updates: Partial<CronTask>) => Promise<void>
|
|
deleteTask: (id: string) => Promise<void>
|
|
runTask: (taskId: string) => Promise<void>
|
|
fetchRecentRuns: () => Promise<void>
|
|
fetchTaskRuns: (taskId: string) => Promise<TaskRun[]>
|
|
}
|
|
|
|
export const useTaskStore = create<TaskStore>((set) => ({
|
|
tasks: [],
|
|
recentRuns: [],
|
|
isLoading: false,
|
|
error: null,
|
|
|
|
fetchTasks: async () => {
|
|
set({ isLoading: true, error: null })
|
|
try {
|
|
const { tasks } = await tasksApi.list()
|
|
set({ tasks, isLoading: false })
|
|
} catch (err) {
|
|
set({ error: (err as Error).message, isLoading: false })
|
|
}
|
|
},
|
|
|
|
createTask: async (input) => {
|
|
const { task } = await tasksApi.create(input)
|
|
set((s) => ({ tasks: [...s.tasks, task] }))
|
|
},
|
|
|
|
updateTask: async (id, updates) => {
|
|
const { task } = await tasksApi.update(id, updates)
|
|
set((s) => ({ tasks: s.tasks.map((t) => (t.id === id ? task : t)) }))
|
|
},
|
|
|
|
deleteTask: async (id) => {
|
|
await tasksApi.delete(id)
|
|
set((s) => ({ tasks: s.tasks.filter((t) => t.id !== id) }))
|
|
},
|
|
|
|
runTask: async (taskId) => {
|
|
await tasksApi.runTask(taskId)
|
|
},
|
|
|
|
fetchRecentRuns: async () => {
|
|
try {
|
|
const { runs } = await tasksApi.getRecentRuns()
|
|
set({ recentRuns: runs })
|
|
} catch {
|
|
// ignore
|
|
}
|
|
},
|
|
|
|
fetchTaskRuns: async (taskId) => {
|
|
const { runs } = await tasksApi.getTaskRuns(taskId)
|
|
return runs
|
|
},
|
|
}))
|