الفصل 3: تكامل الواجهة الأمامية
🎯 الأهداف
- فهم الواجهة الأمامية للاختبار المقدمة
- ربط الواجهة الأمامية بالواجهة الخلفية Spring Boot
- اختبار نموذج الاتصال في بيئة حقيقية
- تكوين CORS لـ Codespaces
📚 موارد الواجهة الأمامية
موارد المشروع
| المورد | الرابط |
|---|---|
| كود الواجهة الأمامية | مجلد الواجهة الأمامية |
| دليل التكامل | 27-guide-formulaire-frontend-codespaces.md |
🎨 عرض الواجهة الأمامية
الواجهة الأمامية المقدمة هي تطبيق بسيط HTML/CSS/JavaScript يسمح بـ:
- ✅ إرسال نماذج الاتصال
- ✅ عرض ردود الـ API
- ✅ اختبار مصادقة المسؤول
- ✅ استعراض قائمة العملاء المحتملين
هيكل الواجهة الأمامية
frontend/
├── index.html # صفحة نموذج الاتصال
├── admin.html # صفحة المسؤول (قائمة العملاء المحتملين)
├── login.html # صفحة تسجيل الدخول
├── css/
│ └── styles.css # الأنماط
└── js/
├── contact.js # منطق نموذج الاتصال
├── admin.js # منطق المسؤول
└── auth.js # إدارة المصادقة
🚀 بدء تشغيل الواجهة الأمامية
الخيار 1: باستخدام Live Server (VS Code / Codespaces)
-
تثبيت إضافة Live Server في VS Code/Codespaces
-
فتح مجلد الواجهة الأمامية:
cd frontend
-
النقر بزر الفأرة الأيمن على
index.html→ Open with Live Server -
يفتح المتصفح تلقائيًا على الواجهة الأمامية
الخيار 2: باستخدام Python (Simple HTTP Server)
# في مجلد الواجهة الأمامية
cd frontend
# Python 3
python -m http.server 3000
# الوصول إلى http://localhost:3000
الخيار 3: باستخدام Node.js
# تثبيت serve عالميًا
npm install -g serve
# تشغيل الخادم
cd frontend
serve -p 3000
⚙️ التكوين لـ Codespaces
مشكلة CORS في Codespaces
في GitHub Codespaces، تكون عناوين الـ URLs مختلفة:
- الواجهة الخلفية:
https://xxx-8080.app.github.dev - الواجهة الأمامية:
https://xxx-3000.app.github.dev
الحل: تكوين عناوين URLs لـ Codespaces
-
الحصول على عنوان URL للواجهة الخلفية لـ Codespaces:
- عند بدء تشغيل تطبيق Spring Boot
- تدوين عنوان URL العام (مثل:
https://abc123-8080.app.github.dev)
-
تعديل ملف JavaScript للواجهة الأمامية:
// js/config.js أو في أعلى contact.js
// تكوين عنوان URL للـ API
const API_BASE_URL = 'https://VOTRE-CODESPACE-8080.app.github.dev';
// أو للتطوير المحلي
// const API_BASE_URL = 'http://localhost:8080';
- تحديث تكوين CORS للواجهة الخلفية:
// SecurityConfig.java
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOriginPatterns(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
configuration.setAllowedHeaders(Arrays.asList("*"));
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
📝 استخدام نموذج الاتصال
الصفحة الرئيسية (index.html)
┌─────────────────────────────────────────────────────────┐
│ اتصل بنا │
├─────────────────────────────────────────────────────────┤
│ │
│ الاسم الكامل * الشركة │
│ ┌─────────────────────────┐ ┌─────────────────────┐│
│ │ أدخل اسمك │ │ شركتك ││
│ └─────────────────────────┘ └─────────────────────┘│
│ │
│ البريد الإلكتروني * الهاتف │
│ ┌─────────────────────────┐ ┌─────────────────────┐│
│ │ your@email.com │ │ 514-555-1234 ││
│ └─────────────────────────┘ └─────────────────────┘│
│ │
│ نوع الطلب * │
│ ┌─────────────────────────────────────────────────┬──┐│
│ │ طلب معلومات │ v││
│ └─────────────────────────────────────────────────┴──┘│
│ │
│ الرسالة * │
│ ┌────────────────────────────────────────────────────┐│
│ │ صف طلبك... ││
│ │ ││
│ └────────────────────────────────────────────────────┘│
│ │
│ ┌─────────────────────┐ │
│ │ إرسال │ │
│ └─────────────────────┘ │
└─────────────────────────────────────────────────────────┘
اختبار الإرسال
- ملء جميع الحقول الإلزامية (*)
- النقر على إرسال
- ملاحظة الرد:
نجاح:
✅ تم إرسال الرسالة بنجاح!
تم تسجيل طلبك. سنتواصل معك قريبًا.
خطأ:
❌ خطأ أثناء الإرسال
يرجى التحقق من الحقول والمحاولة مرة أخرى.
🔐 واجهة المسؤول
تسجيل الدخول (login.html)
- الوصول إلى
login.html - إدخال بيانات الاعتماد:
- البريد الإلكتروني:
admin@test.com - كلمة المرور:
password123(أو حسب التكوين)
- البريد الإلكتروني:
- النقر على تسجيل الدخول
لوحة تحكم المسؤول (admin.html)
بمجرد تسجيل الدخول، يمكنك:
- 📋 رؤية قائمة جميع العملاء المحتملين
- 🔍 التصفية حسب الحالة (NEW, CONTACTED, CONVERTED, LOST)
- ✏️ تغيير حالة العميل المحتمل
- 🗑️ حذف عميل محتمل
┌─────────────────────────────────────────────────────────────────┐
│ لوحة تحكم المسؤول - إدارة العملاء المحتملين [تسجيل الخروج]│
├─────────────────────────────────────────────────────────────────┤
│ │
│ تصفية: [الكل ▼] [NEW] [CONTACTED] [CONVERTED] [LOST] │
│ │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ ID │ الاسم │ البريد الإلكتروني │ النوع │ الحالة │ ⚙ ││
│ ├────┼──────────────┼─────────────────┼─────────┼────────┼───┤│
│ │ 1 │ Jean Dupont │ jean@test.com │ INFO │ NEW │ ✏🗑││
│ │ 2 │ Marie Martin │ marie@test.com │ QUOTE │ CONTACT│ ✏🗑││
│ │ 3 │ Pierre Duval │ pierre@test.com │ SUPPORT │ NEW │ ✏🗑││
│ └─────────────────────────────────────────────────────────────┘│
│ │
│ المجموع: 3 عملاء محتملين | جدد: 2 | قيد التنفيذ: 1 │
└─────────────────────────────────────────────────────────────────┘
🔄 تدفق الاتصال بين الواجهة الأمامية والخلفية
📡 استدعاءات API من الواجهة الأمامية
JavaScript لإرسال النموذج
// contact.js
async function submitContact(formData) {
try {
const response = await fetch(`${API_BASE_URL}/api/contact`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
fullName: formData.fullName,
email: formData.email,
company: formData.company,
phone: formData.phone,
requestType: formData.requestType,
message: formData.message
})
});
if (!response.ok) {
throw new Error('Erreur lors de la soumission');
}
const data = await response.json();
showSuccess('Message envoyé avec succès!');
return data;
} catch (error) {
showError('Erreur: ' + error.message);
}
}
JavaScript لمصادقة المسؤول
// auth.js
async function login(email, password) {
const response = await fetch(`${API_BASE_URL}/api/auth/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ email, password })
});
const data = await response.json();
if (response.ok) {
// تخزين رمز JWT
localStorage.setItem('token', data.token);
window.location.href = 'admin.html';
} else {
showError('Identifiants incorrects');
}
}
JavaScript لاسترجاع العملاء المحتملين (مع رمز)
// admin.js
async function getLeads() {
const token = localStorage.getItem('token');
const response = await fetch(`${API_BASE_URL}/api/admin/leads`, {
headers: {
'Authorization': `Bearer ${token}`
}
});
if (!response.ok) {
if (response.status === 401) {
// رمز منتهي الصلاحية، إعادة التوجيه إلى تسجيل الدخول
window.location.href = 'login.html';
}
throw new Error('Erreur lors du chargement');
}
return await response.json();
}
⚠️ استكشاف أخطاء الواجهة الأمامية وإصلاحها
خطأ CORS
Access to fetch at 'http://localhost:8080/api/contact' has been blocked by CORS policy
الحل: تحقق من تكوين CORS للواجهة الخلفية.
الرمز غير مرسل
الأعراض: 401 على نقاط النهاية الإدارية حتى بعد تسجيل الدخول.
الحل: تحقق من أن الرمز مخزن ومُرسل بشكل صحيح:
console.log('Token:', localStorage.getItem('token'));
عنوان URL غير صحيح
الأعراض: fetch failed أو network error
الحل: تحقق من أن:
- الواجهة الخلفية قيد التشغيل
- عنوان URL في
API_BASE_URLصحيح - لـ Codespaces، استخدم عنوان URL العام
.app.github.dev
✅ قائمة التحقق من التحقق
- الواجهة الأمامية متاحة في المتصفح
- نموذج الاتصال مرئي
- إرسال نموذج الاتصال بنجاح
- عرض رسالة النجاح
- تسجيل دخول المسؤول يعمل
- قائمة العملاء المحتملين مرئية بعد تسجيل الدخول
📖 الدليل الكامل
دليل مفصل
لجميع التعليمات التفصيلية لتكامل الواجهة الأمامية مع Codespaces: