قوائم الأسعار — مراجعة UX/UI وحل بطء الإدخال

تشخيص الوضع الحالي · جذر مشكلة البطء · إعادة تصميم عملية للإضافة/التعديل/الاستيراد/التصدير

1 الخلاصة التنفيذية

1820تحليل تُرسم كلها في الـ DOM على تبويب «الكل»
×3InputNumber ثقيل لكل صف = آلاف المكوّنات
0virtual scroll — لا يوجد (السبب الرئيسي للبطء)
~15الصفوف اللي المفروض تتعرض فعليًا في الشاشة
جذر البطء: جدول التسعير داخل النافذة مش مُحَزَّن (no virtual scroll) — بيرسم كل الـ 1820 صف دفعة واحدة، وكل صف مُضاف فيه 3 مكوّنات PrimeNG InputNumber (ثقيلة). النتيجة: آلاف المكوّنات في الذاكرة، وكل ضغطة زر على أي خانة بتشغّل Change Detection على الجدول كله → تأخير محسوس.
مشكلة UX موازية: «إضافة قائمة أسعار» بتحشر بيانات القائمة + تسعير 1820 تحليل في نافذة واحدة بارتفاع 350px — مساحة تعديل ضيقة جدًا لمهمة ضخمة.

2 الوضع الحالي (بالأدلة من الكود)

صفحة /lab/price-lists — قائمة بالقوائم + نافذة إضافة/تعديل واحدة فيها كل حاجة:

الجزءالوصفالحالة
قائمة القوائمجدول بالقوائم (نشط/افتراضي) + بحث + نسخ قائمةجيد
بيانات القائمةالاسم، الكود، العملة، افتراضي، نشط، تواريخ السريانجيد
«ابدأ من قائمة»نسخ أسعار من قائمة موجودة (وضع الإضافة فقط)ميزة حلوة
تبويبات التسعير«المُضاف» / «الكل» + بحث + عدّادات«الكل» يرسم 1820 صف
أدوات جماعيةتضمين الكل/المرئي/استبعاد الكل + نسبة %± موجودة
الجريدلكل صف: تضمين + سعر افتراضي + سعر القائمة + خصم% + TAT (3 InputNumber)بطيء — بلا تحزين
تمبلت / تصدير / استيرادExcel/CSV — تنزيل قالب، تصدير، استيراد (مطابقة بالكود)موجود لكن مدفون
الكود المسبّب: <p-table [value]="filteredPricingRows()" [scrollable]="true" scrollHeight="350px">scrollable فقط، مفيش [virtualScroll]="true". وكل صف: <p-inputNumber> ×3 مع (onInput) على كل ضغطة.

3 جذر مشكلة البطء + الحل التقني

#السببالحلالأثر
1الجدول بلا virtual scroll → 1820 صف في الـ DOM[virtualScroll]="true" [virtualScrollItemSize]="46"يرسم ~15 صف بس
23 PrimeNG InputNumber لكل صف (مكوّن ثقيل جدًا)إدخال <input type="number"> خفيف للجريدأخف بمرّات
3مفيش dataKey/trackBy → إعادة رسم كاملة عند البحثdataKey="investigation_id" + trackByيحافظ على الصفوف
4Change Detection افتراضي رغم استخدام signalsChangeDetectionStrategy.OnPushCD محدود
5(onInput) يحدّث على كل حرفتثبيت القيمة عند blur أو ngModelChange مُخفّضأقل عمليات
أسرع مكسب فوري: تفعيل virtual scroll + استبدال InputNumber بإدخال HTML خفيف = اختفاء البطء تقريبًا، حتى على تبويب «الكل» بـ 1820 صف.

4 نقد UX/UI — لماذا التجربة مرهِقة؟

5 التصميم المقترح — افصل المهمتين

المبدأ: «إنشاء القائمة» سريع · «التسعير» مساحة كاملة احترافية

① نافذة سريعة: بيانات القائمة فقط

┌─ New Price List ──────────────┐ Name (EN) * [______________] Name (AR) [______________] Code [_____] Currency [SAR ▾] ☑ Active ☐ Default Valid from [__] to [__] Start from: [Existing list ▾] [ Create & price → ] [Cancel] └───────────────────────────────┘

يحفظ القائمة فورًا ويفتح محرّر الأسعار.

② محرّر أسعار — صفحة كاملة (مش مودال)

