mirror of
https://github.com/Since-3/since3-portal.git
synced 2026-10-12 21:41:16 +00:00
111 lines
3.2 KiB
TypeScript
111 lines
3.2 KiB
TypeScript
import * as z from "zod";
|
|
|
|
export const PRODUCT_CATEGORIES = ["website", "hosting", "email", "seo", "other"] as const;
|
|
export type ProductCategory = (typeof PRODUCT_CATEGORIES)[number];
|
|
|
|
export const PRODUCT_STATUSES = ["online", "maintenance", "offline"] as const;
|
|
export type ProductStatus = (typeof PRODUCT_STATUSES)[number];
|
|
|
|
// Beim Seitenaufruf werden nur Produkte geprüft, deren letzte Prüfung älter ist.
|
|
export const AUTO_CHECK_STALE_AFTER_MS = 5 * 60 * 1000;
|
|
|
|
export const TASK_STATUSES =["in_progress", "planned", "done"] as const;
|
|
export type TaskStatus = (typeof TASK_STATUSES)[number];
|
|
|
|
export const CATEGORY_LABELS: Record<ProductCategory, string> = {
|
|
website: "Webseite",
|
|
hosting: "Hosting",
|
|
email: "E-Mail",
|
|
seo: "SEO",
|
|
other: "Sonstiges",
|
|
};
|
|
|
|
export const PRODUCT_STATUS_LABELS: Record<ProductStatus, string> = {
|
|
online: "Operativ",
|
|
maintenance: "Wartung",
|
|
offline: "Ausfall",
|
|
};
|
|
|
|
export const DEFAULT_STATUS_MESSAGES: Record<ProductStatus, string> = {
|
|
online: "Erreichbar, keine Störungen",
|
|
maintenance: "Wartung geplant",
|
|
offline: "Nicht erreichbar",
|
|
};
|
|
|
|
export const TASK_STATUS_LABELS: Record<TaskStatus, string> = {
|
|
in_progress: "In Arbeit",
|
|
planned: "Geplant",
|
|
done: "Erledigt",
|
|
};
|
|
|
|
export type Product = {
|
|
id: string;
|
|
name: string;
|
|
category: ProductCategory;
|
|
url: string | null;
|
|
status: ProductStatus;
|
|
statusMessage: string | null;
|
|
uptime30d: number | null;
|
|
updatedAt: string;
|
|
checkable: boolean;
|
|
checkDue: boolean;
|
|
measuredUptime30d: number | null;
|
|
checks30d: number;
|
|
lastCheck: {
|
|
checkedAt: string;
|
|
ok: boolean;
|
|
responseMs: number | null;
|
|
error: string | null;
|
|
} | null;
|
|
};
|
|
|
|
export type Task = {
|
|
id: string;
|
|
name: string;
|
|
description: string | null;
|
|
status: TaskStatus;
|
|
since: string;
|
|
};
|
|
|
|
export type InternalNote = {
|
|
id: string;
|
|
body: string;
|
|
updatedAt: string;
|
|
editorName: string | null;
|
|
};
|
|
|
|
const optionalText = z
|
|
.string()
|
|
.trim()
|
|
.transform((value) => (value === "" ? null : value));
|
|
|
|
export const ProductSchema = z.object({
|
|
name: z.string().trim().min(1, { error: "Name ist erforderlich." }),
|
|
category: z.enum(PRODUCT_CATEGORIES),
|
|
url: optionalText,
|
|
status: z.enum(PRODUCT_STATUSES),
|
|
statusMessage: optionalText,
|
|
uptime30d: z
|
|
.string()
|
|
.trim()
|
|
.transform((value, ctx) => {
|
|
if (value === "") return null;
|
|
const number = Number(value.replace(",", "."));
|
|
if (!Number.isFinite(number) || number < 0 || number > 100) {
|
|
ctx.addIssue({ code: "custom", message: "Uptime muss zwischen 0 und 100 liegen." });
|
|
return z.NEVER;
|
|
}
|
|
return Math.round(number * 100) / 100;
|
|
}),
|
|
});
|
|
|
|
export const TaskSchema = z.object({
|
|
name: z.string().trim().min(1, { error: "Vorgang ist erforderlich." }),
|
|
description: optionalText,
|
|
status: z.enum(TASK_STATUSES),
|
|
since: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, { error: "Bitte ein Datum wählen." }),
|
|
});
|
|
|
|
export const NoteSchema = z.object({
|
|
body: z.string().trim().min(1, { error: "Notiz darf nicht leer sein." }).max(5000),
|
|
});
|