From 7519f474f38f7cd4f17d97504a75dfd796620ce1 Mon Sep 17 00:00:00 2001 From: "soroush.asadi" Date: Mon, 1 Jun 2026 23:23:39 +0330 Subject: [PATCH] fix(demo): allow Manager to seed demo data + surface seed errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dashboard demo-data banner is shown to Owner and Manager, but the /demo/seed endpoint required strictly Owner, so a Manager clicking it got a silent 403 (the banner had no error handler) — appearing as 'nothing happens, no tables or items'. The endpoint now allows Owner or Manager, and the banner shows the error on failure. Co-Authored-By: Claude Opus 4.8 --- src/Meezi.API/Controllers/DemoSeedController.cs | 4 +++- web/dashboard/src/components/demo/demo-data-banner.tsx | 10 +++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Meezi.API/Controllers/DemoSeedController.cs b/src/Meezi.API/Controllers/DemoSeedController.cs index 5d16ef2..0e306ef 100644 --- a/src/Meezi.API/Controllers/DemoSeedController.cs +++ b/src/Meezi.API/Controllers/DemoSeedController.cs @@ -25,7 +25,9 @@ public class DemoSeedController : CafeApiControllerBase CancellationToken ct) { if (EnsureCafeAccess(cafeId, tenant) is { } denied) return denied; - if (EnsureOwner(tenant) is { } ownerDenied) return ownerDenied; + // Demo data is a setup helper; Owner or Manager may run it (matches the + // dashboard banner, which is shown to both roles). + if (EnsureManager(tenant) is { } managerDenied) return managerDenied; var result = await _demoSeed.SeedAsync(cafeId, ct); return Ok(new ApiResponse(true, result)); diff --git a/web/dashboard/src/components/demo/demo-data-banner.tsx b/web/dashboard/src/components/demo/demo-data-banner.tsx index 212dad6..a5f05b5 100644 --- a/web/dashboard/src/components/demo/demo-data-banner.tsx +++ b/web/dashboard/src/components/demo/demo-data-banner.tsx @@ -3,7 +3,8 @@ import { useState } from "react"; import { useMutation, useQueryClient } from "@tanstack/react-query"; import { Sparkles, Loader2 } from "lucide-react"; -import { apiPost } from "@/lib/api/client"; +import { ApiClientError, apiPost } from "@/lib/api/client"; +import { notify } from "@/lib/notify"; import { useAuthStore } from "@/lib/stores/auth.store"; import { Button } from "@/components/ui/button"; import { cn } from "@/lib/utils"; @@ -39,6 +40,13 @@ export function DemoDataBanner({ invalidateKeys, className }: Props) { qc.invalidateQueries({ queryKey: key }); } }, + onError: (err) => { + notify.error( + err instanceof ApiClientError + ? err.message + : "افزودن داده‌های نمونه ناموفق بود. دوباره تلاش کنید." + ); + }, }); if (!cafeId || (role !== "Owner" && role !== "Manager")) return null;