دليلك الشامل لإنشاء تطبيق حجز مجاني بالكامل باستخدام Cloudflare Pages و Google Sheets (مع ChatGPT)

هل تدير عملك الخاص وتواجه صعوبة في تتبع حجوزات العملاء؟

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

إذا كانت إجابتك نعم، فهذا المقال لك.

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

في هذا الدليل، سنستخدم الذكاء الاصطناعي ممثلاً في ChatGPT لكتابة الكود اللازم للواجهة الأمامية (Frontend) والخلفية (Backend)، ثم نربطهما معًا ونستضيف المشروع بالكامل على الإنترنت مجانًا.

🧠 البنية الأساسية للمشروع: كيف يعمل التطبيق؟

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

المكونالتقنية المستخدمةدوره في التطبيق
واجهة المستخدمHTML, CSS, JavaScriptنموذج حجز بسيط يقوم المستخدم بتعبئته (الاسم، الإيميل، …).
الخلفية البرمجيةGoogle Apps Scriptسكربت بسيط يستقبل البيانات من النموذج ويضيفها كصف جديد في جدول بيانات.
قاعدة البياناتGoogle Sheetsجدول بيانات يعمل كقاعدة بيانات لتخزين جميع الحجوزات الواردة.
الاستضافةCloudflare Pagesخدمة مجانية لنشر موقعنا (نموذج الحجز) على الإنترنت ليكون متاحًا للجميع.

آلية العمل باختصار:

  1. يقوم المستخدم بملء نموذج الحجز على موقعك المستضاف على Cloudflare Pages.
  2. عند الضغط على زر “إرسال”، يقوم كود JavaScript بإرسال البيانات باستخدام fetch() إلى رابط (Endpoint) خاص بـ Google Apps Script.
  3. يستقبل السكربت البيانات، يتأكد منها، ثم يضيفها إلى جدول Google Sheets.
  4. يعيد السكربت رسالة نجاح إلى واجهة المستخدم لتأكيد إتمام الحجز.

🧰 الأدوات التي ستحتاجها (كلها مجانية!)

  1. حساب ChatGPT: لتوليد الأكواد.
  2. حساب Google: للوصول إلى Google Sheets و Google Apps Script.
  3. حساب GitHub: لتخزين ملفات المشروع.
  4. حساب Cloudflare: لاستضافة الموقع.

🚀 خطوة بخطوة: لنبني تطبيق الحجز معًا

سنقوم الآن ببناء كل جزء من التطبيق باستخدام أوامر (Prompts) بسيطة ومباشرة لـ ChatGPT.

الخطوة 1: إنشاء واجهة المستخدم (نموذج الحجز)

اذهب إلى ChatGPT وأعطه الأمر التالي لتوليد كود الواجهة الأمامية.

برومبت #1: توليد نموذج HTML

“اكتب لي كود HTML و CSS لنموذج حجز بسيط وجميل. يجب أن يحتوي النموذج على حقول للاسم (text)، البريد الإلكتروني (email)، التاريخ (date)، والوقت (time). أضف زر إرسال في النهاية.”

النتيجة المتوقعة من ChatGPT:

سيقوم ChatGPT بتوليد كود مشابه لهذا. قم بإنشاء ملف جديد على جهازك باسم index.html والصق الكود التالي فيه.

<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>نموذج حجز موعد</title>
    <style>
        body {
            font-family: 'Tajawal', sans-serif;
            background-color: #f4f7f6;
            margin: 0;
            padding: 20px;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
        }
        .container {
            background-color: #ffffff;
            padding: 30px 40px;
            border-radius: 12px;
            box-shadow: 0 8px 16px rgba(0,0,0,0.1);
            width: 100%;
            max-width: 500px;
        }
        h1 {
            color: #333;
            text-align: center;
            margin-bottom: 25px;
        }
        .form-group {
            margin-bottom: 20px;
        }
        label {
            display: block;
            margin-bottom: 8px;
            color: #555;
            font-weight: bold;
        }
        input[type="text"],
        input[type="email"],
        input[type="date"],
        input[type="time"] {
            width: 100%;
            padding: 12px;
            border: 1px solid #ccc;
            border-radius: 8px;
            box-sizing: border-box;
            transition: border-color 0.3s;
        }
        input:focus {
            border-color: #007bff;
            outline: none;
        }
        button {
            width: 100%;
            padding: 15px;
            background-color: #007bff;
            color: white;
            border: none;
            border-radius: 8px;
            font-size: 16px;
            cursor: pointer;
            transition: background-color 0.3s;
        }
        button:hover {
            background-color: #0056b3;
        }
    </style>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Tajawal:wght@400;700&display=swap" rel="stylesheet">
