hellth-hub/apps/admin/lib/page-editor.ts

83 lines
2.5 KiB
TypeScript
Raw Permalink Normal View History

export type LifecycleStatus = "draft" | "scheduled" | "published" | "archived";
export function slugify(text: string): string {
return text
.toLowerCase()
.normalize("NFKD")
.replace(/[^a-z0-9\s-]/g, "")
.replace(/\s+/g, "-")
.replace(/-+/g, "-")
.slice(0, 100)
.replace(/^-|-$/g, "");
}
function stripHtml(html: string): string {
return html.replace(/<[^>]*>/g, " ").replace(/\s+/g, " ").trim();
}
export function extractH1Title(html: string): string {
const match = html.match(/<h1\b[^>]*>([\s\S]*?)<\/h1>/i);
if (!match?.[1]) return "";
return stripHtml(match[1]).slice(0, 160).trim();
}
export function toDateValue(date?: Date | string | null) {
if (!date) return "";
return new Date(date).toISOString().slice(0, 10);
}
export function toTimeValue(date?: Date | string | null) {
if (!date) return "";
return new Date(date).toISOString().slice(11, 16);
}
export function combineDateTime(date: string, time: string) {
if (!date || !time) return undefined;
return new Date(`${date}T${time}:00`);
}
export function isSchedulingVisible(status: LifecycleStatus) {
return status === "draft" || status === "scheduled";
}
export function validatePublishInputs(
status: LifecycleStatus,
publishDate: string,
publishTime: string,
) {
if (!isSchedulingVisible(status)) return null;
if (status === "scheduled" && (!publishDate || !publishTime)) {
return "Für den Status Geplant sind Datum und Uhrzeit erforderlich.";
}
if ((publishDate && !publishTime) || (!publishDate && publishTime)) {
return "Bitte Datum und Uhrzeit gemeinsam setzen.";
}
return null;
}
export function resolveSubmitStatus(
status: LifecycleStatus,
publishDate: string,
publishTime: string,
) {
if (status === "draft" && publishDate && publishTime) return "scheduled" as const;
return status;
}
export function statusLabel(status: LifecycleStatus) {
if (status === "archived") return "Archiviert";
if (status === "published") return "Veröffentlicht";
if (status === "scheduled") return "Geplant";
return "Entwurf";
}
export function statusClass(status: LifecycleStatus) {
if (status === "archived") return "bg-gray-200 text-gray-700 dark:bg-neutral-700 dark:text-neutral-300";
if (status === "published") return "bg-green-50 text-green-700 dark:bg-green-950/50 dark:text-green-400";
if (status === "scheduled") return "bg-indigo-50 text-indigo-700 dark:bg-indigo-950/50 dark:text-indigo-400";
return "bg-gray-100 text-gray-500 dark:bg-neutral-700 dark:text-neutral-400";
}