Updates 1
CI / ci (push) Canceled after 0s

The session built:

Appointments page: a single list, newest first.
Block Time: edit and delete.
Customer CSV export: with barber notes excluded.
Guest-link regression test: a test that an appointment id alone is rejected, plus fixes to the stale docs.

It built the scheduler, job runner with live progress, backup and restore, and the health alerts. Its own report says a real delete-and-restore on throwaway Docker passed, but I haven’t repeated that. It also says real SMTP and large dumps were not exercised. The manager image needs rebuilding for the backups to work, because it now installs 7zip.
This commit is contained in:
Stefan Lazic committed 2026-10-17 22:29:00 +01:00
1 parent 9f981173f4
commit 17eee5b932
95 files changed
+7955 -150

No files matched your search

@@ -1,9 +1,12 @@
"use client";
import Link from "next/link";
import { useActionState, useState } from "react";
import { JobProgress } from "../../job-progress";
import { PassphraseNotice } from "../../passphrase-notice";
import { deleteBusinessAction, type DeleteBusinessState } from "./actions";
const initialState: DeleteBusinessState = { error: null };
const initialState: DeleteBusinessState = { error: null, jobId: null, newPassphrase: null };
export function DeleteBusinessForm({ slug }: { slug: string }) {
const boundAction = deleteBusinessAction.bind(null, slug);
@@ -11,8 +14,27 @@ export function DeleteBusinessForm({ slug }: { slug: string }) {
const [confirmation, setConfirmation] = useState("");
const canDelete = confirmation === slug;
if (state.jobId) {
return (
<div className="space-y-4">
{state.newPassphrase && <PassphraseNotice passphrase={state.newPassphrase} />}
<JobProgress jobId={state.jobId} refreshOnFinish={false}>
<Link href="/dashboard" className="inline-block rounded-md bg-ink px-4 py-2 text-sm font-semibold text-white">
Back to businesses
</Link>
</JobProgress>
</div>
);
}
return (
<form action={formAction} className="space-y-4">
<label className="flex items-start gap-2 text-sm">
<input type="checkbox" name="finalBackup" defaultChecked className="mt-0.5" />
<span>
Take a final backup first <span className="text-muted">(recommended — kept on this server after the business is gone; deleting stops if the backup fails)</span>
</span>
</label>
<div>
<label htmlFor="confirmation" className="block text-sm font-medium text-muted">
Type <span className="font-mono font-semibold text-ink">{slug}</span> to confirm
@@ -39,7 +61,7 @@ export function DeleteBusinessForm({ slug }: { slug: string }) {
disabled={!canDelete || isPending}
className="w-full rounded-md bg-danger py-2 text-sm font-semibold text-white disabled:opacity-40"
>
{isPending ? "Deleting…" : "Delete Business"}
{isPending ? "Starting…" : "Delete Business"}
</button>
</form>
);