</head>
<body>
    <div class="container">
        <h1>حجز موعد جديد</h1>
        <form id="bookingForm">
            <div class="form-group">
                <label for="name">الاسم الكامل:</label>
                <input type="text" id="name" name="name" required>
            </div>
            <div class="form-group">
                <label for="email">البريد الإلكتروني:</label>
                <input type="email" id="email" name="email" required>
            </div>
            <div class="form-group">
                <label for="date">تاريخ الحجز:</label>
                <input type="date" id="date" name="date" required>
            </div>
            <div class="form-group">
                <label for="time">وقت الحجز:</label>
                <input type="time" id="time" name="time" required>
            </div>
            <button type="submit">تأكيد الحجز</button>
        </form>
    </div>
</body>
</html>

الخطوة 2: إنشاء الخلفية البرمجية (Google Apps Script)

هذا هو الجزء الذي سيستقبل البيانات ويخزنها.

  1. اذهب إلى Google Sheets وأنشئ جدول بيانات جديد. سمّه “بيانات الحجوزات”.
  2. من القائمة العلوية، اذهب إلى Extensions > Apps Script.
  3. سيفتح محرر الأكواد. امسح الكود الموجود وأعطِ ChatGPT الأمر التالي.

برومبت #2: إنشاء سكربت Google Apps Script

“اكتب لي كود Google Apps Script كاملاً. يجب أن يقوم السكربت بالوظائف التالية:

  1. يستقبل طلب POST يحتوي على بيانات (name, email, date, time).
  2. يفتح جدول بيانات Google Sheet معين.
  3. يضيف البيانات المستلمة كصف جديد في الجدول.
  4. يضيف عمودًا لتاريخ تسجيل الحجز (Timestamp).
  5. يرجع استجابة من نوع JSON تحتوي على { "status": "success" } عند النجاح، أو { "status": "error", "message": "رسالة الخطأ" } عند الفشل.”

النتيجة المتوقعة من ChatGPT:

الصق الكود التالي في محرر Apps Script.

// استبدل 'YOUR_SHEET_ID' بمعرف جدول البيانات الخاص بك
const SHEET_ID = 'YOUR_SHEET_ID'; 
const sheet = SpreadsheetApp.openById(SHEET_ID).getActiveSheet();

function doPost(e) {
  try {
    // استلام البيانات من الطلب
    const data = JSON.parse(e.postData.contents);

    // التحقق من وجود البيانات الأساسية
    if (!data.name || !data.email || !data.date || !data.time) {
      throw new Error("البيانات المرسلة غير مكتملة.");
    }
    
    // إضافة صف جديد بالبيانات + تاريخ التسجيل
    const timestamp = new Date();
    sheet.appendRow([timestamp, data.name, data.email, data.date, data.time]);

    // إرجاع رسالة نجاح
    return ContentService
      .createTextOutput(JSON.stringify({ "status": "success", "message": "تم تسجيل الحجز بنجاح!" }))
      .setMimeType(ContentService.MimeType.JSON);

  } catch (error) {
    // إرجاع رسالة خطأ في حال حدوث مشكلة
    return ContentService
      .createTextOutput(JSON.stringify({ "status": "error", "message": error.message }))
      .setMimeType(ContentService.MimeType.JSON);
  }
}

تعديل مهم:

  • احصل على SHEET_ID: من رابط جدول البيانات الخاص بك. الرابط يبدو هكذا: https://docs.google.com/spreadsheets/d/THIS_IS_THE_ID/edit. انسخ الجزء الموجود في المنتصف والصقه مكان YOUR_SHEET_ID.

نشر السكربت كتطبيق ويب:

  1. اضغط على زر “Deploy” الأزرق في الأعلى، ثم اختر “New deployment”.
  2. اضغط على أيقونة الترس بجانب “Select type” واختر “Web app”.
  3. في حقل “Who has access”، غيّره إلى “Anyone”. هذا يسمح لأي شخص بإرسال البيانات إلى السكربت.
  4. اضغط “Deploy”.
  5. سيمنحك Google رابطًا لتطبيق الويب (Web app URL). انسخ هذا الرابط واحتفظ به، سنحتاجه في الخطوة التالية.

الخطوة 3: ربط الواجهة الأمامية بالخلفية

الآن سنعود إلى ملف index.html ونضيف كود JavaScript ليرسل البيانات التي يكتبها المستخدم إلى رابط السكربت الذي حصلنا عليه.

برومبت #3: تحديث كود HTML مع JavaScript

