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

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

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

آخر معاد.مش للشلة كلها.

Bookalto

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

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

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

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

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

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

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

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

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

كلهم ضغطوا تقريبًا في نفس الوقت.

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

إحنا في Softworks بنينا أساس Bookalto علشان رحلة العميل وشغل الاستقبال يتقابلوا على قواعد واضحة. فيه خدمة ومعاد وحجز مؤقت وتأكيد، وفيه walk-ins وانتظار وحضور وتعديل. وكل ده بيكتب بيانات فعلية في PostgreSQL، مش مجرد أزرار بتغيّر لونها.

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

01 / وعد المعاد

كل معاد وعد.

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

الأول نحط الترابيزة: إحنا بنينا إيه؟

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

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

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

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

02 / رحلة الحجز

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

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

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

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

  1. 01اختيار
  2. 02حجز مؤقت
  3. 03مراجعة
  4. 04تأكيد
تطبيق ويب على الموبايل. بيانات محلية تجريبية.
الخدمة بكل تفاصيلها.
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: كل أداة ليها شغلانة

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

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

مفيش NestJS أو Redis أو ORM أو FullCalendar مستخدمين في التنفيذ الحالي. وجود اقتراح ليهم في مستند قديم مش معناه إنهم اتثبتوا في الكود.

وإيه اللي عملناه مخصوص؟

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

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

الشغل اللي بيكمل بعد الحفظ

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

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

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

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

مصادر مخططات التدفق والمعمارية
bookalto-model-1.mermaid
flowchart LR
    A[وصل من غير معاد] --> B[تذكرة انتظار]
    B --> C[الموظف يختار وقت متاح]
    C --> D{الحجز نجح؟}
    D -->|أيوه| E[موعد مؤكد وموارد محجوزة]
    D -->|لأ| F[التذكرة تفضل انتظار]
04 / حماية الوقت

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

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

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

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

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

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

المعاد اللي مية طلب عايزينه

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

«أنا رئيس جمهورية نفسي»

إفيه من «ظرف طارق»، بحسب تجميعة برو عرب. التعليق البرمجي حوالين الإفيه من كتابتنا.

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

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

ببساطة، حماس الزرار مالوش سلطة يغيّر عدد الأوض.

التجربة كانت فعلية

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

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

ثمن الاختيار

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

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

الأوضة مش فاضية لمجرد إن الدكتور فاضي

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

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

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

ده الـatomic allocation في صورته العملية. مفيش أوضة واقفة مستنية موعد ما اتولدش، ومفيش مقدم خدمة محجوز علشان جهاز كان «تقريبًا فاضي».

والحِتة اللي بعد الجلسة؟

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

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

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

الحجز المؤقت نزل يجيب قهوة ومارجعش

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

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

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

ليه ده فارق؟

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

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

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

الحجز اتحفظ والرد تاه في السكة

دي من اللحظات اللي الكمبيوتر فيها يبقى عامل الشغل فعلًا، وإنت باصص للدائرة اللي بتلف ومش عارف تتصرف.

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

هنا بيظهر الـidempotency key. كل نية إنشاء ليها مفتاح، ومعاه محتوى الطلب. نفس المفتاح ونفس البيانات يرجعوا النتيجة الموجودة. نفس المفتاح ببيانات مختلفة يطلع تعارض.

«أنا مش هتفاجئ.. أنا اتعودت خلاص»

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

إعادة المحاولة تبقى سؤالًا عن نفس العملية، مش إنشاء جديد كل مرة. ده الفرق اللي بيخلّي retry مفيد بدل ما يبقى ماكينة نسخ حجوزات.

والواجهة تقول إيه؟

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

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

انقلني واحدة بس وسيبلي القديم

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

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

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

محاولة نقل موعد متعارضة ورسالة إن الموعد الأصلي لم يتغير

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

نفس القاعدة في التمديد. الخدمة طولت؟ ده ما يديهاش حق تاكل من تخصيص الموعد اللي بعدها. تغيير المدة بيعدّي على نفس الفحص.

نجاح قديم مالوش دعوة بخطأ جديد

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

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

إنت فاتح نسخة قديمة يا هندسة

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

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

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

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

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

الساعة اتكررت ومحدش ضغط Duplicate

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

لو خزّنا «واحدة ونص» وخلاص، السؤال يبقى واحدة ونص أنهي واحدة؟ فبنحفظ اللحظة بـUTC، ومعانا منطقة الفرع الزمنية بصيغة IANA للعرض وقواعد يوم العمل.

