From cb31d4e8af2b2a1d208a08a7d6d4d54453ef9705 Mon Sep 17 00:00:00 2001 From: Klemek Date: Fri, 10 Jul 2026 11:24:21 +0200 Subject: [PATCH] refactor: reduce responsability of individual parts --- resources/ts/api/tasks.ts | 14 +-- resources/ts/components/CronInput.vue | 133 +++++++++----------------- resources/ts/components/TaskItem.vue | 23 +---- resources/ts/constants.ts | 1 + resources/ts/enums.ts | 8 ++ resources/ts/lib/cron.ts | 66 +++++++++++++ resources/ts/lib/tasks.ts | 30 ++++++ 7 files changed, 156 insertions(+), 119 deletions(-) create mode 100644 resources/ts/constants.ts create mode 100644 resources/ts/enums.ts create mode 100644 resources/ts/lib/cron.ts create mode 100644 resources/ts/lib/tasks.ts diff --git a/resources/ts/api/tasks.ts b/resources/ts/api/tasks.ts index 59b6d05..9dc38cc 100644 --- a/resources/ts/api/tasks.ts +++ b/resources/ts/api/tasks.ts @@ -1,16 +1,6 @@ -import type { RawTask, Task, TaskCreateData, TaskUpdateData } from "@/types"; +import { parseTask } from "@/lib/tasks"; +import type { Task, TaskCreateData, TaskUpdateData } from "@/types"; -function parseTask(task: RawTask): Task { - return { - id: task.id, - name: task.name, - reset_cron: task.reset_cron, - check_date: task.check_date ? new Date(task.check_date) : null, - previous_check_date: task.previous_check_date - ? new Date(task.previous_check_date) - : null, - }; -} export async function getTasks(list: string): Promise { const response = await fetch(`/api/lists/${list}/tasks`); diff --git a/resources/ts/components/CronInput.vue b/resources/ts/components/CronInput.vue index acac6be..7c78e08 100644 --- a/resources/ts/components/CronInput.vue +++ b/resources/ts/components/CronInput.vue @@ -1,120 +1,79 @@ diff --git a/resources/ts/components/TaskItem.vue b/resources/ts/components/TaskItem.vue index 74b3acc..1bf2729 100644 --- a/resources/ts/components/TaskItem.vue +++ b/resources/ts/components/TaskItem.vue @@ -3,13 +3,10 @@ import { onBeforeMount, ref, watch, computed } from "vue"; import type { Task } from "@/types"; import { Copy, Trash, Save, X } from "@lucide/vue"; import { updateTask } from "@/api/tasks"; -import { CronExpressionParser } from 'cron-parser' import CronInput from "@/components/CronInput.vue"; +import { taskCompleted } from "@/lib/tasks"; -const emit = defineEmits<{ - (e: 'clone', task: Task): void - (e: 'delete', task: Task): void -}>(); +const emit = defineEmits<(e: 'clone' | 'delete', task: Task) => void>(); const task = defineModel({ required: true }); @@ -18,21 +15,7 @@ const editName = ref(''); const editCron = ref(null); const refreshKey = ref(0); -const checked = computed(() => { - if (task.value.check_date === null) { - return false; - } - if (task.value.reset_cron === null) { - return true; - } - try { - const interval = CronExpressionParser.parse(task.value.reset_cron, {currentDate: task.value.check_date}); - const nextDate = interval.next(); - return nextDate.getTime() > (new Date()).getTime(); - } catch { - return false; - } -}); +const checked = computed(() => taskCompleted(task.value)); function onClose() { editMode.value = false; diff --git a/resources/ts/constants.ts b/resources/ts/constants.ts new file mode 100644 index 0000000..53df223 --- /dev/null +++ b/resources/ts/constants.ts @@ -0,0 +1 @@ +export const DEFAULT_CRON = '0 0 * * *'; diff --git a/resources/ts/enums.ts b/resources/ts/enums.ts new file mode 100644 index 0000000..ef25392 --- /dev/null +++ b/resources/ts/enums.ts @@ -0,0 +1,8 @@ +export enum CronType { + ONE_TIME = 1, + EVERY_DAY = 2, + EVERY_WEEK = 3, + EVERY_MONTH = 4, + EVERY_YEAR = 5, + SPECIFIC = 6, +} diff --git a/resources/ts/lib/cron.ts b/resources/ts/lib/cron.ts new file mode 100644 index 0000000..f7ca64b --- /dev/null +++ b/resources/ts/lib/cron.ts @@ -0,0 +1,66 @@ + +import { CronType } from "@/enums"; +import CronExpressionParser from "cron-parser"; + +export function parseCron(cron: string | null): { type: CronType, value: number } { + let value: RegExpMatchArray | null; + if (cron === null) { + return { + type: CronType.ONE_TIME, + value: 0 + } + } else if ((value = /^0 (\d+) \* \* \*$/i.exec(cron)) !== null) { + return { + type: CronType.EVERY_DAY, + value: parseInt(value[1] ?? '') + } + } else if ((value = /^0 0 \* \* (\d+)$/i.exec(cron)) !== null) { + return { + type: CronType.EVERY_WEEK, + value: parseInt(value[1] ?? '') + } + } else if ((value = /^0 0 (\d+) \* \*$/i.exec(cron)) !== null) { + return { + type: CronType.EVERY_MONTH, + value: parseInt(value[1] ?? '') + } + } else if ((value = /^0 0 1 (\d+) \*$/i.exec(cron)) !== null) { + return { + type: CronType.EVERY_YEAR, + value: parseInt(value[1] ?? '') + } + } else { + return { + type: CronType.SPECIFIC, + value: 0 + } + } +} + +export function getCron(type: CronType, value: number, fallback: string): string | null { + switch(type) { + case CronType.EVERY_DAY: + return `0 ${value.toFixed(0)} * * *`; + case CronType.EVERY_WEEK: + return `0 0 * * ${value.toFixed(0)}` + case CronType.EVERY_MONTH: + return `0 0 ${value.toFixed(0)} * *`; + case CronType.EVERY_YEAR: + return `0 0 1 ${value.toFixed(0)} *`; + case CronType.SPECIFIC: + if (validCron(fallback)) { + return fallback; + } + } + + return null; +} + +export function validCron(cron: string): boolean { + try { + CronExpressionParser.parse(cron); + return true; + } catch { + return false; + } +} diff --git a/resources/ts/lib/tasks.ts b/resources/ts/lib/tasks.ts new file mode 100644 index 0000000..d54dfb6 --- /dev/null +++ b/resources/ts/lib/tasks.ts @@ -0,0 +1,30 @@ +import type { RawTask, Task } from "@/types"; +import CronExpressionParser from "cron-parser"; + +export function parseTask(task: RawTask): Task { + return { + id: task.id, + name: task.name, + reset_cron: task.reset_cron, + check_date: task.check_date ? new Date(task.check_date) : null, + previous_check_date: task.previous_check_date + ? new Date(task.previous_check_date) + : null, + }; +} + +export function taskCompleted(task: Task): boolean { + if (task.check_date === null) { + return false; + } + if (task.reset_cron === null) { + return true; + } + try { + const interval = CronExpressionParser.parse(task.reset_cron, {currentDate: task.check_date}); + const nextDate = interval.next(); + return nextDate.getTime() > (new Date()).getTime(); + } catch { + return false; + } +}