Price List: «Madina Lab» · SAR [Export][Import] [ Added 312 | All 1820 ] Search[___] Section[All ▾] Bulk: +%[__] −%[__] [Set=default] [Round] [×All] ───────────────────────────────────────────── ✓ Test (code) Def List Disc% Final ───────────────────────────────────────────── ☑ CBC (CBC) 30.00 [35.0] [0 ] 35.00 ☑ Glucose (GLU) 12.00 [15.0] [10] 13.50 ☑ HbA1c (A1C) 40.00 [45.0] [0 ] 45.00 ☐ Vitamin D ... — — — — ▼ virtual scroll — only ~15 rows in DOM ▼ ───────────────────────────────────────────── 312 priced · total catalog 1820 [ Save ]

عرض كامل · تمرير محزّن · تنقّل بالكيبورد.

ملامح المحرّر

6 الاستيراد/التصدير — اجعله الطريق الأساسي للجملة

تسعير 1820 تحليل يدويًا غير عملي. Excel هو الأسرع. نرفعه لمكانة أساسية:

Export → فايل Excel فيه: code | name | default | list | disc% | tat ↓ (تعدّل في Excel — مكانك الطبيعي) Importمعاينة قبل التطبيق: • 280 سطر هيتغيّر • 12 كود مش متطابق (تتجاهل) • 3 أسعار فاضية [ Apply 280 changes ] [Cancel]

7 مراجعة كل ميزة — يفضل / يتعدّل

الميزةالقرار
قائمة القوائم + نشط/افتراضيتفضل
بيانات القائمة في مودالتتبسّط — مودال سريع للبيانات فقط
تسعير 1820 في نفس الموداليتنقل — لصفحة محرّر كاملة
تبويبات المُضاف/الكلتفضل + virtual scroll
«ابدأ من قائمة»تفضل — قيّمة جدًا
أدوات جماعية + %±تتقوّى (اضبط=الافتراضي، تقريب، فلترة قسم)
استيراد/تصدير/قالبيبرز + معاينة قبل التطبيق
نسخ قائمةتفضل

8 خطة التنفيذ بالمراحل

المرحلة 1 — حل البطء فورًا (نص يوم)
تفعيل virtual scroll + استبدال InputNumber بإدخال خفيف + dataKey + OnPush. من غير تغيير شكل — البطء يختفي.
المرحلة 2 — فصل التسعير لصفحة محرّر (يوم–يومين)
مودال البيانات السريع + صفحة /lab/price-lists/:id/prices بالجريد المحزّن + عمود السعر النهائي + فلترة القسم.
المرحلة 3 — تنقّل كيبورد + أدوات جماعية أقوى (نص يوم)
Enter/Tab/أسهم + اضبط=الافتراضي + تقريب + تضمين المرئي بعد فلترة القسم.
المرحلة 4 — استيراد بمعاينة (نص يوم)
Preview قبل التطبيق + تقرير المطابقة + إبراز القالب/التصدير.

9 قرارات محتاج رأيك فيها

قرار 1 — الأولوية
أبدأ بـ حل البطء فقط (المرحلة 1) وأسلّمه بسرعة، ولا أعمل إعادة التصميم الكاملة دفعة واحدة؟ (توصيتي: المرحلة 1 فورًا ثم الباقي)
قرار 2 — صفحة محرّر منفصلة
توافق نفصل التسعير في صفحة كاملة بدل المودال؟ (توصيتي: نعم — أكبر تحسين تجربة)
قرار 3 — عمود السعر النهائي
نضيف عمود «السعر النهائي» المحسوب (سعر − خصم) للوضوح؟ (توصيتي: نعم)
قرار 4 — فلترة بالقسم
نضيف فلتر القسم/الفئة عشان تسعّر قسم كامل دفعة؟ (توصيتي: نعم)

10 الخلاصة

البطء سببه غياب virtual scroll + 3 InputNumber ثقيلة لكل صف — يتحل في نص يوم (المرحلة 1) من غير ما نغيّر الشكل. وبعدها نفصل التسعير في صفحة محرّر كاملة بتنقّل كيبورد وفلترة قسم وعمود سعر نهائي، ونرفع الاستيراد/التصدير بمعاينة كطريق أساسي للجملة. النتيجة: تسعير سريع، واضح، واحترافي.
دراسة UX/UI — Moon ERP / LIS · قوائم الأسعار · يونيو 2026 · للمراجعة قبل التنفيذ