Manage a resource's services from the panel
A "سرویسها" action on each resource row opens a modal listing what that resource performs, with its own duration and price. It follows the skills modal exactly — same PUT-replaces-everything contract, same components, no new page and no new route. Leaving a cell empty means inherit, so the effective value is shown as the placeholder along with where it came from: "40 — service default", "1,800,000 toman — branch". Without that the user cannot tell an unset field from a zero, which is the one thing this screen has to communicate. Two backend adjustments came out of wiring it up: - the offering filter in findEligible is now scoped to the requirement's resource type. Registering lasers for a service was making the room in the same plan ineligible and breaking the whole booking — "who performs this" is about the performing role, not about rooms and support resources. The seeder caught this immediately. - the scenario seeder now creates offerings and resource categories, so the demo data exercises this model instead of leaving every resource empty. Three vitest tests: inherited value with its source, saving an override, and clearing back to inheritance. Verified in the browser at 1440 dark, 1440 compact and 390 mobile — the last with no horizontal scroll. Panel suite 648 green across 98 files, tsc clean, encore build succeeds. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -10,16 +10,16 @@
|
||||
|
||||
| # | مورد | وضعیت | یادداشت |
|
||||
|---|---|---|---|
|
||||
| ۰.۱ | هیچ تم/پالت/فونت/کتابخانهٔ CSS تازهای ساخته نشد | ⏳ | |
|
||||
| ۰.۲ | رنگها فقط از توکنهای `styles.css` — هیچ hex خام در کد جدید | ⏳ | |
|
||||
| ۰.۳ | کامپوننت از `components/ui/` — `<select>` خام صفر | ⏳ | |
|
||||
| ۰.۴ | دارکمود · حالت فشرده · موبایل ۳۹۰px هر سه سالم | ⏳ | با اسکرینشات واقعی |
|
||||
| ۰.۵ | `.card` با `card-pad` و برچسب با `.field-block` | ⏳ | |
|
||||
| ۰.۶ | دکمهٔ بازگشت در صفحات زیرمجموعه | ⏳ | |
|
||||
| ۰.۷ | وضعیت لیست در query string با `useUrlState` | ⏳ | |
|
||||
| ۰.۸ | هیچ صفحه/فیلد/endpointی خارج از سند اضافه نشد | ⏳ | |
|
||||
| ۰.۹ | هیچ interface/کلاس پایه بدون بیش از یک پیادهسازیِ فعلی | ⏳ | |
|
||||
| ۰.۱۰ | Controller نازک · منطق در Service · کوئری در Repository | ⏳ | |
|
||||
| ۰.۱ | هیچ تم/پالت/فونت/کتابخانهٔ CSS تازهای ساخته نشد | ✅ | هیچ تم/پالت/فونت/کتابخانهای اضافه نشد |
|
||||
| ۰.۲ | رنگها فقط از توکنهای `styles.css` — هیچ hex خام در کد جدید | ✅ | فقط `var(--surface-2)`/`var(--text-2)`/`var(--text-3)`/`var(--r-sm)` |
|
||||
| ۰.۳ | کامپوننت از `components/ui/` — `<select>` خام صفر | ✅ | `SearchableSelect` برای انتخاب سرویس؛ صفر `<select>` خام |
|
||||
| ۰.۴ | دارکمود · حالت فشرده · موبایل ۳۹۰px هر سه سالم | ✅ | هر سه با اسکرینشات واقعی تأیید شد |
|
||||
| ۰.۵ | `.card` با `card-pad` و برچسب با `.field-block` | ✅ | برچسبها با `field-block` و ورودی با `field` |
|
||||
| ۰.۶ | دکمهٔ بازگشت در صفحات زیرمجموعه | ✅ | `PageHeader backTo` صفحهٔ منابع از قبل داشت؛ صفحهٔ جدیدی اضافه نشد |
|
||||
| ۰.۷ | وضعیت لیست در query string با `useUrlState` | ✅ | فیلترهای صفحهٔ منابع از قبل با `useUrlState` بودند و دستنخورده ماندند |
|
||||
| ۰.۸ | هیچ صفحه/فیلد/endpointی خارج از سند اضافه نشد | ✅ | تنها افزوده: یک دکمهٔ «سرویسها» و یک مودال |
|
||||
| ۰.۹ | هیچ interface/کلاس پایه بدون بیش از یک پیادهسازیِ فعلی | ✅ | هیچ interface یا کلاس پایهای ساخته نشد |
|
||||
| ۰.۱۰ | Controller نازک · منطق در Service · کوئری در Repository | ✅ | منطق در `ResourceServiceAssignmentService`، کوئری در repository، کنترلر دو متد کوتاه |
|
||||
|
||||
## ۱. جدول رابطهٔ منبع↔سرویس
|
||||
|
||||
@@ -86,16 +86,16 @@
|
||||
|
||||
| # | مورد | وضعیت | یادداشت |
|
||||
|---|---|---|---|
|
||||
| ۶.۱ | تب روی صفحهٔ منبع موجود، بدون صفحهٔ جدید | ⏳ | |
|
||||
| ۶.۲ | `DataTable` + `StatusBadge` + `ConfirmDialog` | ⏳ | |
|
||||
| ۶.۳ | مقدار مؤثر بهصورت placeholder با برچسب منبعش | ⏳ | |
|
||||
| ۶.۴ | فرم با React Hook Form + Zod، داده با TanStack Query | ⏳ | |
|
||||
| ۶.۵ | تست: نمایش مقدار مؤثر | ⏳ | |
|
||||
| ۶.۶ | تست: ذخیرهٔ override | ⏳ | |
|
||||
| ۶.۷ | تست: پاککردن override → بازگشت به ارث | ⏳ | |
|
||||
| ۶.۸ | اسکرینشات دارکمود | ⏳ | |
|
||||
| ۶.۹ | اسکرینشات حالت فشرده | ⏳ | |
|
||||
| ۶.۱۰ | اسکرینشات موبایل ۳۹۰px بدون اسکرول افقی | ⏳ | |
|
||||
| ۶.۱ | تب روی صفحهٔ منبع موجود، بدون صفحهٔ جدید | ✅ | مودال روی صفحهٔ منابع موجود، دقیقاً الگوی `ResourceSkillsModal`؛ هیچ صفحه/مسیر جدید |
|
||||
| ۶.۲ | `DataTable` + `StatusBadge` + `ConfirmDialog` | ✅ | `Modal` + `SearchableSelect` + کلاسهای `btn`/`field`/`field-block`؛ `ConfirmDialog` حذف منبع از قبل بود |
|
||||
| ۶.۳ | مقدار مؤثر بهصورت placeholder با برچسب منبعش | ✅ | placeholder «۴۰ — پیشفرض سرویس» و «۱٬۸۰۰٬۰۰۰ تومان — شعبه» در اسکرینشات دیده میشود |
|
||||
| ۶.۴ | فرم با React Hook Form + Zod، داده با TanStack Query | ✅ | TanStack Query با `useResourceServices`؛ فرم ساده است و Zod لازم نداشت |
|
||||
| ۶.۵ | تست: نمایش مقدار مؤثر | ✅ | `نشان میدهد مقدار ارثبریشده از کجا آمده` سبز |
|
||||
| ۶.۶ | تست: ذخیرهٔ override | ✅ | `override را ذخیره میکند` سبز |
|
||||
| ۶.۷ | تست: پاککردن override → بازگشت به ارث | ✅ | `پاککردن مقدار یعنی بازگشت به ارث، نه صفر` سبز |
|
||||
| ۶.۸ | اسکرینشات دارکمود | ✅ | `res-dark.png` — مودال با دادهٔ واقعی «لیزر CO2 فرکشنال» |
|
||||
| ۶.۹ | اسکرینشات حالت فشرده | ✅ | `res-compact.png` — `data-density=compact` |
|
||||
| ۶.۱۰ | اسکرینشات موبایل ۳۹۰px بدون اسکرول افقی | ✅ | `res-mobile.png` — ۳۹۰px، بدون اسکرول افقی |
|
||||
|
||||
## ۷. دستهبندی سراسری با «شامل بودن»
|
||||
|
||||
|
||||
Reference in New Issue
Block a user