Skip to content
Softworks
Softworks
hi@softworks.studio
Instagram LinkedIn

BOOKALTO / تطبيق شراكة

هندسة الحجز والتشغيل

كل معاد.في مكانه.

Bookalto

من أول اختيار للمعاد، لآخر خطوة في يوم الشغل.

شوف رحلة الحجز
21 دقيقة قراءة

تصميم المنتج · هندسة الويب · تجربة التشغيل

2026
BOOKALTO / DAILY OPERATIONS01 — 02
أجندة Bookalto الفعلية ببيانات تجريبية
شاشة تأكيد الحجز من التطبيق الفعلي
الحجز على الموبايل. يوم الشغل على الكمبيوتر.WEB APPLICATION
شاشات تجريبية · واجهة بالإنجليزية
شراكة المنتجSoftworks × Binary Solutions
تعرف على شريكنا
العلاقة
تطبيق شراكة
دورنا
تصميم وهندسة المنتج
المنصات
ويب للعملاء والتشغيل
مرحلة المنتج
أساس متحقق منه محليًا

الوقت اللي بنوعد بيه الناس

المعاد مش مجرد مربع في تقويم.

العميل، مقدم الخدمة، الأوضة، والناس المستنية. كلهم محتاجين نفس الإجابة عن سؤال بسيط: الوقت ده متاح؟

رسم أصلي لتقويم وبطاقة موعد وقارئ QR وباركود
تصوّر للماسح · اتجاه مستقبلي

الموعد بالنسبة للعميل وعد بوقت. وبالنسبة للمكان، هو اتفاق بين جدول الشغل ومقدم الخدمة وأي أوضة أو جهاز الخدمة محتاجاه. علشان الوعد ده يبقى قابل للتنفيذ، كل أجزاء النظام لازم تتعامل مع نفس الحقيقة.

في Softworks بنينا الأساس الشغّال لـBookalto حوالين الفكرة دي. العميل يختار خدمة ومعاد من موبايله، وفريق المكان يدير نفس الحجز من شاشة يوم العمل، جنب العملاء اللي بييجوا من غير حجز وقائمة الانتظار. ورا التجربتين محرك جدولة واحد، وبيانات محفوظة فعلًا في PostgreSQL.

دراسة الحالة دي بتشرح قرارات تطوير نظام حجز مواعيد مخصص: إيه اللي بنيناه بنفسنا، إيه اللي استخدمنا فيه أدوات جاهزة، وإزاي تعاملنا مع التزامن وتعديل المواعيد والوقت المحلي من غير ما نخلي الواجهة توعد بحاجة النظام ماحفظهاش.

حدود الكلام هنا: المحتوى مبني على الكود والاختبارات المحلية اللي اتراجعت يوم 18 أكتوبر 2026. المنتج في مرحلة أساس شغّال، وباقي نطاقه لسه بيتبني. المواقف اللي هنشرحها أمثلة توضيحية على حالات بيغطيها التنفيذ أو الاختبار؛ مش قصص عملاء حقيقيين. مفيش ادعاء بنتائج تجارية أو استخدام إنتاجي أو تفاصيل commits مش موجودة.

01 / وعد المعاد

كل معاد وعد.

العميل يحجزالموارد تتأكديوم الشغل يكمل

المشكلة اللي بدأنا منها

شغل المواعيد فيه تفاصيل أكتر من اختيار يوم وساعة. عميل بيحجز من الموقع، وعميل واقف عند الاستقبال، ومقدم خدمة محتاج وقت زيادة، وموظف فاتح نسخة من الجدول بقالها شوية. كل واحد بيتصرف بناءً على معلومة ممكن تكون اتغيرت بالفعل.

لو كل شاشة قررت لوحدها إن المعاد متاح، النظام ممكن يؤكد نفس المورد لأكتر من شخص. ولو تعديل الحجز اتنفذ على خطوتين منفصلتين، ممكن الحجز القديم يضيع قبل ما الجديد ينجح. ولو انتهاء الخدمة اتربط بانتهاء الوقت، الشاشة ممكن تعتبر زيارة خلصت وهي لسه ما بدأتش.

إحنا تعاملنا مع الأسئلة دي كجزء من تصميم المنتج نفسه. شكل الأجندة مهم، لكن القيمة الحقيقية إن اللي الأجندة بتعرضه يبقى له معنى واضح، وإن كل تغيير يبقى ليه نتيجة تقدر تعتمد عليها.

مين بيستخدم النظام؟

العميل محتاج يعرف الخدمات، يلاقي وقت مناسب، يراجع تفاصيله وياخد تأكيد واضح. صاحب المكان محتاج يجهّز النشاط وينشر صفحة الحجز. فريق التشغيل محتاج يعرف مين جاي، مين وصل، مين لسه مستني، ومين بدأ أو خلص الخدمة.

بدل ما نبني واجهة منفصلة لكل موقف بقواعد مختلفة، وصلنا المسارات الأساسية ببعض. الحجز الأونلاين والـwalk-in بيستخدموا نفس قواعد الجدولة. شاشة العميل وشاشة الموظف بيقروا نفس السجلات المحفوظة.

