تقرير تقييم صفحة Requests في نظام المعمل
الصفحة محل التقييم: https://moonui.elbaset.com/app/lab/requests.
التحليل مبني على كود LisRequestsComponent والخدمات التي يعتمد عليها، مع التركيز على الملاءمة التشغيلية،
السرعة، الاعتماد على الباك إند، ونقاط الخطر عند زيادة حجم البيانات.
الخلاصة
الصفحة مناسبة كواجهة يومية لإدارة طلبات المعمل: عرض الطلبات، البحث، فلترة التاريخ والحالة والأولوية، فصل B2B، طباعة التقرير، طباعة الفاتورة، طباعة الباركود، إرسال رابط واتساب، إلغاء الطلب، إعادة سحب deferred/rejected، والحذف النهائي بصلاحية خاصة.
لكن من ناحية الأداء، التصميم الحالي يعتمد على تحميل كل الطلبات من الباك إند عبر listAll() ثم عمل كل الفلاتر في المتصفح.
ده يعطي تجربة بحث سريعة بعد التحميل، لكنه يجعل أول تحميل ثقيل جدًا مع التاريخ الكبير. الصفحة ليست server-side paginated فعليًا؛
الـ paginator الموجود في PrimeNG يقسم المعروض فقط بعد وصول كل البيانات للمتصفح.
مسار تحميل البيانات
ngOnInit().requestService.listAll() يجلب كل صفحات /lis/requests.allData محليًا.نقاط القوة
- واجهة dense ومناسبة لشاشة تشغيل يومية، وليست صفحة شكلية.
- فصل واضح بين الطلبات الداخلية وطلبات المعامل الخارجية B2B.
- الفلاتر العملية موجودة: تاريخ، حالة، أولوية، بحث، external lab.
- البحث يعمل عبر كل التواريخ لأن الصفحة تحمل كل البيانات، وهذا مفيد عند البحث برقم طلب قديم.
- زر الطباعة يستخدم
LisPrintReportServiceالموحد، لذلك التقرير من requests يطابق validation. - حالة الطلب مشتقة من counts راجعة من الباك إند:
leaf_count,released_results_count,active_results_count. هذا أفضل من الاعتماد علىrequest.statusالمتأخر. - تفاصيل التحاليل لا تحمل result statuses إلا عند توسيع الصف، وده lazy loading جيد.
- الحذف النهائي محمي بكتابة رقم الطلب وكلمة المرور وصلاحية
lis.requests.force_delete. - إعادة السحب deferred/rejected تقرأ من pivot
sample-investigationsبدل الاعتماد على sample status فقط، وهذا أدق في partial reject/defer.
مشاكل الأداء والاعتماد على الباك إند
| النقطة | الوضع الحالي | الأثر | التعديل المقترح |
|---|---|---|---|
| تحميل كل الطلبات | listAll() يبدأ بـ per_page=200 ثم يجلب كل الصفحات عبر forkJoin. |
عالي مع الزمن. لو عندك آلاف الطلبات، أول تحميل بطيء وحجم الذاكرة يزيد. | استخدام endpoint بفلاتر server-side: date_from, date_to, status, priority, search, external_lab_id. |
| الـ pagination | PrimeNG paginator يقسم filteredData فقط بعد تحميل كل الداتا. |
المستخدم يرى pagination، لكن السيرفر لا يستفيد منه. | تفعيل lazy table: onLazyLoad يطلب الصفحة المطلوبة من الباك إند. |
| الفلاتر | كلها client-side داخل getter filteredData. |
سريعة بعد التحميل، لكن تعاد كثيرًا مع change detection، خصوصًا مع قوائم كبيرة. | تحويلها إلى computed/cached أو server-side. البحث يحتاج debounce. |
| B2B count | b2bCount يعيد فلترة allData لحساب badge. |
مقبول في القوائم الصغيرة، مكلف مع آلاف الصفوف. | إرجاع counters من الباك إند مع نفس الفلاتر. |
| فتح تفاصيل row | كل row expand يعمل listAllByFilter({ lab_request_id }) لجلب كل نتائج الطلب. |
جيد كـ lazy load، لكن لو المستخدم فتح صفوف كثيرة سيزيد عدد الطلبات. | إما cache موجود بالفعل جزئيًا، أو endpoint للـ row detail يرجع investigations + latest result status مرة واحدة. |
| طباعة الباركود | printLabels() يجلب samples بـ per_page=50. |
خطر محدود لو طلب فيه samples أكثر من 50، لن تطبع كلها. | استخدام per_page=-1 إن كان مدعومًا أو listAllByFilter للعينات. |
| تحميل company للطباعة | loadLabInfoForPrint() يحمل company/logo، لكن الطباعة الآن delegate إلى LisPrintReportService. |
طلب زائد غالبًا legacy، وقد يحمل صورة logo بلا استخدام مباشر. | مراجعة وإزالة المسار القديم لو غير مستخدم. |
| بعد cancel/recollect/delete | الصفحة تعمل loadAll() كامل بعد العملية. |
مكلف مع الداتا الكبيرة. | تحديث الصف محليًا أو إعادة تحميل الصفحة الحالية فقط من السيرفر. |
هل الصفحة مناسبة؟
| الاستخدام | التقييم | السبب |
|---|---|---|
| موظف استقبال يتابع طلبات اليوم | مناسبة | الجدول compact، والفلاتر اليومية واضحة، وأزرار الطباعة والباركود قريبة. |
| البحث عن طلب قديم برقم الطلب أو MRN | مناسبة لكن مكلفة | البحث يعمل عبر كل الداتا، لكنه يتطلب تحميل كل التاريخ أولًا. |
| معمل عنده آلاف أو عشرات آلاف الطلبات | غير مناسبة بالشكل الحالي | تحميل كل الصفحات والفلاتر المحلية سيبطئ الصفحة ويضغط الذاكرة والشبكة. |
| مراقبة B2B يومية | مناسبة جزئيًا | الفصل موجود، لكن الحساب والفلترة محليان ويحتاجان دعم server-side. |
| إدارة تشغيل كاملة للطلب | جيدة | تدعم print/report/receipt/barcodes/WhatsApp/cancel/recollect/delete. |
ملاحظات UX
- الصفحة عملية ومضغوطة، وهذا مناسب للـ back-office وليس landing page.
- أزرار التقرير والفاتورة والباركود inline قرار جيد لأنها أكثر actions استخدامًا.
- الـ overflow menu مناسب للأفعال الأقل استخدامًا مثل WhatsApp، portal link، cancel، delete.
- فصل B2B في tab مستقل يحسن التركيز، لكن عبارة "All requests" فعليًا تستبعد B2B. يفضل تسميتها "Internal requests" أو "Patient requests".
- في mobile، الجدول يعتمد على
min-width: 60rem، وهذا يعني scroll أفقي. مقبول كأداة تشغيل، لكنه ليس تجربة mobile ممتازة. - الصفحة لا تعرض summary counters قوية مثل today's internal، B2B today، cancelled، completed. إضافة counters من الباك إند ستفيد جدًا.
توصيات الباك إند
| الأولوية | التوصية | الفائدة |
|---|---|---|
| P1 | تطوير GET /lis/requests ليدعم server-side filters كاملة ويرجع صفحة واحدة فقط. |
تحسين أول تحميل وتقليل network/memory. |
| P1 | إرجاع counters مع الاستجابة: internal today، B2B today، pending، in_progress، completed، cancelled. | إلغاء حسابات client-side الثقيلة مثل b2bCount. |
| P2 | Endpoint للـ row detail: /lis/requests/{id}/summary يرجع investigations مع latest result status. |
تقليل طلبات التوسيع وتحسين دقة الحالة. |
| P2 | Endpoint لطباعة باركود الطلب يرجع labels جاهزة: /lis/requests/{id}/barcode-labels. |
نقل منطق panel/member/section من الواجهة إلى الباك إند وتفادي نقص per_page=50. |
| P3 | إضافة saved views أو presets للموظف: اليوم، أمس، آخر أسبوع، B2B فقط، STAT. | تحسين سرعة التشغيل اليومية. |
توصيات الفرونت إند
- تحويل
filteredDataمن getter إلىcomputedأو إلى state يأتي من السيرفر. - إضافة debounce للبحث قبل تغيير query أو قبل طلب السيرفر.
- تفعيل
p-tablelazy mode بدل تحميل كل البيانات. - إزالة
loadLabInfoForPrint()من هذه الصفحة لو لم يعد مستخدمًا بعد تفويض الطباعة إلىLisPrintReportService. - بعد cancel/recollect/delete، تحديث الصف المتأثر أو إعادة تحميل الصفحة الحالية فقط.
- تعديل تسمية tab من "كل الطلبات" إلى "طلبات المرضى" أو "الطلبات الداخلية" لأن B2B مستبعدة منه.
خطة تحسين مقترحة
| المرحلة | التعديل | المخاطرة | العائد |
|---|---|---|---|
| سريع | إزالة الطلبات الزائدة، debounce للبحث، إصلاح per_page=50 في الباركود. |
منخفضة | تحسن مباشر بدون تغيير كبير. |
| متوسط | تحويل الفلاتر والـ pagination إلى server-side مع الحفاظ على نفس UI. | متوسطة | فرق كبير في السرعة والاستقرار. |
| كبير | إضافة requests dashboard/counters endpoint وrow summary endpoint. | متوسطة إلى عالية | صفحة قوية تتحمل حجم تشغيل كبير. |
الحكم النهائي
الصفحة من ناحية UX والتشغيل جيدة، ومبنية على فهم حقيقي لدورة طلبات المعمل. لكنها من ناحية الأداء تعتمد أكثر من اللازم على الفرونت إند: تحميل كل الطلبات، فلترة محلية، وحسابات محلية. الاعتماد الصحيح للمرحلة القادمة يجب أن يكون على الباك إند في الفلاتر والـ pagination والـ counters.
لو حجم الداتا اليومي صغير، الصفحة هتفضل شغالة بشكل مقبول. لو النظام سيستخدم فعليًا في معمل عليه ضغط وطلبات تاريخية كثيرة،
فالأولوية الأولى هي تحويل /lis/requests إلى query server-side حقيقي بدل listAll().