mirror of
https://github.com/Dvorinka/Bookra.git
synced 2026-10-28 07:41:16 +00:00
chore: extract shared dashboard chrome strings to i18n keys
Replaces 47 inline cs()/en ternaries with dashboard.* keys: demo notices, save/delete failures, delete aria-labels, loading, and zone/blocked-day copy. Demo fixture names, locale tags, and the zón/locations plural stay inline (Czech plurals need count-aware forms). Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
334b17f4ff
commit
f1b0a3a2f2
5 files changed
+82
-48
No files matched your search
+1
-1
@@ -25,7 +25,7 @@
|
||||
|
||||
## Still Needs Frontend Polish
|
||||
|
||||
- Dashboard inline i18n ternaries remain (~60 as of M30). Systematic extraction to `i18n.t()` keys is an ongoing task.
|
||||
- Dashboard inline i18n ternaries: shared chrome strings extracted to `dashboard.*` keys (demo notices, save/delete failures, delete aria-labels, zone/blocked-day copy). ~56 `cs() ? ...` remain project-wide, of which the dashboard remainder is demo fixture names, `cs-CZ`/`en-US` locale tags, and the `zón`/`locations` plural — all correct inline (Czech plurals need count-aware forms, not a single key).
|
||||
- Registration cannot be fully customer-tested locally until Neon Auth environment variables are configured.
|
||||
|
||||
## Fixed This Session (platform audit pass)
|
||||
|
||||
@@ -551,6 +551,23 @@ const dictionaries = {
|
||||
"dashboard.notification.reminder": "Připomínka: rezervace u",
|
||||
"dashboard.notification.upgrade": "Blížíte se limitu plánu",
|
||||
"dashboard.notification.trialEnding": "Vaše zkušební doba končí za 3 dny",
|
||||
"dashboard.demo.noSave": "V demo režimu nelze ukládat.",
|
||||
"dashboard.demo.noDelete": "V demo režimu nelze mazat.",
|
||||
"dashboard.demo.noModify": "V demo režimu nelze měnit rezervace.",
|
||||
"dashboard.action.delete": "Smazat",
|
||||
"dashboard.loading": "Načítání…",
|
||||
"dashboard.saveFailed": "Uložení selhalo.",
|
||||
"dashboard.deleteFailed": "Smazání selhalo.",
|
||||
"dashboard.availability.hint": "Nastavte dny a časy, kdy přijímáte rezervace.",
|
||||
"dashboard.blockedDay.hint": "Dny, kdy nejsou dostupné rezervace.",
|
||||
"dashboard.blockedDay.empty": "Zatím žádné blokované dny.",
|
||||
"dashboard.blockedDay.placeholder": "např. Státní svátek",
|
||||
"dashboard.blockedDay.date": "Datum",
|
||||
"dashboard.day.closed": "Zavřeno",
|
||||
"dashboard.day.open": "Otevřeno",
|
||||
"dashboard.zone.addFirst": "Přidejte první zónu nebo místnost.",
|
||||
"dashboard.zone.limitHint": "Váš plán umožňuje pouze omezený počet lokací. Pro více lokací upgradujte.",
|
||||
"dashboard.zone.saveFailed": "Uložení zóny selhalo.",
|
||||
"booking.title": "Rezervace",
|
||||
"booking.body": "Vyberte dostupný termín, doplňte kontaktní údaje a potvrzení přijde e-mailem.",
|
||||
"booking.slots": "Dostupné termíny",
|
||||
@@ -1190,6 +1207,23 @@ const dictionaries = {
|
||||
"dashboard.notification.reminder": "Reminder: booking at",
|
||||
"dashboard.notification.upgrade": "You're nearing your plan limit",
|
||||
"dashboard.notification.trialEnding": "Your trial ends in 3 days",
|
||||
"dashboard.demo.noSave": "Cannot save in demo mode.",
|
||||
"dashboard.demo.noDelete": "Cannot delete in demo mode.",
|
||||
"dashboard.demo.noModify": "Cannot modify bookings in demo mode.",
|
||||
"dashboard.action.delete": "Delete",
|
||||
"dashboard.loading": "Loading…",
|
||||
"dashboard.saveFailed": "Save failed.",
|
||||
"dashboard.deleteFailed": "Delete failed.",
|
||||
"dashboard.availability.hint": "Set the days and times you accept bookings.",
|
||||
"dashboard.blockedDay.hint": "Days when bookings are unavailable.",
|
||||
"dashboard.blockedDay.empty": "No blocked days yet.",
|
||||
"dashboard.blockedDay.placeholder": "e.g. Public holiday",
|
||||
"dashboard.blockedDay.date": "Date",
|
||||
"dashboard.day.closed": "Closed",
|
||||
"dashboard.day.open": "Open",
|
||||
"dashboard.zone.addFirst": "Add your first location or room.",
|
||||
"dashboard.zone.limitHint": "Your plan only allows a limited number of locations. Upgrade for more.",
|
||||
"dashboard.zone.saveFailed": "Failed to save location.",
|
||||
"booking.title": "Book a visit",
|
||||
"booking.body": "Choose an available time, add your contact details, and receive confirmation by email.",
|
||||
"booking.slots": "Available times",
|
||||
|
||||
@@ -141,7 +141,7 @@ function ServicesPage() {
|
||||
const duration = parseInt(form().durationMinutes, 10);
|
||||
if (!name || !duration || duration <= 0) return;
|
||||
if (!bearer || bearer.startsWith("demo.")) {
|
||||
data.setDemoNotice(cs() ? "V demo režimu nelze ukládat." : "Cannot save in demo mode.");
|
||||
data.setDemoNotice(data.i18n.t("dashboard.demo.noSave"));
|
||||
return;
|
||||
}
|
||||
setSaving(true);
|
||||
@@ -180,7 +180,7 @@ function ServicesPage() {
|
||||
const handleDelete = async (id: string) => {
|
||||
const bearer = data.token();
|
||||
if (!bearer || bearer.startsWith("demo.")) {
|
||||
data.setDemoNotice(cs() ? "V demo režimu nelze mazat." : "Cannot delete in demo mode.");
|
||||
data.setDemoNotice(data.i18n.t("dashboard.demo.noDelete"));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
@@ -287,7 +287,7 @@ function ServicesPage() {
|
||||
<input type="checkbox" checked={field.required} onChange={(e) => setIntake(i(), { required: e.currentTarget.checked })} class="rounded accent-accent" />
|
||||
{data.i18n.t("dashboard.service.intakeRequired")}
|
||||
</label>
|
||||
<button onClick={() => removeIntake(i())} class="p-1.5 text-ink-subtle hover:text-red-600 rounded-lg" aria-label={cs() ? "Smazat" : "Delete"}><Trash2Icon /></button>
|
||||
<button onClick={() => removeIntake(i())} class="p-1.5 text-ink-subtle hover:text-red-600 rounded-lg" aria-label={data.i18n.t("dashboard.action.delete")}><Trash2Icon /></button>
|
||||
</div>
|
||||
)}
|
||||
</For>
|
||||
@@ -304,7 +304,7 @@ function ServicesPage() {
|
||||
</Show>
|
||||
|
||||
<Show when={!services.loading} fallback={
|
||||
<div class="p-12 text-center text-ink-muted text-sm animate-pulse">{cs() ? "Načítání…" : "Loading…"}</div>
|
||||
<div class="p-12 text-center text-ink-muted text-sm animate-pulse">{data.i18n.t("dashboard.loading")}</div>
|
||||
}>
|
||||
<Show when={resolvedServices().length > 0} fallback={
|
||||
<div class="p-12 text-center">
|
||||
@@ -336,7 +336,7 @@ function ServicesPage() {
|
||||
<button onClick={() => openEdit(service)} class="p-2 text-ink-subtle hover:text-accent hover:bg-accent-subtle rounded-lg transition-colors" aria-label={data.i18n.t("dashboard.edit")}>
|
||||
<EditIcon />
|
||||
</button>
|
||||
<button onClick={() => void handleDelete(service.id)} class="p-2 text-ink-subtle hover:text-red-600 hover:bg-red-50 rounded-lg transition-colors" aria-label={cs() ? "Smazat" : "Delete"}>
|
||||
<button onClick={() => void handleDelete(service.id)} class="p-2 text-ink-subtle hover:text-red-600 hover:bg-red-50 rounded-lg transition-colors" aria-label={data.i18n.t("dashboard.action.delete")}>
|
||||
<Trash2Icon />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -114,7 +114,7 @@ function StaffPage() {
|
||||
const name = form().displayName.trim();
|
||||
if (!name) return;
|
||||
if (!bearer || bearer.startsWith("demo.")) {
|
||||
data.setDemoNotice(cs() ? "V demo režimu nelze ukládat." : "Cannot save in demo mode.");
|
||||
data.setDemoNotice(data.i18n.t("dashboard.demo.noSave"));
|
||||
return;
|
||||
}
|
||||
setSaving(true);
|
||||
@@ -146,7 +146,7 @@ function StaffPage() {
|
||||
const handleToggleActive = async (member: any) => {
|
||||
const bearer = data.token();
|
||||
if (!bearer || bearer.startsWith("demo.")) {
|
||||
data.setDemoNotice(cs() ? "V demo režimu nelze ukládat." : "Cannot save in demo mode.");
|
||||
data.setDemoNotice(data.i18n.t("dashboard.demo.noSave"));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
@@ -164,7 +164,7 @@ function StaffPage() {
|
||||
const handleDelete = async (id: string) => {
|
||||
const bearer = data.token();
|
||||
if (!bearer || bearer.startsWith("demo.")) {
|
||||
data.setDemoNotice(cs() ? "V demo režimu nelze mazat." : "Cannot delete in demo mode.");
|
||||
data.setDemoNotice(data.i18n.t("dashboard.demo.noDelete"));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
@@ -254,7 +254,7 @@ function StaffPage() {
|
||||
</Show>
|
||||
|
||||
<Show when={!staff.loading} fallback={
|
||||
<div class="p-12 text-center text-ink-muted text-sm animate-pulse">{cs() ? "Načítání…" : "Loading…"}</div>
|
||||
<div class="p-12 text-center text-ink-muted text-sm animate-pulse">{data.i18n.t("dashboard.loading")}</div>
|
||||
}>
|
||||
<Show when={resolvedStaff().length > 0} fallback={
|
||||
<div class="p-12 text-center">
|
||||
@@ -294,7 +294,7 @@ function StaffPage() {
|
||||
<button onClick={() => openEdit(member)} class="p-2 text-ink-subtle hover:text-accent hover:bg-accent-subtle rounded-lg transition-colors" aria-label={data.i18n.t("dashboard.edit")}>
|
||||
<EditIcon />
|
||||
</button>
|
||||
<button onClick={() => void handleDelete(member.id)} class="p-2 text-ink-subtle hover:text-red-600 hover:bg-red-50 rounded-lg transition-colors" aria-label={cs() ? "Smazat" : "Delete"}>
|
||||
<button onClick={() => void handleDelete(member.id)} class="p-2 text-ink-subtle hover:text-red-600 hover:bg-red-50 rounded-lg transition-colors" aria-label={data.i18n.t("dashboard.action.delete")}>
|
||||
<Trash2Icon />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -203,7 +203,7 @@ function ZonesPage() {
|
||||
const handlePromote = async (bookingId: string, allowOverCapacity: boolean) => {
|
||||
const bearer = data.token();
|
||||
if (!bearer || bearer.startsWith("demo.")) {
|
||||
data.setDemoNotice(cs() ? "V demo režimu nelze měnit rezervace." : "Cannot modify bookings in demo mode.");
|
||||
data.setDemoNotice(data.i18n.t("dashboard.demo.noModify"));
|
||||
return;
|
||||
}
|
||||
setPromoteBusy(bookingId);
|
||||
@@ -237,7 +237,7 @@ function ZonesPage() {
|
||||
if (!newZoneName().trim()) return;
|
||||
if (!canAddLocation()) { setShowUpgradePrompt(true); setShowAddZone(false); return; }
|
||||
if (!bearer || bearer.startsWith("demo.")) {
|
||||
data.setDemoNotice(cs() ? "V demo režimu nelze ukládat." : "Cannot save in demo mode.");
|
||||
data.setDemoNotice(data.i18n.t("dashboard.demo.noSave"));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
@@ -248,25 +248,25 @@ function ZonesPage() {
|
||||
setNewZoneName(""); setNewZoneType("room"); setNewZoneCapacity(10); setShowAddZone(false);
|
||||
void refetchLocations();
|
||||
} catch {
|
||||
data.setDemoNotice(cs() ? "Uložení zóny selhalo." : "Failed to save location.");
|
||||
data.setDemoNotice(data.i18n.t("dashboard.zone.saveFailed"));
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteZone = async (id: string) => {
|
||||
const bearer = data.token();
|
||||
if (!bearer || bearer.startsWith("demo.")) { data.setDemoNotice(cs() ? "V demo režimu nelze mazat." : "Cannot delete in demo mode."); return; }
|
||||
if (!bearer || bearer.startsWith("demo.")) { data.setDemoNotice(data.i18n.t("dashboard.demo.noDelete")); return; }
|
||||
try {
|
||||
await (apiClient as any).DELETE(`/v1/catalog/locations/${id}`, authHeaders());
|
||||
void refetchLocations();
|
||||
} catch {
|
||||
data.setDemoNotice(cs() ? "Smazání selhalo." : "Delete failed.");
|
||||
data.setDemoNotice(data.i18n.t("dashboard.deleteFailed"));
|
||||
}
|
||||
};
|
||||
|
||||
const handleAddBlockedDay = async () => {
|
||||
const bearer = data.token();
|
||||
if (!newBlockedDate()) return;
|
||||
if (!bearer || bearer.startsWith("demo.")) { data.setDemoNotice(cs() ? "V demo režimu nelze ukládat." : "Cannot save in demo mode."); return; }
|
||||
if (!bearer || bearer.startsWith("demo.")) { data.setDemoNotice(data.i18n.t("dashboard.demo.noSave")); return; }
|
||||
setBlockedSaving(true);
|
||||
try {
|
||||
await (apiClient as any).POST("/v1/catalog/blocked-days", {
|
||||
@@ -274,14 +274,14 @@ function ZonesPage() {
|
||||
body: {
|
||||
date: new Date(`${newBlockedDate()}T00:00:00`).toISOString(),
|
||||
type: "closure",
|
||||
reason: newBlockedReason().trim() || (cs() ? "Zavřeno" : "Closed"),
|
||||
reason: newBlockedReason().trim() || (data.i18n.t("dashboard.day.closed")),
|
||||
...(newBlockedStaffId() ? { staffId: newBlockedStaffId() } : {}),
|
||||
},
|
||||
});
|
||||
setNewBlockedDate(""); setNewBlockedReason(""); setNewBlockedStaffId("");
|
||||
void refetchBlocked();
|
||||
} catch {
|
||||
data.setDemoNotice(cs() ? "Uložení selhalo." : "Save failed.");
|
||||
data.setDemoNotice(data.i18n.t("dashboard.saveFailed"));
|
||||
} finally {
|
||||
setBlockedSaving(false);
|
||||
}
|
||||
@@ -298,7 +298,7 @@ function ZonesPage() {
|
||||
|
||||
const handleSaveHours = async (day: { dayOfWeek: number; open: string; close: string; isOpen: boolean }) => {
|
||||
const bearer = data.token();
|
||||
if (!bearer || bearer.startsWith("demo.")) { data.setDemoNotice(cs() ? "V demo režimu nelze ukládat." : "Cannot save in demo mode."); return; }
|
||||
if (!bearer || bearer.startsWith("demo.")) { data.setDemoNotice(data.i18n.t("dashboard.demo.noSave")); return; }
|
||||
setHoursSaving(day.dayOfWeek);
|
||||
try {
|
||||
const scope = hoursScope();
|
||||
@@ -309,7 +309,7 @@ function ZonesPage() {
|
||||
});
|
||||
void refetchHours();
|
||||
} catch {
|
||||
data.setDemoNotice(cs() ? "Uložení selhalo." : "Save failed.");
|
||||
data.setDemoNotice(data.i18n.t("dashboard.saveFailed"));
|
||||
} finally {
|
||||
setHoursSaving(null);
|
||||
}
|
||||
@@ -322,7 +322,7 @@ function ZonesPage() {
|
||||
const handleSaveTemplate = async () => {
|
||||
const bearer = data.token();
|
||||
if (!newTemplateTitle().trim()) return;
|
||||
if (!bearer || bearer.startsWith("demo.")) { data.setDemoNotice(cs() ? "V demo režimu nelze ukládat." : "Cannot save in demo mode."); return; }
|
||||
if (!bearer || bearer.startsWith("demo.")) { data.setDemoNotice(data.i18n.t("dashboard.demo.noSave")); return; }
|
||||
setTemplateSaving(true);
|
||||
try {
|
||||
const body = { title: newTemplateTitle().trim(), durationMinutes: newTemplateDuration(), capacity: newTemplateCapacity() };
|
||||
@@ -335,7 +335,7 @@ function ZonesPage() {
|
||||
resetTemplateForm();
|
||||
void refetchTemplates(); void refetchSessions();
|
||||
} catch {
|
||||
data.setDemoNotice(cs() ? "Uložení selhalo." : "Save failed.");
|
||||
data.setDemoNotice(data.i18n.t("dashboard.saveFailed"));
|
||||
} finally {
|
||||
setTemplateSaving(false);
|
||||
}
|
||||
@@ -350,19 +350,19 @@ function ZonesPage() {
|
||||
|
||||
const handleDeleteTemplate = async (id: string) => {
|
||||
const bearer = data.token();
|
||||
if (!bearer || bearer.startsWith("demo.")) { data.setDemoNotice(cs() ? "V demo režimu nelze mazat." : "Cannot delete in demo mode."); return; }
|
||||
if (!bearer || bearer.startsWith("demo.")) { data.setDemoNotice(data.i18n.t("dashboard.demo.noDelete")); return; }
|
||||
try {
|
||||
await (apiClient as any).DELETE(`/v1/catalog/class-templates/${id}`, authHeaders());
|
||||
void refetchTemplates(); void refetchSessions();
|
||||
} catch {
|
||||
data.setDemoNotice(cs() ? "Smazání selhalo." : "Delete failed.");
|
||||
data.setDemoNotice(data.i18n.t("dashboard.deleteFailed"));
|
||||
}
|
||||
};
|
||||
|
||||
const handleAddSession = async () => {
|
||||
const bearer = data.token();
|
||||
if (!newSessionTemplateId() || !newSessionStartsAt()) return;
|
||||
if (!bearer || bearer.startsWith("demo.")) { data.setDemoNotice(cs() ? "V demo režimu nelze ukládat." : "Cannot save in demo mode."); return; }
|
||||
if (!bearer || bearer.startsWith("demo.")) { data.setDemoNotice(data.i18n.t("dashboard.demo.noSave")); return; }
|
||||
setSessionSaving(true);
|
||||
try {
|
||||
await (apiClient as any).POST("/v1/catalog/class-sessions", {
|
||||
@@ -376,7 +376,7 @@ function ZonesPage() {
|
||||
setNewSessionTemplateId(""); setNewSessionLocationId(""); setNewSessionStartsAt("");
|
||||
void refetchSessions();
|
||||
} catch {
|
||||
data.setDemoNotice(cs() ? "Uložení selhalo." : "Save failed.");
|
||||
data.setDemoNotice(data.i18n.t("dashboard.saveFailed"));
|
||||
} finally {
|
||||
setSessionSaving(false);
|
||||
}
|
||||
@@ -384,19 +384,19 @@ function ZonesPage() {
|
||||
|
||||
const handleDeleteSession = async (id: string) => {
|
||||
const bearer = data.token();
|
||||
if (!bearer || bearer.startsWith("demo.")) { data.setDemoNotice(cs() ? "V demo režimu nelze mazat." : "Cannot delete in demo mode."); return; }
|
||||
if (!bearer || bearer.startsWith("demo.")) { data.setDemoNotice(data.i18n.t("dashboard.demo.noDelete")); return; }
|
||||
try {
|
||||
await (apiClient as any).DELETE(`/v1/catalog/class-sessions/${id}`, authHeaders());
|
||||
void refetchSessions();
|
||||
} catch {
|
||||
data.setDemoNotice(cs() ? "Smazání selhalo." : "Delete failed.");
|
||||
data.setDemoNotice(data.i18n.t("dashboard.deleteFailed"));
|
||||
}
|
||||
};
|
||||
|
||||
const handleAddSchedule = async () => {
|
||||
const bearer = data.token();
|
||||
if (!newSchedTemplateId() || !newSchedStartsLocal()) return;
|
||||
if (!bearer || bearer.startsWith("demo.")) { data.setDemoNotice(cs() ? "V demo režimu nelze ukládat." : "Cannot save in demo mode."); return; }
|
||||
if (!bearer || bearer.startsWith("demo.")) { data.setDemoNotice(data.i18n.t("dashboard.demo.noSave")); return; }
|
||||
setSchedSaving(true);
|
||||
try {
|
||||
await (apiClient as any).POST("/v1/catalog/class-schedules", {
|
||||
@@ -412,7 +412,7 @@ function ZonesPage() {
|
||||
void refetchSchedules();
|
||||
void refetchSessions();
|
||||
} catch {
|
||||
data.setDemoNotice(cs() ? "Uložení selhalo." : "Save failed.");
|
||||
data.setDemoNotice(data.i18n.t("dashboard.saveFailed"));
|
||||
} finally {
|
||||
setSchedSaving(false);
|
||||
}
|
||||
@@ -431,7 +431,7 @@ function ZonesPage() {
|
||||
const bearer = data.token();
|
||||
const id = editingSchedId();
|
||||
if (!id) return;
|
||||
if (!bearer || bearer.startsWith("demo.")) { data.setDemoNotice(cs() ? "V demo režimu nelze ukládat." : "Cannot save in demo mode."); return; }
|
||||
if (!bearer || bearer.startsWith("demo.")) { data.setDemoNotice(data.i18n.t("dashboard.demo.noSave")); return; }
|
||||
setSchedEditSaving(true);
|
||||
try {
|
||||
await (apiClient as any).PATCH(`/v1/catalog/class-schedules/${id}`, {
|
||||
@@ -448,7 +448,7 @@ function ZonesPage() {
|
||||
void refetchSchedules();
|
||||
void refetchSessions();
|
||||
} catch {
|
||||
data.setDemoNotice(cs() ? "Uložení selhalo." : "Save failed.");
|
||||
data.setDemoNotice(data.i18n.t("dashboard.saveFailed"));
|
||||
} finally {
|
||||
setSchedEditSaving(false);
|
||||
}
|
||||
@@ -462,7 +462,7 @@ function ZonesPage() {
|
||||
|
||||
const handleSaveCapacity = async (session: any, allowOverCapacity: boolean) => {
|
||||
const bearer = data.token();
|
||||
if (!bearer || bearer.startsWith("demo.")) { data.setDemoNotice(cs() ? "V demo režimu nelze ukládat." : "Cannot save in demo mode."); return; }
|
||||
if (!bearer || bearer.startsWith("demo.")) { data.setDemoNotice(data.i18n.t("dashboard.demo.noSave")); return; }
|
||||
setCapSaving(true);
|
||||
try {
|
||||
const response = await (apiClient as any).PATCH(`/v1/catalog/class-sessions/${session.id}`, {
|
||||
@@ -477,7 +477,7 @@ function ZonesPage() {
|
||||
setCapOverbookConfirm(null);
|
||||
void refetchSessions();
|
||||
} catch {
|
||||
data.setDemoNotice(cs() ? "Uložení selhalo." : "Save failed.");
|
||||
data.setDemoNotice(data.i18n.t("dashboard.saveFailed"));
|
||||
} finally {
|
||||
setCapSaving(false);
|
||||
}
|
||||
@@ -485,12 +485,12 @@ function ZonesPage() {
|
||||
|
||||
const handleDeleteSchedule = async (id: string) => {
|
||||
const bearer = data.token();
|
||||
if (!bearer || bearer.startsWith("demo.")) { data.setDemoNotice(cs() ? "V demo režimu nelze mazat." : "Cannot delete in demo mode."); return; }
|
||||
if (!bearer || bearer.startsWith("demo.")) { data.setDemoNotice(data.i18n.t("dashboard.demo.noDelete")); return; }
|
||||
try {
|
||||
await (apiClient as any).DELETE(`/v1/catalog/class-schedules/${id}`, authHeaders());
|
||||
void refetchSchedules();
|
||||
} catch {
|
||||
data.setDemoNotice(cs() ? "Smazání selhalo." : "Delete failed.");
|
||||
data.setDemoNotice(data.i18n.t("dashboard.deleteFailed"));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -558,7 +558,7 @@ function ZonesPage() {
|
||||
<Show when={resolvedLocations().length > 0} fallback={
|
||||
<div class="p-12 text-center">
|
||||
<p class="text-ink-muted font-medium">{data.i18n.t("dashboard.empty.title")}</p>
|
||||
<p class="text-sm text-ink-subtle mt-1">{cs() ? "Přidejte první zónu nebo místnost." : "Add your first location or room."}</p>
|
||||
<p class="text-sm text-ink-subtle mt-1">{data.i18n.t("dashboard.zone.addFirst")}</p>
|
||||
</div>
|
||||
}>
|
||||
<div class="divide-y divide-border/60">
|
||||
@@ -571,7 +571,7 @@ function ZonesPage() {
|
||||
<p class="text-sm text-ink-muted">{typeLabel(zone.type)} • {data.i18n.t("dashboard.zone.capacity")}: {zone.capacity}</p>
|
||||
</div>
|
||||
</div>
|
||||
<button onClick={() => void handleDeleteZone(zone.id)} class="p-2 text-ink-subtle hover:text-red-600 hover:bg-red-50 rounded-lg transition-colors" aria-label={cs() ? "Smazat" : "Delete"}>
|
||||
<button onClick={() => void handleDeleteZone(zone.id)} class="p-2 text-ink-subtle hover:text-red-600 hover:bg-red-50 rounded-lg transition-colors" aria-label={data.i18n.t("dashboard.action.delete")}>
|
||||
<Trash2Icon />
|
||||
</button>
|
||||
</div>
|
||||
@@ -585,12 +585,12 @@ function ZonesPage() {
|
||||
<div class="surface-card overflow-hidden">
|
||||
<div class="p-6 border-b border-border">
|
||||
<h3 class="text-lg font-display font-semibold text-ink">{data.i18n.t("dashboard.zone.blockedDays")}</h3>
|
||||
<p class="text-sm text-ink-muted mt-1">{cs() ? "Dny, kdy nejsou dostupné rezervace." : "Days when bookings are unavailable."}</p>
|
||||
<p class="text-sm text-ink-muted mt-1">{data.i18n.t("dashboard.blockedDay.hint")}</p>
|
||||
</div>
|
||||
<div class="p-6 border-b border-border bg-canvas-subtle/50">
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
<Input type="date" label={cs() ? "Datum" : "Date"} value={newBlockedDate()} onInput={(e) => setNewBlockedDate(e.currentTarget.value)} />
|
||||
<Input type="text" label={cs() ? "Důvod" : "Reason"} value={newBlockedReason()} onInput={(e) => setNewBlockedReason(e.currentTarget.value)} placeholder={cs() ? "např. Státní svátek" : "e.g. Public holiday"} />
|
||||
<Input type="date" label={data.i18n.t("dashboard.blockedDay.date")} value={newBlockedDate()} onInput={(e) => setNewBlockedDate(e.currentTarget.value)} />
|
||||
<Input type="text" label={cs() ? "Důvod" : "Reason"} value={newBlockedReason()} onInput={(e) => setNewBlockedReason(e.currentTarget.value)} placeholder={data.i18n.t("dashboard.blockedDay.placeholder")} />
|
||||
<Select
|
||||
label={data.i18n.t("dashboard.zone.staff")}
|
||||
value={newBlockedStaffId()}
|
||||
@@ -611,7 +611,7 @@ function ZonesPage() {
|
||||
<div class="p-12 text-center">
|
||||
<div class="w-16 h-16 rounded-full bg-canvas-subtle flex items-center justify-center mx-auto mb-4"><BanIcon /></div>
|
||||
<p class="text-ink-muted font-medium">{data.i18n.t("dashboard.empty.title")}</p>
|
||||
<p class="text-sm text-ink-muted">{cs() ? "Zatím žádné blokované dny." : "No blocked days yet."}</p>
|
||||
<p class="text-sm text-ink-muted">{data.i18n.t("dashboard.blockedDay.empty")}</p>
|
||||
</div>
|
||||
}>
|
||||
<div class="divide-y divide-border/60">
|
||||
@@ -641,7 +641,7 @@ function ZonesPage() {
|
||||
<div class="p-6 border-b border-border flex flex-col sm:flex-row sm:items-center justify-between gap-4">
|
||||
<div>
|
||||
<h3 class="text-lg font-display font-semibold text-ink">{data.i18n.t("dashboard.zone.workingHours")}</h3>
|
||||
<p class="text-sm text-ink-muted mt-1">{cs() ? "Nastavte dny a časy, kdy přijímáte rezervace." : "Set the days and times you accept bookings."}</p>
|
||||
<p class="text-sm text-ink-muted mt-1">{data.i18n.t("dashboard.availability.hint")}</p>
|
||||
</div>
|
||||
<div class="w-full sm:w-56 shrink-0">
|
||||
<Select
|
||||
@@ -673,7 +673,7 @@ function ZonesPage() {
|
||||
onChange={(e) => setField({ isOpen: e.currentTarget.checked, open: e.currentTarget.checked ? (day.open || "09:00") : day.open, close: e.currentTarget.checked ? (day.close || "18:00") : day.close })}
|
||||
class="rounded border-border accent-[#c25e3a]"
|
||||
/>
|
||||
{cs() ? "Otevřeno" : "Open"}
|
||||
{data.i18n.t("dashboard.day.open")}
|
||||
</label>
|
||||
<Show when={isOpen()}>
|
||||
<div class="flex items-center gap-2">
|
||||
@@ -808,7 +808,7 @@ function ZonesPage() {
|
||||
</div>
|
||||
<div class="flex items-center gap-1">
|
||||
<button onClick={() => startEditSchedule(sch)} class="p-2 text-ink-subtle hover:text-accent hover:bg-accent-subtle/40 rounded-lg transition-colors" aria-label={data.i18n.t("dashboard.class.editSchedule")}><PencilIcon /></button>
|
||||
<button onClick={() => void handleDeleteSchedule(sch.id)} class="p-2 text-ink-subtle hover:text-red-600 hover:bg-red-50 rounded-lg transition-colors" aria-label={cs() ? "Smazat" : "Delete"}><Trash2Icon /></button>
|
||||
<button onClick={() => void handleDeleteSchedule(sch.id)} class="p-2 text-ink-subtle hover:text-red-600 hover:bg-red-50 rounded-lg transition-colors" aria-label={data.i18n.t("dashboard.action.delete")}><Trash2Icon /></button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -927,7 +927,7 @@ function ZonesPage() {
|
||||
<span class={`inline-flex transition-transform duration-200 ${expanded() ? "rotate-180" : ""}`}><ChevronDownIcon /></span>
|
||||
</button>
|
||||
<button onClick={() => startEditCapacity(session)} class="p-2 text-ink-subtle hover:text-accent hover:bg-accent-subtle/40 rounded-lg transition-colors" aria-label={data.i18n.t("dashboard.class.editCapacity")}><PencilIcon /></button>
|
||||
<button onClick={() => void handleDeleteSession(session.id)} class="p-2 text-ink-subtle hover:text-red-600 hover:bg-red-50 rounded-lg transition-colors" aria-label={cs() ? "Smazat" : "Delete"}><Trash2Icon /></button>
|
||||
<button onClick={() => void handleDeleteSession(session.id)} class="p-2 text-ink-subtle hover:text-red-600 hover:bg-red-50 rounded-lg transition-colors" aria-label={data.i18n.t("dashboard.action.delete")}><Trash2Icon /></button>
|
||||
</div>
|
||||
</div>
|
||||
<Show when={editingCapSessionId() === session.id}>
|
||||
@@ -1045,7 +1045,7 @@ function ZonesPage() {
|
||||
<div class="w-10 h-10 rounded-full bg-accent-subtle flex items-center justify-center shrink-0"><SparklesIcon /></div>
|
||||
<div class="flex-1">
|
||||
<h4 class="font-medium text-ink mb-1">{data.i18n.t("dashboard.locationLimitReached")}</h4>
|
||||
<p class="text-sm text-ink-muted">{cs() ? "Váš plán umožňuje pouze omezený počet lokací. Pro více lokací upgradujte." : "Your plan only allows a limited number of locations. Upgrade for more."}</p>
|
||||
<p class="text-sm text-ink-muted">{data.i18n.t("dashboard.zone.limitHint")}</p>
|
||||
<div class="flex gap-3 mt-3">
|
||||
<button onClick={() => { setShowUpgradePrompt(false); void data.openCheckout(); }} class="px-4 py-2 bg-accent text-canvas text-sm font-medium rounded-lg hover:bg-accent-hover transition-colors">{data.i18n.t("dashboard.upgrade")}</button>
|
||||
<button onClick={() => setShowUpgradePrompt(false)} class="px-4 py-2 bg-canvas-subtle text-ink-muted text-sm font-medium rounded-lg hover:bg-canvas transition-colors">{data.i18n.t("dashboard.close")}</button>
|
||||
|
||||
Reference in new issue
Block a user