02 / رحلة الحجز

خطوات بسيطة. وموعد نعتمد عليه.

رحلة العميل / واجهات فعلية

الخدمة بكل تفاصيلها.

مدة الخدمة وسعرها وسياسة المكان واضحين قبل اختيار المعاد.

  1. 01اختيار
  2. 02حجز مؤقت
  3. 03مراجعة
  4. 04تأكيد
تطبيق ويب على الموبايل. بيانات محلية تجريبية.
الخدمة بكل تفاصيلها.

النطاق اللي نفذناه

الجزءاللي بيحصل حاليًا
تجهيز النشاطخطوات إعداد محفوظة، فرع أول، خدمة أولى، مقدم خدمة وساعات عمل
صفحة العميلاختيار الخدمة، عرض المواعيد، حجز مؤقت، مراجعة وتأكيد
إدارة الحجوزاتعرض حجوزات العميل وإلغاء الحجز المؤهل
يوم التشغيلأجندة حسب يوم الفرع، بحث وفلاتر وحالات الزيارة
العملاء من غير حجزحجز بوقت محدد أو تذكرة انتظار وبعدين تعيين وقت
تعديل الموعدنقل أو تغيير مدة الموعد مع فحص التعارض
الخدماتإضافة خدمات وربطها بالموارد الموجودة المطلوبة
الإعداداتالتحكم في نشر صفحة الحجز وبعض إعدادات الحساب

النطاق ده بيغطي رحلة متصلة من تجهيز المكان لحد تشغيل الحجز. التقويم المتقدم، إدارة الفروع والفرق بالكامل، المقاعد المشتركة، التكرار والتذكيرات الآلية لسه خارج الجزء المكتمل.

رحلة صاحب المكان

صاحب النشاط بيدخل بياناته وبيكمل خطوات الإعداد: اسم النشاط، رابط الحجز، بيانات الفرع، العملة، المنطقة الزمنية، مواعيد العمل، الخدمة وسياستها الأساسية.

كل مرة يضغط Continue، المسودة بتتحفظ. لو رجع بعدين، بيلاقي القيم اللي كان كتبها. ولما يراجع ويعمل إنشاء، النظام بيحفظ السجلات المرتبطة في معاملة واحدة، بدل ما يسيبه بنشاط موجود من غير فرع أو خدمة ناقصة.

التسجيل العادي بيبدأ بمكان فاضي. بيانات الصور اتعملت عن قصد من خلال أداة ديمو منفصلة، علشان مانخلطش بيانات العرض ببيانات أي مستخدم جديد.

مراجعة إعداد نشاط تجريبي في Bookalto

مرحلة المراجعة قبل إنشاء مساحة العمل. النشاط والعنوان وبيانات الاتصال هنا للتجربة فقط.

رحلة العميل

العميل بيفتح رابط المكان من المتصفح. يختار خدمة، يشوف بدايات المواعيد اللي السيرفر رجّعها، ويكمل بياناته قبل التأكيد. الحجز مش محتاج تثبيت تطبيق أو إنشاء حساب Bookalto إلزامي.

بعد اختيار الوقت، النظام بيحجزه مؤقتًا. شاشة المراجعة بتوضح الخدمة والمدة والسعر والمنطقة الزمنية وسياسة التعديل، ومعاهم عدّاد الوقت الباقي للحجز المؤقت. الإعداد الحالي للحجز المؤقت خمس دقايق، وده افتراض للمرحلة الحالية قابل للمراجعة مع الاستخدام الفعلي.

العميل يقدر يختار حفظ بياناته لنفس النشاط، ويقدر يمسح البيانات المتذكرة بعدين. إدارة الحجوزات بتعرض حجزه وإمكانية إلغائه حسب السياسة. واجهة كاملة لاختيار وقت بديل عند إعادة الجدولة لسه مش موجودة، رغم وجود العملية في الـAPI.

رحلة فريق التشغيل

الموظف يشوف اليوم بتوقيت الفرع، ويفتح الحجز وينفذ الإجراء المناسب: تسجيل وصول، بدء خدمة، إنهاء خدمة، تعديل موعد أو إلغاء. العميل اللي لسه ملوش وقت مؤكد يفضل ظاهر في قائمة الانتظار.

الفصل ده بيمنع سوء تفاهم بسيط لكنه مؤثر: وجود اسم العميل في المكان مش معناه إننا ضمنّا له الساعة عشرة. التأكيد بيحصل لما النظام يقدر يحجز الموارد المطلوبة فعلًا.

03 / المحرك المشترك

واجهتين. ومرجع واحد للحقيقة.

أدوات محددة. مسؤوليات واضحة.BOOKALTO / ENGINEERING
01

التجربة

واجهات واضحة وسريعة للعميل وفريق التشغيل.

  • Next.js
  • React
  • Tailwind CSS
  • Radix UI
02

القرار

طلبات بتعريفات واضحة ومدخلات متحقّق منها وقواعد صريحة.

  • TypeScript
  • Zod
  • Node.js
03

الحفظ

