Fix build: syntax errors, duplicate useEffects, import paths
All checks were successful
Build frontend / build (push) Successful in 1m26s
All checks were successful
Build frontend / build (push) Successful in 1m26s
- Fixed broken useEffect syntax in 4 owner pages (bookings, calendar, profits, properties) - Removed duplicate useEffect blocks - Fixed ClientLayout import path for AuthService (../ -> ./)
This commit is contained in:
@ -36,7 +36,7 @@ import {
|
|||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { useState, useEffect, useRef } from "react";
|
import { useState, useEffect, useRef } from "react";
|
||||||
import { motion, AnimatePresence } from "framer-motion";
|
import { motion, AnimatePresence } from "framer-motion";
|
||||||
import AuthService from "../services/AuthService";
|
import AuthService from "./services/AuthService";
|
||||||
import { UserRole, UserRoleLabels } from "./enums/UserRole";
|
import { UserRole, UserRoleLabels } from "./enums/UserRole";
|
||||||
import "./i18n/config";
|
import "./i18n/config";
|
||||||
|
|
||||||
@ -64,7 +64,9 @@ export default function ClientLayout({ children }) {
|
|||||||
name: authUser.name || authUser.email,
|
name: authUser.name || authUser.email,
|
||||||
email: authUser.email,
|
email: authUser.email,
|
||||||
phone: authUser.phone,
|
phone: authUser.phone,
|
||||||
role: AuthService.isOwner() ? UserRole.OWNER : UserRole.CUSTOMER,
|
role: AuthService.isAdmin() ? UserRole.ADMIN
|
||||||
|
: AuthService.isOwner() ? UserRole.OWNER
|
||||||
|
: UserRole.CUSTOMER,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
setUser(null);
|
setUser(null);
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
import { useState } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
|
import { useRouter } from 'next/navigation';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import {
|
import {
|
||||||
Home,
|
Home,
|
||||||
@ -18,14 +19,22 @@ import UsersList from '../components/admin/UsersList';
|
|||||||
import LedgerBook from '../components/admin/LedgerBook';
|
import LedgerBook from '../components/admin/LedgerBook';
|
||||||
import AddPropertyForm from '../components/admin/AddPropertyForm';
|
import AddPropertyForm from '../components/admin/AddPropertyForm';
|
||||||
import { PropertyProvider } from '../contexts/PropertyContext';
|
import { PropertyProvider } from '../contexts/PropertyContext';
|
||||||
|
import AuthService from '../services/AuthService';
|
||||||
import '../i18n/config';
|
import '../i18n/config';
|
||||||
|
|
||||||
export default function AdminPage() {
|
export default function AdminPage() {
|
||||||
const { t, i18n } = useTranslation();
|
const { t, i18n } = useTranslation();
|
||||||
|
const router = useRouter();
|
||||||
const [activeTab, setActiveTab] = useState('dashboard');
|
const [activeTab, setActiveTab] = useState('dashboard');
|
||||||
const [showAddProperty, setShowAddProperty] = useState(false);
|
const [showAddProperty, setShowAddProperty] = useState(false);
|
||||||
const [notifications, setNotifications] = useState(3);
|
const [notifications, setNotifications] = useState(3);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!AuthService.isAuthenticated() || !AuthService.isAdmin()) {
|
||||||
|
router.push('/');
|
||||||
|
}
|
||||||
|
}, [router]);
|
||||||
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
{ id: 'dashboard', label: 'لوحة التحكم', icon: Home },
|
{ id: 'dashboard', label: 'لوحة التحكم', icon: Home },
|
||||||
{ id: 'properties', label: 'العقارات', icon: Home },
|
{ id: 'properties', label: 'العقارات', icon: Home },
|
||||||
|
|||||||
@ -95,8 +95,8 @@ export default function LoginPage() {
|
|||||||
|
|
||||||
// Decode token to get user info via AuthService
|
// Decode token to get user info via AuthService
|
||||||
const authUser = AuthService.getUser();
|
const authUser = AuthService.getUser();
|
||||||
const userRole = authUser?.roles?.includes('Owner') ? 'owner'
|
const userRole = AuthService.isAdmin() ? 'admin'
|
||||||
: authUser?.roles?.includes('Admin') ? 'admin'
|
: AuthService.isOwner() ? 'owner'
|
||||||
: 'customer';
|
: 'customer';
|
||||||
console.log('[Login] User role:', userRole);
|
console.log('[Login] User role:', userRole);
|
||||||
|
|
||||||
|
|||||||
@ -33,7 +33,7 @@ import {
|
|||||||
Building
|
Building
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import toast, { Toaster } from 'react-hot-toast';
|
import toast, { Toaster } from 'react-hot-toast';
|
||||||
import AuthService from '../../../services/AuthService';
|
import AuthService from '../../services/AuthService';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
|
|
||||||
const OwnerBookingCalendar = ({ property, onDateSelect, selectedDates }) => {
|
const OwnerBookingCalendar = ({ property, onDateSelect, selectedDates }) => {
|
||||||
@ -425,20 +425,20 @@ export default function OwnerBookingsPage() {
|
|||||||
const [showCalendar, setShowCalendar] = useState(false);
|
const [showCalendar, setShowCalendar] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const storedUser = localStorage.getItem('user');
|
const authUser = AuthService.getUser();
|
||||||
// User loaded via AuthService
|
if (authUser && AuthService.isOwner()) {
|
||||||
// Handled above
|
setUser({
|
||||||
if (userData.role !== 'owner') {
|
name: authUser.name || authUser.email,
|
||||||
router.push('/');
|
email: authUser.email,
|
||||||
} else {
|
role: 'owner',
|
||||||
setUser(userData);
|
});
|
||||||
loadBookings();
|
loadBookings();
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
router.push('/auth/choose-role');
|
router.push('/auth/choose-role');
|
||||||
}
|
}
|
||||||
}, [router]);
|
}, [router]);
|
||||||
|
|
||||||
|
|
||||||
const loadBookings = () => {
|
const loadBookings = () => {
|
||||||
const storedBookings = localStorage.getItem('ownerBookings');
|
const storedBookings = localStorage.getItem('ownerBookings');
|
||||||
if (storedBookings) {
|
if (storedBookings) {
|
||||||
@ -511,30 +511,7 @@ export default function OwnerBookingsPage() {
|
|||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
let filtered = [...bookings];
|
|
||||||
|
|
||||||
if (filterStatus !== 'all') {
|
|
||||||
filtered = filtered.filter(b => b.status === filterStatus);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (searchTerm) {
|
|
||||||
filtered = filtered.filter(b =>
|
|
||||||
b.propertyTitle.includes(searchTerm) ||
|
|
||||||
b.tenantName.includes(searchTerm) ||
|
|
||||||
b.id.includes(searchTerm)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dateRange.start) {
|
|
||||||
filtered = filtered.filter(b => b.startDate >= dateRange.start);
|
|
||||||
}
|
|
||||||
if (dateRange.end) {
|
|
||||||
filtered = filtered.filter(b => b.endDate <= dateRange.end);
|
|
||||||
}
|
|
||||||
|
|
||||||
setFilteredBookings(filtered);
|
|
||||||
}, [filterStatus, searchTerm, dateRange, bookings]);
|
|
||||||
|
|
||||||
const handleViewDetails = (booking) => {
|
const handleViewDetails = (booking) => {
|
||||||
setSelectedBooking(booking);
|
setSelectedBooking(booking);
|
||||||
|
|||||||
@ -36,7 +36,7 @@ import {
|
|||||||
Calendar as CalendarIcon
|
Calendar as CalendarIcon
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import toast, { Toaster } from 'react-hot-toast';
|
import toast, { Toaster } from 'react-hot-toast';
|
||||||
import AuthService from '../../../services/AuthService';
|
import AuthService from '../../services/AuthService';
|
||||||
|
|
||||||
const MonthlyCalendar = ({ properties, selectedPropertyId, onDateClick, onPropertySelect }) => {
|
const MonthlyCalendar = ({ properties, selectedPropertyId, onDateClick, onPropertySelect }) => {
|
||||||
const [currentMonth, setCurrentMonth] = useState(new Date());
|
const [currentMonth, setCurrentMonth] = useState(new Date());
|
||||||
@ -484,20 +484,21 @@ export default function OwnerCalendarPage() {
|
|||||||
const [showFilters, setShowFilters] = useState(false);
|
const [showFilters, setShowFilters] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const storedUser = localStorage.getItem('user');
|
const authUser = AuthService.getUser();
|
||||||
// User loaded via AuthService
|
if (authUser && AuthService.isOwner()) {
|
||||||
// Handled above
|
setUser({
|
||||||
if (userData.role !== 'owner') {
|
name: authUser.name || authUser.email,
|
||||||
router.push('/');
|
email: authUser.email,
|
||||||
} else {
|
role: 'owner',
|
||||||
setUser(userData);
|
});
|
||||||
loadProperties();
|
loadCalendar();
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
router.push('/auth/choose-role');
|
router.push('/auth/choose-role');
|
||||||
}
|
}
|
||||||
}, [router]);
|
}, [router]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const loadProperties = () => {
|
const loadProperties = () => {
|
||||||
const storedProperties = localStorage.getItem('ownerProperties');
|
const storedProperties = localStorage.getItem('ownerProperties');
|
||||||
if (storedProperties) {
|
if (storedProperties) {
|
||||||
|
|||||||
@ -28,7 +28,7 @@ import {
|
|||||||
XCircle
|
XCircle
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import toast, { Toaster } from 'react-hot-toast';
|
import toast, { Toaster } from 'react-hot-toast';
|
||||||
import AuthService from '../../../services/AuthService';
|
import AuthService from '../../services/AuthService';
|
||||||
|
|
||||||
const StatCard = ({ title, value, change, icon: Icon, color, trend }) => {
|
const StatCard = ({ title, value, change, icon: Icon, color, trend }) => {
|
||||||
return (
|
return (
|
||||||
@ -234,22 +234,23 @@ export default function OwnerProfitsPage() {
|
|||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const [selectedProperty, setSelectedProperty] = useState(null);
|
const [selectedProperty, setSelectedProperty] = useState(null);
|
||||||
const [dateRange, setDateRange] = useState({ start: '', end: '' });
|
const [dateRange, setDateRange] = useState({ start: '', end: '' });
|
||||||
const [selectedPeriod, setSelectedPeriod] = useState('month'); // month, year, all
|
const [selectedPeriod, setSelectedPeriod] = useState('month');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const storedUser = localStorage.getItem('user');
|
const authUser = AuthService.getUser();
|
||||||
// User loaded via AuthService
|
if (authUser && AuthService.isOwner()) {
|
||||||
// Handled above
|
setUser({
|
||||||
if (userData.role !== 'owner') {
|
name: authUser.name || authUser.email,
|
||||||
router.push('/');
|
email: authUser.email,
|
||||||
} else {
|
role: 'owner',
|
||||||
setUser(userData);
|
});
|
||||||
loadProfitsData();
|
loadData();
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
router.push('/auth/choose-role');
|
router.push('/auth/choose-role');
|
||||||
}
|
}
|
||||||
}, [router]);
|
}, [router]); // month, year, all
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const loadProfitsData = () => {
|
const loadProfitsData = () => {
|
||||||
const storedProfits = localStorage.getItem('ownerProfits');
|
const storedProfits = localStorage.getItem('ownerProfits');
|
||||||
|
|||||||
@ -45,7 +45,7 @@ import {
|
|||||||
X
|
X
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import toast, { Toaster } from 'react-hot-toast';
|
import toast, { Toaster } from 'react-hot-toast';
|
||||||
import AuthService from '../../../services/AuthService';
|
import AuthService from '../../services/AuthService';
|
||||||
|
|
||||||
const DeleteConfirmationModal = ({ isOpen, onClose, onConfirm, propertyTitle }) => {
|
const DeleteConfirmationModal = ({ isOpen, onClose, onConfirm, propertyTitle }) => {
|
||||||
if (!isOpen) return null;
|
if (!isOpen) return null;
|
||||||
@ -693,20 +693,21 @@ export default function OwnerPropertiesPage() {
|
|||||||
const [editModal, setEditModal] = useState({ isOpen: false, property: null });
|
const [editModal, setEditModal] = useState({ isOpen: false, property: null });
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const storedUser = localStorage.getItem('user');
|
const authUser = AuthService.getUser();
|
||||||
// User loaded via AuthService
|
if (authUser && AuthService.isOwner()) {
|
||||||
// Handled above
|
setUser({
|
||||||
if (userData.role !== 'owner') {
|
name: authUser.name || authUser.email,
|
||||||
router.push('/');
|
email: authUser.email,
|
||||||
} else {
|
role: 'owner',
|
||||||
setUser(userData);
|
});
|
||||||
loadProperties();
|
loadProperties();
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
router.push('/auth/choose-role');
|
router.push('/auth/choose-role');
|
||||||
}
|
}
|
||||||
}, [router]);
|
}, [router]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const loadProperties = () => {
|
const loadProperties = () => {
|
||||||
const storedProperties = localStorage.getItem('ownerProperties');
|
const storedProperties = localStorage.getItem('ownerProperties');
|
||||||
if (storedProperties) {
|
if (storedProperties) {
|
||||||
|
|||||||
@ -86,16 +86,23 @@ const AuthService = Object.freeze({
|
|||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
isOwner() {
|
isOwner() {
|
||||||
const roles = this.getRoles();
|
return this.getRoles().includes('Owner');
|
||||||
return roles.includes('Owner');
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authenticated user without Owner role (i.e. customer)
|
* User has Admin role
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
isAdmin() {
|
||||||
|
return this.getRoles().includes('Admin');
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authenticated user without Owner or Admin role (i.e. customer)
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
isCustomer() {
|
isCustomer() {
|
||||||
return this.isAuthenticated() && !this.isOwner();
|
return this.isAuthenticated() && !this.isOwner() && !this.isAdmin();
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user