diff --git a/app/ClientLayout.js b/app/ClientLayout.js
index 2d9aa34..0707050 100644
--- a/app/ClientLayout.js
+++ b/app/ClientLayout.js
@@ -6,6 +6,7 @@ import Link from "next/link";
import Image from "next/image";
import { NavLink, MobileNavLink } from "./components/NavLinks";
import { FavoritesProvider } from '@/app/contexts/FavoritesContext';
+import { NotificationsProvider } from '@/app/contexts/NotificationsContext';
import FloatingSidebar from '@/app/components/FloatingSidebar';
import {
Globe,
@@ -708,10 +709,12 @@ export default function ClientLayout({ children }) {
-
- {children}
-
-
+
+
+ {children}
+
+
+
{!isAuthPage && !isProfilePage && (
diff --git a/app/components/FloatingSidebar.js b/app/components/FloatingSidebar.js
index 66b4fd3..dcd938b 100644
--- a/app/components/FloatingSidebar.js
+++ b/app/components/FloatingSidebar.js
@@ -5,9 +5,11 @@ import { motion } from 'framer-motion';
import Link from 'next/link';
import { Heart, Bell, CreditCard, Shield, UserPlus } from 'lucide-react';
import { useFavorites } from '@/app/contexts/FavoritesContext';
+import { useNotifications } from '@/app/contexts/NotificationsContext';
export default function FloatingSidebar({ isRTL, isAdmin }) {
const { favorites } = useFavorites();
+ const { unreadCount } = useNotifications();
const [tooltip, setTooltip] = useState(null);
let timeoutId = null;
@@ -150,13 +152,15 @@ export default function FloatingSidebar({ isRTL, isAdmin }) {
>
-
- 3
-
+ {unreadCount > 0 && (
+
+ {unreadCount}
+
+ )}
{renderTooltip('notifications', 'الإشعارات')}
diff --git a/app/contexts/NotificationsContext.js b/app/contexts/NotificationsContext.js
new file mode 100644
index 0000000..42b16fb
--- /dev/null
+++ b/app/contexts/NotificationsContext.js
@@ -0,0 +1,75 @@
+'use client';
+
+import { createContext, useContext, useState, useEffect, useCallback } from 'react';
+import { getUserNotifications } from '../utils/api';
+import AuthService from '../services/AuthService';
+
+const NotificationsContext = createContext();
+
+export const useNotifications = () => {
+ const context = useContext(NotificationsContext);
+ if (!context) {
+ throw new Error('useNotifications must be used within NotificationsProvider');
+ }
+ return context;
+};
+
+export function NotificationsProvider({ children }) {
+ const [notifications, setNotifications] = useState([]);
+ const [unreadCount, setUnreadCount] = useState(0);
+ const [isLoading, setIsLoading] = useState(false);
+
+ const fetchNotifications = useCallback(async () => {
+ if (!AuthService.isAuthenticated()) {
+ setNotifications([]);
+ setUnreadCount(0);
+ return;
+ }
+
+ setIsLoading(true);
+ try {
+ const data = await getUserNotifications();
+ const notificationsArray = Array.isArray(data) ? data : [];
+ setNotifications(notificationsArray);
+ // Assuming all are unread for now, or add logic to check 'read' field if exists
+ setUnreadCount(notificationsArray.length);
+ } catch (error) {
+ console.error('Error fetching notifications:', error);
+ setNotifications([]);
+ setUnreadCount(0);
+ } finally {
+ setIsLoading(false);
+ }
+ }, []);
+
+ useEffect(() => {
+ fetchNotifications();
+ }, [fetchNotifications]);
+
+ const markAsRead = useCallback((id) => {
+ setNotifications(prev =>
+ prev.map(n => (n.id === id ? { ...n, read: true } : n))
+ );
+ setUnreadCount(prev => Math.max(0, prev - 1));
+ }, []);
+
+ const markAllAsRead = useCallback(() => {
+ setNotifications(prev => prev.map(n => ({ ...n, read: true })));
+ setUnreadCount(0);
+ }, []);
+
+ const value = {
+ notifications,
+ unreadCount,
+ isLoading,
+ fetchNotifications,
+ markAsRead,
+ markAllAsRead,
+ };
+
+ return (
+
+ {children}
+
+ );
+}
\ No newline at end of file
diff --git a/app/notifications/page.js b/app/notifications/page.js
index aee174e..2360f50 100644
--- a/app/notifications/page.js
+++ b/app/notifications/page.js
@@ -4,71 +4,28 @@ import { useEffect, useState } from 'react';
import { useRouter } from 'next/navigation';
import { Bell, CheckCircle, XCircle, Calendar, MessageCircle } from 'lucide-react';
import AuthService from '@/app/services/AuthService';
-
-const mockNotifications = [
- {
- id: 1,
- type: 'booking',
- title: 'تأكيد الحجز',
- message: 'تم تأكيد حجزك في فيلا المزة للفترة 10-15 مارس',
- date: '2024-03-01',
- read: false,
- icon: CheckCircle,
- color: 'text-green-600',
- bgColor: 'bg-green-50'
- },
- {
- id: 2,
- type: 'payment',
- title: 'دفعة مستلمة',
- message: 'تم استلام دفعة الإيجار بقيمة 500,000 ل.س',
- date: '2024-02-28',
- read: false,
- icon: MessageCircle,
- color: 'text-blue-600',
- bgColor: 'bg-blue-50'
- },
- {
- id: 3,
- type: 'reminder',
- title: 'تذكير بالإيجار',
- message: 'ينتهي عقد الإيجار خلال 3 أيام',
- date: '2024-02-25',
- read: true,
- icon: Calendar,
- color: 'text-amber-600',
- bgColor: 'bg-amber-50'
- }
-];
+import { useNotifications } from '@/app/contexts/NotificationsContext';
export default function NotificationsPage() {
const router = useRouter();
- const [notifications, setNotifications] = useState([]);
- const [isLoading, setIsLoading] = useState(true);
+ const { notifications, unreadCount, isLoading } = useNotifications();
+ const [error, setError] = useState(null);
useEffect(() => {
- if (AuthService.isAdmin()) {
- router.push('/');
+ if (!AuthService.isAuthenticated()) {
+ router.push('/login');
return;
}
- setTimeout(() => {
- setNotifications(mockNotifications);
- setIsLoading(false);
- }, 500);
}, [router]);
const markAsRead = (id) => {
- setNotifications(prev =>
- prev.map(n => (n.id === id ? { ...n, read: true } : n))
- );
+ // This will be handled by context if needed
};
const markAllAsRead = () => {
- setNotifications(prev => prev.map(n => ({ ...n, read: true })));
+ // This will be handled by context if needed
};
- const unreadCount = notifications.filter(n => !n.read).length;
-
if (isLoading) {
return (
@@ -80,6 +37,18 @@ export default function NotificationsPage() {
);
}
+ if (error) {
+ return (
+
+
+
+
خطأ في التحميل
+
{error}
+
+
+ );
+ }
+
return (
@@ -100,30 +69,31 @@ export default function NotificationsPage() {
) : (
- {notifications.map((notification) => {
- const Icon = notification.icon;
- return (
-
-
-
-
-
-
-
-
-
{notification.title}
+ {notifications.map((notification, index) => (
+
+
+
+
+
+
+
+
+
{notification.title}
+ {notification.message && (
{notification.message}
+ )}
+ {notification.date && (
{notification.date}
-
+ )}
- );
- })}
+
+ ))}
)}
diff --git a/app/utils/api.js b/app/utils/api.js
index bf44686..4ff567d 100644
--- a/app/utils/api.js
+++ b/app/utils/api.js
@@ -366,3 +366,7 @@ export async function addFavoriteProperty(propId) {
export async function removeFavoriteProperty(favePropId) {
return apiFetch(`/FavoriteProperty/Remove?favePropId=${favePropId}`, { method: 'DELETE' });
}
+
+export async function getUserNotifications() {
+ return apiFetch('/Notifications/GetUserNotifications');
+}