fix(suppliers): enforce Category → Supplier hierarchy, remove rogue-category bug

Domain model (v2.6): suppliers.category_id NOT NULL (1:N from the 8 fixed
categories), materials are global and link to suppliers via
supplier_materials. This fixes three regressions of the old inverted tree:

- remove the intermediate 'یک متریال را انتخاب کنید' screen: a category
  card now routes straight to that category's supplier list
  (/suppliers/category/:category); TopicPage is deleted and legacy
  /topics/:topic[/:category] URLs redirect to the new hierarchy
- kill the accidental-category bug: api.materials.create silently POSTed
  /material-categories for any unknown 'category' (a material name!), which
  is how the rogue «پریز» category (+ junk material) appeared. Unknown
  categories now fail loudly instead of creating catalog rows (DB cleaned:
  exactly the 8 canonical categories remain)
- fix inverted wording: supplier list is «تأمین‌کننده‌های این دسته» with
  category-first breadcrumbs; the legacy material multi-select on the
  add-supplier form is gone (a supplier gets the page's category)
- supplier details screen logic untouched — only its breadcrumb link
  targets were updated to the new routes
This commit is contained in:
ali_mohaghegh
2026-09-03 15:00:50 +03:30
parent b4ed18af71
commit f9ec68815e
7 changed files with 44 additions and 231 deletions
+12 -10
View File
@@ -10,7 +10,6 @@ const WizardPage = lazy(() => import("./pages/Wizard/WizardPage").then((m) => ({
const SuppliersPage = lazy(() =>
import("./pages/Suppliers/SuppliersPage").then((m) => ({ default: m.SuppliersPage })),
);
const TopicPage = lazy(() => import("./pages/Suppliers/TopicPage").then((m) => ({ default: m.TopicPage })));
const CategoryPage = lazy(() =>
import("./pages/Suppliers/CategoryPage").then((m) => ({ default: m.CategoryPage })),
);
@@ -93,22 +92,25 @@ export default function App() {
</RequireAuth>
}
/>
{/* سلسله‌مراتب دامنه: دسته → تأمین‌کننده. کارت دسته مستقیم به
فهرست تأمین‌کننده‌های همان دسته می‌رود (بدون صفحه‌ی واسط متریال). */}
<Route
path="/topics/:topic"
element={
<RequireAuth>
<TopicPage />
</RequireAuth>
}
/>
<Route
path="/topics/:topic/:category"
path="/suppliers/category/:category"
element={
<RequireAuth>
<CategoryPage />
</RequireAuth>
}
/>
{/* مسیرهای قدیمی (درخت معکوس topic → material → supplier) — ریدایرکت */}
<Route
path="/topics/:topic/:category"
element={<Navigate to="/suppliers/category/:category" replace />}
/>
<Route
path="/topics/:topic"
element={<Navigate to="/suppliers" replace />}
/>
<Route
path="/suppliers/:id"
element={