feat: delete actions for warehouse/reservations/coupons/customers + Koja listing toggle
CI/CD / CI · API (dotnet build + test) (push) Successful in 1m10s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 52s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m5s
CI/CD / CI · Admin Web (tsc) (push) Successful in 35s
CI/CD / CI · Website (tsc) (push) Successful in 45s
CI/CD / CI · Koja (tsc) (push) Successful in 55s
CI/CD / Deploy · all services (push) Successful in 3m29s
CI/CD / CI · API (dotnet build + test) (push) Successful in 1m10s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 52s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m5s
CI/CD / CI · Admin Web (tsc) (push) Successful in 35s
CI/CD / CI · Website (tsc) (push) Successful in 45s
CI/CD / CI · Koja (tsc) (push) Successful in 55s
CI/CD / Deploy · all services (push) Successful in 3m29s
Delete (every manageable entity that only had "add" now has delete):
- Ingredients (warehouse): new DELETE /inventory/ingredients/{id} (soft-delete via
the global DeletedAt filter — no FK trouble with recipes/movements) + NoOp stub +
trash button in the materials cards.
- Reservations: new DELETE /reservations/{id} (soft-delete) + per-card delete button.
- Coupons & Customers: backend DELETE already existed; wired delete buttons in the UI.
- Shared ConfirmDialog component used by all delete flows (RTL-aware).
- Audit result: tables/branches/taxes/kitchen-stations/expenses/menu/terminals already
had delete; HR has no "add" so no delete needed; shifts intentionally excluded
(financial open/close records, not add-style entities).
Koja visibility:
- New Cafe.ShowOnKoja flag, default TRUE (DB default true so existing cafés stay
listed). Discover query now filters IsVerified && !Deleted && ShowOnKoja.
- public-profile GET/PUT expose showOnKoja; dashboard public-profile panel has an
on-by-default toggle that persists immediately. Platform IsVerified gate unchanged.
- EF migration AddCafeShowOnKoja (defaultValue: true).
Also: added the missing errors.generic i18n key (fa/en/ar) so useApiError's fallback
resolves instead of rendering the literal "errors.generic". 81 API tests pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,7 @@ import {
|
||||
updateCafePublicProfile,
|
||||
uploadGalleryPhoto,
|
||||
type CafeProfileEdit,
|
||||
type UpdateCafeProfilePayload,
|
||||
} from "@/lib/api/cafe-public-profile";
|
||||
import type { WorkingHours } from "@/lib/api/public-discover";
|
||||
import { resolveMediaUrl } from "@/lib/api/client";
|
||||
@@ -42,6 +43,7 @@ export function CafePublicProfilePanel({ cafeId }: Props) {
|
||||
const [instagram, setInstagram] = useState<string>("");
|
||||
const [website, setWebsite] = useState<string>("");
|
||||
const [hours, setHours] = useState<WorkingHours>(emptyHours());
|
||||
const [showOnKoja, setShowOnKoja] = useState(true);
|
||||
const [initialized, setInitialized] = useState(false);
|
||||
|
||||
// Populate local state once we get server data
|
||||
@@ -50,17 +52,20 @@ export function CafePublicProfilePanel({ cafeId }: Props) {
|
||||
setInstagram(profile.instagramHandle ?? "");
|
||||
setWebsite(profile.websiteUrl ?? "");
|
||||
setHours(profile.workingHours ?? emptyHours());
|
||||
setShowOnKoja(profile.showOnKoja ?? true);
|
||||
setInitialized(true);
|
||||
}
|
||||
|
||||
// ── Save info/social/hours ────────────────────────────────────────────────
|
||||
const saveMutation = useMutation({
|
||||
mutationFn: () =>
|
||||
mutationFn: (override?: Partial<UpdateCafeProfilePayload>) =>
|
||||
updateCafePublicProfile(cafeId, {
|
||||
description,
|
||||
instagramHandle: instagram || null,
|
||||
websiteUrl: website || null,
|
||||
workingHours: hours,
|
||||
showOnKoja,
|
||||
...override,
|
||||
}),
|
||||
onSuccess: (data) => {
|
||||
qc.setQueryData(["cafe-public-profile", cafeId], data);
|
||||
@@ -157,6 +162,23 @@ export function CafePublicProfilePanel({ cafeId }: Props) {
|
||||
{tab === "info" && (
|
||||
<Card className="rounded-xl border border-border/80">
|
||||
<CardContent className="space-y-4 p-4">
|
||||
<label className="flex cursor-pointer items-center justify-between gap-3 rounded-lg border border-[#0F6E56]/25 bg-[#E1F5EE]/40 px-3 py-2.5">
|
||||
<span className="min-w-0">
|
||||
<span className="block text-sm font-medium">{t("showOnKoja")}</span>
|
||||
<span className="block text-xs text-muted-foreground">{t("showOnKojaHint")}</span>
|
||||
</span>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={showOnKoja}
|
||||
onChange={(e) => {
|
||||
const v = e.target.checked;
|
||||
setShowOnKoja(v);
|
||||
// Persist immediately (pass the new value to avoid stale state).
|
||||
saveMutation.mutate({ showOnKoja: v });
|
||||
}}
|
||||
className="h-5 w-5 shrink-0 cursor-pointer accent-[#0F6E56]"
|
||||
/>
|
||||
</label>
|
||||
<div className="space-y-1">
|
||||
<Label>{t("description")}</Label>
|
||||
<textarea
|
||||
@@ -167,7 +189,7 @@ export function CafePublicProfilePanel({ cafeId }: Props) {
|
||||
className="w-full resize-none rounded-lg border border-border/80 bg-white px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#0F6E56]"
|
||||
/>
|
||||
</div>
|
||||
<SaveButton saving={saveMutation.isPending} saved={saved} onSave={() => saveMutation.mutate()} t={t} />
|
||||
<SaveButton saving={saveMutation.isPending} saved={saved} onSave={() => saveMutation.mutate(undefined)} t={t} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
@@ -276,7 +298,7 @@ export function CafePublicProfilePanel({ cafeId }: Props) {
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<SaveButton saving={saveMutation.isPending} saved={saved} onSave={() => saveMutation.mutate()} t={t} />
|
||||
<SaveButton saving={saveMutation.isPending} saved={saved} onSave={() => saveMutation.mutate(undefined)} t={t} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
@@ -307,7 +329,7 @@ export function CafePublicProfilePanel({ cafeId }: Props) {
|
||||
dir="ltr"
|
||||
/>
|
||||
</div>
|
||||
<SaveButton saving={saveMutation.isPending} saved={saved} onSave={() => saveMutation.mutate()} t={t} />
|
||||
<SaveButton saving={saveMutation.isPending} saved={saved} onSave={() => saveMutation.mutate(undefined)} t={t} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user