'use client';
import { useState, useEffect } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import {
Search,
MapPin,
Bed,
Bath,
Square,
DollarSign,
Filter,
Grid3x3,
List,
Heart,
Share2,
ChevronDown,
Star,
Camera,
Home,
Building2,
Trees,
Waves,
Warehouse,
Sparkles,
Shield,
Calendar,
Phone,
Mail,
MessageCircle
} from 'lucide-react';
import Image from 'next/image';
import Link from 'next/link';
import { getRentProperties, getSaleProperties } from '../utils/api';
import { useFavorites } from '@/app/contexts/FavoritesContext';
import AuthService from '@/app/services/AuthService';
import toast, { Toaster } from 'react-hot-toast';
import { useTranslation } from 'react-i18next';
// Map API data to UI format
function mapApiProperty(t, item, index) {
const info = item.propertyInformation || {};
const dailyPrice = item.dailyRent ?? item.monthlyRent ?? item.price ?? 0;
const monthlyPrice = item.monthlyRent ?? 0;
const buildingTypeMap = { 0: 'apartment', 1: 'villa', 2: 'sweet', 3: 'room', 4: 'studio', 5: 'office', 6: 'farms', 7: 'shop', 8: 'warehouse' };
const propType = buildingTypeMap[info.buildingType] ?? buildingTypeMap[item.type] ?? 'apartment';
const statusMap = { 0: 'available', 1: 'notAvailable', 2: 'booked' };
const status = statusMap[info.status] ?? statusMap[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('bedrooms')}`);
if (info.numberOfBathRooms) features.push(`${info.numberOfBathRooms} ${t('bathrooms')}`);
// Extract images from API and build full URLs
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'];
return {
id: item.id ?? index + 1,
title: info.address || `${t('property')} #${item.id || index + 1}`,
description: info.description || '',
type: propType,
price: dailyPrice,
priceUnit: 'daily',
location: {
city: extractCity(info.address) || 'damascus',
district: info.address || '',
},
bedrooms: info.numberOfBedRooms || 0,
bathrooms: info.numberOfBathRooms || 0,
area: info.space || 0,
features,
images,
status,
rating: item.rating || 0,
isNew: false,
_raw: item,
};
}
function extractCity(address) {
if (!address) return '';
const cityMap = {
'دمشق': 'damascus',
'حلب': 'aleppo',
'حمص': 'homs',
'اللاذقية': 'latakia',
'درعا': 'daraa',
'طرطوس': 'tartous',
'السويداء': 'suweida',
'دير الزور': 'deirEzzor',
'الرقة': 'raqqa',
'إدلب': 'idlib',
'الحسكة': 'hasakah',
'القامشلي': 'qamishli',
'ريف دمشق': 'ruralDamascus'
};
for (const [arabic, key] of Object.entries(cityMap)) {
if (address.includes(arabic)) return key;
}
return '';
}
// API-only — no fallback data
const PropertyCard = ({ property, viewMode = 'grid', onLoginRequired }) => {
const { t, i18n } = useTranslation();
const { isFavorite: checkFavorite, addFavorite, removeFavorite } = useFavorites();
const [favLoading, setFavLoading] = useState(false);
const [currentImage, setCurrentImage] = useState(0);
const isFav = checkFavorite(property.id);
const toggleFavorite = async (e) => {
e.preventDefault();
e.stopPropagation();
if (!AuthService.isAuthenticated()) { onLoginRequired?.(); return; }
setFavLoading(true);
if (isFav) {
await removeFavorite(property.id);
} else {
await addFavorite(property.id);
}
setFavLoading(false);
};
const formatCurrency = (amount) => {
return amount?.toLocaleString() + ' ' + t('syp-symbol');
};
const getPropertyTypeIcon = (type) => {
switch (type) {
case 'villa': return ;
case 'apartment': return ;
case 'house': return ;
case 'studio': return ;
default: return ;
}
};
const getPropertyTypeLabel = (type) => {
switch (type) {
case 'villa': return t('buildingType.villa');
case 'apartment': return t('buildingType.apartment');
case 'house': return t('house');
case 'studio': return t('buildingType.studio');
default: return type;
}
};
if (viewMode === 'list') {
return (
{property.images.length > 1 && (
{property.images.map((_, idx) => (
)}
{getPropertyTypeIcon(property.type)}
{getPropertyTypeLabel(property.type)}
{property.status === 'available' ? t('available') : t('booked')}
{property.title}
{t('city.' + property.location.city)}، {property.location.district}
{formatCurrency(property.price)}
/{property.priceUnit === 'daily' ? t('day') : t('month')}
{property.bedrooms} {t('rooms')}
{property.bathrooms} {t('bathrooms')}
{property.area} {t('sqm')}
{property.description}
);
}
return (
{getPropertyTypeIcon(property.type)}
{getPropertyTypeLabel(property.type)}
{property.status === 'available' && (
{t('available')}
)}
{property.title}
{t('city.' + property.location.city)}، {property.location.district}
{formatCurrency(property.price)}
/{property.priceUnit === 'daily' ? t('day') : t('month')}
{property.bedrooms}
{property.bathrooms}
{property.area}{t('sqm')}
{property.rating > 0 && (
{property.rating.toFixed(1)}
)}
{t('viewDetails')}
);
};
const FilterBar = ({ filters, onFilterChange }) => {
const { t, i18n } = useTranslation();
const [showFilters, setShowFilters] = useState(false);
const propertyTypes = [
{ id: 'all', label: t('all') },
{ id: 'apartment', label: t('buildingType.apartment'), icon: Building2 },
{ id: 'villa', label: t('buildingType.villa'), icon: Home },
{ id: 'house', label: t('house'), icon: Home },
];
const priceRanges = [
{ id: 'all', label: t('allPrices') },
{ id: '0-500000', label: t('price-range-less-than-500k') },
{ id: '500000-1000000', label: t('price-range-500k-to-1m') },
{ id: '1000000-2000000', label: t('price-range-1m-to-2m') },
{ id: '2000000-5000000', label: t('price-range-2m-to-5m') },
{ id: '5000000+', label: t('price-range-more-than-5m') }
];
const cities = [
{ id: 'all', label: t('allCities') },
{ id: 'damascus', label: t('city.damascus') },
{ id: 'aleppo', label: t('city.aleppo') },
{ id: 'homs', label: t('city.homs') },
{ id: 'latakia', label: t('city.latakia') },
{ id: 'daraa', label: t('city.daraa') },
{ id: 'tartous', label: t('city.tartous') },
{ id: 'suweida', label: t('city.suweida') },
{ id: 'deirEzzor', label: t('city.deirEzzor') },
{ id: 'raqqa', label: t('city.raqqa') },
{ id: 'idlib', label: t('city.idlib') },
{ id: 'hasakah', label: t('city.hasakah') },
{ id: 'qamishli', label: t('city.qamishli') },
{ id: 'ruralDamascus', label: t('city.ruralDamascus') }
];
return (
{showFilters && (
{propertyTypes.map((type) => {
const Icon = type.icon;
return (
);
})}
)}
);
};
export default function PropertiesPage() {
const { t, i18n } = useTranslation();
const [purposeTab, setPurposeTab] = useState('rent');
const [viewMode, setViewMode] = useState('grid');
const [sortBy, setSortBy] = useState('newest');
const [properties, setProperties] = useState([]);
const [loading, setLoading] = useState(true);
const [showLoginDialog, setShowLoginDialog] = useState(false);
const [filters, setFilters] = useState({
search: '',
propertyType: 'all',
city: 'all',
priceRange: 'all',
bedrooms: 'all',
minArea: '',
maxArea: '',
features: []
});
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 mapped = [
...rentList.map((p, i) => ({ ...mapApiProperty(t, p, i), purpose: 'rent' })),
...saleList.map((p, i) => ({ ...mapApiProperty(t, p, rentList.length + i), purpose: 'sale' })),
];
if (mapped.length > 0) {
setProperties(mapped);
}
} catch (err) {
console.error('[Properties] Failed to fetch properties:', err);
} finally {
setLoading(false);
}
}
fetchProperties();
}, []);
const filteredProperties = properties
.filter(p => p.purpose === purposeTab)
.filter(property => {
if (filters.search && !property.title.includes(filters.search) && !property.description.includes(filters.search)) {
return false;
}
if (filters.propertyType !== 'all' && property.type !== filters.propertyType) {
return false;
}
if (filters.city !== 'all' && property.location.city !== filters.city) {
return false;
}
if (filters.priceRange !== 'all') {
const [min, max] = filters.priceRange.split('-');
if (max) {
if (property.price < parseInt(min) || property.price > parseInt(max)) return false;
} else if (filters.priceRange.endsWith('+')) {
const minVal = parseInt(filters.priceRange.replace('+', ''));
if (property.price < minVal) return false;
}
}
if (filters.bedrooms !== 'all' && property.bedrooms < parseInt(filters.bedrooms)) {
return false;
}
if (filters.minArea && property.area < parseInt(filters.minArea)) return false;
if (filters.maxArea && property.area > parseInt(filters.maxArea)) return false;
return true;
})
.sort((a, b) => {
switch (sortBy) {
case 'price_asc': return a.price - b.price;
case 'price_desc': return b.price - a.price;
case 'rating': return b.rating - a.rating;
default: return 0;
}
});
return (
{purposeTab === 'rent' ? t('properties-for-rent') : t('properties-for-sale')}
{t('best-properties-in-syria')}
{/* Purpose Toggle */}
{loading && (
)}
{filteredProperties.length} {t('property-available')}
{filteredProperties.map((property) => (
setShowLoginDialog(true)} />
))}
{filteredProperties.length === 0 && (
{t('no-properties')}
{t('try-changing-search-criteria')}
)}
{showLoginDialog && (
setShowLoginDialog(false)}>
e.stopPropagation()}
className="bg-white rounded-2xl p-6 max-w-sm w-full mx-4 shadow-xl text-center"
>
{t('login-required-title')}
{t('login-required-favorites-desc')}
{t('login')}
)}
);
}