forked from amer2004/SweetHome
Added translation to all site with edit style
This commit is contained in:
@ -6,6 +6,7 @@ import { useRouter, useSearchParams } from 'next/navigation';
|
||||
import Link from 'next/link';
|
||||
import Image from 'next/image';
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
ArrowLeft,
|
||||
MapPin,
|
||||
@ -74,6 +75,7 @@ export default function AddPropertyPage() {
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
const purpose = searchParams.get('purpose') || 'rent';
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [step, setStep] = useState(1);
|
||||
const totalSteps = purpose === 'sale' ? 4 : 4;
|
||||
@ -171,15 +173,15 @@ export default function AddPropertyPage() {
|
||||
const fileInputRef = useRef(null);
|
||||
|
||||
const propertyTypes = [
|
||||
{ id: 'apartment', label: 'شقة', icon: Building },
|
||||
{ id: 'villa', label: 'فيلا', icon: Home },
|
||||
{ id: 'sweet', label: 'سويت', icon: Sofa },
|
||||
{ id: 'room', label: 'غرفة ضمن شقة (سكن مشترك)', icon: DoorOpen },
|
||||
{ id: 'studio', label: 'استوديو', icon: Sofa },
|
||||
{ id: 'office', label: 'مكتب', icon: Building },
|
||||
{ id: 'farms', label: 'مزرعة', icon: Trees },
|
||||
{ id: 'shop', label: 'متجر', icon: Warehouse },
|
||||
{ id: 'warehouse', label: 'مستودع', icon: Warehouse },
|
||||
{ id: 'apartment', label: t('buildingType.apartment'), icon: Building },
|
||||
{ id: 'villa', label: t('buildingType.villa'), icon: Home },
|
||||
{ id: 'sweet', label: t('buildingType.sweet'), icon: Sofa },
|
||||
{ id: 'room', label: t('buildingType.room'), icon: DoorOpen },
|
||||
{ id: 'studio', label: t('buildingType.studio'), icon: Sofa },
|
||||
{ id: 'office', label: t('buildingType.office'), icon: Building },
|
||||
{ id: 'farms', label: t('buildingType.farms'), icon: Trees },
|
||||
{ id: 'shop', label: t('buildingType.shop'), icon: Warehouse },
|
||||
{ id: 'warehouse', label: t('buildingType.warehouse'), icon: Warehouse },
|
||||
];
|
||||
|
||||
const serviceList = [
|
||||
@ -199,9 +201,9 @@ export default function AddPropertyPage() {
|
||||
];
|
||||
|
||||
const offerTypes = [
|
||||
{ id: 'daily', label: 'إيجار يومي', icon: Clock },
|
||||
{ id: 'monthly', label: 'إيجار شهري', icon: Calendar },
|
||||
{ id: 'both', label: 'إيجار يومي وشهري', icon: Calendar },
|
||||
{ id: 'daily', label: t('dailyRent'), icon: Clock },
|
||||
{ id: 'monthly', label: t('monthlyRent'), icon: Calendar },
|
||||
{ id: 'both', label: t('addProperty.dailyAndMonthly'), icon: Calendar },
|
||||
].filter(Boolean);
|
||||
|
||||
useEffect(() => {
|
||||
@ -218,7 +220,7 @@ export default function AddPropertyPage() {
|
||||
const handleSearch = async () => {
|
||||
if (!searchQuery) return;
|
||||
|
||||
toast.loading('جاري البحث...', { id: 'search' });
|
||||
toast.loading(t('toast.searching'), { id: 'search' });
|
||||
|
||||
try {
|
||||
const response = await fetch(
|
||||
@ -245,23 +247,23 @@ export default function AddPropertyPage() {
|
||||
address: addressData.display_name || result.display_name
|
||||
});
|
||||
|
||||
toast.success('تم العثور على الموقع', { id: 'search' });
|
||||
toast.success(t('toast.locationFound'), { id: 'search' });
|
||||
} else {
|
||||
toast.error('لم يتم العثور على العنوان', { id: 'search' });
|
||||
toast.error(t('toast.locationNotFound'), { id: 'search' });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('خطأ في البحث:', error);
|
||||
toast.error('حدث خطأ في البحث', { id: 'search' });
|
||||
console.error(t('search.error'), error);
|
||||
toast.error(t('search.error'), { id: 'search' });
|
||||
}
|
||||
};
|
||||
|
||||
const handleGeolocation = () => {
|
||||
if (!navigator.geolocation) {
|
||||
toast.error('المتصفح لا يدعم تحديد الموقع');
|
||||
if (!navigator.geolocation) {
|
||||
toast.error(t('toast.geolocationNotSupported'));
|
||||
return;
|
||||
}
|
||||
|
||||
toast.loading('جاري تحديد موقعك...', { id: 'geolocation' });
|
||||
|
||||
toast.loading(t('toast.geolocationLoading'), { id: 'geolocation' });
|
||||
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
async (position) => {
|
||||
@ -269,30 +271,30 @@ export default function AddPropertyPage() {
|
||||
setMapCenter([latitude, longitude]);
|
||||
setMapZoom(18);
|
||||
|
||||
try {
|
||||
const response = await fetch(
|
||||
`https://nominatim.openstreetmap.org/reverse?format=json&lat=${latitude}&lon=${longitude}&accept-language=ar`
|
||||
);
|
||||
const data = await response.json();
|
||||
|
||||
setSelectedLocation({
|
||||
lat: latitude,
|
||||
lng: longitude,
|
||||
address: data.display_name || 'موقعك الحالي'
|
||||
});
|
||||
|
||||
toast.success('تم تحديد موقعك', { id: 'geolocation' });
|
||||
} catch (error) {
|
||||
setSelectedLocation({
|
||||
lat: latitude,
|
||||
lng: longitude,
|
||||
address: 'موقعك الحالي'
|
||||
});
|
||||
toast.success('تم تحديد موقعك', { id: 'geolocation' });
|
||||
}
|
||||
try {
|
||||
const response = await fetch(
|
||||
`https://nominatim.openstreetmap.org/reverse?format=json&lat=${latitude}&lon=${longitude}&accept-language=ar`
|
||||
);
|
||||
const data = await response.json();
|
||||
|
||||
setSelectedLocation({
|
||||
lat: latitude,
|
||||
lng: longitude,
|
||||
address: data.display_name || t('addProperty.currentLocation')
|
||||
});
|
||||
|
||||
toast.success(t('toast.geolocationSuccess'), { id: 'geolocation' });
|
||||
} catch (error) {
|
||||
setSelectedLocation({
|
||||
lat: latitude,
|
||||
lng: longitude,
|
||||
address: t('addProperty.currentLocation')
|
||||
});
|
||||
toast.success(t('toast.geolocationSuccess'), { id: 'geolocation' });
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
toast.error('فشل في تحديد الموقع', { id: 'geolocation' });
|
||||
toast.error(t('toast.geolocationFailed'), { id: 'geolocation' });
|
||||
}
|
||||
);
|
||||
};
|
||||
@ -301,32 +303,32 @@ const handleMapClick = async (coords) => {
|
||||
try {
|
||||
const [lat, lng] = coords;
|
||||
|
||||
toast.loading('جاري تحديد الموقع...', { id: 'location' });
|
||||
toast.loading(t('addProperty.locationSelecting'), { id: 'location' });
|
||||
|
||||
const response = await fetch(
|
||||
`https://nominatim.openstreetmap.org/reverse?format=json&lat=${lat}&lon=${lng}&accept-language=ar`
|
||||
);
|
||||
const data = await response.json();
|
||||
|
||||
setSelectedLocation({
|
||||
lat: lat,
|
||||
lng: lng,
|
||||
address: data.display_name || 'موقع محدد'
|
||||
});
|
||||
|
||||
setMapZoom(18);
|
||||
toast.success('تم تحديد الموقع بنجاح!', { id: 'location' });
|
||||
const response = await fetch(
|
||||
`https://nominatim.openstreetmap.org/reverse?format=json&lat=${lat}&lon=${lng}&accept-language=ar`
|
||||
);
|
||||
const data = await response.json();
|
||||
|
||||
setSelectedLocation({
|
||||
lat: lat,
|
||||
lng: lng,
|
||||
address: data.display_name || t('addProperty.defaultAddress')
|
||||
});
|
||||
|
||||
setMapZoom(18);
|
||||
toast.success(t('toast.locationSelectedSuccess'), { id: 'location' });
|
||||
|
||||
} catch (error) {
|
||||
console.error('خطأ في تحديد الموقع:', error);
|
||||
console.error(t('addProperty.locationError'), error);
|
||||
const [lat, lng] = coords;
|
||||
setSelectedLocation({
|
||||
lat: lat,
|
||||
lng: lng,
|
||||
address: 'موقع محدد'
|
||||
address: t('addProperty.defaultAddress')
|
||||
});
|
||||
setMapZoom(18);
|
||||
toast.success('تم تحديد الموقع', { id: 'location' });
|
||||
toast.success(t('toast.locationConfirmed'), { id: 'location' });
|
||||
}
|
||||
};
|
||||
const handleMarkerDragEnd = async (lat, lng) => {
|
||||
@ -338,13 +340,13 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
setSelectedLocation({
|
||||
lat,
|
||||
lng,
|
||||
address: data.display_name || 'موقع محدد'
|
||||
address: data.display_name || t('addProperty.defaultAddress')
|
||||
});
|
||||
} catch (error) {
|
||||
setSelectedLocation({
|
||||
lat,
|
||||
lng,
|
||||
address: 'موقع محدد'
|
||||
address: t('addProperty.defaultAddress')
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -357,7 +359,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
address: selectedLocation.address
|
||||
});
|
||||
|
||||
toast.success('تم تأكيد الموقع بنجاح');
|
||||
toast.success(t('toast.locationConfirmed'));
|
||||
}
|
||||
};
|
||||
|
||||
@ -370,25 +372,25 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
address: ''
|
||||
});
|
||||
setMapZoom(15);
|
||||
toast.info('تم إلغاء تحديد الموقع');
|
||||
toast.info(t('toast.clearLocation'));
|
||||
};
|
||||
|
||||
const handleImageUpload = async (files) => {
|
||||
const newImages = Array.from(files);
|
||||
|
||||
if (formData.images.length + newImages.length > 5) {
|
||||
toast.error('يمكنك رفع 5 صور كحد أقصى');
|
||||
toast.error(t('toast.maxImages'));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const file of newImages) {
|
||||
if (!file.type.startsWith('image/')) {
|
||||
toast.error('الرجاء اختيار صور صالحة فقط');
|
||||
toast.error(t('toast.imageRequired'));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (file.size > 5 * 1024 * 1024) {
|
||||
toast.error('حجم الصورة يجب أن يكون أقل من 5 ميجابايت');
|
||||
toast.error(t('toast.imageSize'));
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -410,7 +412,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
setUploadedImagePaths(prev => [...prev, path]);
|
||||
} catch (err) {
|
||||
console.error('[AddProperty] Image upload failed:', err);
|
||||
toast.error('فشل رفع الصورة: ' + file.name);
|
||||
toast.error(`${t('toast.imageUploadFailed')}: ${file.name}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -519,48 +521,48 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
switch(step) {
|
||||
case 1:
|
||||
if (!formData.propertyType) {
|
||||
newErrors.propertyType = 'نوع العقار مطلوب';
|
||||
newErrors.propertyType = t('addProperty.propertyTypeRequired');
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (!formData.bedrooms) {
|
||||
newErrors.bedrooms = 'عدد الغرف مطلوب';
|
||||
newErrors.bedrooms = t('addProperty.bedroomsRequired');
|
||||
}
|
||||
if (!formData.bathrooms) {
|
||||
newErrors.bathrooms = 'عدد الحمامات مطلوب';
|
||||
newErrors.bathrooms = t('addProperty.bathroomsRequired');
|
||||
}
|
||||
if (!formData.livingRooms) {
|
||||
newErrors.livingRooms = 'عدد الصالونات مطلوب';
|
||||
newErrors.livingRooms = t('addProperty.livingRoomsRequired');
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (purpose === 'sale') {
|
||||
if (!formData.salePrice) newErrors.salePrice = 'سعر البيع مطلوب';
|
||||
if (!formData.salePrice) newErrors.salePrice = t('addProperty.salePriceRequired');
|
||||
} else {
|
||||
if (!formData.offerType) {
|
||||
newErrors.offerType = 'الرجاء اختيار نوع العرض';
|
||||
newErrors.offerType = t('addProperty.offerTypeRequired');
|
||||
} else if (formData.offerType === 'daily' && !formData.dailyPrice) {
|
||||
newErrors.dailyPrice = 'السعر اليومي مطلوب';
|
||||
newErrors.dailyPrice = t('addProperty.dailyPriceRequired');
|
||||
} else if (formData.offerType === 'monthly' && !formData.monthlyPrice) {
|
||||
newErrors.monthlyPrice = 'السعر الشهري مطلوب';
|
||||
newErrors.monthlyPrice = t('addProperty.monthlyPriceRequired');
|
||||
} else if (formData.offerType === 'both') {
|
||||
if (!formData.dailyPrice) newErrors.dailyPrice = 'السعر اليومي مطلوب';
|
||||
if (!formData.monthlyPrice) newErrors.monthlyPrice = 'السعر الشهري مطلوب';
|
||||
if (!formData.dailyPrice) newErrors.dailyPrice = t('addProperty.dailyPriceRequired');
|
||||
if (!formData.monthlyPrice) newErrors.monthlyPrice = t('addProperty.monthlyPriceRequired');
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if (!formData.lat || !formData.lng) {
|
||||
newErrors.location = 'الرجاء تحديد موقع العقار على الخريطة';
|
||||
newErrors.location = t('addProperty.locationRequired');
|
||||
}
|
||||
if (formData.images.length < 2) {
|
||||
newErrors.images = 'يجب رفع صورتين على الأقل';
|
||||
newErrors.images = t('addProperty.minImagesRequired');
|
||||
}
|
||||
if (formData.images.length > 5) {
|
||||
newErrors.images = 'يمكن رفع 5 صور كحد أقصى';
|
||||
newErrors.images = t('addProperty.maxImagesError');
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -670,7 +672,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
currencyId: selectedCurrencyId,
|
||||
};
|
||||
const res = await addSaleProperty(payload);
|
||||
toast.success('تم إضافة عقار للبيع بنجاح!');
|
||||
toast.success(t('toast.salePropertySuccess'));
|
||||
} else {
|
||||
const rentTypeMap = { daily: RentType.DAILY, monthly: RentType.MONTHLY, both: RentType.MONTHLY };
|
||||
const payload = {
|
||||
@ -685,14 +687,14 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
allowedPaymentPeriod: formData.allowedPaymentPeriod || '',
|
||||
};
|
||||
const res = await addRentProperty(payload);
|
||||
toast.success('تم إضافة عقار للإيجار بنجاح!');
|
||||
toast.success(t('toast.rentPropertySuccess'));
|
||||
}
|
||||
setTimeout(() => {
|
||||
router.push('/owner/properties');
|
||||
}, 1500);
|
||||
} catch (err) {
|
||||
console.error('[AddProperty] API error:', err);
|
||||
toast.error(err.message || 'فشل في إضافة العقار');
|
||||
toast.error(err.message || t('toast.propertyAddFailed'));
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
@ -713,15 +715,15 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
<div className="container mx-auto px-4 max-w-4xl">
|
||||
<div className="mb-8">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<Link
|
||||
href="/owner/properties"
|
||||
className="flex items-center gap-2 text-gray-600 hover:text-amber-600 transition-colors group"
|
||||
>
|
||||
<ArrowLeft className="w-4 h-4 group-hover:-translate-x-1 transition-transform" />
|
||||
<span>العودة للعقارات</span>
|
||||
</Link>
|
||||
<Link
|
||||
href="/owner/properties"
|
||||
className="flex items-center gap-2 text-gray-600 hover:text-amber-600 transition-colors group"
|
||||
>
|
||||
<ArrowLeft className="w-4 h-4 group-hover:-translate-x-1 transition-transform" />
|
||||
<span>{t('addProperty.backToProperties')}</span>
|
||||
</Link>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-sm font-medium text-amber-600">خطوة {step} من {totalSteps}</span>
|
||||
<span className="text-sm font-medium text-amber-600">{t('addProperty.stepCounter', { step, total: totalSteps })}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -738,10 +740,10 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between mt-2 text-xs text-gray-500">
|
||||
<span>معلومات العقار</span>
|
||||
<span>التفاصيل والخدمات</span>
|
||||
<span>{purpose === 'sale' ? 'سعر البيع' : 'السعر'}</span>
|
||||
<span>الموقع والصور</span>
|
||||
<span>{t('addProperty.stepInfo')}</span>
|
||||
<span>{t('addProperty.stepDetails')}</span>
|
||||
<span>{purpose === 'sale' ? t('addProperty.stepSalePrice') : t('addProperty.stepRentPrice')}</span>
|
||||
<span>{t('addProperty.stepLocation')}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -759,14 +761,14 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
<div className="w-20 h-20 bg-amber-100 rounded-2xl flex items-center justify-center mx-auto mb-4">
|
||||
<Home className="w-10 h-10 text-amber-600" />
|
||||
</div>
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-2">معلومات العقار</h2>
|
||||
<p className="text-gray-600">اختر نوع العقار والحالة</p>
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-2">{t('addProperty.stepInfo')}</h2>
|
||||
<p className="text-gray-600">{t('addProperty.propertyInfoSubtitle')}</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-3">
|
||||
نوع العقار <span className="text-red-500">*</span>
|
||||
</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-3">
|
||||
{t('addProperty.propertyTypeLabel')} <span className="text-red-500">*</span>
|
||||
</label>
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-3">
|
||||
{propertyTypes.map((type) => {
|
||||
const Icon = type.icon;
|
||||
@ -794,7 +796,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-3">
|
||||
حالة العقار
|
||||
{t('addProperty.furnishedStatus')}
|
||||
</label>
|
||||
<div className="flex gap-4">
|
||||
<label className="flex items-center gap-2 p-3 border rounded-xl cursor-pointer hover:bg-gray-50 flex-1">
|
||||
@ -805,7 +807,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
onChange={() => setFormData({...formData, furnished: true})}
|
||||
className="w-4 h-4 text-amber-500"
|
||||
/>
|
||||
<span className="text-gray-700">مفروش</span>
|
||||
<span className="text-gray-700">{t('addProperty.furnished')}</span>
|
||||
</label>
|
||||
<label className="flex items-center gap-2 p-3 border rounded-xl cursor-pointer hover:bg-gray-50 flex-1">
|
||||
<input
|
||||
@ -815,21 +817,21 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
onChange={() => setFormData({...formData, furnished: false})}
|
||||
className="w-4 h-4 text-amber-500"
|
||||
/>
|
||||
<span className="text-gray-700">غير مفروش</span>
|
||||
<span className="text-gray-700">{t('addProperty.unfurnished')}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
وصف إضافي (اختياري)
|
||||
{t('addProperty.additionalDescription')}
|
||||
</label>
|
||||
<textarea
|
||||
value={formData.description}
|
||||
onChange={(e) => setFormData({...formData, description: e.target.value})}
|
||||
rows="4"
|
||||
className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500"
|
||||
placeholder="أضف وصفاً إضافياً للعقار..."
|
||||
placeholder={t('addProperty.descriptionPlaceholder')}
|
||||
/>
|
||||
</div>
|
||||
</motion.div>
|
||||
@ -841,14 +843,14 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
<div className="w-20 h-20 bg-amber-100 rounded-2xl flex items-center justify-center mx-auto mb-4">
|
||||
<Layers className="w-10 h-10 text-amber-600" />
|
||||
</div>
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-2">تفاصيل العقار</h2>
|
||||
<p className="text-gray-600">أدخل التفاصيل والخدمات المتاحة</p>
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-2">{t('addProperty.propertyDetailsTitle')}</h2>
|
||||
<p className="text-gray-600">{t('addProperty.propertyDetailsSubtitle')}</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-6">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
المساحة (م²)
|
||||
{t('addProperty.space')}
|
||||
</label>
|
||||
<div className="relative">
|
||||
<Square className="absolute right-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" />
|
||||
@ -858,14 +860,14 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
value={formData.space}
|
||||
onChange={(e) => setFormData({...formData, space: e.target.value})}
|
||||
className="w-full pr-10 pl-3 py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500"
|
||||
placeholder="مثال: 120"
|
||||
placeholder={t('addProperty.spacePlaceholder')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
عدد الغرف <span className="text-red-500">*</span>
|
||||
{t('addProperty.bedrooms')} <span className="text-red-500">*</span>
|
||||
</label>
|
||||
<div className="flex items-center gap-2">
|
||||
<button
|
||||
@ -893,7 +895,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
عدد الحمامات <span className="text-red-500">*</span>
|
||||
{t('addProperty.bathrooms')} <span className="text-red-500">*</span>
|
||||
</label>
|
||||
<div className="flex items-center gap-2">
|
||||
<button
|
||||
@ -921,7 +923,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
عدد الصالونات <span className="text-red-500">*</span>
|
||||
{t('addProperty.livingRooms')} <span className="text-red-500">*</span>
|
||||
</label>
|
||||
<div className="flex items-center gap-2">
|
||||
<button
|
||||
@ -950,41 +952,41 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">رقم الطابق</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">{t('addProperty.floorNumber')}</label>
|
||||
<input
|
||||
type="number"
|
||||
value={formData.floorNumber}
|
||||
onChange={(e) => setFormData({...formData, floorNumber: e.target.value})}
|
||||
className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500"
|
||||
placeholder="مثال: 3"
|
||||
placeholder={t('addProperty.floorPlaceholder')}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">عدد الصالونات</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">{t('addProperty.salons')}</label>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
value={formData.salons}
|
||||
onChange={(e) => setFormData({...formData, salons: e.target.value})}
|
||||
className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500"
|
||||
placeholder="مثال: 1"
|
||||
placeholder={t('addProperty.salonsPlaceholder')}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">عدد الشرفات</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">{t('addProperty.balconies')}</label>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
value={formData.balconies}
|
||||
onChange={(e) => setFormData({...formData, balconies: e.target.value})}
|
||||
className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500"
|
||||
placeholder="مثال: 1"
|
||||
placeholder={t('addProperty.balconiesPlaceholder')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-lg font-bold text-gray-900 mb-4">الخدمات المتوفرة <span className="text-red-500">*</span></h3>
|
||||
<h3 className="text-lg font-bold text-gray-900 mb-4">{t('addProperty.servicesLabel')} <span className="text-red-500">*</span></h3>
|
||||
<div className="space-y-3">
|
||||
{serviceList.map((service) => {
|
||||
const Icon = service.icon;
|
||||
@ -1010,7 +1012,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
value={formData.serviceDetails[service.id] || ''}
|
||||
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"
|
||||
placeholder="تفاصيل الخدمة (مثال: في جميع الغرف)"
|
||||
placeholder={t('addProperty.serviceDetailPlaceholder')}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@ -1023,11 +1025,11 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
<div className="bg-white rounded-xl p-6 border border-gray-200 mt-6">
|
||||
<h3 className="text-lg font-bold text-gray-800 mb-4 flex items-center gap-2">
|
||||
<MapPin className="w-5 h-5 text-amber-600" />
|
||||
القرب من الخدمات
|
||||
{t('addProperty.nearbyServicesTitle')}
|
||||
</h3>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">المسافة إلى أقرب مدرسة (كم)</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">{t('addProperty.nearbySchoolLabel')}</label>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
@ -1035,11 +1037,11 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
value={formData.nearbySchool}
|
||||
onChange={(e) => setFormData({...formData, nearbySchool: e.target.value})}
|
||||
className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500"
|
||||
placeholder="مثال: 0.5"
|
||||
placeholder={t('addProperty.nearbyPlaceholder')}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">المسافة إلى أقرب مستشفى (كم)</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">{t('addProperty.nearbyHospitalLabel')}</label>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
@ -1047,11 +1049,11 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
value={formData.nearbyHospital}
|
||||
onChange={(e) => setFormData({...formData, nearbyHospital: e.target.value})}
|
||||
className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500"
|
||||
placeholder="مثال: 1.0"
|
||||
placeholder={t('addProperty.nearbyPlaceholder')}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">المسافة إلى أقرب مطعم (كم)</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">{t('addProperty.nearbyRestaurantLabel')}</label>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
@ -1059,11 +1061,11 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
value={formData.nearbyRestaurant}
|
||||
onChange={(e) => setFormData({...formData, nearbyRestaurant: e.target.value})}
|
||||
className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500"
|
||||
placeholder="مثال: 0.3"
|
||||
placeholder={t('addProperty.nearbyPlaceholder')}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">المسافة إلى أقرب جامعة (كم)</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">{t('addProperty.nearbyUniversityLabel')}</label>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
@ -1071,11 +1073,11 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
value={formData.nearbyUniversity}
|
||||
onChange={(e) => setFormData({...formData, nearbyUniversity: e.target.value})}
|
||||
className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500"
|
||||
placeholder="مثال: 2.0"
|
||||
placeholder={t('addProperty.nearbyPlaceholder')}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">المسافة إلى أقرب حديقة (كم)</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">{t('addProperty.nearbyParkLabel')}</label>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
@ -1083,11 +1085,11 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
value={formData.nearbyPark}
|
||||
onChange={(e) => setFormData({...formData, nearbyPark: e.target.value})}
|
||||
className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500"
|
||||
placeholder="مثال: 0.5"
|
||||
placeholder={t('addProperty.nearbyPlaceholder')}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">المسافة إلى أقرب مول (كم)</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">{t('addProperty.nearbyMallLabel')}</label>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
@ -1095,7 +1097,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
value={formData.nearbyMall}
|
||||
onChange={(e) => setFormData({...formData, nearbyMall: e.target.value})}
|
||||
className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500"
|
||||
placeholder="مثال: 1.5"
|
||||
placeholder={t('addProperty.nearbyPlaceholder')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -1103,7 +1105,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
|
||||
{purpose === 'rent' && (
|
||||
<div>
|
||||
<h3 className="text-lg font-bold text-gray-900 mb-4">شروط استخدام العقار</h3>
|
||||
<h3 className="text-lg font-bold text-gray-900 mb-4">{t('addProperty.termsTitle')}</h3>
|
||||
<div className="grid grid-cols-2 md:grid-cols-3 gap-3">
|
||||
{termsList.map((term) => {
|
||||
const Icon = term.icon;
|
||||
@ -1137,14 +1139,14 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
|
||||
{/* Custom Terms */}
|
||||
<div className="mt-4 p-4 border border-dashed border-gray-300 rounded-xl">
|
||||
<p className="text-sm font-medium text-gray-700 mb-2">إضافة شرط مخصص</p>
|
||||
<p className="text-sm font-medium text-gray-700 mb-2">{t('addProperty.customTermsTitle')}</p>
|
||||
<div className="flex gap-2">
|
||||
<input
|
||||
type="text"
|
||||
value={customTermInput}
|
||||
onChange={(e) => setCustomTermInput(e.target.value)}
|
||||
onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); addCustomTerm(); } }}
|
||||
placeholder="اكتب شرطاً مخصصاً..."
|
||||
placeholder={t('addProperty.customTermPlaceholder')}
|
||||
className="flex-1 px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-amber-500 focus:border-transparent outline-none"
|
||||
/>
|
||||
<button
|
||||
@ -1153,7 +1155,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
disabled={!customTermInput.trim()}
|
||||
className="px-4 py-2 bg-amber-500 text-white rounded-lg text-sm font-medium hover:bg-amber-600 disabled:bg-gray-300 disabled:cursor-not-allowed transition-colors"
|
||||
>
|
||||
إضافة
|
||||
{t('addProperty.add')}
|
||||
</button>
|
||||
</div>
|
||||
{customTerms.length > 0 && (
|
||||
@ -1187,13 +1189,13 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
<div className="w-20 h-20 bg-amber-100 rounded-2xl flex items-center justify-center mx-auto mb-4">
|
||||
<DollarSign className="w-10 h-10 text-amber-600" />
|
||||
</div>
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-2">سعر البيع</h2>
|
||||
<p className="text-gray-600">حدد سعر البيع والعملة</p>
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-2">{t('addProperty.salePriceTitle')}</h2>
|
||||
<p className="text-gray-600">{t('addProperty.salePriceSubtitle')}</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
سعر البيع (ل.س) <span className="text-red-500">*</span>
|
||||
{t('addProperty.salePriceLabel')} <span className="text-red-500">*</span>
|
||||
</label>
|
||||
<div className="relative">
|
||||
<span className="absolute right-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400 font-bold text-sm flex items-center justify-center">{currencySymbol}</span>
|
||||
@ -1211,7 +1213,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
className={`w-full pr-12 pl-4 py-3 border rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500 ${
|
||||
errors.salePrice ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="مثال: 50000000"
|
||||
placeholder={t('addProperty.salePricePlaceholder')}
|
||||
/>
|
||||
</div>
|
||||
{errors.salePrice && <p className="text-red-500 text-sm mt-1">{errors.salePrice}</p>}
|
||||
@ -1219,16 +1221,16 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
العملة <span className="text-red-500">*</span>
|
||||
{t('addProperty.currencyLabel')} <span className="text-red-500">*</span>
|
||||
</label>
|
||||
<select
|
||||
value={selectedCurrencyId}
|
||||
onChange={(e) => setSelectedCurrencyId(parseInt(e.target.value))}
|
||||
className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500"
|
||||
>
|
||||
<option value={Currency.USD}>دولار امريكي $</option>
|
||||
<option value={Currency.SYP}>عملة سورية SP</option>
|
||||
</select>
|
||||
<select
|
||||
value={selectedCurrencyId}
|
||||
onChange={(e) => setSelectedCurrencyId(parseInt(e.target.value))}
|
||||
className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500"
|
||||
>
|
||||
<option value={Currency.USD}>{t('addProperty.usdOption')}</option>
|
||||
<option value={Currency.SYP}>{t('addProperty.sypOption')}</option>
|
||||
</select>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
@ -1239,13 +1241,13 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
<div className="w-20 h-20 bg-amber-100 rounded-2xl flex items-center justify-center mx-auto mb-4">
|
||||
<DollarSign className="w-10 h-10 text-amber-600" />
|
||||
</div>
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-2">نوع العرض والسعر</h2>
|
||||
<p className="text-gray-600">اختر نوع العرض وحدد السعر المناسب</p>
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-2">{t('addProperty.offerAndPriceTitle')}</h2>
|
||||
<p className="text-gray-600">{t('addProperty.offerAndPriceSubtitle')}</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-3">
|
||||
نوع العرض <span className="text-red-500">*</span>
|
||||
{t('addProperty.offerTypeLabel')} <span className="text-red-500">*</span>
|
||||
</label>
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-3">
|
||||
{offerTypes.map((type) => {
|
||||
@ -1272,15 +1274,15 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
{/* Currency dropdown */}
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
العملة <span className="text-red-500">*</span>
|
||||
{t('addProperty.currencyLabel')} <span className="text-red-500">*</span>
|
||||
</label>
|
||||
<select
|
||||
value={selectedCurrencyId}
|
||||
onChange={(e) => setSelectedCurrencyId(parseInt(e.target.value))}
|
||||
className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500"
|
||||
>
|
||||
<option value={Currency.USD}>دولار امريكي $</option>
|
||||
<option value={Currency.SYP}>عملة سورية SP</option>
|
||||
<option value={Currency.USD}>{t('addProperty.usdOption')}</option>
|
||||
<option value={Currency.SYP}>{t('addProperty.sypOption')}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@ -1292,7 +1294,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
{!formData.offerType && (
|
||||
<div className="border-2 border-dashed border-gray-200 rounded-2xl p-8 text-center">
|
||||
<DollarSign className="w-8 h-8 text-gray-300 mx-auto mb-3" />
|
||||
<p className="text-gray-400 font-medium">اختر نوع العرض اولا</p>
|
||||
<p className="text-gray-400 font-medium">{t('addProperty.selectOfferTypeFirst')}</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -1307,7 +1309,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
سعر الايجار اليومي ({currencySymbol}) <span className="text-red-500">*</span>
|
||||
{t('addProperty.dailyPriceLabel')} ({currencySymbol}) <span className="text-red-500">*</span>
|
||||
</label>
|
||||
<div className="relative">
|
||||
<span className="absolute right-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400 font-bold text-sm flex items-center justify-center">{currencySymbol}</span>
|
||||
@ -1325,7 +1327,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
className={`w-full pr-12 pl-4 py-3 border rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500 ${
|
||||
errors.dailyPrice ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="مثال: 50000"
|
||||
placeholder={t('addProperty.dailyPricePlaceholder')}
|
||||
/>
|
||||
</div>
|
||||
{errors.dailyPrice && (
|
||||
@ -1334,7 +1336,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
مبلغ التأمين ({currencySymbol})
|
||||
{t('addProperty.depositLabel')} ({currencySymbol})
|
||||
</label>
|
||||
<div className="relative">
|
||||
<span className="absolute right-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400 font-bold text-sm flex items-center justify-center">{currencySymbol}</span>
|
||||
@ -1350,7 +1352,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
}}
|
||||
onKeyDown={(e) => { if (['-', 'e', 'E', '+'].includes(e.key)) e.preventDefault() }}
|
||||
className="w-full pr-12 pl-4 py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500"
|
||||
placeholder="مثال: 500000"
|
||||
placeholder={t('addProperty.depositPlaceholder')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -1367,7 +1369,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
سعر الايجار الشهري ({currencySymbol}) <span className="text-red-500">*</span>
|
||||
{t('addProperty.monthlyPriceLabel')} ({currencySymbol}) <span className="text-red-500">*</span>
|
||||
</label>
|
||||
<div className="relative">
|
||||
<span className="absolute right-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400 font-bold text-sm flex items-center justify-center">{currencySymbol}</span>
|
||||
@ -1385,7 +1387,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
className={`w-full pr-12 pl-4 py-3 border rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500 ${
|
||||
errors.monthlyPrice ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="مثال: 1000000"
|
||||
placeholder={t('addProperty.monthlyPricePlaceholder')}
|
||||
/>
|
||||
</div>
|
||||
{errors.monthlyPrice && (
|
||||
@ -1394,7 +1396,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
مبلغ التأمين ({currencySymbol})
|
||||
{t('addProperty.depositLabel')} ({currencySymbol})
|
||||
</label>
|
||||
<div className="relative">
|
||||
<span className="absolute right-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400 font-bold text-sm flex items-center justify-center">{currencySymbol}</span>
|
||||
@ -1410,7 +1412,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
}}
|
||||
onKeyDown={(e) => { if (['-', 'e', 'E', '+'].includes(e.key)) e.preventDefault() }}
|
||||
className="w-full pr-12 pl-4 py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500"
|
||||
placeholder="مثال: 500000"
|
||||
placeholder={t('addProperty.depositPlaceholder')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -1427,7 +1429,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
سعر الايجار اليومي ({currencySymbol}) <span className="text-red-500">*</span>
|
||||
{t('addProperty.dailyPriceLabel')} ({currencySymbol}) <span className="text-red-500">*</span>
|
||||
</label>
|
||||
<div className="relative">
|
||||
<span className="absolute right-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400 font-bold text-sm flex items-center justify-center">{currencySymbol}</span>
|
||||
@ -1445,7 +1447,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
className={`w-full pr-12 pl-4 py-3 border rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500 ${
|
||||
errors.dailyPrice ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="مثال: 50000"
|
||||
placeholder={t('addProperty.dailyPricePlaceholder')}
|
||||
/>
|
||||
</div>
|
||||
{errors.dailyPrice && (
|
||||
@ -1454,7 +1456,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
سعر الايجار الشهري ({currencySymbol}) <span className="text-red-500">*</span>
|
||||
{t('addProperty.monthlyPriceLabel')} ({currencySymbol}) <span className="text-red-500">*</span>
|
||||
</label>
|
||||
<div className="relative">
|
||||
<span className="absolute right-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400 font-bold text-sm flex items-center justify-center">{currencySymbol}</span>
|
||||
@ -1472,7 +1474,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
className={`w-full pr-12 pl-4 py-3 border rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500 ${
|
||||
errors.monthlyPrice ? 'border-red-500' : 'border-gray-300'
|
||||
}`}
|
||||
placeholder="مثال: 1000000"
|
||||
placeholder={t('addProperty.monthlyPricePlaceholder')}
|
||||
/>
|
||||
</div>
|
||||
{errors.monthlyPrice && (
|
||||
@ -1481,7 +1483,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
مبلغ التأمين ({currencySymbol})
|
||||
{t('addProperty.depositLabel')} ({currencySymbol})
|
||||
</label>
|
||||
<div className="relative">
|
||||
<span className="absolute right-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400 font-bold text-sm flex items-center justify-center">{currencySymbol}</span>
|
||||
@ -1497,7 +1499,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
}}
|
||||
onKeyDown={(e) => { if (['-', 'e', 'E', '+'].includes(e.key)) e.preventDefault() }}
|
||||
className="w-full pr-12 pl-4 py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500"
|
||||
placeholder="مثال: 500000"
|
||||
placeholder={t('addProperty.depositPlaceholder')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -1513,12 +1515,12 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
<div className="w-20 h-20 bg-amber-100 rounded-2xl flex items-center justify-center mx-auto mb-4">
|
||||
<MapPin className="w-10 h-10 text-amber-600" />
|
||||
</div>
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-2">الموقع والصور</h2>
|
||||
<p className="text-gray-600">حدد موقع العقار وأضف الصور</p>
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-2">{t('addProperty.locationAndImagesTitle')}</h2>
|
||||
<p className="text-gray-600">{t('addProperty.locationAndImagesSubtitle')}</p>
|
||||
</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">{t('addProperty.selectLocationTitle')}</h3>
|
||||
|
||||
<div className="flex gap-2 mb-4">
|
||||
<div className="flex-1 relative">
|
||||
@ -1527,7 +1529,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
onKeyPress={(e) => e.key === 'Enter' && handleSearch()}
|
||||
placeholder="ابحث عن عنوان..."
|
||||
placeholder={t('addProperty.searchAddress')}
|
||||
className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500 pr-12"
|
||||
/>
|
||||
<Search className="absolute left-4 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
|
||||
@ -1536,16 +1538,16 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
onClick={handleSearch}
|
||||
className="px-6 py-3 bg-amber-500 text-white rounded-xl hover:bg-amber-600 transition-colors"
|
||||
>
|
||||
بحث
|
||||
{t('addProperty.searchButton')}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="bg-amber-50 border border-amber-200 rounded-xl p-4 mb-4 text-sm text-amber-800 leading-relaxed">
|
||||
<Search className="w-4 h-4 inline ml-1" />
|
||||
ابحث أولاً ثم اضغط على النتيجة لتحريك الخريطة و تثبيت العلامة .
|
||||
{t('addProperty.searchHint')}
|
||||
<br />
|
||||
<MapPin className="w-4 h-4 inline ml-1" />
|
||||
اضغط على الخريطة لتحديد موقع العقار
|
||||
{t('addProperty.clickMapHint')}
|
||||
</div>
|
||||
|
||||
<div className="relative w-full h-96 rounded-xl overflow-hidden border-2 border-gray-200 mb-4">
|
||||
@ -1564,7 +1566,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
className="w-full mb-4 bg-green-500 text-white py-3 rounded-xl font-medium hover:bg-green-600 transition-colors flex items-center justify-center gap-2"
|
||||
>
|
||||
<CheckCircle className="w-5 h-5" />
|
||||
تأكيد هذا الموقع
|
||||
{t('addProperty.confirmLocation')}
|
||||
</button>
|
||||
)}
|
||||
|
||||
@ -1572,7 +1574,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
<div className="bg-green-50 border border-green-200 rounded-xl p-4 mb-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<CheckCircle className="w-5 h-5 text-green-600" />
|
||||
<span className="text-green-800 font-medium">تم تأكيد الموقع:</span>
|
||||
<span className="text-green-800 font-medium">{t('addProperty.locationConfirmed')}:</span>
|
||||
</div>
|
||||
<p className="text-green-700 text-sm mt-2 line-clamp-2">{formData.address}</p>
|
||||
</div>
|
||||
@ -1584,7 +1586,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
</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">{t('addProperty.imagesTitle')}</h3>
|
||||
|
||||
<div
|
||||
onClick={() => fileInputRef.current?.click()}
|
||||
@ -1602,16 +1604,16 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
/>
|
||||
|
||||
<Upload className="w-12 h-12 text-gray-400 mx-auto mb-3" />
|
||||
<p className="text-gray-600 font-medium">اضغط لرفع الصور</p>
|
||||
<p className="text-gray-600 font-medium">{t('addProperty.uploadImages')}</p>
|
||||
<p className="text-xs text-gray-500 mt-2">
|
||||
JPEG, PNG, JPG • حتى 5MB • 800x600 بكسل • 2-5 صور
|
||||
{t('addProperty.imageFormatHint')}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p className="text-sm text-gray-500 mt-2 mb-4 text-center">
|
||||
يرجى رفع عدة صور واضحة
|
||||
{t('addProperty.uploadMultipleHintLine1')}
|
||||
<br />
|
||||
(اضغط على الرفع أكثر من مرة)
|
||||
{t('addProperty.uploadMultipleHintLine2')}
|
||||
</p>
|
||||
|
||||
{errors.images && (
|
||||
@ -1649,8 +1651,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
<div className="border-t border-gray-200 pt-6 mt-8">
|
||||
<div className="bg-gray-50 rounded-2xl p-5 border border-gray-200">
|
||||
<p className="text-sm text-gray-700 leading-relaxed mb-4">
|
||||
أنا صاحب العقار أقر أنني مالك العقار أو مخول قانونياً بعرضه للإيجار أو البيع،
|
||||
وأن جميع المعلومات المدخلة صحيحة، وأتحمل كامل المسؤولية عن أي معلومات غير صحيحة.
|
||||
{t('addProperty.ownerAgreement')}
|
||||
</p>
|
||||
<label className="flex items-start gap-3 cursor-pointer">
|
||||
<input
|
||||
@ -1660,9 +1661,9 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
className="w-5 h-5 mt-0.5 text-amber-500 rounded shrink-0"
|
||||
/>
|
||||
<span className="text-sm text-gray-600">
|
||||
أوافق على{' '}
|
||||
{t('addProperty.agreeToText')}{' '}
|
||||
<Link href="/terms" target="_blank" className="text-amber-600 underline hover:text-amber-700">
|
||||
شروط الاستخدام
|
||||
{t('addProperty.termsOfUseText')}
|
||||
</Link>
|
||||
</span>
|
||||
</label>
|
||||
@ -1680,7 +1681,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
className="flex-1 py-3 px-4 bg-gray-100 text-gray-700 rounded-xl font-medium hover:bg-gray-200 transition-colors flex items-center justify-center gap-2"
|
||||
>
|
||||
<ChevronRight className="w-5 h-5" />
|
||||
السابق
|
||||
{t('addProperty.previous')}
|
||||
</button>
|
||||
)}
|
||||
|
||||
@ -1691,7 +1692,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
step === 1 ? 'w-full' : ''
|
||||
}`}
|
||||
>
|
||||
التالي
|
||||
{t('addProperty.next')}
|
||||
<ChevronLeft className="w-5 h-5" />
|
||||
</button>
|
||||
) : (
|
||||
@ -1703,12 +1704,12 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
{isLoading ? (
|
||||
<>
|
||||
<Loader2 className="w-5 h-5 animate-spin" />
|
||||
جاري الحفظ...
|
||||
{t('addProperty.saving')}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Save className="w-5 h-5" />
|
||||
حفظ العقار
|
||||
{t('addProperty.saveProperty')}
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user