معاملات مترابطة وقيود على الموارد واختبارات قابلة للتكرار.

  • PostgreSQL
  • Vitest
  • Docker

وكمان: Luxon لتوقيت الفروع · pg للوصول المباشر لقاعدة البيانات · Playwright وaxe لاختبار الواجهات.

من الشاشة، للقرار، للحفظ

اختار عنصر

حدث داخلي محفوظ مع المعاملة

02 / 04

محرك المواعيد

TypeScriptZodNode.js

الأهلية ومواعيد العمل وكل الموارد المطلوبة ونسخة السجل بيتراجعوا على السيرفر. القرار النهائي مش ملك الشاشة.

المعمارية والـTech Stack

اخترنا معمارية modular monolith: تطبيق واحد، لكن منظم لوحدات واضحة، ومعاه worker مستقل قابل للتشغيل لوحده. Next.js بيخدم الواجهات والـHTTP routes، وPostgreSQL بيحفظ البيانات وينفذ المعاملات.

الهدف من التقسيم إن قواعد التشغيل يبقى ليها مكان معروف. مكوّن React مسؤول عن التفاعل والعرض، والـroute مسؤول عن استقبال الطلب، ووحدة الجدولة مسؤولة عن قرار الموعد والتغييرات المرتبطة بيه.

الأداةدورها في النسخة الحالية
Next.js 16.4.0الصفحات وApp Router والـroute handlers
React 19.3.0التفاعل في رحلة الحجز ومساحة العمل
TypeScript 5.9عقود البيانات والفحص الصارم للأنواع
PostgreSQL 18البيانات الدائمة والمعاملات ونطاقات الوقت
pgالاتصال بقاعدة البيانات وتنفيذ SQL واضح
Zod 4تحويل القيم الواردة لصيغ متوقعة وفحصها
Luxon 3حسابات المنطقة الزمنية والتحويل بين الوقت المحلي وUTC
Tailwind CSS 4جزء من أساس تنسيق الواجهة
CSS semantic tokensتوحيد ألوان Bookalto والمسافات والسلوك البصري
Radixأساس الـdialogs والـtoasts داخل مكونات بنملكها
Inter وLucideالخط والأيقونات
Vitestاختبارات السيناريوهات على PostgreSQL حقيقي
Playwright وaxeتجربة المتصفح وفحوص الاستجابة والإتاحة الآلية
pnpm وDocker Composeتشغيل البيئة المحلية بشكل قابل للإعادة

دي الأدوات الفعلية المرتبطة بالشرح. مش كل تقنية مقترحة في مستند التصميم القديم موجودة في المشروع. مفيش تطبيق NestJS منفصل، أو ORM، أو Redis queue، أو FullCalendar مستخدم في النسخة دي.

الوحدات بتتواصل إزاي؟

الـworker الحالي بيتعامل مع أحداث داخلية وتنظيف الحجوزات المؤقتة. إرسال رسائل المواعيد والتذكيرات للعملاء لسه مش جزء شغّال من التنفيذ ده. وجود حدث محفوظ جوه النظام ما يثبتش إن رسالة وصلت للعميل.

الأحداث الداخلية وتجهيز الشغل اللي بيحصل بعد الحفظ

تغيير بيانات التشغيل وتسجيل نية الحدث الداخلي بيحصلوا في نفس معاملة قاعدة البيانات. بعدين الـworker بيقرأ الأحداث المعلقة على دفعات، ويعمل لها سجلات inbox داخلية قابلة لإعادة المعالجة من غير تكرار نفس السجل.

الفكرة بتدي نقطة بداية واضحة لأي شغل غير متزامن هنضيفه بعدين. نجاح حجز الموعد يفضل مرتبطًا بحفظه، وأي قناة إرسال مستقبلية يبقى ليها تنفيذها ونتيجتها المنفصلة.

الموجود حاليًا هو الأساس الداخلي. مركز إشعارات كامل للموظف، ورسائل تأكيد مواعيد وتذكيرات للعملاء، لسه محتاجين تنفيذ واختبار فعلي. لوحة آخر النشاط الموجودة حاليًا بتقرأ النشاط المسجل؛ مش دليل على وصول إشعار خارجي.

مصادر مخططات التدفق والمعمارية
bookalto-model-1.mermaid
flowchart TB
    U[واجهة العميل] --> R[Route handlers]
    M[واجهة التشغيل] --> R
    R --> S[وحدة الجدولة]
    R --> O[وحدة النشاط والخدمات]
    S --> D[(PostgreSQL)]
    O --> D
    D --> W[Worker مستقل]
    W --> I[معالجة أحداث داخلية]
    W --> E[تنظيف الحجوزات المؤقتة المنتهية]
04 / حماية الوقت

لما الخطط تتعارض؟

وراء المعاد / جرّب القاعدة

10:00الموعد الأصلي

شاشة متاحة. طلبين متنافسين.

القرار النهائي بيحصل داخل المعاملة، مش في الشاشة.

فحص المواردفحص الإتاحة
نموذج توضيحي حتمي للقواعد؛ مش اختبار ضغط مباشر.

المشاكل الهندسية وحلولها