“حدّث لي كود HTML السابق. أضف قسم <script> في الأسفل. يجب أن يقوم هذا السكربت بالآتي:

  1. يمنع الإرسال الافتراضي للنموذج.
  2. يجمع البيانات من حقول النموذج عند الضغط على زر الإرسال.
  3. يرسل البيانات باستخدام fetch() إلى رابط خارجي عبر طلب POST.
  4. يعرض رسالة نجاح أو فشل للمستخدم في صفحة الويب نفسها.”

النتيجة المحدثة لملف index.html:

استبدل محتوى ملف index.html بالكامل بالكود التالي.

<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>نموذج حجز موعد</title>
    <style>
        body {
            font-family: 'Tajawal', sans-serif;
            background-color: #f4f7f6;
            margin: 0;
            padding: 20px;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
        }
        .container {
            background-color: #ffffff;
            padding: 30px 40px;
            border-radius: 12px;
            box-shadow: 0 8px 16px rgba(0,0,0,0.1);
            width: 100%;
            max-width: 500px;
        }
        h1 {
            color: #333;
            text-align: center;
            margin-bottom: 25px;
        }
        .form-group {
            margin-bottom: 20px;
        }
        label {
            display: block;
            margin-bottom: 8px;
            color: #555;
            font-weight: bold;
        }
        input[type="text"],
        input[type="email"],
        input[type="date"],
        input[type="time"] {
            width: 100%;
            padding: 12px;
            border: 1px solid #ccc;
            border-radius: 8px;
            box-sizing: border-box;
            transition: border-color 0.3s;
        }
        input:focus {
            border-color: #007bff;
            outline: none;
        }
        button {
            width: 100%;
            padding: 15px;
            background-color: #007bff;
            color: white;
            border: none;
            border-radius: 8px;
            font-size: 16px;
            cursor: pointer;
            transition: background-color 0.3s;
        }
        button:hover {
            background-color: #0056b3;
        }
        button:disabled {
            background-color: #aaa;
            cursor: not-allowed;
        }
        #message {
            margin-top: 20px;
            padding: 15px;
            border-radius: 8px;
            text-align: center;
            font-weight: bold;
            display: none; /* مخفي بشكل افتراضي */
        }
        #message.success {
            background-color: #d4edda;
            color: #155724;
            display: block;
        }
        #message.error {
            background-color: #f8d7da;
            color: #721c24;
            display: block;
        }
    </style>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Tajawal:wght@400;700&display=swap" rel="stylesheet">
</head>
<body>
    <div class="container">
        <h1>حجز موعد جديد</h1>
        <form id="bookingForm">
            <div class="form-group">
                <label for="name">الاسم الكامل:</label>
                <input type="text" id="name" name="name" required>
            </div>
            <div class="form-group">
                <label for="email">البريد الإلكتروني:</label>
                <input type="email" id="email" name="email" required>
            </div>
            <div class="form-group">
                <label for="date">تاريخ الحجز:</label>
                <input type="date" id="date" name="date" required>
            </div>
            <div class="form-group">
                <label for="time">وقت الحجز:</label>
                <input type="time" id="time" name="time" required>
            </div>
            <button type="submit" id="submitButton">تأكيد الحجز</button>
        </form>
        <div id="message"></div>
    </div>

    <script>
        const form = document.getElementById('bookingForm');
        const messageDiv = document.getElementById('message');
        const submitButton = document.getElementById('submitButton');
        
        // استبدل هذا الرابط بالرابط الذي حصلت عليه من Google Apps Script
        const scriptURL = 'YOUR_WEB_APP_URL';

        form.addEventListener('submit', e => {
            e.preventDefault();
            submitButton.disabled = true;
            submitButton.textContent = 'جاري الإرسال...';

            const formData = {
                name: form.name.value,
                email: form.email.value,
                date: form.date.value,
                time: form.time.value
            };

            fetch(scriptURL, { 
                method: 'POST', 
                body: JSON.stringify(formData),
                headers: {
                    'Content-Type': 'text/plain;charset=utf-8', // Apps Script يتعامل مع text/plain أفضل
                },
                mode: 'cors' // ضروري للطلبات بين النطاقات
            })
            .then(response => response.json())
            .then(data => {
                messageDiv.className = ''; // إزالة الكلاسات السابقة
                if (data.status === 'success') {
                    messageDiv.textContent = data.message;
                    messageDiv.classList.add('success');
                    form.reset();
                } else {
                    throw new Error(data.message || 'حدث خطأ غير متوقع.');
                }
            })
            .catch(error => {
                messageDiv.className = '';
                messageDiv.textContent = 'فشل الإرسال: ' + error.message;
                messageDiv.classList.add('error');
            })
            .finally(() => {
                submitButton.disabled = false;
                submitButton.textContent = 'تأكيد الحجز';
            });
        });
    </script>