توليد المواعيد بيمشي على لحظات حقيقية في UTC خلال اليوم المحلي. بعد كده بيشوف هل اللحظة دي مناسبة لساعات العمل والقواعد ولا لأ. لو الوقت المحلي متكرر، الـlabel بيعرض فرق التوقيت علشان يميّزهم.

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

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

الديمو هنا Africa/Cairo والأسعار EGP. العنوان تجريبي، واختيار المكان ده مش إعلان إننا عملنا إطلاق تجاري في مصر. هو سياق عرض مفهوم للصور والشرح.

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

الانتظار مش حجز بالحب

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

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

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

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

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. اكتمل

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

الخدمة خلصت، الفلوس لسه سؤال تاني

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

علشان كده حالة الموعد مستقلة عن حالة الدفع. والنسخة الحالية بتوضح إن الدفع عند المكان. إكمال الخدمة ما بيكتبش Paid تلقائيًا.

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

مراجعة إثباتات الدفع وتقارير مدفوعات التاجر لسه خصائص لاحقة. إحنا موضحين التصميم اللي هتتبني عليه، من غير ما نلبّس خانة UNPAID بدلة بوابة دفع كاملة.

الشكل الهادي وراه شغل كتير

إحنا اخترنا واجهة هادية: خلفيات فاتحة، Ink للنص، Coral للتأكيدات المهمة، وخط Inter. مفيش ظلال في الستايل الحالي. الفواصل والمسافات شايلة تنظيم المحتوى.

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

أجندة Bookalto في مقاس الموبايل

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

مش كل حاجة تتحط في toast

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

إحنا ممكن نهزر في دراسة الحالة. شاشة موظف بيحل مشكلة عميل محتاجة لغة مباشرة. مش هنكتب له «الدنيا بايظة يا معلم» ونسيبه يكتشف باقي القصة.

Light وDark والعربي

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

العربي والـDark mode محتاجين تصميم ومراجعة واختبارات خاصة بيهم. تصوير الشاشة بفلتر غامق مش هيدخلهم ضمن الخصائص المكتملة.

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

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

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

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

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

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

BOOKALTODEMO PASS
11:30

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

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

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

01

اعثر

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

02

راجع

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

03

أكد

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

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

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

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

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

الاختبارات قالت إيه؟

«ده كان امتحان يا موهيي، ونجحت»

من «فول الصين العظيم»، بحسب تجميعة برو عرب. النتيجة الفعلية وحدودها تحت، بعيدًا عن الإفيه.

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

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

الـdatabase tests بتجهز قاعدة مؤقتة منفصلة وبتطبق نفس migrations. فإحنا بنراجع سلوك المعاملة والقيد الحقيقي، مش دالة وهمية قررت ترجع true علشان يومنا يعدّي.

المقاسات والإتاحة

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

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

اللي نقدر نفرح بيه فعلًا

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

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

طب والـcommits والحكايات الدرامية؟

النسخة اللي اتراجعنا عليها مفيهاش Git history متاح. فمش هنحكي إن commit معين أنقذ الجمعة، أو إن الفريق فضل صاحي لتلاتة الصبح يصلّح incident مفيش دليل عليه.

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

تفاصيل الربط بين الادعاء والدليل موجودة في حزمة التحرير الداخلية. النص العام بيشرح القرار ونتيجته وحدوده، علشان القارئ يفهم اللي اتبنى فعلًا.

الإفيه لطيف، والشرح لازم يكمل

في النسخة الخفيفة، الريأكشن بيعمل فاصل ويقرّب الموقف. لكنه مش بديل عن شرح transaction أو version أو buffer. لو شيلنا كل الإفيهات، المفروض تفضل دراسة الحالة مفهومة.

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

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

اللي جاي له شغل حقيقي

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

المقعد الأخير محتاج منافسة حقيقية في الاختبار. التذكير محتاج إرسال فعلًا. العربي محتاج نصوص ومقاسات واتجاهات. والـDark محتاج ألوان اتراجعت، مش اختصار من إعدادات المتصفح.

الأساس الحالي منظم علشان الشغل ده يلاقي مكانه. لكن «له مكان في المعمارية» مش معناها «اتعمل». الفرق ده هو اللي بيخلي وصف المنتج مفيد للقارئ اللي هيقرر يبني معاك.

لو عندك فكرة فيها مواعيد وناس وموارد

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

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

هاتلنا الفكرة والمواقف اللي مقلقاك. القهوة ممكن نختلف عليها؛ إنما معنى «تم تأكيد الحجز» لازم نتفق عليه من أول يوم.

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

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

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

Softworks × Binary Solutions

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

Softworks Studio