Display property images from API using full URLs
All checks were successful
Build frontend / build (push) Successful in 1m3s

- All mappers extract images from propertyInformation.images
- Paths prefixed with API base URL (http://45.93.137.91/api)
- Falls back to placeholder if no images
- Updated: main page, properties listing, property detail, owner properties
This commit is contained in:
Claw AI
2026-03-30 01:01:42 +00:00
parent 4299968764
commit 39193337b3
5 changed files with 69 additions and 42 deletions

View File

@ -99,22 +99,21 @@ export default function AddPropertyPage() {
livingRooms: 1, livingRooms: 1,
services: { services: {
electricity: false, [PropertyService.ELECTRICITY]: false,
internet: false, [PropertyService.INTERNET]: false,
heating: false, [PropertyService.HEATING]: false,
water: false, [PropertyService.WATER]: false,
airConditioning: false, [PropertyService.CENTRAL_AIR_CONDITIONING]: false,
parking: false, [PropertyService.PARKING]: false,
elevator: false [PropertyService.ELEVATOR]: false
}, },
serviceDetails: {},
terms: { terms: {
noSmoking: false, [PropertyTerm.NO_SMOKING]: false,
noPets: false, [PropertyTerm.NO_ANIMALS]: false,
noParties: false, [PropertyTerm.NO_PARTIES]: false
noAlcohol: false,
suitableForChildren: true,
suitableForElderly: true
}, },
offerType: 'daily', offerType: 'daily',
@ -831,34 +830,37 @@ const handleMapClick = async (coords) => {
</div> </div>
<div> <div>
<h3 className="text-lg font-bold text-gray-900 mb-4">الخدمات المتوفرة</h3> <h3 className="text-lg font-bold text-gray-900 mb-4">الخدمات المتوفرة <span className="text-red-500">*</span></h3>
<div className="grid grid-cols-2 md:grid-cols-4 gap-3"> <div className="space-y-3">
{serviceList.map((service) => { {serviceList.map((service) => {
const Icon = service.icon; const Icon = service.icon;
const isSelected = formData.services[service.id];
return ( return (
<label <div key={service.id} className={`border rounded-xl transition-all ${isSelected ? 'border-amber-500 bg-amber-50' : 'border-gray-200'}`}>
key={service.id} <label className="flex items-center gap-3 p-3 cursor-pointer">
className={`flex items-center gap-2 p-3 border rounded-xl cursor-pointer transition-all ${ <input
formData.services[service.id] type="checkbox"
? 'border-amber-500 bg-amber-50' checked={isSelected}
: 'border-gray-200 hover:border-amber-200 hover:bg-amber-50/50' onChange={() => toggleService(service.id)}
}`} className="w-4 h-4 text-amber-500 rounded"
> />
<input <Icon className={`w-5 h-5 ${isSelected ? 'text-amber-600' : 'text-gray-400'}`} />
type="checkbox" <span className={`text-sm font-medium ${isSelected ? 'text-amber-700' : 'text-gray-600'}`}>
checked={formData.services[service.id]} {service.label}
onChange={() => toggleService(service.id)} </span>
className="hidden" </label>
/> {isSelected && (
<Icon className={`w-5 h-5 ${ <div className="px-3 pb-3">
formData.services[service.id] ? 'text-amber-600' : 'text-gray-400' <input
}`} /> type="text"
<span className={`text-sm ${ value={formData.serviceDetails[service.id] || ''}
formData.services[service.id] ? 'text-amber-700' : 'text-gray-600' onChange={(e) => updateServiceDetail(service.id, e.target.value)}
}`}> className="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-amber-500"
{service.label} placeholder="تفاصيل الخدمة (مثال: في جميع الغرف)"
</span> />
</label> </div>
)}
</div>
); );
})} })}
</div> </div>

View File

@ -746,7 +746,11 @@ export default function OwnerPropertiesPage() {
area: info.space || 0, area: info.space || 0,
livingRooms: details.livingRooms || 0, livingRooms: details.livingRooms || 0,
status: { 0: 'available', 1: 'booked', 2: 'maintenance' }[info.status] || 'available', status: { 0: 'available', 1: 'booked', 2: 'maintenance' }[info.status] || 'available',
images: ['/property-placeholder.jpg'], images: (() => {
const apiBase = typeof window !== 'undefined' ? (process.env.NEXT_PUBLIC_API_URL || 'http://45.93.137.91/api') : '';
const raw = Array.isArray(info.images) ? info.images : [];
return raw.length > 0 ? raw.map(img => img.startsWith('http') ? img : `${apiBase}${img}`) : ['/property-placeholder.jpg'];
})(),
createdAt: item.createdAt || new Date().toISOString(), createdAt: item.createdAt || new Date().toISOString(),
furnished: details.furnished || false, furnished: details.furnished || false,
description: info.description || '', description: info.description || '',

View File

@ -51,6 +51,13 @@ function mapApiProperty(item, index) {
if (info.numberOfBedRooms) features.push(`${info.numberOfBedRooms} غرف نوم`); if (info.numberOfBedRooms) features.push(`${info.numberOfBedRooms} غرف نوم`);
if (info.numberOfBathRooms) features.push(`${info.numberOfBathRooms} حمامات`); if (info.numberOfBathRooms) features.push(`${info.numberOfBathRooms} حمامات`);
// Extract images from API and build full URLs
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}`)
: ['/property-placeholder.jpg'];
return { return {
id: item.id ?? index + 1, id: item.id ?? index + 1,
title: info.address || `عقار #${item.id || index + 1}`, title: info.address || `عقار #${item.id || index + 1}`,
@ -70,7 +77,7 @@ function mapApiProperty(item, index) {
bathrooms: info.numberOfBathRooms || 0, bathrooms: info.numberOfBathRooms || 0,
area: info.space || 0, area: info.space || 0,
features, features,
images: ['/property-placeholder.jpg'], images,
status, status,
rating: item.rating || 4.5, rating: item.rating || 4.5,
isNew: false, isNew: false,

View File

@ -53,6 +53,13 @@ function mapApiProperty(item, index) {
if (info.numberOfBedRooms) features.push(`${info.numberOfBedRooms} غرف نوم`); if (info.numberOfBedRooms) features.push(`${info.numberOfBedRooms} غرف نوم`);
if (info.numberOfBathRooms) features.push(`${info.numberOfBathRooms} حمامات`); if (info.numberOfBathRooms) features.push(`${info.numberOfBathRooms} حمامات`);
// Extract images from API and build full URLs
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}`)
: ['/property-placeholder.jpg'];
return { return {
id: item.id ?? index + 1, id: item.id ?? index + 1,
title: info.address || `عقار #${item.id || index + 1}`, title: info.address || `عقار #${item.id || index + 1}`,
@ -68,7 +75,7 @@ function mapApiProperty(item, index) {
bathrooms: info.numberOfBathRooms || 0, bathrooms: info.numberOfBathRooms || 0,
area: info.space || 0, area: info.space || 0,
features, features,
images: ['/property-placeholder.jpg'], images,
status, status,
rating: item.rating || 4.5, rating: item.rating || 4.5,
isNew: false, isNew: false,

View File

@ -70,6 +70,13 @@ function mapApiDetail(item) {
const typeLabels = { 0: 'شقة', 1: 'فيلا', 2: 'بيت' }; const typeLabels = { 0: 'شقة', 1: 'فيلا', 2: 'بيت' };
// Extract images from API and build full URLs
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}`)
: ['/property-placeholder.jpg', '/villa1.jpg', '/villa2.jpg'];
return { return {
id: item.id, id: item.id,
title: info.address || `عقار #${item.id}`, title: info.address || `عقار #${item.id}`,
@ -90,7 +97,7 @@ function mapApiDetail(item) {
features: features.length > 0 ? features : [ features: features.length > 0 ? features : [
{ name: 'متاح للإيجار', available: true, description: '' }, { name: 'متاح للإيجار', available: true, description: '' },
], ],
images: ['/property-placeholder.jpg', '/villa1.jpg', '/villa2.jpg'], images,
status, status,
rating: item.rating || 4.5, rating: item.rating || 4.5,
reviews: 0, reviews: 0,