diff --git a/app/properties/page.js b/app/properties/page.js
index 28fecbf..70f9a85 100644
--- a/app/properties/page.js
+++ b/app/properties/page.js
@@ -8,26 +8,16 @@ import {
Bed,
Bath,
Square,
- DollarSign,
Filter,
Grid3x3,
List,
Heart,
- Share2,
ChevronDown,
Star,
- Camera,
Home,
Building2,
- Trees,
- Waves,
- Warehouse,
- Sparkles,
- Shield,
- Calendar,
Phone,
- Mail,
- MessageCircle
+ FileText
} from 'lucide-react';
import Image from 'next/image';
import Link from 'next/link';
@@ -37,28 +27,51 @@ 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 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')}`);
+ const cityMap = {
+ 0: 'damascus',
+ 1: 'aleppo',
+ 2: 'homs',
+ 3: 'latakia',
+ 4: 'daraa',
+ 5: 'tartous',
+ 6: 'suweida',
+ 7: 'deirEzzor',
+ 8: 'raqqa',
+ 9: 'idlib',
+ 10: 'hasakah',
+ 11: 'qamishli',
+ 12: 'ruralDamascus'
+ };
- // 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 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', 'حمامات')}`);
+
+ const apiBase = typeof window !== 'undefined' ? (process.env.NEXT_PUBLIC_API_URL || 'http://45.93.137.91/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}`)
@@ -66,13 +79,13 @@ function mapApiProperty(t, item, index) {
return {
id: item.id ?? index + 1,
- title: info.address || `${t('property')} #${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',
+ city: cityMap[info.city] || extractCity(info.address) || 'damascus',
district: info.address || '',
},
bedrooms: info.numberOfBedRooms || 0,
@@ -110,8 +123,6 @@ function extractCity(address) {
return '';
}
-// API-only — no fallback data
-
const PropertyCard = ({ property, viewMode = 'grid', onLoginRequired }) => {
const { t, i18n } = useTranslation();
const { isFavorite: checkFavorite, addFavorite, removeFavorite } = useFavorites();
@@ -134,7 +145,7 @@ const PropertyCard = ({ property, viewMode = 'grid', onLoginRequired }) => {
};
const formatCurrency = (amount) => {
- return amount?.toLocaleString() + ' ' + t('syp-symbol');
+ return amount?.toLocaleString() + ' ' + t('syp-symbol', 'ل.س');
};
const getPropertyTypeIcon = (type) => {
@@ -149,10 +160,16 @@ const PropertyCard = ({ property, viewMode = 'grid', onLoginRequired }) => {
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');
+ case 'villa': return t('buildingType.villa', 'فيلا');
+ case 'apartment': return t('buildingType.apartment', 'شقة');
+ case 'house': return t('house', 'منزل');
+ case 'studio': return t('buildingType.studio', 'ستوديو');
+ case 'sweet': return t('buildingType.sweet', 'جناح');
+ case 'room': return t('buildingType.room', 'غرفة');
+ case 'office': return t('buildingType.office', 'مكتب');
+ case 'farms': return t('buildingType.farms', 'مزرعة');
+ case 'shop': return t('buildingType.shop', 'محل تجاري');
+ case 'warehouse': return t('buildingType.warehouse', 'مستودع');
default: return type;
}
};
@@ -203,33 +220,33 @@ const PropertyCard = ({ property, viewMode = 'grid', onLoginRequired }) => {
{getPropertyTypeLabel(property.type)}
- {property.status === 'available' ? t('available') : t('booked')}
+ {property.status === 'available' ? t('available', 'متاح') : t('booked', 'محجوز')}
{property.title}
- {t('city.' + property.location.city)}، {property.location.district}
+ {t('city.' + property.location.city, property.location.city)}، {property.location.district}
{formatCurrency(property.price)}
-
/{property.priceUnit === 'daily' ? t('day') : t('month')}
+
/{property.priceUnit === 'daily' ? t('day', 'يوم') : t('month', 'شهر')}
- {property.bedrooms} {t('rooms')}
+ {property.bedrooms} {t('rooms', 'غرف')}
- {property.bathrooms} {t('bathrooms')}
+ {property.bathrooms} {t('bathrooms', 'حمامات')}
- {property.area} {t('sqm')}
+ {property.area} {t('sqm', 'م²')}
@@ -240,7 +257,7 @@ const PropertyCard = ({ property, viewMode = 'grid', onLoginRequired }) => {
href={`/property/${property.id}`}
className="flex-1 bg-gray-800 text-white py-3 rounded-xl font-medium hover:bg-gray-900 transition-colors text-center"
>
- {t('viewDetails')}
+ {t('viewDetails', 'عرض التفاصيل')}
@@ -402,32 +440,39 @@ const FilterBar = ({ filters, onFilterChange }) => {
exit={{ height: 0, opacity: 0 }}
className="overflow-hidden"
>
-
+
-
-
- {propertyTypes.map((type) => {
- const Icon = type.icon;
- return (
-
- );
- })}
-
+
+
-
+
+
+
+
+
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
onFilterChange({ ...filters, minArea: e.target.value })}
/>
onFilterChange({ ...filters, maxArea: e.target.value })}
/>
@@ -490,22 +563,25 @@ const FilterBar = ({ filters, onFilterChange }) => {
onClick={() => onFilterChange({
search: '',
propertyType: 'all',
+ buildingType: 'all',
city: 'all',
priceRange: 'all',
bedrooms: 'all',
+ bathrooms: 'all',
+ certificate: 'all',
minArea: '',
maxArea: '',
features: []
})}
- className="px-6 py-2 bg-gray-100 rounded-xl font-medium hover:bg-gray-200 transition-colors text-gray-700"
+ className="px-6 py-2 bg-gray-100 rounded-xl font-medium hover:bg-gray-200 transition-colors text-gray-700 text-sm"
>
- {t('reset')}
+ {t('reset', 'إعادة تعيين')}
@@ -526,9 +602,12 @@ export default function PropertiesPage() {
const [filters, setFilters] = useState({
search: '',
propertyType: 'all',
+ buildingType: 'all',
city: 'all',
priceRange: 'all',
bedrooms: 'all',
+ bathrooms: 'all',
+ certificate: 'all',
minArea: '',
maxArea: '',
features: []
@@ -536,13 +615,74 @@ export default function PropertiesPage() {
useEffect(() => {
async function fetchProperties() {
+ setLoading(true);
try {
- const [rentData, saleData] = await Promise.all([
- getRentProperties().catch(() => []),
+ const queryParams = new URLSearchParams();
+
+ if (filters.bedrooms !== 'all') {
+ queryParams.append('numberOfBedRooms', filters.bedrooms);
+ }
+
+ if (filters.bathrooms !== 'all') {
+ queryParams.append('numberOfBathRooms', filters.bathrooms);
+ }
+
+ if (filters.minArea) {
+ queryParams.append('space', filters.minArea);
+ }
+
+ const buildingTypeReverseMap = {
+ 'apartment': 'Apartment',
+ 'villa': 'Villa',
+ 'sweet': 'Sweet',
+ 'room': 'Room',
+ 'studio': 'Studio',
+ 'office': 'Office',
+ 'farms': 'Farms',
+ 'shop': 'Shop',
+ 'warehouse': 'Warehouse'
+ };
+ if (filters.buildingType !== 'all' && buildingTypeReverseMap[filters.buildingType] !== undefined) {
+ queryParams.append('buildingType', buildingTypeReverseMap[filters.buildingType]);
+ }
+
+ const propertyTypeReverseMap = {
+ 'residential': 'Residential',
+ 'commercial': 'Commercial',
+ 'agricultural': 'Agricultural'
+ };
+ if (filters.propertyType !== 'all' && propertyTypeReverseMap[filters.propertyType] !== undefined) {
+ queryParams.append('propertyType', propertyTypeReverseMap[filters.propertyType]);
+ }
+
+ const certificateReverseMap = {
+ 'realEstateTitle': 'RealEstateTitle',
+ 'courtRuling': 'CourtRuling',
+ 'notary': 'Notary',
+ 'shares': 'Shares'
+ };
+ if (filters.certificate !== 'all' && certificateReverseMap[filters.certificate] !== undefined) {
+ queryParams.append('certificate', certificateReverseMap[filters.certificate]);
+ }
+
+ if (filters.city !== 'all') {
+ const cityFormatted = filters.city.charAt(0).toUpperCase() + filters.city.slice(1);
+ queryParams.append('city', cityFormatted);
+ }
+
+ const baseUrl = process.env.NEXT_PUBLIC_API_URL || 'http://45.93.137.91/api';
+ const rentEndpoint = `${baseUrl}/RentProperties/FilterRentProperties?${queryParams.toString()}`;
+
+ const [rentRes, saleData] = await Promise.all([
+ fetch(rentEndpoint, {
+ headers: {
+ 'Accept': 'application/json',
+ }
+ }).then(res => res.json()).catch(() => ({ data: [], isSuccess: false })),
getSaleProperties().catch(() => []),
]);
- const rentList = Array.isArray(rentData) ? rentData : [];
+ const rentList = rentRes.isSuccess && Array.isArray(rentRes.data) ? rentRes.data : [];
const saleList = Array.isArray(saleData) ? saleData : [];
const mapped = [
@@ -550,9 +690,7 @@ export default function PropertiesPage() {
...saleList.map((p, i) => ({ ...mapApiProperty(t, p, rentList.length + i), purpose: 'sale' })),
];
- if (mapped.length > 0) {
- setProperties(mapped);
- }
+ setProperties(mapped);
} catch (err) {
console.error('[Properties] Failed to fetch properties:', err);
} finally {
@@ -561,7 +699,7 @@ export default function PropertiesPage() {
}
fetchProperties();
- }, []);
+ }, [filters, t]);
const filteredProperties = properties
.filter(p => p.purpose === purposeTab)
@@ -569,12 +707,6 @@ export default function PropertiesPage() {
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) {
@@ -584,11 +716,6 @@ export default function PropertiesPage() {
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) => {
@@ -608,19 +735,18 @@ export default function PropertiesPage() {
animate={{ opacity: 1, y: 0 }}
className="text-center mb-8"
>
-
{purposeTab === 'rent' ? t('properties-for-rent') : t('properties-for-sale')}
-
{t('best-properties-in-syria')}
+
{purposeTab === 'rent' ? t('properties-for-rent', 'عقارات للإيجار') : t('properties-for-sale', 'عقارات للبيع')}
+
{t('best-properties-in-syria', 'أفضل العقارات المتاحة في سوريا مباشرة وبسهولة')}
- {/* Purpose Toggle */}
@@ -635,18 +761,18 @@ export default function PropertiesPage() {
- {filteredProperties.length} {t('property-available')}
+ {filteredProperties.length} {t('property-available', 'عقار متاح')}
-
{t('no-properties')}
-
{t('try-changing-search-criteria')}
+
{t('no-properties', 'لا يوجد نتائج تطابق بحثك')}
+
{t('try-changing-search-criteria', 'يرجى تجربة تعديل خيارات الفلترة والبحث')}
)}
@@ -700,20 +826,20 @@ export default function PropertiesPage() {
-
{t('login-required-title')}
-
{t('login-required-favorites-desc')}
+
{t('login-required-title', 'تسجيل الدخول مطلوب')}
+
{t('login-required-favorites-desc', 'يجب تسجيل الدخول لتتمكن من إضافة العقار للمفضلة')}
- {t('login')}
+ {t('login', 'دخول')}
@@ -721,4 +847,4 @@ export default function PropertiesPage() {
)}
);
-}
+}
\ No newline at end of file