Skip to main content

Command Palette

Search for a command to run...

كيف برمجت صانع جداول جامعية Client-Side يعمل بدون قاعدة بيانات؟ 📅⚡

جولة معمارية داخل أداة (Adawati Timetable Builder): خوارزمية التعارض الزمني، الـ LocalStorage، وتحويل الـ DOM إلى صورة PNG.

Updated
•3 min read•View as Markdown
كيف برمجت صانع جداول جامعية Client-Side يعمل بدون قاعدة بيانات؟ 📅⚡
A
Indie developer building Adawati.app 🚀. I create fast, privacy-first (100% client-side) web tools for students & job seekers. Building in public.

عندما نتحدث عن بناء تطبيقات الجداول (Scheduling Apps)، فإن أول ما يتبادر إلى ذهن أي مطور هو: إعداد قاعدة بيانات (PostgreSQL/MongoDB)، بناء واجهة برمجية (API) للتحقق من التعارضات الزمنية، ونظام مصادقة (Auth) لكي يتمكن المستخدم من حفظ جدوله.

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

لذلك، قررت الاستغناء عن الـ Backend تماماً وبناء الأداة لتعمل حصرياً داخل المتصفح (Client-Side). إليكم التحديات الهندسية الثلاثة التي واجهتني وكيف تغلبت عليها باستخدام تقنيات الـ Front-end.

🧠 التحدي الأول: خوارزمية اكتشاف التعارض الزمني (Conflict Detection)

إذا أضاف الطالب مادة من الساعة 09:00 إلى 10:30، وأراد إضافة مادة أخرى تبدأ في 10:00 في نفس اليوم، يجب أن يرفض النظام ذلك فوراً.

بدون سيرفر للقيام بهذه العملية، كان يجب كتابة خوارزمية (Validation Engine) تعمل محلياً قبل تحديث واجهة المستخدم. قمت بتحويل جميع الأوقات المدخلة إلى صيغة دقائق (Minutes from Midnight) لتسهيل المقارنة الرياضية. الخوارزمية بكل بساطة تمر على مصفوفة المواد المحفوظة وتتحقق من الشرط التالي: هل وقت بداية المادة الجديدة يقع قبل وقت نهاية مادة مسجلة؟ وهل وقت نهايتها يقع بعد وقت بداية نفس المادة المسجلة؟

إذا تحقق الشرط، يتم إطلاق تنبيه (Alert) فوري يمنع التداخل ويخبر المستخدم باسم المادة المتعارضة. سرعة هذه الخوارزمية في المتصفح أسرع بمراحل من إرسال طلب POST لـ API وانتظار الرد.

💾 التحدي الثاني: إدارة الحالة وحفظ البيانات (State Persistence)

بما أنه لا يوجد قاعدة بيانات، كيف نضمن ألا يفقد الطالب جدوله إذا قام بتحديث الصفحة (Refresh) بالخطأ؟

الجواب الكلاسيكي هو: localStorage API. كل مرة يضغط فيها المستخدم على زر "إضافة مادة"، يتم تحديث مصفوفة الكائنات (Array of Objects) التي تمثل الجدول، ويتم عمل JSON.stringify لها وحفظها محلياً. عند تحميل الصفحة (On Load)، تتحقق الأداة من وجود بيانات سابقة وتقوم بعمل JSON.parse لتحديث الـ DOM فوراً (Hydration).

هذا يعطي تجربة (Auto-save) لتطبيق ويب متكامل، لكن ببيانات لا تغادر القرص الصلب للمستخدم أبداً.

🖼️ التحدي الثالث: تصدير الجدول كصورة عالية الدقة (DOM to Image)

الميزة الأهم للطلاب هي تحميل الجدول كصورة (PNG) لوضعها كخلفية للهاتف (Lock Screen).

تحويل عناصر HTML/CSS (مثل Grid أو Flexbox) إلى صورة ليس بالأمر البسيط برمجياً. للقيام بذلك داخل المتصفح، تعتمد البنية على تقنيات مثل الـ Canvas API أو استخدام مكتبات متخصصة مثل html2canvas أو dom-to-image. العملية تقوم بأخذ "لقطة" (Snapshot) للشجرة الهيكلية للـ DOM الخاص بالجدول، ترسمه على عنصر <canvas> مخفي، ثم تحوله إلى رابط (Data URL). لضمان جودة الصورة (Crisp Quality)، قمت بمضاعفة دقة الـ Canvas لتكون 3x، مما يضمن ألا تظهر النصوص بشكل ضبابي (Blurry) عند فتحها على شاشات الهواتف الحديثة ذات الكثافة النقطية العالية (Retina Displays).

🚀 النتيجة: أداة مجانية وسريعة جداً

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

يمكنكم تجربة الأداة حية ومحاولة تحدي خوارزمية التعارض الزمني من هنا: 👉 Adawati Timetable Builder

سؤال لمجتمع المطورين: عند بناء أدوات مشابهة تتطلب حفظ الحالة محلياً، هل تفضلون الاعتماد على localStorage العادي، أم تفضلون استخدام IndexedDB للمشاريع الأكثر تعقيداً؟ شاركوني آراءكم في التعليقات!