Edit admin page
Edit home image Added properties page
This commit is contained in:
103
app/utils/PropertyContext.js
Normal file
103
app/utils/PropertyContext.js
Normal file
@ -0,0 +1,103 @@
|
||||
'use client';
|
||||
|
||||
import { createContext, useContext, useState, useCallback } from 'react';
|
||||
|
||||
const PropertyContext = createContext();
|
||||
|
||||
export const useProperties = () => {
|
||||
const context = useContext(PropertyContext);
|
||||
if (!context) {
|
||||
throw new Error('useProperties must be used within PropertyProvider');
|
||||
}
|
||||
return context;
|
||||
};
|
||||
|
||||
export const PropertyProvider = ({ children }) => {
|
||||
const [properties, setProperties] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
const addProperty = useCallback(async (propertyData) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const newProperty = {
|
||||
id: Date.now().toString(),
|
||||
...propertyData,
|
||||
createdAt: new Date().toISOString(),
|
||||
status: 'available',
|
||||
bookings: [],
|
||||
commission: {
|
||||
rate: propertyData.commissionRate || 5,
|
||||
type: propertyData.commissionType || 'from_owner',
|
||||
isActive: true
|
||||
}
|
||||
};
|
||||
|
||||
setProperties(prev => [...prev, newProperty]);
|
||||
return newProperty;
|
||||
} catch (err) {
|
||||
setError(err.message);
|
||||
throw err;
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const updateProperty = useCallback(async (id, updates) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
setProperties(prev =>
|
||||
prev.map(p => p.id === id ? { ...p, ...updates } : p)
|
||||
);
|
||||
} catch (err) {
|
||||
setError(err.message);
|
||||
throw err;
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const deleteProperty = useCallback(async (id) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
setProperties(prev => prev.filter(p => p.id !== id));
|
||||
} catch (err) {
|
||||
setError(err.message);
|
||||
throw err;
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const checkAvailability = useCallback((propertyId, startDate, endDate) => {
|
||||
const property = properties.find(p => p.id === propertyId);
|
||||
if (!property) return false;
|
||||
|
||||
return !property.bookings?.some(booking => {
|
||||
const bookingStart = new Date(booking.startDate);
|
||||
const bookingEnd = new Date(booking.endDate);
|
||||
const checkStart = new Date(startDate);
|
||||
const checkEnd = new Date(endDate);
|
||||
|
||||
return (
|
||||
(checkStart >= bookingStart && checkStart <= bookingEnd) ||
|
||||
(checkEnd >= bookingStart && checkEnd <= bookingEnd) ||
|
||||
(checkStart <= bookingStart && checkEnd >= bookingEnd)
|
||||
);
|
||||
});
|
||||
}, [properties]);
|
||||
|
||||
return (
|
||||
<PropertyContext.Provider value={{
|
||||
properties,
|
||||
loading,
|
||||
error,
|
||||
addProperty,
|
||||
updateProperty,
|
||||
deleteProperty,
|
||||
checkAvailability
|
||||
}}>
|
||||
{children}
|
||||
</PropertyContext.Provider>
|
||||
);
|
||||
};
|
||||
67
app/utils/calculations.js
Normal file
67
app/utils/calculations.js
Normal file
@ -0,0 +1,67 @@
|
||||
export const calculateRentWithCommission = (
|
||||
dailyPrice,
|
||||
numberOfDays,
|
||||
commissionRate,
|
||||
commissionType
|
||||
) => {
|
||||
const baseRent = dailyPrice * numberOfDays;
|
||||
const commission = (baseRent * commissionRate) / 100;
|
||||
|
||||
switch(commissionType) {
|
||||
case 'from_tenant':
|
||||
return {
|
||||
totalForTenant: baseRent + commission,
|
||||
totalForOwner: baseRent,
|
||||
commission: commission
|
||||
};
|
||||
case 'from_owner':
|
||||
return {
|
||||
totalForTenant: baseRent,
|
||||
totalForOwner: baseRent - commission,
|
||||
commission: commission
|
||||
};
|
||||
case 'from_both':
|
||||
return {
|
||||
totalForTenant: baseRent + (commission / 2),
|
||||
totalForOwner: baseRent - (commission / 2),
|
||||
commission: commission
|
||||
};
|
||||
default:
|
||||
return {
|
||||
totalForTenant: baseRent,
|
||||
totalForOwner: baseRent,
|
||||
commission: 0
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
export const calculateDaysBetween = (startDate, endDate) => {
|
||||
const start = new Date(startDate);
|
||||
const end = new Date(endDate);
|
||||
const diffTime = Math.abs(end - start);
|
||||
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
|
||||
return diffDays;
|
||||
};
|
||||
|
||||
|
||||
export const formatCurrency = (amount) => {
|
||||
return new Intl.NumberFormat('ar-SY', {
|
||||
style: 'currency',
|
||||
currency: 'SYP',
|
||||
minimumFractionDigits: 0,
|
||||
maximumFractionDigits: 0
|
||||
}).format(amount).replace('SYP', '') + ' ل.س';
|
||||
};
|
||||
|
||||
export const calculateTenantBalance = (bookings, securityDeposits) => {
|
||||
return bookings.reduce((acc, booking) => {
|
||||
const deposit = securityDeposits.find(d => d.bookingId === booking.id) || 0;
|
||||
return {
|
||||
totalRent: acc.totalRent + booking.totalAmount,
|
||||
paidAmount: acc.paidAmount + booking.paidAmount,
|
||||
securityDeposit: acc.securityDeposit + deposit.amount,
|
||||
pendingAmount: (acc.pendingAmount + (booking.totalAmount - booking.paidAmount))
|
||||
};
|
||||
}, { totalRent: 0, paidAmount: 0, securityDeposit: 0, pendingAmount: 0 });
|
||||
};
|
||||
41
app/utils/constants.js
Normal file
41
app/utils/constants.js
Normal file
@ -0,0 +1,41 @@
|
||||
export const PROPERTY_STATUS = {
|
||||
AVAILABLE: 'available',
|
||||
BOOKED: 'booked',
|
||||
MAINTENANCE: 'maintenance'
|
||||
};
|
||||
|
||||
export const BOOKING_STATUS = {
|
||||
PENDING: 'pending',
|
||||
OWNER_APPROVED: 'owner_approved',
|
||||
ADMIN_APPROVED: 'admin_approved',
|
||||
REJECTED: 'rejected',
|
||||
ACTIVE: 'active',
|
||||
COMPLETED: 'completed',
|
||||
CANCELLED: 'cancelled'
|
||||
};
|
||||
|
||||
export const COMMISSION_TYPE = {
|
||||
FROM_OWNER: 'from_owner',
|
||||
FROM_TENANT: 'from_tenant',
|
||||
FROM_BOTH: 'from_both'
|
||||
};
|
||||
|
||||
export const IDENTITY_TYPE = {
|
||||
SYRIAN: 'syrian',
|
||||
PASSPORT: 'passport'
|
||||
};
|
||||
|
||||
export const PAYMENT_METHOD = {
|
||||
CASH: 'cash',
|
||||
ELECTRONIC: 'electronic'
|
||||
};
|
||||
|
||||
export const CITIES = {
|
||||
DAMASCUS: 'damascus',
|
||||
ALEPPO: 'aleppo',
|
||||
HOMS: 'homs',
|
||||
LATTAKIA: 'latakia',
|
||||
DARAA: 'daraa'
|
||||
};
|
||||
|
||||
export const DEFAULT_COMMISSION_RATE = 5;
|
||||
Reference in New Issue
Block a user