From ce6caf08ebd4b668fbc97a26da426328d7dae799 Mon Sep 17 00:00:00 2001 From: Rahaf Date: Tue, 9 Jun 2026 18:21:52 +0300 Subject: [PATCH 1/3] Added Active or DeActive for owner with API --- app/owner/properties/page.js | 187 ++++++++++++++++++++++++++++++++--- app/utils/api.js | 14 +++ 2 files changed, 190 insertions(+), 11 deletions(-) diff --git a/app/owner/properties/page.js b/app/owner/properties/page.js index fe27fc2..1088d44 100644 --- a/app/owner/properties/page.js +++ b/app/owner/properties/page.js @@ -59,6 +59,8 @@ import { getMySaleListings, editRentProperty, editSaleProperty, + updateRentPropertyStatus, + updateSalePropertyStatus, } from "../../utils/api"; const DeleteConfirmationModal = ({ @@ -117,6 +119,86 @@ const DeleteConfirmationModal = ({ ); }; +const DeactivateConfirmationModal = ({ + isOpen, + onClose, + onConfirm, + propertyTitle, + isActivating, +}) => { + if (!isOpen) return null; + + return ( + + e.stopPropagation()} + > +
+
+ +
+

+ {isActivating ? "تأكيد التنشيط" : "تأكيد إلغاء التنشيط"} +

+

+ العقار:{" "} + "{propertyTitle}" +

+ {!isActivating ? ( +
+

+ ⚠️ تحذير +

+

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

+
+ ) : ( +
+

+ ✅ تنشيط العقار +

+

+ سيصبح العقار متاحاً مرة أخرى للحجز أو الشراء. +

+
+ )} +
+ +
+ + +
+
+
+ ); +}; + const serviceLabels = { Electricity: "كهرباء", Internet: "إنترنت", @@ -1074,6 +1156,11 @@ export default function OwnerPropertiesPage() { }); const [viewModal, setViewModal] = useState({ isOpen: false, property: null }); const [editModal, setEditModal] = useState({ isOpen: false, property: null }); + const [deactivateModal, setDeactivateModal] = useState({ + isOpen: false, + property: null, + isActivating: false, + }); const filteredProperties = properties.filter((p) => p.purpose === activeTab); const rentCount = properties.filter((p) => p.purpose === "rent").length; @@ -1511,11 +1598,44 @@ export default function OwnerPropertiesPage() { toast.success('تم تحديث العقار بنجاح'); } catch (err) { console.error('[OwnerProperties] Edit failed:', err); - toast.error('فشل تحديث العقار'); + toast.error("فشل تحديث العقار"); throw err; } }; + const handleToggleActivation = async () => { + const prop = deactivateModal.property; + if (!prop) return; + + const willActivate = deactivateModal.isActivating; + const newStatus = willActivate ? "available" : "notAvailable"; + const statusCode = willActivate ? 0 : 1; + + setDeactivateModal({ isOpen: false, property: null, isActivating: false }); + + try { + if (prop.purpose === "rent") { + await updateRentPropertyStatus(prop.id, statusCode); + } else { + await updateSalePropertyStatus(prop.id, statusCode); + } + + const newProperties = properties.map((p) => + p.id === prop.id ? { ...p, status: newStatus } : p, + ); + setProperties(newProperties); + localStorage.setItem("ownerProperties", JSON.stringify(newProperties)); + toast.success( + willActivate + ? "تم تنشيط العقار بنجاح" + : "تم إلغاء تنشيط العقار بنجاح", + ); + } catch (err) { + console.error("[OwnerProperties] Toggle status failed:", err); + toast.error("فشل تحديث حالة العقار"); + } + }; + const fadeInUp = { initial: { opacity: 0, y: 20 }, animate: { opacity: 1, y: 0 }, @@ -1557,6 +1677,16 @@ export default function OwnerPropertiesPage() { onSave={handleSaveEdit} /> + + setDeactivateModal({ isOpen: false, property: null, isActivating: false }) + } + onConfirm={handleToggleActivation} + propertyTitle={deactivateModal.property?.title} + isActivating={deactivateModal.isActivating} + /> +
)} -
- - {property.status === "available" ? "متاح" : "مؤجر"} - +
+ + {property.status === "notAvailable" + ? "غير متاح" + : property.status === "available" + ? "متاح" + : "مؤجل"} + {property.purpose === "rent" && property.furnished !== undefined && (
+ {property.status === "notAvailable" ? ( + + ) : ( + + )} - - {saved && ( -
- تم حفظ بيانات المدير بنجاح -
- )} - -
-
- - ); -} diff --git a/app/admin/error.js b/app/admin/error.js deleted file mode 100644 index a88abe0..0000000 --- a/app/admin/error.js +++ /dev/null @@ -1,27 +0,0 @@ -'use client'; - -import { motion } from 'framer-motion'; -import { AlertTriangle, RefreshCw, Home } from 'lucide-react'; -import Link from 'next/link'; - -export default function Error({ error, reset }) { - return ( -
- -
- -
-

حدث خطأ

-

نعتذر، حدث خطأ أثناء تحميل الصفحة

-
- - - الرئيسية - -
-
-
- ); -} diff --git a/app/admin/loading.js b/app/admin/loading.js deleted file mode 100644 index 0c01106..0000000 --- a/app/admin/loading.js +++ /dev/null @@ -1,14 +0,0 @@ -'use client'; - -import { motion } from 'framer-motion'; - -export default function Loading() { - return ( -
- -
-

جاري التحميل...

- -
- ); -} diff --git a/app/admin/page.js b/app/admin/page.js deleted file mode 100644 index 007988d..0000000 --- a/app/admin/page.js +++ /dev/null @@ -1,230 +0,0 @@ -'use client'; - -import { motion } from 'framer-motion'; -import { useState, useEffect } from 'react'; -import { useTranslation } from 'react-i18next'; -import Link from 'next/link'; -import { - Home, - Calendar, - Users, - DollarSign, - TrendingUp, - Bell, - Frown -} from 'lucide-react'; -import DashboardStats from '../components/admin/DashboardStats'; -import PropertiesTable from '../components/admin/PropertiesTable'; -import BookingRequests from '../components/admin/BookingRequests'; -import UsersList from '../components/admin/UsersList'; -import LedgerBook from '../components/admin/LedgerBook'; -import AddPropertyForm from '../components/admin/AddPropertyForm'; -import { PropertyProvider } from '../contexts/PropertyContext'; -import AuthService from '../services/AuthService'; -import '../i18n/config'; - -export default function AdminPage() { - const { t, i18n } = useTranslation(); - const [activeTab, setActiveTab] = useState('dashboard'); - const [showAddProperty, setShowAddProperty] = useState(false); - const [notifications, setNotifications] = useState(3); - const [isAdmin, setIsAdmin] = useState(false); - const [checked, setChecked] = useState(false); - - useEffect(() => { - setIsAdmin(AuthService.isAuthenticated() && AuthService.isAdmin()); - setChecked(true); - }, []); - - // ─── 404 for non-admins ─── - if (checked && !isAdmin) { - return ( -
- -
- - - - - - عذراً! - الصفحة غير موجودة - -
-

404 - الصفحة غير موجودة

-

عذراً، لا يمكنك الوصول إلى هذه الصفحة

- - - العودة للرئيسية - -
-
- ); - } - - if (!checked) { - return ( -
-
-
- ); - } - - const tabs = [ - { id: 'dashboard', label: 'لوحة التحكم', icon: Home }, - { id: 'properties', label: 'العقارات', icon: Home }, - { id: 'bookings', label: 'طلبات الحجز', icon: Calendar, badge: notifications }, - { id: 'users', label: 'المستخدمين', icon: Users }, - { id: 'ledger', label: 'دفتر الحسابات', icon: DollarSign }, - // { id: 'reports', label: 'التقارير', icon: TrendingUp } - ]; - - return ( - -
- -
-
-

- {t('adminDashboard')} -

-

- إدارة العقارات، الحجوزات، والحسابات المالية -

-
- - -
-
- -
-
- {tabs.map((tab) => { - const Icon = tab.icon; - return ( - - ); - })} -
-
- -
- {activeTab === 'dashboard' && ( - - - - )} - - {activeTab === 'properties' && ( - -
-
-

إدارة العقارات

-

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

-
- -
- -
- )} - - {activeTab === 'bookings' && ( - - - - )} - - {activeTab === 'users' && ( - - - - )} - - {activeTab === 'ledger' && ( - - - - )} - - {activeTab === 'reports' && ( - -
- قريباً... تقارير متقدمة -
-
- )} -
- - {showAddProperty && ( - setShowAddProperty(false)} - onSuccess={() => { - setShowAddProperty(false); - }} - /> - )} -
-
- ); -} \ No newline at end of file diff --git a/app/admin/privacy/page.js b/app/admin/privacy/page.js deleted file mode 100644 index 35bdb5d..0000000 --- a/app/admin/privacy/page.js +++ /dev/null @@ -1,85 +0,0 @@ -'use client'; - -import { useEffect, useState } from 'react'; -import AuthService from '@/app/services/AuthService'; -import Link from 'next/link'; - -const initialPolicy = `1. نحترم خصوصيتك ونلتزم بحماية بياناتك الشخصية. -2. يتم استخدام المعلومات لتحسين تجربة المستخدم وتأمين الخدمة. -3. لا نشارك البيانات مع أطراف خارجية بدون موافقتك. -4. يمكنك طلب حذف بياناتك من النظام في أي وقت.`; - -export default function PrivacyPolicyAdminPage() { - const [isAdmin, setIsAdmin] = useState(false); - const [checked, setChecked] = useState(false); - const [policyText, setPolicyText] = useState(initialPolicy); - const [saved, setSaved] = useState(false); - - useEffect(() => { - setIsAdmin(AuthService.isAuthenticated() && AuthService.isAdmin()); - setChecked(true); - }, []); - - const handleSave = (event) => { - event.preventDefault(); - setSaved(true); - console.log('Privacy policy updated:', policyText); - }; - - if (!checked) { - return ( -
-
-
- ); - } - - if (!isAdmin) { - return ( -
-
-

هذه الصفحة لتحرير سياسة الخصوصية ولا يمكن الوصول إليها إلا للمدير.

- - العودة للرئيسية - -
-
- ); - } - return ( -
-
-
-
-
-

لوحة المدير

-

قم بتحديث نص سياسة الخصوصية

-
-
-
- -
-
- -