1. آخر معاد متاح، وطلبات كتير عليه

الموقف التوضيحي: مجموعة عملاء شايفين نفس المعاد، وكلهم ضغطوا حجز قريب من بعض. موظف الاستقبال كمان ممكن يكون بيحاول يضيف walk-in.

قائمة المواعيد اللي في المتصفح بتعبّر عن لحظة سابقة. علشان كده بنراجع القواعد مرة تانية جوه معاملة الكتابة قبل ما نعمل الحجز المؤقت أو الموعد.

التنفيذ الحالي بيمسك قفل على سجل الفرع، وبيراجع الخدمة والموارد وساعات العمل والإغلاقات ومدة الإشعار والحجوزات الموجودة. PostgreSQL نفسه عنده exclusion constraint يمنع تداخل نطاقين نشطين لنفس المورد الحصري.

يعني فحص التطبيق وقيد قاعدة البيانات بيكملوا بعض. الأول بينظم اتخاذ القرار، والتاني بيرفض تمثيل التعارض كبيانات صحيحة حتى لو في مسار كتابة حاول يعمل كده.

الدليل: اختبار بيبعت مية محاولة حجز مؤقت على نفس الوقت، وبيتحقق من فائز واحد وبعده تأكيد واحد. اختبار تاني بيعمل مية walk-in متنافسة، وبيتحقق من فائز واحد وبعده تعارض في المسار العام.

المقابل الهندسي: قفل الفرع اختيار محافظ وبيخلي الكتابات على نفس الفرع تتنفذ بترتيب. ده بيسهّل إثبات الصحة في المرحلة دي، لكنه مش دليل على قدرة تشغيل إنتاجية معينة أو زمن استجابة مضمون.

2. الخدمة محتاجة أكتر من مورد

الموقف التوضيحي: مقدم الخدمة فاضي، لكن الأوضة اللي الجلسة محتاجاها محجوزة.

ربط الخدمة بالموارد عندنا معناه إن كل الموارد المختارة مطلوبة. لو الخدمة مرتبطة بمقدم خدمة وأوضة، الاتنين لازم يكونوا متاحين في نفس الفترة. ربط مقدمَي خدمة مش معناه اختيار أي واحد فيهم تلقائيًا؛ ده نوع قواعد مختلف لسه مش موجود.

الحجز بيحفظ كل تخصيصات الموارد في معاملة واحدة. لو تخصيص واحد فشل، كل التخصيصات اللي اتعملت في نفس العملية بترجع. مفيش مقدم خدمة يفضل محجوز لوحده لحجز ماكملش.

الحساب بيشمل كمان وقت الخدمة والـbuffer اللي بعدها. جلسة تلاتين دقيقة ومعاها ربع ساعة تجهيز بين الجلسات بتشغل المورد خمسة وأربعين دقيقة، حتى لو مدة الخدمة المعروضة للعميل تلاتين.

الدليل: اختبارات قاعدة البيانات بتراجع الرجوع الكامل عند تعارض مورد، وبتجرب إدخال تخصيص متداخل مباشرةً علشان تتأكد إن القيد نفسه شغّال.

واجهة الخدمات تقدر تختار موارد موجودة، لكن إدارة إنشاء الأوض والماكينات وجداول كل مورد بشكل كامل لسه مش رحلة مكتملة. المثال هنا بيشرح قدرة محرك الجدولة واختباره.

3. عميل ساب الحجز المؤقت ومارجعش

الموقف التوضيحي: عميل اختار موعد، ساب الصفحة مفتوحة، وبعد فترة عميل تاني حاول يحجز نفس الوقت.

الحجز المؤقت له سجل ووقت انتهاء وحالة واضحة. وهو ساري، بيحسب ضمن إشغال المورد. لما عملية حجز جديدة تمسك قفل الفرع، بتنهي الحجوزات المؤقتة اللي وقتها خلص وتوقف تخصيصاتها قبل ما تكمل قرارها.

الـworker بيعمل تنظيف كمان، لكن صحة الحجز مش متوقفة على إنه يشتغل في الثانية المناسبة. مسار الكتابة نفسه بيعالج الإشغال المنتهي اللي ممكن يعطّله.

وقت التأكيد بنراجع صلاحية الحجز المؤقت ونسخة الخدمة والأهلية من جديد. لو وقت الحجز خلص، الواجهة بتطلب اختيار وقت جديد. العدّاد وسيلة توضيح للعميل؛ القرار النهائي بيعتمد على بيانات السيرفر.

الدليل: الاختبارات بتغطي رفض تأكيد حجز انتهى، وكمان تحرير تخصيصاته خلال كتابة حجز لاحق.

4. الحجز اتحفظ، لكن الرد ماوصلش

الموقف التوضيحي: الاتصال انقطع بعد حفظ الموعد وقبل ما المتصفح يستقبل التأكيد.

لو اعتبرنا كل timeout فشلًا نهائيًا، العميل ممكن يكرر الطلب وينتج حجز تاني. علشان كده عمليات الإنشاء ليها idempotency key مرتبط بنطاق العملية ومحتواها.

