-
- {t('accountBook')}
- {t('financialRecords')}
+
+ {t("accountBook")}
+ {t("financialRecords")}
-
- {t('accountBook.ownerFinancialOverview')}
+
+ {t("accountBook.ownerFinancialOverview")}
-
-
-
+
+
+
-
- {t('accountBook.directPropertyStats')}
+
+ {t("accountBook.directPropertyStats")}
-
-
-
-
-
+
+
+
+
+
diff --git a/app/owner/bookings/loading.js b/app/owner/bookings/loading.js
deleted file mode 100644
index 0c01106..0000000
--- a/app/owner/bookings/loading.js
+++ /dev/null
@@ -1,14 +0,0 @@
-'use client';
-
-import { motion } from 'framer-motion';
-
-export default function Loading() {
- return (
-
-
-
- جاري التحميل...
-
-
- );
-}
diff --git a/app/owner/calendar/loading.js b/app/owner/calendar/loading.js
deleted file mode 100644
index 0c01106..0000000
--- a/app/owner/calendar/loading.js
+++ /dev/null
@@ -1,14 +0,0 @@
-'use client';
-
-import { motion } from 'framer-motion';
-
-export default function Loading() {
- return (
-
-
-
- جاري التحميل...
-
-
- );
-}
diff --git a/app/owner/profits/loading.js b/app/owner/profits/loading.js
deleted file mode 100644
index 0c01106..0000000
--- a/app/owner/profits/loading.js
+++ /dev/null
@@ -1,14 +0,0 @@
-'use client';
-
-import { motion } from 'framer-motion';
-
-export default function Loading() {
- return (
-
-
-
- جاري التحميل...
-
-
- );
-}
diff --git a/app/page.js b/app/page.js
index d50f6aa..ec2d62a 100644
--- a/app/page.js
+++ b/app/page.js
@@ -1,600 +1,9 @@
-'use client';
-
-import { useState, useRef, useEffect } from 'react';
-import { motion, AnimatePresence } from 'framer-motion';
-import { usePathname } from 'next/navigation';
-import {
- ShieldCheck,
- Lock,
- Zap,
- Star,
- Rocket,
- Search,
- MapPin,
- Home,
- DollarSign,
- ChevronDown,
- Shield,
- Award,
- Sparkles,
- UserCircle,
- LogOut,
- Calendar,
- Building,
- PlusCircle,
- Heart,
- MessageCircle
-} from 'lucide-react';
-import HeroSearch from './components/home/HeroSearch';
-import PropertyMapWithMarkers from './components/PropertyMapWithMarkers';
-import Link from 'next/link';
-import Image from 'next/image';
-import { getRentProperties, getSaleProperties } from './utils/api';
-import { BuildingTypeKeys, PropertyStatusKeys, extractCity } from './enums';
-import AuthService from './services/AuthService';
-import { useTranslation } from 'react-i18next';
-
-function mapApiProperty(t, item, index) {
- const info = item.propertyInformation || {};
-
- const dailyPrice = item.dailyRent ?? 0;
- const monthlyPrice = item.monthlyRent ?? 0;
- const salePrice = item.price ?? 0;
- const isRentListing = Boolean(item.dailyRent != null || item.monthlyRent != null);
-
- const price = isRentListing ? (dailyPrice || monthlyPrice || 0) : salePrice;
- const priceUnit = isRentListing ? (monthlyPrice ? 'monthly' : 'daily') : 'sale';
-
- const propType = BuildingTypeKeys[info.buildingType] ?? BuildingTypeKeys[item.type] ?? (item.type || 'apartment');
- const status = PropertyStatusKeys[info.status] ?? PropertyStatusKeys[item.status] ?? 'available';
-
- const features = [];
- if (item.isSmokeAllow) features.push(t('smoke-allowed'));
- if (item.isVisitorAllow) features.push(t('visitors-allowed'));
- if (item.specializedFor) features.push(t('specialized'));
- if (info.numberOfBedRooms) features.push(`${info.numberOfBedRooms} ${t('rooms')}`);
- if (info.numberOfBathRooms) features.push(`${info.numberOfBathRooms} ${t('bathrooms')}`);
-
- const apiBase = typeof window !== 'undefined' ? (process.env.NEXT_PUBLIC_API_URL || 'https://45.93.137.91.nip.io/api') : '';
- const rawImages = Array.isArray(info.images) ? info.images : [];
- const images = rawImages.length > 0
- ? rawImages.map(img => img.startsWith('http') ? img : `${apiBase}${img.startsWith('/') ? '' : '/Pictures/'}${img}`)
- : ['/property-placeholder.jpg'];
-
- const ownerSource = info.ownerType == null && item.ownerType == null
- ? 'all'
- : [info.ownerType, item.ownerType].find((value) => value != null) === 1
- ? 'agency'
- : 'owner';
-
- return {
- id: item.id ?? index + 1,
- title: info.address || t('propertyWithId', { id: item.id || index + 1 }),
- description: info.description || '',
- type: propType,
- price: price,
- priceUSD: price,
- priceUnit,
- listingType: isRentListing ? 'rent' : 'sale',
- location: {
- city: extractCity(info.address) || 'damascus',
- district: info.address || '',
- address: info.address || '',
- lat: parseFloat(info.cordsX) || 0,
- lng: parseFloat(info.cordsY) || 0,
- },
- bedrooms: info.numberOfBedRooms || 0,
- bathrooms: info.numberOfBathRooms || 0,
- area: info.space || 0,
- features,
- images,
- status,
- rating: item.rating || 4.5,
- isNew: false,
- allowedIdentities: ['syrian', 'passport'],
- priceDisplay: {
- daily: dailyPrice,
- monthly: monthlyPrice,
- sale: salePrice,
- },
- ownerSource,
- bookings: [],
- _raw: item,
- };
-}
+import HomeClient from "./components/home/HomeClient";
+export const metadata = {
+ title: "الصفحة الرئيسية | عقاراتك",
+ description: "ابحث عن العقارات والبيوت للإيجار والبيع بأسهل الطرق.",
+};
export default function HomePage() {
- const { t } = useTranslation();
- const mapSectionRef = useRef(null);
- const [searchFilters, setSearchFilters] = useState(null);
- const [showMap, setShowMap] = useState(false);
- const [filteredProperties, setFilteredProperties] = useState([]);
- const [isScrolling, setIsScrolling] = useState(false);
- const [user, setUser] = useState(null);
- const [showUserMenu, setShowUserMenu] = useState(false);
- const menuRef = useRef(null);
- const pathname = usePathname();
-
- const [allProperties, setAllProperties] = useState([]);
- const [rentProperties, setRentProperties] = useState([]);
- const [saleProperties, setSaleProperties] = useState([]);
- const [loading, setLoading] = useState(true);
-
- useEffect(() => {
- const authUser = AuthService.getUser();
- if (authUser) {
- setUser({
- name: authUser.name || authUser.email,
- email: authUser.email,
- role: AuthService.isOwner() ? 'owner' : 'customer',
- });
- } else {
- setUser(null);
- }
- }, [pathname]);
-
- useEffect(() => {
-
- async function fetchProperties() {
- try {
- const [rentData, saleData] = await Promise.all([
- getRentProperties().catch(() => []),
- getSaleProperties().catch(() => []),
- ]);
-
- const rentList = Array.isArray(rentData) ? rentData : [];
- const saleList = Array.isArray(saleData) ? saleData : [];
-
- const mappedRent = rentList.map((p, i) => mapApiProperty(t, p, i));
- const mappedSale = saleList.map((p, i) => mapApiProperty(t, p, rentList.length + i));
-
- setRentProperties(mappedRent);
- setSaleProperties(mappedSale);
- setAllProperties([...mappedRent, ...mappedSale]);
- } catch (err) {
- console.error('[Home] Failed to fetch properties:', err);
- } finally {
- setLoading(false);
- }
- }
-
- fetchProperties();
- }, []);
-
- useEffect(() => {
- if (searchFilters) {
- applyFilters(searchFilters);
- }
- }, [rentProperties, saleProperties, searchFilters]);
-
- const logout = () => {
- AuthService.deleteToken();
- setUser(null);
- setShowUserMenu(false);
- };
-
- const applyFilters = (filters) => {
- setSearchFilters(filters);
-
- let propertiesToFilter = [];
- if (filters.mode === 'rent') {
- propertiesToFilter = rentProperties;
- } else if (filters.mode === 'buy' || filters.mode === 'sell') {
- propertiesToFilter = saleProperties;
- } else {
- propertiesToFilter = allProperties;
- }
-
- const filtered = propertiesToFilter.filter(property => {
- if (filters.city && filters.city !== 'all' && property.location.city !== filters.city) {
- return false;
- }
-
- if (filters.propertyType && filters.propertyType !== 'all' && property.type !== filters.propertyType) {
- return false;
- }
-
- if (filters.priceRange && filters.priceRange !== 'all') {
- const priceUSD = property.priceUSD;
- switch (filters.priceRange) {
- case '0-500': if (priceUSD > 50) return false; break;
- case '500-1000': if (priceUSD < 51 || priceUSD > 100) return false; break;
- case '1000-2000': if (priceUSD < 101 || priceUSD > 200) return false; break;
- case '2000-3000': if (priceUSD < 201 || priceUSD > 300) return false; break;
- case '3000+': if (priceUSD < 301) return false; break;
- }
- }
-
- if (filters.ownerSource && filters.ownerSource !== 'all') {
- if (filters.ownerSource === 'owner' && property.ownerSource !== 'owner') return false;
- if (filters.ownerSource === 'agency' && property.ownerSource !== 'agency') return false;
- }
-
- if (filters.rentPeriod && filters.rentPeriod !== 'all' && property.listingType === 'rent') {
- if (filters.rentPeriod === 'daily' && !property.priceDisplay.daily) return false;
- if (filters.rentPeriod === 'monthly' && !property.priceDisplay.monthly) return false;
- }
-
- if (filters.availableToday) {
- if (property.status !== 'available') return false;
- }
-
- if (filters.identityType && property.allowedIdentities) {
- if (!property.allowedIdentities.includes(filters.identityType)) {
- return false;
- }
- }
-
- return true;
- });
-
- setFilteredProperties(filtered);
-
- if (!showMap) {
- setShowMap(true);
-
- setTimeout(() => {
- if (mapSectionRef.current) {
- setIsScrolling(true);
- mapSectionRef.current.scrollIntoView({
- behavior: 'smooth',
- block: 'center'
- });
-
- setTimeout(() => setIsScrolling(false), 1000);
- }
- }, 300);
- } else {
- if (mapSectionRef.current) {
- setIsScrolling(true);
- mapSectionRef.current.scrollIntoView({
- behavior: 'smooth',
- block: 'center'
- });
- setTimeout(() => setIsScrolling(false), 1000);
- }
- }
- };
-
- const resetSearch = () => {
- setShowMap(false);
- setSearchFilters(null);
- setFilteredProperties([]);
- window.scrollTo({
- top: 0,
- behavior: 'smooth'
- });
- };
-
- const getUserInitial = () => {
- if (user?.name) {
- return user.name.charAt(0).toUpperCase();
- }
- return null;
- };
-
- const isOwner = user?.role === 'owner';
-
- return (
-
-
-
-
-
-
- {t("heroTitleLine1")}
-
- {t("heroTitleLine2")}
-
-
-
- {t("heroSubtitle")}
-
-
-
- {!isOwner &&
}
-
- {isOwner && (
-
-
- {t("ownerGreeting")} {user?.name}!
-
-
- {t("ownerDescription")}
-
-
-
- {t("manageMyProperties")}
-
-
- )}
-
-
-
- {!showMap && !isOwner && (
- window.scrollTo({
- top: window.innerHeight,
- behavior: 'smooth'
- })}
- >
-
-
- )}
-
-
- {!isOwner && (<>
-
- {showMap && (
-
- {isScrolling && (
-
- )}
-
-
-
-
-
- {filteredProperties.length > 0 ? t('searchResults') : t('no-properties')}
-
-
-
- {t('newSearch')}
-
-
-
- {filteredProperties.length > 0 ? (
-
- {t('foundPropertiesCount', { count: filteredProperties.length })}
-
- ) : (
-
- {t('noPropertiesMatchFilters')}
-
- )}
-
-
-
- {filteredProperties.length > 0 ? (
- ({
- ...p,
- lat: p.location.lat,
- lng: p.location.lng,
- address: p.location.address
- }))}
- onPropertyClick={() => {}}
- />
- ) : (
-
-
-
{t('no-properties')}
-
{t('try-changing-search-criteria')}
-
- )}
-
-
-
- )}
-
- >)}
-
-
-
- {t('whyChooseUsTitle')}
-
-
- {t('whyChooseUsSubtitle')}
-
-
-
-
-
-
-
-
-
-
- {t('feature1Title')}
-
-
-
- {t('feature1Description')}
-
-
-
-
-
-
-
-
-
- {t('feature2Title')}
-
-
-
- {t('feature2Description')}
-
-
-
-
-
-
-
-
-
- {t('feature3Title')}
-
-
-
- {t('feature3Description')}
-
-
-
-
- {filteredProperties.length > 0 && searchFilters && (
-
-
- {t('filterPropertyTypeLabel')}
-
- {searchFilters.propertyType === 'all' ? t('all') :
- searchFilters.propertyType === 'apartment' ? t('buildingType.apartment') :
- searchFilters.propertyType === 'villa' ? t('buildingType.villa') : t('house')}
-
-
-
- {t('filterPriceRangeLabel')}
-
- {searchFilters.priceRange === 'all' ? t('allPrices') :
- searchFilters.priceRange === '0-500' ? t('priceRangeUnder500') :
- searchFilters.priceRange === '500-1000' ? t('priceRange50to100') :
- searchFilters.priceRange === '1000-2000' ? t('priceRange100to200') :
- searchFilters.priceRange === '2000-3000' ? t('priceRange200to300') : t('priceRangeOver300')}
-
-
-
- {t('filterSourceLabel')}
-
- {searchFilters.ownerSource === 'all' ? t('all') :
- searchFilters.ownerSource === 'owner' ? t('fromOwner') : t('fromAgency')}
-
-
-
- {t('filterRentTypeLabel')}
-
- {searchFilters.rentPeriod === 'all' ? t('all') :
- searchFilters.rentPeriod === 'daily' ? t('dailyRent') : t('monthlyRent')}
-
-
- {searchFilters.availableToday && (
-
- {t('availableFromToday')}
-
- )}
-
- )}
-
- );
-}
\ No newline at end of file
+ return
;
+}
diff --git a/app/profile/loading.js b/app/profile/loading.js
deleted file mode 100644
index af02e7b..0000000
--- a/app/profile/loading.js
+++ /dev/null
@@ -1,14 +0,0 @@
-'use client';
-
-import { motion } from 'framer-motion';
-
-export default function Loading() {
- return (
-
-
-
- جاري التحميل...
-
-
- );
-}
diff --git a/app/properties/loading.js b/app/properties/loading.js
deleted file mode 100644
index af02e7b..0000000
--- a/app/properties/loading.js
+++ /dev/null
@@ -1,14 +0,0 @@
-'use client';
-
-import { motion } from 'framer-motion';
-
-export default function Loading() {
- return (
-
-
-
- جاري التحميل...
-
-
- );
-}
diff --git a/app/property/[id]/PropertyDetail.js b/app/property/[id]/PropertyDetail.js
index 5ead963..ab1f1e9 100644
--- a/app/property/[id]/PropertyDetail.js
+++ b/app/property/[id]/PropertyDetail.js
@@ -55,22 +55,14 @@ import {
CassetteTape,
Info,
} from "lucide-react";
-import {
- getRentProperty,
- getSaleProperty,
- getSalePropertyById,
- bookReservation,
- getAvailableDateRanges,
- getOwnerContactInformation,
- getMyRentListings,
- getMySaleListings,
-} from "../../utils/api";
+import { getRentProperty, getSaleProperty, getSalePropertyById, bookReservation, getAvailableDateRanges, getOwnerContactInformation, getMyRentListings, getMySaleListings } from "../../utils/api";
import AuthService from "../../services/AuthService";
import { useFavorites } from "@/app/contexts/FavoritesContext";
import { BuildingTypeKeys, PropertyStatusKeys, extractCity } from "../../enums";
import PropertyRatingList from "@/app/components/ratings/PropertyRatingList";
import { getPropertyAverageRating } from "../../utils/ratings";
import "leaflet/dist/leaflet.css";
+import Loading from "@/app/loading";
function PropertyDetailMap({ lat, lng, title }) {
const mapRef = useRef(null);
@@ -88,12 +80,9 @@ function PropertyDetailMap({ lat, lng, title }) {
delete L.Icon.Default.prototype._getIconUrl;
L.Icon.Default.mergeOptions({
- iconRetinaUrl:
- "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon-2x.png",
- iconUrl:
- "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon.png",
- shadowUrl:
- "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-shadow.png",
+ iconRetinaUrl: "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon-2x.png",
+ iconUrl: "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon.png",
+ shadowUrl: "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-shadow.png",
});
const map = L.map(mapRef.current, {
@@ -103,8 +92,7 @@ function PropertyDetailMap({ lat, lng, title }) {
});
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
- attribution:
- '©
OpenStreetMap contributors',
+ attribution: '©
OpenStreetMap contributors',
maxZoom: 19,
}).addTo(map);
@@ -142,10 +130,7 @@ function formatCurrency(amount) {
function buildImageUrl(img) {
if (!img) return "";
- const apiBase =
- typeof window !== "undefined"
- ? process.env.NEXT_PUBLIC_API_URL || "https://45.93.137.91.nip.io/api"
- : "";
+ const apiBase = typeof window !== "undefined" ? process.env.NEXT_PUBLIC_API_URL || "https://45.93.137.91.nip.io/api" : "";
if (img.startsWith("http")) return img;
return `${apiBase}${img.startsWith("/") ? "" : "/Pictures/"}${img}`;
}
@@ -175,14 +160,8 @@ function mapApiDetail(item) {
const price = isRent ? monthlyPrice || dailyPrice : salePrice;
const priceUnit = isRent ? (monthlyPrice ? "monthly" : "daily") : "sale";
- const propType =
- BuildingTypeKeys[info.buildingType] ??
- BuildingTypeKeys[item.type] ??
- "apartment";
- const status =
- PropertyStatusKeys[info.status] ??
- PropertyStatusKeys[item.status] ??
- "available";
+ const propType = BuildingTypeKeys[info.buildingType] ?? BuildingTypeKeys[item.type] ?? "apartment";
+ const status = PropertyStatusKeys[info.status] ?? PropertyStatusKeys[item.status] ?? "available";
const rawImages = Array.isArray(info.images) ? info.images : [];
const photosFallback = Array.isArray(details.photos) ? details.photos : [];
@@ -191,9 +170,7 @@ function mapApiDetail(item) {
// Normalize services: Flutter sends list of strings or object with boolean values
const rawServices = details.services || {};
- const serviceList = Array.isArray(rawServices)
- ? rawServices
- : Object.keys(rawServices).filter((k) => rawServices[k]);
+ const serviceList = Array.isArray(rawServices) ? rawServices : Object.keys(rawServices).filter((k) => rawServices[k]);
const serviceDetails = details.serviceDetails || {};
const services = {};
serviceList.forEach((s) => {
@@ -201,19 +178,12 @@ function mapApiDetail(item) {
});
const rawTerms = details.terms || {};
- const terms = Array.isArray(rawTerms)
- ? rawTerms.reduce((acc, t) => ({ ...acc, [t]: true }), {})
- : rawTerms;
+ const terms = Array.isArray(rawTerms) ? rawTerms.reduce((acc, t) => ({ ...acc, [t]: true }), {}) : rawTerms;
// Try multiple key aliases like Flutter does
const floor = details.floorNumber ?? details.floor ?? 0;
- const salons =
- details.numberOfSalons ?? details.salonsCount ?? details.salons ?? 0;
- const balconies =
- details.numberOfBalconies ??
- details.balconiesCount ??
- details.balconies ??
- 0;
+ const salons = details.numberOfSalons ?? details.salonsCount ?? details.salons ?? 0;
+ const balconies = details.numberOfBalconies ?? details.balconiesCount ?? details.balconies ?? 0;
const rawProximity = details.nearbyDistances || details.proximity || {};
const proximity = {};
Object.entries(rawProximity).forEach(([k, v]) => {
@@ -223,19 +193,9 @@ function mapApiDetail(item) {
});
const roomDetails = details.room || details.roomDetails || {};
- const displayType =
- details.displayType ||
- (isRent
- ? monthlyPrice && dailyPrice
- ? "Both"
- : monthlyPrice
- ? "Monthly"
- : "Daily"
- : "Sale");
+ const displayType = details.displayType || (isRent ? (monthlyPrice && dailyPrice ? "Both" : monthlyPrice ? "Monthly" : "Daily") : "Sale");
const propertyCondition = details.propertyCondition || "";
- const furnished = propertyCondition.toLowerCase().includes("furniture")
- ? propertyCondition.toLowerCase() === "withfurniture"
- : !!item.isFurnished;
+ const furnished = propertyCondition.toLowerCase().includes("furniture") ? propertyCondition.toLowerCase() === "withfurniture" : !!item.isFurnished;
return {
id: item.id,
@@ -300,12 +260,8 @@ export default function PropertyDetailsPage() {
const [bookingStep, setBookingStep] = useState("entry");
const [selectedStart, setSelectedStart] = useState(null);
const [selectedEnd, setSelectedEnd] = useState(null);
- const [calendarMonth, setCalendarMonth] = useState(() =>
- new Date().getMonth(),
- );
- const [calendarYear, setCalendarYear] = useState(() =>
- new Date().getFullYear(),
- );
+ const [calendarMonth, setCalendarMonth] = useState(() => new Date().getMonth());
+ const [calendarYear, setCalendarYear] = useState(() => new Date().getFullYear());
const [pricingMode, setPricingMode] = useState("daily");
const [isOwnProperty, setIsOwnProperty] = useState(false);
const [favLoading, setFavLoading] = useState(false);
@@ -327,8 +283,7 @@ export default function PropertyDetailsPage() {
} catch {}
if (!data) {
try {
- data =
- (await getSalePropertyById(id)) || (await getSaleProperty(id));
+ data = (await getSalePropertyById(id)) || (await getSaleProperty(id));
} catch {}
}
if (!data) {
@@ -343,8 +298,7 @@ export default function PropertyDetailsPage() {
if (mapped) fetchAvgRating(mapped.id);
if (mapped && mapped.isRent) {
try {
- const propInfoId =
- mapped._raw?.propertyInformationId || mapped.id;
+ const propInfoId = mapped._raw?.propertyInformationId || mapped.id;
const ranges = await getAvailableDateRanges(propInfoId);
if (ranges && Array.isArray(ranges)) {
setAvailableRanges(ranges);
@@ -356,16 +310,11 @@ export default function PropertyDetailsPage() {
// Check if current user owns this property via their own listings
if (AuthService.isAuthenticated() && AuthService.isOwner()) {
try {
- const [myRent, mySale] = await Promise.allSettled([
- getMyRentListings(),
- getMySaleListings(),
- ]);
+ const [myRent, mySale] = await Promise.allSettled([getMyRentListings(), getMySaleListings()]);
const myPropIds = new Set();
const collectIds = (result) => {
if (result.status !== "fulfilled" || !result.value) return;
- const list = Array.isArray(result.value)
- ? result.value
- : [result.value];
+ const list = Array.isArray(result.value) ? result.value : [result.value];
list.filter(Boolean).forEach((p) => {
const info = p.propertyInformation || {};
if (info.id) myPropIds.add(Number(info.id));
@@ -375,10 +324,7 @@ export default function PropertyDetailsPage() {
collectIds(myRent);
collectIds(mySale);
const propInfoId = mapped._raw?.propertyInformation?.id;
- if (
- myPropIds.has(Number(mapped.id)) ||
- (propInfoId && myPropIds.has(Number(propInfoId)))
- ) {
+ if (myPropIds.has(Number(mapped.id)) || (propInfoId && myPropIds.has(Number(propInfoId)))) {
setIsOwnProperty(true);
}
} catch (e) {
@@ -406,9 +352,7 @@ export default function PropertyDetailsPage() {
const fetchContactInfo = async () => {
if (!property) return;
try {
- const info = await getOwnerContactInformation(
- property._raw?.propertyInformationId || property.id,
- );
+ const info = await getOwnerContactInformation(property._raw?.propertyInformationId || property.id);
setContactInfo(info);
setShowContact(true);
} catch (err) {
@@ -448,11 +392,7 @@ export default function PropertyDetailsPage() {
setBookingLoading(true);
setBookingError(null);
try {
- await bookReservation(
- property._raw?.propertyInformationId || property.id,
- bookingDates.start,
- bookingDates.end,
- );
+ await bookReservation(property._raw?.propertyInformationId || property.id, bookingDates.start, bookingDates.end);
setBookingSuccess(true);
toast.success(t("bookingSentSuccess"));
} catch (err) {
@@ -463,14 +403,20 @@ export default function PropertyDetailsPage() {
};
const MONTH_KEYS = [
- "month.january", "month.february", "month.march", "month.april",
- "month.may", "month.june", "month.july", "month.august",
- "month.september", "month.october", "month.november", "month.december",
- ];
- const DAY_KEYS = [
- "dayAbbr.sun", "dayAbbr.mon", "dayAbbr.tue", "dayAbbr.wed",
- "dayAbbr.thu", "dayAbbr.fri", "dayAbbr.sat",
+ "month.january",
+ "month.february",
+ "month.march",
+ "month.april",
+ "month.may",
+ "month.june",
+ "month.july",
+ "month.august",
+ "month.september",
+ "month.october",
+ "month.november",
+ "month.december",
];
+ const DAY_KEYS = ["dayAbbr.sun", "dayAbbr.mon", "dayAbbr.tue", "dayAbbr.wed", "dayAbbr.thu", "dayAbbr.fri", "dayAbbr.sat"];
const availableDatesSet = useMemo(() => {
const dates = new Set();
@@ -555,14 +501,7 @@ export default function PropertyDetailsPage() {
};
if (loading) {
- return (
-
-
-
-
{t("loadingProperty")}
-
-
- );
+ return
;
}
if (!property) {
@@ -572,14 +511,9 @@ export default function PropertyDetailsPage() {
-
- {t("propertyNotFound")}
-
+
{t("propertyNotFound")}
{t("propertyNotFoundDesc")}
-
+
{t("backToProperties")}
@@ -591,30 +525,16 @@ export default function PropertyDetailsPage() {
const isFav = isFavorite(property.id);
const isRoomType = property.type === "room";
const isMostRequested = avgRating !== null && avgRating >= 4.5;
- const showPricingToggle =
- property.isRent &&
- property.priceDisplay?.daily > 0 &&
- property.priceDisplay?.monthly > 0;
- const effectivePricingMode = showPricingToggle
- ? pricingMode
- : property.isRent && property.priceDisplay?.monthly > 0
- ? "monthly"
- : "daily";
+ const showPricingToggle = property.isRent && property.priceDisplay?.daily > 0 && property.priceDisplay?.monthly > 0;
+ const effectivePricingMode = showPricingToggle ? pricingMode : property.isRent && property.priceDisplay?.monthly > 0 ? "monthly" : "daily";
return (
-
+
-
-
+
+
{t("backToProperties")}
@@ -623,27 +543,12 @@ export default function PropertyDetailsPage() {
{/* Image Gallery */}
-
-
+
+
{property.images.length > 0 ? (
-

+

) : (
-
+
{t("noImages")}
@@ -653,7 +558,7 @@ export default function PropertyDetailsPage() {
{isMostRequested && (
-
+
{t("mostRequested")}
@@ -662,23 +567,13 @@ export default function PropertyDetailsPage() {
{property.images.length > 1 && (
<>