</body>
</html>

تعديل مهم جدًا:

  • ابحث عن const scriptURL = 'YOUR_WEB_APP_URL'; واستبدل YOUR_WEB_APP_URL بالرابط الذي نسخته من Google Apps Script في الخطوة السابقة.

الخطوة 4: نشر الموقع على Cloudflare Pages

الآن بعد أن أصبح كل شيء جاهزًا محليًا، حان وقت نشره على الإنترنت.

برومبت #4: شرح النشر على Cloudflare Pages

“اشرح لي بخطوات بسيطة ومرقمة كيفية نشر موقع ثابت من مستودع GitHub على Cloudflare Pages. الموقع يحتوي فقط على ملف index.html.”

خطوات النشر:

  1. إنشاء مستودع على GitHub:
    • اذهب إلى حسابك في GitHub وأنشئ مستودعًا جديدًا (New repository). اجعله عامًا (Public).
    • ارفع ملف index.html الذي أنشأته إلى هذا المستودع.
  2. ربط Cloudflare بـ GitHub:
    • سجّل الدخول إلى حسابك في Cloudflare.
    • من القائمة الجانبية، اذهب إلى Workers & Pages.
    • اضغط على Create application ثم اختر تبويب Pages.
    • اضغط على Connect to Git واختر حساب GitHub الخاص بك.
  3. إعداد المشروع والنشر:
    • اختر المستودع الذي أنشأته للتو.
    • في صفحة الإعدادات (Set up builds and deployments)، لا تحتاج لتغيير أي شيء. Cloudflare ذكي بما يكفي ليعرف أنه موقع ثابت. اترك قسم Build settings فارغًا.
    • اضغط على Save and Deploy.

انتظر دقيقة أو اثنتين، وسيمنحك Cloudflare رابطًا لموقعك (مثال: your-project.pages.dev). مبروك! تطبيق الحجز الخاص بك أصبح الآن مباشرًا على الإنترنت. جرب تعبئة النموذج وتأكد من وصول البيانات إلى جدول Google Sheets الخاص بك.

✅ قائمة التحقق النهائية

تأكد من أنك أكملت جميع الخطوات التالية لضمان عمل التطبيق بشكل صحيح:

  • [ ] قمت بإنشاء جدول بيانات جديد في Google Sheets.
  • [ ] قمت بنسخ معرّف جدول البيانات (SHEET_ID) ولصقه في كود Apps Script.
  • [ ] قمت بنشر سكربت Apps Script كتطبيق ويب (Web App) وجعلت الوصول متاحًا لـ Anyone.
  • [ ] قمت بنسخ رابط تطبيق الويب (Web App URL) ولصقه في ملف index.html.
  • [ ] قمت برفع ملف index.html المحدّث إلى مستودع GitHub.
  • [ ] قمت بربط المستودع بـ Cloudflare Pages ونشرت المشروع بنجاح.

🔍 تحسينات إضافية وأسئلة شائعة (FAQ)

لجعل تطبيقك أكثر احترافية، يمكنك أن تطلب من ChatGPT مساعدتك في إضافة الميزات التالية:

  • إضافة التحقق من الحقول (Validation):برومبت إضافي: “حدّث كود JavaScript في ملف index.html ليتأكد من أن حقل البريد الإلكتروني يحتوي على صيغة بريد إلكتروني صحيحة، وأن جميع الحقول ليست فارغة قبل الإرسال.”
  • إضافة حماية من السبام (reCAPTCHA):برومبت إضافي: “اشرح لي كيفية إضافة Google reCAPTCHA v2 إلى نموذج HTML الخاص بي، وكيف يمكنني التحقق منه في كود JavaScript قبل إرسال البيانات.”

س: ماذا لو لم تصل البيانات إلى Google Sheets؟

ج: تأكد من ثلاث نقاط: 1) أنك نشرت Apps Script بشكل صحيح واخترت Anyone للوصول. 2) أنك استخدمت رابط تطبيق الويب (Web App URL) وليس رابط المحرر. 3) أنك استبدلت YOUR_WEB_APP_URL في ملف index.html بالرابط الصحيح.

س: هل يمكنني إضافة حقول أخرى للنموذج؟

ج: بالتأكيد! كل ما عليك فعله هو: 1) إضافة الحقل الجديد في ملف index.html. 2) تحديث كود JavaScript ليجمع بيانات الحقل الجديد. 3) تحديث كود Apps Script (doPost function) ليستقبل الحقل الجديد ويضيفه إلى الجدول.

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


اكتشف المزيد من كيف عربي

اشترك للحصول على أحدث المشاركات المرسلة إلى بريدك الإلكتروني.