لما نفس المفتاح يتبعت بنفس البيانات، النظام بيرجع النتيجة الموجودة. لو المفتاح اتستخدم مع بيانات مختلفة، بيرفض إعادة الاستخدام. كده إعادة المحاولة تبقى طريقة للوصول لنتيجة الطلب الأصلي.

ده بيأثر على الكتابة في الواجهة كمان. نتيجة مجهولة محتاجة رسالة مختلفة عن رفض مؤكد. وإظهار نجاح قبل ما الطلب يكتمل بيعمل توقع غلط مهما كان شكل الرسالة مريح.

الدليل: اختبار بيعيد نفس العملية بعد نجاحها، وبيتحقق من نفس النتيجة، وبعدين بيغيّر المحتوى ويتأكد من الرفض. ده مش وضع حجز أوفلاين؛ دي آلية للتعامل مع نتيجة اتصال غير مؤكدة.

5. نقل المعاد فشل؛ القديم لازم يفضل موجود

الموقف التوضيحي: موظف حاول ينقل حجز من اتنين لواحدة، لكن واحدة مشغولة. أو حاول يزود المدة فدخل على الحجز اللي بعده.

بنحسب النطاق الجديد ومعاه الـbuffer، ونراجع كل الموارد المطلوبة. تغيير التخصيصات وتحديث الموعد بيحصلوا في معاملة واحدة. لو التغيير فشل، الحالة الأصلية بتفضل محفوظة.

الموظف مش المفروض يعيد بناء حجز صحيح لمجرد إن تعديلًا مقترحًا ماتقبلش. علشان كده الواجهة بتعرض رسالة تعارض واضحة، وبتأكد إن الموعد الأصلي ما اتغيرش.

رسالة تعارض عند محاولة نقل موعد في Bookalto

محاولة فعلية مرفوضة في البيئة المحلية. ميعاد فرح التجريبي الأصلي فضل الساعة اتنين.

الدليل: اختبارات فعلية لنقل فاشل وتمديد فاشل مع بقاء التخصيصات القديمة. واختبار المتصفح بيشوف رسالة الخطأ وبيراجع الوقت الأصلي بعد إغلاق لوحة التعديل.

6. شاشتان مفتوحان على نسختين مختلفتين

الموقف التوضيحي: موظف سجّل وصول العميل، وموظف تاني لسه فاتح الحالة القديمة وبيحاول يعدّلها.

كل تعديل بيبعت رقم النسخة اللي المستخدم كان شايفها. السيرفر بيقارنه بالنسخة الحالية. لما تغيير ينجح، الرقم بيزيد. الطلب القديم بيترفض وبيطلب تحديث البيانات.

مساحة العمل بتتحدث كل تلاتين ثانية وهي ظاهرة، وعند الرجوع للنافذة، وفيها زر تحديث يدوي. وفي تحميل البيانات، استجابة قديمة ماينفعش تمسح نتيجة طلب أحدث منها.

التحديث الدوري بيقلل احتمال البيانات القديمة، ورقم النسخة بيتعامل مع الفجوة اللي لسه ممكن تحصل بين القراءة والتعديل. النظام الحالي مش بيستخدم تحديث تقويم فوري بالـWebSockets أو SSE.

7. الساعة المحلية ممكن تتكرر أو تختفي

الموقف التوضيحي: التوقيت الصيفي اتغير، فالساعة اتقدمت أو رجعت. وعميل فاتح الصفحة من موبايل مضبوط على منطقة زمنية مختلفة.

بنحفظ لحظة الموعد بصيغة UTC، وبنستخدم المنطقة الزمنية للفرع بصيغة IANA في تفسير يوم العمل وعرض الوقت. اختيار Africa/Cairo مثلًا بيعبّر عن قواعد المنطقة، مش مجرد رقم فرق ساعات ثابت.

توليد المواعيد بيمشي على لحظات UTC حقيقية خلال اليوم المحلي، وبعدين يطبق قواعد ساعات العمل. الوقت المحلي اللي مش موجود بسبب انتقال الساعة ما بيتخلقش في القائمة. ولو نفس الوقت المحلي ظهر مرتين، العرض بيضيف فرق التوقيت للتمييز بينهم.

بدايات المواعيد في التنفيذ الحالي ماشية على شبكة كل ربع ساعة. مدة الخدمة والـbuffer وساعات الفتح وأفق الحجز بيحددوا إيه اللي ينفع يتعرض من البدايات دي.

الدليل: الاختبارات بتغطي أوقات مفقودة وأوقات متكررة. استخدام القاهرة والجنيه المصري في الديمو اختيار للعرض، مش إعلان عن إطلاق تجاري معتمد في سوق معين.

8. الانتظار له معنى مختلف عن الحجز

الموقف التوضيحي: عميل وصل ولسه مفيش معاد متاح. الاستقبال محتاج يسجل وجوده من غير ما يوعده بساعة ما اتحجزتش.

تذكرة الانتظار بتحفظ العميل والخدمة المطلوبة، لكنها ما بتحجزش أي مورد. لما الموظف يختار وقتًا متاحًا، الترقية بتحولها لموعد وتخصص الموارد وتغيّر حالة التذكرة في نفس المعاملة.

بنراجع حالة التذكرة ونسختها وقت العملية، علشان نفس التذكرة ما تتحولش لحجزين بسبب شاشتين مفتوحين. لو الترقية فشلت، العميل يفضل في حالة مفهومة بدل ما يظهر كأنه اتحجز من غير تخصيص.

الدليل: الاختبار بيتأكد إن الانتظار ما بيستهلكش سعة، وإن الترقية بتحصل كوحدة واحدة. رحلة المتصفح كمان بتضيف عميل للقائمة وتعيّن له وقت من الواجهة.

reservation.illustration.ts
// Explanatory model — not a production source extract.
async function reserveTime(command: BookingIntent) {
  return database.transaction(async (tx) => {
    await tx.branches.lock(command.branchId);
    await tx.holds.releaseExpired(command.branchId);

    const previous = await tx.operations.find(command.key);
    if (previous) return replayMatchingIntent(previous, command);

    await assertEligible(tx, command);
    const hold = await tx.holds.create(command);
    // Every required resource must fit, including its buffer.
    await tx.allocations.reserveAll(hold);
    await tx.operations.record(command.key, command, hold);
    return hold;
  });
}

مثال توضيحي مبسّط. مش مقتطف من كود الإنتاج.

05 / يوم الشغل

الحجز مجرد البداية.

كل حالة ليها معنى

  1. 01مؤكد
  2. 02وصل
  3. 03في الخدمة
  4. اكتمل

اكتمال الخدمة مش معناه تحصيل الفلوس. حالة الدفع مستقلة.

تصميم تجربة التشغيل

حالات قليلة لكن معناها محدد

الحجز المؤكد غير تسجيل الوصول. وتسجيل الوصول غير بدء الخدمة. وإنهاء الخدمة غير تسجيل الدفع. إحنا حافظنا على الفروق دي في الواجهة وفي البيانات.

مسار الخدمة الأساسي هو تأكيد، وصول، بدء، ثم إنهاء. الإلغاء بيحرر الموارد مع الاحتفاظ بسجل الموعد. عملية عدم الحضور في السيرفر ليها مهلة قبل السماح بيها. الوقت لوحده مش بيكمل الزيارة تلقائيًا.

حالة الدفع مستقلة. الخدمة ممكن تكون خلصت ولسه ما اتدفعتش. الرحلة الحالية بتوضح الدفع عند المكان؛ رفع إثبات دفع ومراجعته وتقارير المدفوعات لسه نطاق لاحق.

شاشة اليوم بتعرض اللي الموظف محتاجه

الأجندة بتجمع حجوزات اليوم، وقائمة الانتظار، والموارد، وآخر النشاط. أرقام الملخص محسوبة من البيانات الموجودة فعلًا: المجدول، المنتظر، اللي في الخدمة واللي خلص.

في نسخة العرض، الأرقام دي جاية من بيانات تجريبية. ما استخدمناش إيرادات أو نسب نمو أو تقييمات عملاء متخيلة علشان نوحي إن المنتج عنده نتائج تجارية مثبتة.

على الكمبيوتر، فيه شريط جانبي مدمج ومساحة واضحة للأجندة. على الموبايل، التنقل بينتقل لشريط سفلي وصفوف المواعيد بتتظبط على العرض الأصغر. الإجراءات الأساسية متاحة بزر ظاهر، مش معتمدة على حركة خاصة يعرفها مستخدم خبير بس.

أجندة Bookalto على موبايل بعرض 390 بكسل

نفس بيانات التشغيل في عرض الموبايل. الصورة لسيناريو عرض محلي، مش أداء نشاط حقيقي.

هوية بصرية هادية وواضحة

استخدمنا خلفيات بيضا وقريبة من الأبيض، نص Ink، ولمسات Coral محدودة. خط Inter، فواصل خفيفة، ومسافات بتخدم القراءة. الستايل الحالي بيشيل الظلال الاختيارية اللي كانت في نسخة التوكنز الأولى.

زرار Coral عليه نص غامق، وحالات النجاح أو الانتظار أو الخطأ معاها وصف مكتوب. اللون بيساعد على القراءة، لكنه مش الوسيلة الوحيدة لفهم الحالة.

مكونات الـdialog والـtoast مبنية على Radix، لكن شكلها وطريقة استخدامها جزء من مكونات Bookalto المملوكة للمشروع. ده بيسمح بإعادة الاستخدام مع الحفاظ على شخصية الواجهة وسلوكها.

المنتج الحالي Light فقط. مفيش Dark theme متصمم ومختبر. ونسخة دراسة الحالة المصرية مش معناها إن واجهة التطبيق اتترجمت؛ التطبيق لسه بالإنجليزي، وفحص RTL الحالي محدود باختبار اتجاه التخطيط.

إيه اللي خصصناه لـBookalto

