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
@@ -1,8 +1,7 @@
import { Link } from "react-router-dom";
import { MapPin, Phone, User, Plus } from "lucide-react";
import type { Material, Supplier, Topic } from "../../lib/types";
import type { Material, Supplier } from "../../lib/types";
import { normalize } from "../../lib/normalize";
import { topicByName } from "../../lib/topics";
export function topicCategories(topic: string, materials: Material[], suppliers: Supplier[]): string[] {
const out = new Set<string>();
materials
@@ -20,12 +19,6 @@ export function suppliersOfCategory(topic: string, cat: string, suppliers: Suppl
);
}
export function topicFromParam(param: string | null, topics: Topic[]): string | null {
if (!param) return null;
const t = topicByName(param, topics);
return t ? t.name : null;
}
// کارت تأمین‌کننده
export function SupplierCard({
s,