| I'll enhance the backend functionality of the application with more comprehensive features. Here's the complete HTML file with an improved backend implementation: |
|
|
| ```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> |
| <script src="https://cdn.tailwindcss.com"></script> |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
| <style> |
| @import url('https://fonts.googleapis.com/css2?family=Tajawal:wght@400;500;700;900&display=swap'); |
| |
| body { |
| font-family: 'Tajawal', sans-serif; |
| } |
| |
| .country-flag { |
| width: 30px; |
| height: 20px; |
| object-fit: cover; |
| border-radius: 2px; |
| margin-left: 8px; |
| } |
| |
| .item-card { |
| transition: transform 0.3s ease, box-shadow 0.3s ease; |
| } |
| |
| .item-card:hover { |
| transform: translateY(-5px); |
| box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1); |
| } |
| |
| .tab-active { |
| color: #3b82f6; |
| border-bottom: 2px solid #3b82f6; |
| } |
| |
| .line-clamp-2 { |
| display: -webkit-box; |
| -webkit-line-clamp: 2; |
| -webkit-box-orient: vertical; |
| overflow: hidden; |
| } |
| |
| .chat-message { |
| max-width: 70%; |
| word-wrap: break-word; |
| } |
| </style> |
| </head> |
| <body class="bg-gray-50"> |
| |
| <div id="countryModal" class="fixed inset-0 bg-gray-900 bg-opacity-50 flex items-center justify-center z-50"> |
| <div class="bg-white rounded-lg p-8 w-full max-w-md mx-4"> |
| <h2 class="text-2xl font-bold text-center mb-6">اختر بلدك</h2> |
| <div class="flex flex-col space-y-4"> |
| <button onclick="selectCountry('sa')" class="flex items-center justify-center py-4 px-6 border border-gray-300 rounded-lg hover:bg-gray-100 transition"> |
| <img src="https://flagcdn.com/w20/sa.png" class="country-flag" alt="Saudi Arabia"> |
| <span class="font-medium">السعودية (ريال سعودي)</span> |
| </button> |
| <button onclick="selectCountry('eg')" class="flex items-center justify-center py-4 px-6 border border-gray-300 rounded-lg hover:bg-gray-100 transition"> |
| <img src="https://flagcdn.com/w20/eg.png" class="country-flag" alt="Egypt"> |
| <span class="font-medium">مصر (جنيه مصري)</span> |
| </button> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <nav class="bg-white shadow-sm sticky top-0 z-40"> |
| <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> |
| <div class="flex justify-between h-16"> |
| <div class="flex items-center"> |
| <a href="#" onclick="showHome()" class="flex-shrink-0 flex items-center"> |
| <span class="text-blue-600 font-bold text-xl">جاري</span> |
| </a> |
| </div> |
| <div class="hidden md:ml-6 md:flex md:items-center md:space-x-4 space-x-reverse"> |
| <button id="homeTab" onclick="showHome()" class="px-3 py-2 text-sm font-medium tab-active">الرئيسية</button> |
| <button id="addItemTab" onclick="showAddItem()" class="px-3 py-2 text-sm font-medium text-gray-700 hover:text-blue-600">إضافة غرض</button> |
| <button id="loginTab" onclick="showLogin()" class="px-3 py-2 text-sm font-medium text-gray-700 hover:text-blue-600">تسجيل الدخول</button> |
| <button id="profileTab" onclick="showProfile()" class="px-3 py-2 text-sm font-medium text-gray-700 hover:text-blue-600 hidden">حسابي</button> |
| <button id="logoutBtn" onclick="logout()" class="px-3 py-2 text-sm font-medium text-gray-700 hover:text-blue-600 hidden">تسجيل خروج</button> |
| <div id="countrySelector" class="flex items-center"> |
| <span id="currentCountry" class="text-sm text-gray-600"></span> |
| <button onclick="changeCountry()" class="ml-2 text-blue-600 hover:text-blue-800 text-sm"> |
| <i class="fas fa-exchange-alt"></i> |
| </button> |
| </div> |
| </div> |
| <div class="-mr-2 flex items-center md:hidden"> |
| <button onclick="toggleMobileMenu()" class="inline-flex items-center justify-center p-2 rounded-md text-gray-700 hover:text-blue-600 hover:bg-gray-100 focus:outline-none"> |
| <i class="fas fa-bars text-xl"></i> |
| </button> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div id="mobileMenu" class="hidden md:hidden bg-white border-t"> |
| <div class="px-2 pt-2 pb-3 space-y-1 sm:px-3"> |
| <button onclick="showHome()" class="block w-full text-right px-3 py-2 text-base font-medium text-gray-700 hover:text-blue-600 hover:bg-gray-50">الرئيسية</button> |
| <button onclick="showAddItem()" class="block w-full text-right px-3 py-2 text-base font-medium text-gray-700 hover:text-blue-600 hover:bg-gray-50">إضافة غرض</button> |
| <button id="mobileLoginTab" onclick="showLogin()" class="block w-full text-right px-3 py-2 text-base font-medium text-gray-700 hover:text-blue-600 hover:bg-gray-50">تسجيل الدخول</button> |
| <button id="mobileProfileTab" onclick="showProfile()" class="block w-full text-right px-3 py-2 text-base font-medium text-gray-700 hover:text-blue-600 hover:bg-gray-50 hidden">حسابي</button> |
| <button id="mobileLogoutBtn" onclick="logout()" class="block w-full text-right px-3 py-2 text-base font-medium text-gray-700 hover:text-blue-600 hover:bg-gray-50 hidden">تسجيل خروج</button> |
| <div class="flex items-center justify-between px-3 py-2"> |
| <span id="mobileCurrentCountry" class="text-sm text-gray-600"></span> |
| <button onclick="changeCountry()" class="text-blue-600 hover:text-blue-800 text-sm"> |
| <i class="fas fa-exchange-alt"></i> تغيير البلد |
| </button> |
| </div> |
| </div> |
| </div> |
| </nav> |
|
|
| |
| <main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8"> |
| |
| <div id="homePage"> |
| <div class="flex justify-between items-center mb-6"> |
| <h1 class="text-2xl font-bold text-gray-900">الأغراض المتاحة للإيجار</h1> |
| <div class="flex items-center space-x-2 space-x-reverse"> |
| <select id="categoryFilter" class="border border-gray-300 rounded-md px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"> |
| <option value="">كل التصنيفات</option> |
| </select> |
| <select id="cityFilter" class="border border-gray-300 rounded-md px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"> |
| <option value="">كل المدن</option> |
| </select> |
| </div> |
| </div> |
| |
| <div id="itemsContainer" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6"> |
| |
| </div> |
| </div> |
| |
| |
| <div id="addItemPage" class="hidden max-w-2xl mx-auto"> |
| <h1 class="text-2xl font-bold text-gray-900 mb-6">إضافة غرض جديد للإيجار</h1> |
| |
| <form id="addItemForm" class="space-y-4"> |
| <div> |
| <label for="itemTitle" class="block text-sm font-medium text-gray-700">عنوان الغرض</label> |
| <input type="text" id="itemTitle" required class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500"> |
| </div> |
| |
| <div> |
| <label for="itemDescription" class="block text-sm font-medium text-gray-700">وصف الغرض</label> |
| <textarea id="itemDescription" rows="4" required class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500"></textarea> |
| </div> |
| |
| <div> |
| <label for="itemImage" class="block text-sm font-medium text-gray-700">صورة الغرض</label> |
| <input type="file" id="itemImage" accept="image/*" class="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-blue-50 file:text-blue-700 hover:file:bg-blue-100"> |
| <div id="imagePreview" class="mt-2 hidden"> |
| <img id="previewImage" src="#" alt="Preview" class="h-32 object-cover rounded-md"> |
| </div> |
| </div> |
| |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-4"> |
| <div> |
| <label for="itemPrice" class="block text-sm font-medium text-gray-700">السعر اليومي</label> |
| <div class="mt-1 relative rounded-md shadow-sm"> |
| <div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"> |
| <span id="priceCurrency" class="text-gray-500 sm:text-sm">ريال</span> |
| </div> |
| <input type="number" id="itemPrice" min="1" required class="focus:ring-blue-500 focus:border-blue-500 block w-full pr-12 pl-16 py-2 sm:text-sm border-gray-300 rounded-md"> |
| </div> |
| </div> |
| |
| <div> |
| <label for="itemCity" class="block text-sm font-medium text-gray-700">المدينة</label> |
| <select id="itemCity" required class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500"> |
| <option value="">اختر المدينة</option> |
| </select> |
| </div> |
| </div> |
| |
| <div> |
| <label for="itemCategory" class="block text-sm font-medium text-gray-700">التصنيف</label> |
| <select id="itemCategory" required class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500"> |
| <option value="">اختر التصنيف</option> |
| <option value="electronics">إلكترونيات</option> |
| <option value="tools">أدوات</option> |
| <option value="sports">رياضة</option> |
| <option value="fashion">أزياء</option> |
| <option value="home">أدوات منزلية</option> |
| <option value="other">أخرى</option> |
| </select> |
| </div> |
| |
| <div class="pt-4"> |
| <button type="submit" class="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"> |
| إضافة الغرض |
| </button> |
| </div> |
| </form> |
| </div> |
| |
| |
| <div id="loginPage" class="hidden max-w-md mx-auto"> |
| <div class="bg-white py-8 px-4 shadow rounded-lg sm:px-10"> |
| <div class="text-center mb-8"> |
| <h1 class="text-2xl font-bold text-gray-900">مرحباً بك في جاري</h1> |
| <p class="mt-2 text-sm text-gray-600">سجل الدخول أو أنشئ حساباً جديداً</p> |
| </div> |
| |
| <div class="flex border-b mb-6"> |
| <button id="loginTabBtn" class="flex-1 py-2 px-4 text-center font-medium tab-active">تسجيل الدخول</button> |
| <button id="registerTabBtn" class="flex-1 py-2 px-4 text-center font-medium text-gray-5 hover:text-blue-600">إنشاء حساب</button> |
| </div> |
| |
| <form id="loginForm" class="space-y-4"> |
| <div> |
| <label for="loginEmail" class="block text-sm font-medium text-gray-700">البريد الإلكتروني</label> |
| <input type="email" id="loginEmail" required class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500"> |
| </div> |
| |
| <div> |
| <label for="loginPassword" class="block text-sm font-medium text-gray-700">كلمة المرور</label> |
| <input type="password" id="loginPassword" required class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500"> |
| </div> |
| |
| <div> |
| <button type="submit" class="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"> |
| تسجيل الدخول |
| </button> |
| </div> |
| </form> |
| |
| <form id="registerForm" class="hidden space-y-4"> |
| <div> |
| <label for="registerName" class="block text-sm font-medium text-gray-700">الاسم الكامل</label> |
| <input type="text" id="registerName" required class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500"> |
| </div> |
| |
| <div> |
| <label for="registerEmail" class="block text-sm font-medium text-gray-700">البريد الإلكتروني</label> |
| <input type="email" id="registerEmail" required class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500"> |
| </div> |
| |
| <div> |
| <label for="registerPhone" class="block text-sm font-medium text-gray-700">رقم الهاتف</label> |
| <input type="tel" id="registerPhone" required class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500"> |
| </div> |
| |
| <div> |
| <label for="registerPassword" class="block text-sm font-medium text-gray-700">كلمة المرور</label> |
| <input type="password" id="registerPassword" required class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500"> |
| </div> |
| |
| <div> |
| <label for="registerConfirmPassword" class="block text-sm font-medium text-gray-700">تأكيد كلمة المرور</label> |
| <input type="password" id="registerConfirmPassword" required class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500"> |
| </div> |
| |
| <div> |
| <button type="submit" class="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"> |
| إنشاء حساب |
| </button> |
| </div> |
| </form> |
| |
| <div class="mt-4 text-center"> |
| <p class="text-sm text-gray-600"> |
| بمتابعتك أنت توافق على |
| <a href="#" class="font-medium text-blue-600 hover:text-blue-500">شروط الاستخدام</a> |
| و |
| <a href="#" class="font-medium text-blue-600 hover:text-blue-500">سياسة الخصوصية</a> |
| </p> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div id="profilePage" class="hidden max-w-4xl mx-auto"> |
| <div class="bg-white shadow rounded-lg overflow-hidden"> |
| <div class="bg-blue-600 py-6 px-6 text-white"> |
| <div class="flex items-center justify-between"> |
| <div> |
| <h1 class="text-2xl font-bold">حسابي</h1> |
| <p id="profileEmail" class="text-blue-100 mt-1"></p> |
| </div> |
| <button onclick="showEditProfile()" class="bg-white text-blue-600 px-4 py-2 rounded-md text-sm font-medium hover:bg-blue-50"> |
| تعديل الملف الشخصي |
| </button> |
| </div> |
| </div> |
| |
| <div class="p-6"> |
| <div class="grid grid-cols-1 md:grid-cols-3 gap-6"> |
| <div class="md:col-span-2"> |
| <h2 class="text-lg font-medium text-gray-900 mb-4">الأغراض التي أضفتها</h2> |
| <div id="userItemsContainer" class="space-y-4"> |
| |
| </div> |
| |
| <h2 class="text-lg font-medium text-gray-900 mt-8 mb-4">طلبات الإيجار</h2> |
| <div id="rentalRequestsContainer" class="space-y-4"> |
| |
| </div> |
| </div> |
| |
| <div> |
| <div class="bg-gray-50 p-4 rounded-lg"> |
| <div class="flex items-center mb-4"> |
| <div class="bg-blue-100 text-blue-800 rounded-full p-3 mr-3"> |
| <i class="fas fa-user text-xl"></i> |
| </div> |
| <div> |
| <h3 id="profileName" class="font-medium"></h3> |
| <p id="profilePhone" class="text-sm text-gray-500"></p> |
| </div> |
| </div> |
| |
| <div class="border-t pt-4"> |
| <h3 class="font-medium text-gray-900 mb-2">إحصائيات</h3> |
| <div class="grid grid-cols-2 gap-4"> |
| <div class="bg-white p-3 rounded-md shadow-sm text-center"> |
| <p class="text-sm text-gray-500">الأغراض</p> |
| <p id="itemsCount" class="font-bold text-lg">0</p> |
| </div> |
| <div class="bg-white p-3 rounded-md shadow-sm text-center"> |
| <p class="text-sm text-gray-500">الإيجارات</p> |
| <p id="rentalsCount" class="font-bold text-lg">0</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div id="editProfilePage" class="hidden max-w-2xl mx-auto"> |
| <div class="flex items-center mb-6"> |
| <button onclick="showProfile()" class="text-blue-600 hover:text-blue-800 mr-2"> |
| <i class="fas fa-arrow-right"></i> |
| </button> |
| <h1 class="text-2xl font-bold text-gray-900">تعديل الملف الشخصي</h1> |
| </div> |
| |
| <form id="editProfileForm" class="space-y-4"> |
| <div> |
| <label for="editProfileName" class="block text-sm font-medium text-gray-700">الاسم الكامل</label> |
| <input type="text" id="editProfileName" required class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500"> |
| </div> |
| |
| <div> |
| <label for="editProfileEmail" class="block text-sm font-medium text-gray-700">البريد الإلكتروني</label> |
| <input type="email" id="editProfileEmail" required class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500"> |
| </div> |
| |
| <div> |
| <label for="editProfilePhone" class="block text-sm font-medium text-gray-700">رقم الهاتف</label> |
| <input type="tel" id="editProfilePhone" required class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500"> |
| </div> |
| |
| <div> |
| <label for="editProfilePassword" class="block text-sm font-medium text-gray-700">كلمة المرور الجديدة (اختياري)</label> |
| <input type="password" id="editProfilePassword" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500"> |
| </div> |
| |
| <div> |
| <label for="editProfileConfirmPassword" class="block text-sm font-medium text-gray-700">تأكيد كلمة المرور الجديدة</label> |
| <input type="password" id="editProfileConfirmPassword" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500"> |
| </div> |
| |
| <div class="pt-4"> |
| <button type="submit" class="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"> |
| حفظ التغييرات |
| </button> |
| </div> |
| </form> |
| </div> |
| |
| |
| <div id="itemDetailsModal" class="fixed inset-0 bg-gray-900 bg-opacity-50 flex items-center justify-center z-50 hidden"> |
| <div class="bg-white rounded-lg p-6 w-full max-w-2xl mx-4 max-h-[90vh] overflow-y-auto"> |
| <div class="flex justify-between items-start mb-4"> |
| <h2 id="itemDetailsTitle" class="text-xl font-bold"></h2> |
| <button onclick="closeItemDetails()" class="text-gray-500 hover:text-gray-700"> |
| <i class="fas fa-times"></i> |
| </button> |
| </div> |
| |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-6"> |
| <div> |
| <img id="itemDetailsImage" src="" alt="" class="w-full h-64 object-cover rounded-lg"> |
| <div class="mt-4 flex items-center justify-between"> |
| <div> |
| <span id="itemDetailsPrice" class="text-lg font-bold text-blue-600"></span> |
| <span class="text-gray-500">/ يوم</span> |
| </div> |
| <div class="flex items-center"> |
| <i class="fas fa-map-marker-alt text-gray-500 mr-1"></i> |
| <span id="itemDetailsCity" class="text-gray-600"></span> |
| </div> |
| </div> |
| </div> |
| |
| <div> |
| <h3 class="font-medium mb-2">الوصف</h3> |
| <p id="itemDetailsDescription" class="text-gray-700 mb-4"></p> |
| |
| <div class="border-t pt-4"> |
| <h3 class="font-medium mb-2">المالك</h3> |
| <div class="flex items-center"> |
| <div class="bg-blue-100 text-blue-800 rounded-full p-2 mr-3"> |
| <i class="fas fa-user"></i> |
| </div> |
| <div> |
| <p id="itemDetailsOwner" class="font-medium"></p> |
| <p id="itemDetailsOwnerRating" class="text-sm text-gray-500"> |
| <i class="fas fa-star text-yellow-400"></i> 4.8 (12 تقييم) |
| </p> |
| </div> |
| </div> |
| </div> |
| |
| <div class="border-t pt-4 mt-4"> |
| <h3 class="font-medium mb-2">تواصل مع المالك</h3> |
| <div id="itemDetailsChat" class="space-y-2 max-h-40 overflow-y-auto mb-4"> |
| |
| </div> |
| |
| <div class="flex items-center"> |
| <input type="text" id="itemDetailsMessage" placeholder="اكتب رسالتك..." class="flex-1 border border-gray-300 rounded-l-md py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500"> |
| <button onclick="sendMessage()" class="bg-blue-600 text-white px-4 py-2 rounded-r-md hover:bg-blue-700"> |
| <i class="fas fa-paper-plane"></i> |
| </button> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| <div class="mt-6 pt-4 border-t"> |
| <button id="rentItemBtn" onclick="requestRental()" class="w-full bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700"> |
| طلب الإيجار |
| </button> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div id="rentalRequestModal" class="fixed inset-0 bg-gray-900 bg-opacity-50 flex items-center justify-center z-50 hidden"> |
| <div class="bg-white rounded-lg p-6 w-full max-w-md mx-4"> |
| <div class="flex justify-between items-start mb-4"> |
| <h2 class="text-xl font-bold">طلب إيجار</h2> |
| <button onclick="closeRentalRequestModal()" class="text-gray-500 hover:text-gray-700"> |
| <i class="fas fa-times"></i> |
| </button> |
| </div> |
| |
| <form id="rentalRequestForm" class="space-y-4"> |
| <div> |
| <label for="rentalStartDate" class="block text-sm font-medium text-gray-700">تاريخ البدء</label> |
| <input type="date" id="rentalStartDate" required class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500"> |
| </div> |
| |
| <div> |
| <label for="rentalEndDate" class="block text-sm font-medium text-gray-700">تاريخ الانتهاء</label> |
| <input type="date" id="rentalEndDate" required class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500"> |
| </div> |
| |
| <div> |
| <label for="rentalMessage" class="block text-sm font-medium text-gray-700">ملاحظات (اختياري)</label> |
| <textarea id="rentalMessage" rows="3" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500"></textarea> |
| </div> |
| |
| <div class="pt-4"> |
| <button type="submit" class="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"> |
| تأكيد الطلب |
| </button> |
| </div> |
| </form> |
| </div> |
| </div> |
| |
| |
| <div id="rentalRequestDetailsModal" class="fixed inset-0 bg-gray-900 bg-opacity-50 flex items-center justify-center z-50 hidden"> |
| <div class="bg-white rounded-lg p-6 w-full max-w-md mx-4"> |
| <div class="flex justify-between items-start mb-4"> |
| <h2 id="rentalRequestTitle" class="text-xl font-bold">تفاصيل طلب الإيجار</h2> |
| <button onclick="closeRentalRequestDetailsModal()" class="text-gray-500 hover:text-gray-700"> |
| <i class="fas fa-times"></i> |
| </button> |
| </div> |
| |
| <div class="space-y-4"> |
| <div> |
| <h3 class="font-medium text-gray-700">المستأجر</h3> |
| <p id="rentalRequestRenter" class="text-gray-900"></p> |
| </div> |
| |
| <div> |
| <h3 class="font-medium text-gray-700">فترة الإيجار</h3> |
| <p id="rentalRequestPeriod" class="text-gray-900"></p> |
| </div> |
| |
| <div> |
| <h3 class="font-medium text-gray-700">الحالة</h3> |
| <p id="rentalRequestStatus" class="text-gray-900"></p> |
| </div> |
| |
| <div> |
| <h3 class="font-medium text-gray-700">الملاحظات</h3> |
| <p id="rentalRequestNotes" class="text-gray-900"></p> |
| </div> |
| |
| <div id="rentalRequestActions" class="pt-4 flex space-x-2 space-x-reverse"> |
| |
| </div> |
| </div> |
| </div> |
| </div> |
| </main> |
| |
| |
| <footer class="bg-white border-t mt-12"> |
| <div class="max-w-7xl mx-auto py-8 px-4 sm:px-6 lg:px-8"> |
| <div class="grid grid-cols-1 md:grid-cols-3 gap-8"> |
| <div> |
| <h3 class="text-lg font-medium text-gray-900 mb-4">جاري</h3> |
| <p id="footerDescription" class="text-gray-500 text-sm">منصة لتأجير الأغراض الشخصية بين الأفراد</p> |
| </div> |
| |
| <div> |
| <h3 class="text-lg font-medium text-gray-900 mb-4">روابط سريعة</h3> |
| <ul class="space-y-2"> |
| <li><a href="#" onclick="showHome()" class="text-gray-500 hover:text-blue-600 text-sm">الرئيسية</a></li> |
| <li><a href="#" onclick="showAddItem()" class="text-gray-500 hover:text-blue-600 text-sm">إضافة غرض</a></li> |
| <li><a href="#" onclick="showLogin()" class="text-gray-500 hover:text-blue-600 text-sm">تسجيل الدخول</a></li> |
| </ul> |
| </div> |
| |
| <div> |
| <h3 class="text-lg font-medium text-gray-900 mb-4">تواصل معنا</h3> |
| <div class="flex space-x-4 space-x-reverse"> |
| <a href="#" class="text-gray-500 hover:text-blue-600"> |
| <i class="fab fa-facebook-f"></i> |
| </a> |
| <a href="#" class="text-gray-500 hover:text-blue-600"> |
| <i class="fab fa-twitter"></i> |
| </a> |
| <a href="#" class="text-gray-500 hover:text-blue-600"> |
| <i class="fab fa-instagram"></i> |
| </a> |
| </div> |
| <p class="text-gray-500 text-sm mt-4">info@jari.com</p> |
| </div> |
| </div> |
| |
| <div class="mt-8 pt-8 border-t border-gray-200 text-center"> |
| <p class="text-gray-500 text-sm">© 2023 جاري. جميع الحقوق محفوظة.</p> |
| </div> |
| </div> |
| </footer> |
| |
| |
| <div id="loadingSpinner" class="fixed inset-0 bg-gray-900 bg-opacity-50 flex items-center justify-center z-50 hidden"> |
| <div class="animate-spin rounded-full h-16 w-16 border-t-2 border-b-2 border-blue-500"></div> |
| </div> |
| |
| |
| <div id="successNotification" class="fixed bottom-4 right-4 bg-green-500 text-white px-4 py-2 rounded-md shadow-lg flex items-center hidden z-50"> |
| <i class="fas fa-check-circle mr-2"></i> |
| <span id="successMessage"></span> |
| </div> |
| |
| |
| <div id="errorNotification" class="fixed bottom-4 right-4 bg-red-500 text-white px-4 py-2 rounded-md shadow-lg flex items-center hidden z-50"> |
| <i class="fas fa-exclamation-circle mr-2"></i> |
| <span id="errorMessage"></span> |
| </div> |
|
|
| |
| <script> |
| |
| let selectedCountry = null; |
| let currentPage = null; |
| let currentUser = null; |
| let currentItemDetails = null; |
| let currentRentalRequest = null; |
| |
| |
| const cities = { |
| sa: ['الرياض', 'جدة', 'مكة المكرمة', 'المدينة المنورة', 'الدمام', 'الخبر', 'الطائف', 'بريدة', 'تبوك', 'نجران'], |
| eg: ['القاهرة', 'الجيزة', 'الإسكندرية', 'المنصورة', 'طنطا', 'المنيا', 'أسيوط', 'سوهاج', 'الأقصر', 'أسوان'] |
| }; |
| |
| |
| const categories = [ |
| { value: 'electronics', label: 'إلكترونيات' }, |
| { value: 'tools', label: 'أدوات' }, |
| { value: 'sports', label: 'رياضة' }, |
| { value: 'fashion', label: 'أزياء' }, |
| { value: 'home', label: 'أدوات منزلية' }, |
| { value: 'other', label: 'أخرى' } |
| ]; |
| |
| |
| const rentalStatuses = { |
| pending: { text: 'بانتظار الموافقة', color: 'bg-yellow-100 text-yellow-800' }, |
| approved: { text: 'تمت الموافقة', color: 'bg-green-100 text-green-800' }, |
| rejected: { text: 'تم الرفض', color: 'bg-red-100 text-red-800' }, |
| completed: { text: 'مكتمل', color: 'bg-blue-100 text-blue-800' }, |
| cancelled: { text: 'ملغي', color: 'bg-gray-100 text-gray-800' } |
| }; |
| |
| |
| document.addEventListener('DOMContentLoaded', function() { |
| |
| const savedCountry = localStorage.getItem('country'); |
| if (savedCountry) { |
| selectedCountry = savedCountry; |
| initApp(); |
| } else { |
| |
| document.getElementById('countryModal').classList.remove('hidden'); |
| } |
| |
| |
| const savedUser = localStorage.getItem('user'); |
| if (savedUser) { |
| currentUser = JSON.parse(savedUser); |
| updateAuthUI(); |
| } |
| |
| |
| setupEventListeners(); |
| }); |
| |
| |
| function selectCountry(country) { |
| selectedCountry = country; |
| localStorage.setItem('country', country); |
| document.getElementById('countryModal').classList.add('hidden'); |
| initApp(); |
| } |
| |
| |
| function changeCountry() { |
| localStorage.removeItem('country'); |
| selectedCountry = null; |
| document.getElementById('countryModal').classList.remove('hidden'); |
| } |
| |
| |
| function initApp() { |
| if (!selectedCountry) return; |
| |
| |
| const currency = selectedCountry === 'sa' ? 'ريال' : 'جنيه'; |
| const countryName = selectedCountry === 'sa' ? 'السعودية' : 'مصر'; |
| |
| document.getElementById('priceCurrency').textContent = currency; |
| document.getElementById('currentCountry').textContent = countryName; |
| document.getElementById('mobileCurrentCountry').textContent = countryName; |
| |
| |
| document.getElementById('footerDescription').textContent = |
| `منصة لتأجير الأغراض الشخصية بين الأفراد في ${countryName}`; |
| |
| |
| populateCitySelect('cityFilter', 'كل المدن'); |
| populateCitySelect('itemCity', 'اختر المدينة'); |
| |
| |
| populateCategoryFilter(); |
| |
| |
| loadItems(); |
| |
| |
| showHome(); |
| } |
| |
| |
| function populateCitySelect(selectId, defaultText) { |
| const select = document.getElementById(selectId); |
| select.innerHTML = ''; |
| |
| const defaultOption = document.createElement('option'); |
| defaultOption.value = ''; |
| defaultOption.textContent = defaultText; |
| select.appendChild(defaultOption); |
| |
| cities[selectedCountry].forEach(city => { |
| const option = document.createElement('option'); |
| option.value = city; |
| option.textContent = city; |
| select.appendChild(option); |
| }); |
| } |
| |
| |
| function populateCategoryFilter() { |
| const select = document.getElementById('categoryFilter'); |
| select.innerHTML = ''; |
| |
| const defaultOption = document.createElement('option'); |
| defaultOption.value = ''; |
| defaultOption.textContent = 'كل التصنيفات'; |
| select.appendChild(defaultOption); |
| |
| categories.forEach(category => { |
| const option = document.createElement('option'); |
| option.value = category.value; |
| option.textContent = category.label; |
| select.appendChild(option); |
| }); |
| } |
| |
| |
| function setupEventListeners() { |
| |
| document.getElementById('itemImage').addEventListener('change', function(e) { |
| if (e.target.files.length > 0) { |
| const reader = new FileReader(); |
| reader.onload = function(event) { |
| document.getElementById('previewImage').src = event.target.result; |
| document.getElementById('imagePreview').classList.remove('hidden'); |
| }; |
| reader.readAsDataURL(e.target.files[0]); |
| } |
| }); |
| |
| |
| document.getElementById('cityFilter').addEventListener('change', function() { |
| loadItems(); |
| }); |
| |
| |
| document.getElementById('categoryFilter').addEventListener('change', function() { |
| loadItems(); |
| }); |
| |
| |
| document.getElementById('loginTabBtn').addEventListener('click', function(e) { |
| e.preventDefault(); |
| document.getElementById('loginForm').classList.remove('hidden'); |
| document.getElementById('registerForm').classList.add('hidden'); |
| document.getElementById('loginTabBtn').classList.add('tab-active'); |
| document.getElementById('registerTabBtn').classList.remove('tab-active'); |
| }); |
| |
| document.getElementById('registerTabBtn').addEventListener('click', function(e) { |
| e.preventDefault(); |
| document.getElementById('loginForm').classList.add('hidden'); |
| document.getElementById('registerForm').classList.remove('hidden'); |
| document.getElementById('loginTabBtn').classList.remove('tab-active'); |
| document.getElementById('registerTabBtn').classList.add('tab-active'); |
| }); |
| |
| |
| document.getElementById('loginForm').addEventListener('submit', function(e) { |
| e.preventDefault(); |
| login(); |
| }); |
| |
| document.getElementById('registerForm').addEventListener('submit', function(e) { |
| e.preventDefault(); |
| register(); |
| }); |
| |
| document.getElementById('addItemForm').addEventListener('submit', function(e) { |
| e.preventDefault(); |
| addItem(); |
| }); |
| |
| document.getElementById('editProfileForm').addEventListener('submit', function(e) { |
| e.preventDefault(); |
| updateProfile(); |
| }); |
| |
| document.getElementById('rentalRequestForm').addEventListener('submit', function(e) { |
| e.preventDefault(); |
| submitRentalRequest(); |
| }); |
| } |
| |
| |
| function showLoading() { |
| document.getElementById('loadingSpinner').classList.remove('hidden'); |
| } |
| |
| |
| function hideLoading() { |
| document.getElementById('loadingSpinner').classList.add('hidden'); |
| } |
| |
| |
| function showSuccess(message) { |
| const notification = document.getElementById('successNotification'); |
| document.getElementById('successMessage').textContent = message; |
| notification.classList.remove('hidden'); |
| |
| setTimeout(() => { |
| notification.classList.add('hidden'); |
| }, 3000); |
| } |
| |
| |
| function showError(message) { |
| const notification = document.getElementById('errorNotification'); |
| document.getElementById('errorMessage').textContent = message; |
| notification.classList.remove('hidden'); |
| |
| setTimeout(() => { |
| notification.classList.add('hidden'); |
| }, 3000); |
| } |
| |
| |
| function toggleMobileMenu() { |
| document.getElementById('mobileMenu').classList.toggle('hidden'); |
| } |
| |
| |
| function updateAuthUI() { |
| if (currentUser) { |
| document.getElementById('loginTab').classList.add('hidden'); |
| document.getElementById('profileTab').classList.remove('hidden'); |
| document.getElementById('logoutBtn').classList.remove('hidden'); |
| document.getElementById('addItemTab').classList.remove('hidden'); |
| |
| document.getElementById('mobileLoginTab').classList.add('hidden'); |
| document.getElementById('mobileProfileTab').classList.remove('hidden'); |
| document.getElementById('mobileLogoutBtn').classList.remove('hidden'); |
| } else { |
| document.getElementById('loginTab').classList.remove('hidden'); |
| document.getElementById('profileTab').classList.add('hidden'); |
| document.getElementById('logoutBtn').classList.add('hidden'); |
| document.getElementById('addItemTab').classList.add('hidden'); |
| |
| document.getElementById('mobileLoginTab').classList.remove('hidden'); |
| document.getElementById('mobileProfileTab').classList.add('hidden'); |
| document.getElementById('mobileLogoutBtn').classList.add('hidden'); |
| } |
| } |
| |
| |
| function showHome() { |
| if (!selectedCountry) { |
| document.getElementById('countryModal').classList.remove('hidden'); |
| return; |
| } |
| |
| hideAllPages(); |
| document.getElementById('homePage').classList.remove('hidden'); |
| document.getElementById('homeTab').classList.add('tab-active'); |
| document.getElementById('addItemTab').classList.remove('tab-active'); |
| document.getElementById('loginTab').classList.remove('tab-active'); |
| document.getElementById('profileTab').classList.remove('tab-active'); |
| currentPage = 'home'; |
| |
| loadItems(); |
| } |
| |
| function showAddItem() { |
| if (!selectedCountry) { |
| document.getElementById('countryModal').classList.remove('hidden'); |
| return; |
| } |
| |
| if (!currentUser) { |
| showLogin(); |
| showError('يجب تسجيل الدخول لإضافة غرض'); |
| return; |
| } |
| |
| hideAllPages(); |
| document.getElementById('addItemPage').classList.remove('hidden'); |
| document.getElementById('homeTab').classList.remove('tab-active'); |
| document.getElementById('addItemTab').classList.add('tab-active'); |
| document.getElementById('loginTab').classList.remove('tab-active'); |
| document.getElementById('profileTab').classList.remove('tab-active'); |
| currentPage = 'addItem'; |
| } |
| |
| function showLogin() { |
| if (!selectedCountry) { |
| document.getElementById('countryModal').classList.remove('hidden'); |
| return; |
| } |
| |
| hideAllPages(); |
| document.getElementById('loginPage').classList.remove('hidden'); |
| document.getElementById('homeTab').classList.remove('tab-active'); |
| document.getElementById('addItemTab').classList.remove('tab-active'); |
| document.getElementById('loginTab').classList.add('tab-active'); |
| document.getElementById('profileTab').classList.remove('tab-active'); |
| currentPage = 'login'; |
| |
| |
| document.getElementById('loginForm').reset(); |
| document.getElementById('registerForm').reset(); |
| document.getElementById('loginTabBtn').click(); |
| } |
| |
| function showProfile() { |
| if (!selectedCountry) { |
| document.getElementById('countryModal').classList.remove('hidden'); |
| return; |
| } |
| |
| if (!currentUser) { |
| showLogin(); |
| showError('يجب تسجيل الدخول لعرض الملف الشخصي'); |
| return; |
| } |
| |
| hideAllPages(); |
| document.getElementById('profilePage').classList.remove('hidden'); |
| document.getElementById('homeTab').classList.remove('tab-active'); |
| document.getElementById('addItemTab').classList.remove('tab-active'); |
| document.getElementById('loginTab').classList.remove('tab-active'); |
| document.getElementById('profileTab').classList.add('tab-active'); |
| currentPage = 'profile'; |
| |
| loadProfileData(); |
| } |
| |
| function showEditProfile() { |
| hideAllPages(); |
| document.getElementById('editProfilePage').classList.remove('hidden'); |
| currentPage = 'editProfile'; |
| |
| |
| document.getElementById('editProfileName').value = currentUser.name; |
| document.getElementById('editProfileEmail').value = currentUser.email; |
| document.getElementById('editProfilePhone').value = currentUser.phone; |
| } |
| |
| function hideAllPages() { |
| const pages = ['homePage', 'addItemPage', 'loginPage', 'profilePage', 'editProfilePage']; |
| pages.forEach(page => { |
| document.getElementById(page).classList.add('hidden'); |
| }); |
| } |
| |
| |
| |
| |
| |
| |
| const db = { |
| users: [ |
| { |
| id: 1, |
| name: "محمد أحمد", |
| email: "user@example.com", |
| phone: "0501234567", |
| password: "password123", |
| country: "sa", |
| createdAt: new Date() |
| }, |
| { |
| id: 2, |
| name: "أحمد علي", |
| email: "ahmed@example.com", |
| phone: "0123456789", |
| password: "password123", |
| country: "eg", |
| createdAt: new Date() |
| } |
| ], |
| items: [ |
| { |
| id: 1, |
| title: "كاميرا احترافية", |
| description: "كاميرا كانون EOS 5D مارك الرابع مع عدسة 24-70mm، حالة ممتازة", |
| price: 150, |
| city: "الرياض", |
| category: "electronics", |
| image: "https://images.unsplash.com/photo-1516035069371-29a1b244cc32?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=800&q=80", |
| ownerId: 1, |
| country: "sa", |
| createdAt: new Date() |
| }, |
| { |
| id: 2, |
| title: "دراجة هوائية", |
| description: "دراجة هوائية ماركة تريك بحالة جيدة، مناسبة للطرق الوعرة", |
| price: 80, |
| city: "جدة", |
| category: "sports", |
| image: "https://images.unsplash.com/photo-1485965120184-e220f721d03e?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=800&q=80", |
| ownerId: 1, |
| country: "sa", |
| createdAt: new Date() |
| }, |
| { |
| id: 3, |
| title: "ماكينة خياطة", |
| description: "ماكينة خياطة سنجر بحالة ممتازة مع جميع الملحقات", |
| price: 50, |
| city: "القاهرة", |
| category: "home", |
| image: "https://images.unsplash.com/photo-1539109132442-1bafc7a8a010?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=800&q=80", |
| ownerId: 2, |
| country: "eg", |
| createdAt: new Date() |
| } |
| ], |
| rentals: [ |
| { |
| id: 1, |
| itemId: 1, |
| renterId: 2, |
| ownerId: 1, |
| startDate: "2023-06-15", |
| endDate: "2023-06-20", |
| totalPrice: 750, |
| status: "completed", |
| message: "أحتاج الكاميرا لتصوير حفل زفاف", |
| createdAt: new Date("2023-06-10") |
| }, |
| { |
| id: 2, |
| itemId: 2, |
| renterId: 2, |
| ownerId: 1, |
| startDate: "2023-07-01", |
| endDate: "2023-07-05", |
| totalPrice: 320, |
| status: "approved", |
| message: "لرحلة عائلية", |
| createdAt: new Date("2023-06-25") |
| } |
| ], |
| messages: [ |
| { |
| id: 1, |
| rentalId: 1, |
| senderId: 2, |
| receiverId: 1, |
| message: "مرحباً، هل الكاميرا متاحة للإيجار في تاريخ 15 يونيو؟", |
| createdAt: new Date("2023-06-08T10:00:00") |
| }, |
| { |
| id: 2, |
| rentalId: 1, |
| senderId: 1, |
| receiverId: 2, |
| message: "نعم متاحة، يمكنك حجزها الآن", |
| createdAt: new Date("2023-06-08T10:15:00") |
| }, |
| { |
| id: 3, |
| rentalId: 1, |
| senderId: 2, |
| receiverId: 1, |
| message: "شكراً، سأقوم بحجزها الآن", |
| createdAt: new Date("2023-06-08T10:30:00") |
| } |
| ] |
| }; |
| |
| |
| function generateId() { |
| return Math.floor(Math.random() * 1000000) + 1; |
| } |
| |
| |
| function formatDate(dateString) { |
| const options = { year: 'numeric', month: 'long', day: 'numeric' }; |
| return new Date(dateString).toLocaleDateString('ar-EG', options); |
| } |
| |
| |
| function calculateDays(startDate, endDate) { |
| const start = new Date(startDate); |
| const end = new Date(endDate); |
| const diffTime = Math.abs(end - start); |
| return Math.ceil(diffTime / (1000 * 60 * 60 * 24)); |
| } |
| |
| |
| function login() { |
| const email = document.getElementById('loginEmail').value; |
| const password = document.getElementById('loginPassword').value; |
| |
| if (!email || !password) { |
| showError('الرجاء إدخال البريد الإلكتروني وكلمة المرور'); |
| return; |
| } |
| |
| showLoading(); |
| |
| |
| setTimeout(() => { |
| const user = db.users.find(u => u.email === email && u.password === password); |
| |
| if (user) { |
| currentUser = user; |
| localStorage.setItem('user', JSON.stringify(user)); |
| updateAuthUI(); |
| showSuccess('تم تسجيل الدخول بنجاح'); |
| showHome(); |
| } else { |
| showError('البريد الإلكتروني أو كلمة المرور غير صحيحة'); |
| } |
| |
| hideLoading(); |
| }, 1000); |
| } |
| |
| |
| function register() { |
| const name = document.getElementById('registerName').value; |
| const email = document.getElementById('registerEmail').value; |
| const phone = document.getElementById('registerPhone').value; |
| const password = document.getElementById('registerPassword').value; |
| const confirmPassword = document.getElementById('registerConfirmPassword').value; |
| |
| if (!name || !email || !phone || !password || !confirmPassword) { |
| showError('الرجاء ملء جميع الحقول'); |
| return; |
| } |
| |
| if (password !== confirmPassword) { |
| showError('كلمة المرور غير متطابقة'); |
| return; |
| } |
| |
| if (password.length < 6) { |
| showError('كلمة المرور يجب أن تكون 6 أحرف على الأقل'); |
| return; |
| } |
| |
| |
| const emailExists = db.users.some(u => u.email === email); |
| if (emailExists) { |
| showError('البريد الإلكتروني مسجل بالفعل'); |
| return; |
| } |
| |
| showLoading(); |
| |
| |
| setTimeout(() => { |
| const newUser = { |
| id: generateId(), |
| name, |
| email, |
| phone, |
| password, |
| country: selectedCountry, |
| createdAt: new Date() |
| }; |
| |
| db.users.push(newUser); |
| currentUser = newUser; |
| localStorage.setItem('user', JSON.stringify(newUser)); |
| updateAuthUI(); |
| |
| hideLoading(); |
| showSuccess('تم إنشاء الحساب بنجاح'); |
| document.getElementById('loginTabBtn').click(); |
| document.getElementById('loginEmail').value = email; |
| document.getElementById('loginPassword').value = ''; |
| }, 1500); |
| } |
| |
| |
| function updateProfile() { |
| const name = document.getElementById('editProfileName').value; |
| const email = document.getElementById('editProfileEmail').value; |
| const phone = document.getElementById('editProfilePhone').value; |
| const password = document.getElementById('editProfilePassword').value; |
| const confirmPassword = document.getElementById('editProfileConfirmPassword').value; |
| |
| if (!name || !email || !phone) { |
| showError('الرجاء ملء جميع الحقول المطلوبة'); |
| return; |
| } |
| |
| if (password && password.length < 6) { |
| showError('كلمة المرور يجب أن تكون 6 أحرف على الأقل'); |
| return; |
| } |
| |
| if (password && password !== confirmPassword) { |
| showError('كلمة المرور غير متطابقة'); |
| return; |
| } |
| |
| |
| const emailExists = db.users.some(u => u.email === email && u.id !== currentUser.id); |
| if (emailExists) { |
| showError('البريد الإلكتروني مسجل بالفعل'); |
| return; |
| } |
| |
| showLoading(); |
| |
| |
| setTimeout(() => { |
| |
| const userIndex = db.users.findIndex(u => u.id === currentUser.id); |
| if (userIndex !== -1) { |
| db.users[userIndex].name = name; |
| db.users[userIndex].email = email; |
| db.users[userIndex].phone = phone; |
| |
| if (password) { |
| db.users[userIndex].password = password; |
| } |
| |
| |
| currentUser = db.users[userIndex]; |
| localStorage.setItem('user', JSON.stringify(currentUser)); |
| |
| hideLoading(); |
| showSuccess('تم تحديث الملف الشخصي بنجاح'); |
| showProfile(); |
| } else { |
| hideLoading(); |
| showError('حدث خطأ أثناء تحديث الملف الشخصي'); |
| } |
| }, 1500); |
| } |
| |
| |
| function logout() { |
| currentUser = null; |
| localStorage.removeItem('user'); |
| updateAuthUI(); |
| showSuccess('تم تسجيل الخروج بنجاح'); |
| showHome(); |
| } |
| |
| |
| function addItem() { |
| if (!currentUser) { |
| showError('يجب تسجيل الدخول لإضافة غرض'); |
| showLogin(); |
| return; |
| } |
| |
| const title = document.getElementById('itemTitle').value; |
| const description = document.getElementById('itemDescription').value; |
| const price = parseFloat(document.getElementById('itemPrice').value); |
| const city = document.getElementById('itemCity').value; |
| const category = document.getElementById('itemCategory').value; |
| const imageFile = document.getElementById('itemImage').files[0]; |
| |
| if (!title || !description || !price || !city || !category) { |
| showError('الرجاء ملء جميع الحقول المطلوبة'); |
| return; |
| } |
| |
| if (price <= 0) { |
| showError('السعر يجب أن يكون أكبر من الصفر'); |
| return; |
| } |
| |
| showLoading(); |
| |
| |
| setTimeout(() => { |
| |
| |
| const imageUrl = imageFile ? |
| URL.createObjectURL(imageFile) : |
| 'https://via.placeholder.com/400x300?text=No+Image'; |
| |
| const newItem = { |
| id: generateId(), |
| title, |
| description, |
| price, |
| city, |
| category, |
| image: imageUrl, |
| ownerId: currentUser.id, |
| country: selectedCountry, |
| createdAt: new Date() |
| }; |
| |
| db.items.push(newItem); |
| |
| |
| document.getElementById('addItemForm').reset(); |
| document.getElementById('imagePreview').classList.add('hidden'); |
| |
| hideLoading(); |
| showSuccess('تم إضافة الغرض بنجاح'); |
| showHome(); |
| }, 1500); |
| } |
| |
| |
| function loadItems() { |
| if (!selectedCountry) return; |
| |
| const cityFilter = document.getElementById('cityFilter').value; |
| const categoryFilter = document.getElementById('categoryFilter').value; |
| let items = db.items.filter(item => item.country === selectedCountry); |
| |
| |
| if (cityFilter) { |
| items = items.filter(item => item.city === cityFilter); |
| } |
| |
| |
| if (categoryFilter) { |
| items = items.filter(item => item.category === categoryFilter); |
| } |
| |
| const itemsContainer = document.getElementById('itemsContainer'); |
| itemsContainer.innerHTML = ''; |
| |
| if (items.length === 0) { |
| itemsContainer.innerHTML = ` |
| <div class="col-span-full text-center py-12"> |
| <i class="fas fa-box-open text-4xl text-gray-300 mb-4"></i> |
| <p class="text-gray-500">لا توجد أغراض متاحة للإيجار حالياً</p> |
| </div> |
| `; |
| return; |
| } |
| |
| const currency = selectedCountry === 'sa' ? 'ريال' : 'جنيه'; |
| |
| items.forEach(item => { |
| const owner = db.users.find(u => u.id === item.ownerId); |
| const itemCard = document.createElement('div'); |
| itemCard.className = 'bg-white rounded-lg shadow-md overflow-hidden item-card'; |
| itemCard.innerHTML = ` |
| <div class="h-48 bg-gray-200 relative cursor-pointer" onclick="showItemDetails(${item.id})"> |
| <img src="${item.image}" alt="${item.title}" class="w-full h-full object-cover"> |
| <div class="absolute bottom-2 left-2 bg-blue-600 text-white px-2 py-1 rounded text-sm"> |
| ${item.price} ${currency} / يوم |
| </div> |
| </div> |
| <div class="p-4"> |
| <h3 class="font-bold text-lg mb-1 cursor-pointer" onclick="showItemDetails(${item.id})">${item.title}</h3> |
| <p class="text-gray-600 text-sm mb-2">${item.city}</p> |
| <p class="text-gray-700 text-sm mb-4 line-clamp-2">${item.description}</p> |
| <div class="flex justify-between items-center"> |
| <button onclick="showItemDetails(${item.id})" class="text-blue-600 hover:text-blue-800 text-sm font-medium"> |
| <i class="fas fa-comment-dots mr-1"></i> تواصل |
| </button> |
| <span class="text-xs text-gray-500">${owner ? owner.name : 'مستخدم'}</span> |
| </div> |
| </div> |
| `; |
| itemsContainer.appendChild(itemCard); |
| }); |
| } |
| |
| |
| function showItemDetails(itemId) { |
| const item = db.items.find(i => i.id === itemId); |
| if (!item) { |
| showError('الغرض غير موجود'); |
| return; |
| } |
| |
| currentItemDetails = item; |
| |
| const owner = db.users.find(u => u.id === item.ownerId); |
| const currency = selectedCountry === 'sa' ? 'ريال' : 'جنيه'; |
| |
| |
| document.getElementById('itemDetailsTitle').textContent = item.title; |
| document.getElementById('itemDetailsImage').src = item.image; |
| document.getElementById('itemDetailsImage').alt = item.title; |
| document.getElementById('itemDetailsPrice').textContent = item.price + ' ' + currency; |
| document.getElementById('itemDetailsCity').textContent = item.city; |
| document.getElementById('itemDetailsDescription').textContent = item.description; |
| document.getElementById('itemDetailsOwner').textContent = owner ? owner.name : 'مستخدم'; |
| |
| |
| document.getElementById('itemDetailsChat').innerHTML = ''; |
| |
| |
| const rentButton = document.getElementById('rentItemBtn'); |
| if (currentUser && currentUser.id === item.ownerId) { |
| rentButton.classList.add('hidden'); |
| } else { |
| rentButton.classList.remove('hidden'); |
| } |
| |
| |
| const rental = db.rentals.find(r => r.itemId === item.id && |
| (r.renterId === currentUser?.id || r.ownerId === currentUser?.id)); |
| |
| if (rental) { |
| loadChatMessages(rental.id); |
| } |
| |
| |
| document.getElementById('itemDetailsModal').classList.remove('hidden'); |
| } |
| |
| |
| function closeItemDetails() { |
| document.getElementById('itemDetailsModal').classList.add('hidden'); |
| currentItemDetails = null; |
| } |
| |
| |
| function loadChatMessages(rentalId) { |
| const chatContainer = document.getElementById('itemDetailsChat'); |
| chatContainer.innerHTML = ''; |
| |
| const messages = db.messages |
| .filter(m => m.rentalId === rentalId) |
| .sort((a, b) => new Date(a.createdAt) - new Date(b.createdAt)); |
| |
| messages.forEach(message => { |
| const isCurrentUser = message.senderId === currentUser?.id; |
| const messageDiv = document.createElement('div'); |
| messageDiv.className = `flex ${isCurrentUser ? 'justify-end' : 'justify-start'}`; |
| |
| messageDiv.innerHTML = ` |
| <div class="chat-message bg-${isCurrentUser ? 'blue' : 'gray'}-100 rounded-lg px-4 py-2"> |
| <p class="text-sm">${message.message}</p> |
| <p class="text-xs text-gray-500 mt-1 text-right">${formatDate(message.createdAt)}</p> |
| </div> |
| `; |
| |
| chatContainer.appendChild(messageDiv); |
| }); |
| |
| |
| chatContainer.scrollTop = chatContainer.scrollHeight; |
| } |
| |
| |
| function sendMessage() { |
| if (!currentUser) { |
| showError('يجب تسجيل الدخول لإرسال رسالة'); |
| showLogin(); |
| return; |
| } |
| |
| if (!currentItemDetails) { |
| showError('لا يوجد غرض محدد'); |
| return; |
| } |
| |
| const messageInput = document.getElementById('itemDetailsMessage'); |
| const messageText = messageInput.value.trim(); |
| |
| if (!messageText) { |
| showError('الرجاء إدخال رسالة'); |
| return; |
| } |
| |
| |
| let rental = db.rentals.find(r => r.itemId === currentItemDetails.id && |
| (r.renterId === currentUser.id || r.ownerId === currentUser.id)); |
| |
| if (!rental) { |
| |
| rental = { |
| id: generateId(), |
| itemId: currentItemDetails.id, |
| renterId: currentUser.id, |
| ownerId: currentItemDetails.ownerId, |
| startDate: '', |
| endDate: '', |
| totalPrice: 0, |
| status: 'pending', |
| message: messageText, |
| createdAt: new Date() |
| }; |
| |
| db.rentals.push(rental); |
| } |
| |
| |
| const newMessage = { |
| id: generateId(), |
| rentalId: rental.id, |
| senderId: currentUser.id, |
| receiverId: currentUser.id === rental.renterId ? rental.ownerId : rental.renterId, |
| message: messageText, |
| createdAt: new Date() |
| }; |
| |
| db.messages.push(newMessage); |
| |
| |
| messageInput.value = ''; |
| |
| |
| loadChatMessages(rental.id); |
| } |
| |
| |
| function requestRental() { |
| if (!currentUser) { |
| showError('يجب تسجيل الدخول لطلب الإيجار'); |
| showLogin(); |
| return; |
| } |
| |
| if (!currentItemDetails) { |
| showError('لا يوجد غرض محدد'); |
| return; |
| } |
| |
| |
| if (currentUser.id === currentItemDetails.ownerId) { |
| showError('لا يمكنك طلب إيجار غرضك الخاص'); |
| return; |
| } |
| |
| |
| const existingRental = db.rentals.find(r => r.itemId === currentItemDetails.id && r.renterId === currentUser.id); |
| |
| if (existingRental) { |
| showError('لديك طلب إيجار بالفعل لهذا الغرض'); |
| return; |
| } |
| |
| |
| document.getElementById('rentalRequestModal').classList.remove('hidden'); |
| |
| |
| const today = new Date(); |
| const tomorrow = new Date(today); |
| tomorrow.setDate(tomorrow.getDate() + 1); |
| |
| const threeDaysLater = new Date(today); |
| threeDaysLater.setDate(threeDaysLater.getDate() + 3); |
| |
| document.getElementById('rentalStartDate').valueAsDate = tomorrow; |
| document.getElementById('rentalEndDate').valueAsDate = threeDaysLater; |
| } |
| |
| |
| function closeRentalRequestModal() { |
| document.getElementById('rentalRequestModal').classList.add('hidden'); |
| } |
| |
| |
| function submitRentalRequest() { |
| if (!currentUser || !currentItemDetails) { |
| showError('حدث خطأ أثناء تقديم الطلب'); |
| return; |
| } |
| |
| const startDate = document.getElementById('rentalStartDate').value; |
| const endDate = document.getElementById('rentalEndDate').value; |
| const message = document.getElementById('rentalMessage').value; |
| |
| if (!startDate || !endDate) { |
| showError('الرجاء تحديد تاريخ البدء والانتهاء'); |
| return; |
| } |
| |
| const days = calculateDays(startDate, endDate); |
| if (days <= 0) { |
| showError('تاريخ الانتهاء يجب أن يكون بعد تاريخ البدء'); |
| return; |
| } |
| |
| const totalPrice = currentItemDetails.price * days; |
| |
| showLoading(); |
| |
| |
| setTimeout(() => { |
| |
| const newRental = { |
| id: generateId(), |
| itemId: currentItemDetails.id, |
| renterId: currentUser.id, |
| ownerId: currentItemDetails.ownerId, |
| startDate, |
| endDate, |
| totalPrice, |
| status: 'pending', |
| message, |
| createdAt: new Date() |
| }; |
| |
| db.rentals.push(newRental); |
| |
| |
| const newMessage = { |
| id: generateId(), |
| rentalId: newRental.id, |
| senderId: currentUser.id, |
| receiverId: currentItemDetails.ownerId, |
| message: message || 'أريد استئجار هذا الغرض', |
| createdAt: new Date() |
| }; |
| |
| db.messages.push(newMessage); |
| |
| hideLoading(); |
| showSuccess('تم تقديم طلب الإيجار بنجاح'); |
| closeRentalRequestModal(); |
| closeItemDetails(); |
| |
| |
| loadItems(); |
| }, 1500); |
| } |
| |
| |