الجزءشغل Softworks المخصصالأساس الجاهز
محرك المواعيدالأهلية، الحجز المؤقت، تخصيص الموارد وتعديل الموعدمعاملات PostgreSQL ونطاقات الوقت
تجهيز النشاطحفظ المسودة وإنشاء السجلات المرتبطة مع بعضNext.js وSQL
تشغيل اليومالأجندة، فلاتر الحالة، الانتظار والحضورReact وعقود بيانات مشتركة
حجز العميلخطوات الخدمة والوقت والمراجعة والتأكيدمكونات الفورم وLuxon
التصميمInk وCoral، الشاشات المسطحة والتخطيط المتجاوبTailwind وInter وLucide
التفاعلاتالـsheets والأخطاء والرسائل الموحدةRadix primitives
الاختباراتحالات التنافس والرجوع وإعادة المحاولة والرحلة الكاملةVitest وPlaywright وaxe
المعالجة الخلفيةأحداث داخلية وتنظيف الحجوزات المؤقتةPostgreSQL وNode.js worker

التخصيص هنا مش مجرد تغيير ألوان مكونات جاهزة. الجزء الأكبر في تعريف معنى كل عملية، وربطها بالموارد والوقت والحالة، وبعدها عرض النتيجة للمستخدم بطريقة مفهومة.

06 / المسح والوصول

طريق أقصر لمكتب الاستقبال.

اتجاه المنتج / تصور تفاعلي

من الكود، لـ«وصلت».

تصور لربط بطاقة الموعد بمكتب الاستقبال. QR أو باركود يفتح الحجز الصحيح؛ الموظف يراجع ويؤكد الوصول.

الماسح تصور للمرحلة الجاية. مش ميزة منفذة في التطبيق الموثّق، والمثال مش بيستخدم الكاميرا أو بيانات حقيقية.

BOOKALTODEMO PASS
11:30

استشارة / 60 دقيقة

رمز توضيحي غير قابل للمسح

جاهز للمثال التوضيحي.

01

اعثر

الكود يحدد موعدًا؛ مش هوية دخول مفتوحة.

02

راجع

الموظف يراجع الخدمة والمعاد والحالة.

03

أكد

تأكيد الوصول يفضل إجراء صريح، مستقل عن الدفع.

07 / الأدلة والخطوة الجاية

بناء محسوب. وخطوة لقدّام.

من تحقق التطبيق المحلي / 18 أكتوبر 2026
100طلب متنافس في اختبار الموعد01فائز بالموعد الحصري16لقطة من التطبيق الفعلي

نتائج اختبارات محلية موثّقة. مش أرقام استخدام أو مبيعات أو قياس أداء في الإنتاج.

اختبرنا إيه والنتيجة بتثبت إيه

المراجعة المحلية الأخيرة عدّت lint، وفحص TypeScript، وخمستاشر اختبار على PostgreSQL حقيقي، وبناء الإنتاج، وسيناريو المتصفح الكامل على Edge.

اختبارات قاعدة البيانات بتجهز قاعدة مؤقتة منفصلة، وبتطبق نفس ملفات الـSQL migrations اللي التطبيق بيستخدمها. ده بيسمح باختبار القيود والمعاملات نفسها، مش مجرد محاكاة النتيجة في الذاكرة.

رحلة المتصفح بتغطي تجهيز النشاط، حفظ المسودة بعد إعادة تحميل الصفحة، حجز العميل، البيانات المتذكرة، الانتظار والحضور، رفض نقل متعارض، إضافة خدمة والتحكم في نشر الصفحة. فحص axe ما رجعش مخالفات في حالتي مساحة العمل الممتلئة وصفحة الحجز اللي اتفحصوا.

اتراجع عدم وجود overflow أفقي عند عروض 320 و360 و375 و390 و430 و768 و1440 بكسل، ومعاهم فحص landscape واتجاه RTL. دي أدلة محددة على الحالات اللي اتنفذت. مراجعة قارئ شاشة بواسطة إنسان، ونسخة عربية كاملة، وتجربة مستخدمين حقيقيين لسه شغل منفصل.

الدليلاللي نقدر نستنتجهاللي ما نقدرش نستنتجه
فائز واحد في اختبار المية طلبقاعدة عدم تداخل المورد اشتغلت في السيناريو المختبررقم تحمل إنتاجي أو latency مضمون
رجوع كامل عند فشل موردالعملية ما سابتش حجز موارد جزئيدعم مقاعد المجموعات
نفس الطلب يرجع نفس النتيجةإعادة المحاولة تقدر توصل للحجز المحفوظدعم تأكيد أوفلاين
النقل الفاشل يحافظ على الأصلتعديل غير مقبول ما يضيّعش الموعدتقويم drag-and-drop مكتمل
رحلة المتصفح كاملةالواجهات بتستخدم بيانات محفوظة فعلًا محليًاإطلاق إنتاجي أو نتائج تجارية
نجاح البناء وفحص الأنواعالنسخة بتتبني وبتعدّي الفحوص الحاليةاكتمال كل متطلبات المنتج

النتيجة اللي نقدر نقولها بوضوح

Bookalto عنده أساس شغّال بيربط حجز العميل بيوم تشغيل المكان، ومعاه اختبارات بتراجع مواقف صعبة فعلًا. مش مجرد شاشة مواعيد ببيانات ثابتة، ولا إعلان إن كل المنتج خلص.

القيمة الهندسية في إن القرارات الأساسية ليها مكان واضح: مين يقرر إن الوقت متاح، إمتى الحجز المؤقت ينتهي، إزاي نعيد المحاولة، وإيه اللي يحصل لما التعديل يترفض. التوسعات الجاية تقدر تبني على القرارات دي بدل ما تعمل قواعد مختلفة لكل شاشة.

اللي اتعلمناه من التنفيذ

صياغة الرسالة جزء من صحة التجربة. رفض التعديل محتاج يوضح حالة الموعد الأصلي. نتيجة الاتصال غير المعروفة محتاجة تبقى واضحة. العميل المنتظر محتاج حالة مختلفة عن العميل اللي عنده وقت مؤكد.

ونفس الدقة مطلوبة في النموذج: وقت الخدمة غير وقت إشغال المورد، والحجز المؤقت غير الموعد، والحضور غير الدفع، وحفظ حدث داخلي غير إرسال رسالة. كل فرق فيهم بيمنع التباس ممكن يكبر مع زيادة خصائص المنتج.

اختيار قفل الفرع كمان له حدود معروفة. هو مناسب لإثبات قواعد النسخة الحالية، لكن أي قرار لتوسيع الأداء لازم يبقى مبني على قياس حمل واقعي. تحسين السرعة لازم يحافظ على نفس نتيجة الحجز الصحيحة.

الخطوة الجاية في المنتج

الخطوات اللي لسه مطلوبة تشمل إدارة أوسع للفروع والفريق، جداول مقدمي الخدمة والإجازات، التقويم، واجهة إعادة جدولة العميل، السعة المشتركة، التذكيرات، مدفوعات التاجر والتقييمات وتعريب التطبيق.

كل خطوة ليها دليل قبول مناسب. المقاعد محتاجة اختبار تنافس على آخر مقعد. التقويم محتاج كل حركة تعديل تستخدم نفس المعاملة الصحيحة. التذكيرات محتاجة إرسال فعلي ومتابعة فشل وإعادة محاولة. التعريب محتاج نصوص ومراجعة تخطيط واتجاه، مش قلب الصفحة بس.

المراحل دي لسه مش مواعيد تسليم معلنة ولا خصائص مكتملة. هي حدود واضحة للانتقال من الأساس الحالي لمنتج أوسع.

أسئلة متوقعة

هل Bookalto مجرد تقويم؟

الأساس الحالي بيجمع حجز العميل وإدارة التشغيل وقواعد جدولة محفوظة في قاعدة البيانات. واجهة الموظف أجندة، والتقويم المتقدم بعروض الأسبوع والموارد لسه قدّام.

هل الحجز الأونلاين والعميل اللي جاي المكان بيستخدموا نفس القواعد؟

أيوه. الاتنين بيراجعوا الأهلية وتخصيص الموارد من خلال نفس وحدة الجدولة. الاختبارات بتغطي التنافس ورفض الوقت المشغول.

هل نقدر نحجز أوضة ومقدم خدمة مع بعض؟

المحرك واختباراته بيدعموا موارد حصرية متعددة مطلوبة مع بعض. إدارة الموارد من الواجهة بشكل كامل واختيار بديل من مجموعة مقدمي خدمة لسه مش متنفذين بالكامل.

الصور حقيقية ولا تصميم؟

الصور من التطبيق المحلي وهو شغّال. البيانات اتعملت للتجربة من خلال مساراته وواجهاته الفعلية، وكل الأسماء والأسعار والأرقام تجريبية.

هل فيه دفع أونلاين؟

الرحلة الحالية بتوضح الدفع عند المكان. إكمال الخدمة ما يغيّرش حالة الدفع تلقائيًا. بوابة دفع ومراجعة إثباتات التاجر لسه مش جزء شغّال من النسخة المعروضة.

هل فيه نسخة عربية وDark mode؟

دراسة الحالة ليها نسخة إنجليزي ونسختين مصري. التطبيق الحالي نفسه Light وبالإنجليزي. تعريب المنتج وتصميم Dark theme محتاجين شغل واختبار مستقلين.

نبدأ من أصعب جزء في فكرتك

في Bookalto، الشغل الهندسي بيربط قرار قاعدة البيانات بالرسالة اللي الموظف بيقراها وبالاختبار اللي يثبت النتيجة. ده اللي بيخلي تفاصيل زي نقل موعد أو إعادة محاولة جزءًا مفهومًا من المنتج.

لو بتبني منتج للحجز أو تشغيل الخدمات، احكيلنا في Softworks عن رحلة المستخدم والقواعد والمواقف اللي بتعطّل الشغل. نقدر نحولهم معاك لنطاق تنفيذ واضح وخطة اختبار تثبت اللي اتبنى.

كل منتج له مواعيده الصعبة.

خلّينا نبني الجزء المهم.

نتكلم عن مشروعك
Bookalto

Softworks × Binary Solutions

دراسة تانية: Falcon Group CIT
Softworks

Softworks Studio