Edit AddProperty

This commit is contained in:
Rahaf
2026-05-28 17:42:51 +03:00
parent a5577765ed
commit 417b6cb393
3 changed files with 122 additions and 17 deletions

View File

@ -297,6 +297,7 @@ export default function AddPropertyForm({ onClose, onSuccess }) {
<option value="house">بيت</option>
<option value="villa">فيلا</option>
<option value="studio">استوديو</option>
<option value="office">مكتب</option>
</select>
</div>

View File

@ -1,12 +1,19 @@
/**
* BuildingType Enum
* Backend values are numeric (0, 1, 2)
* Backend values are numeric
* Used in: PropertyInformation.buildingType
*/
const BuildingType = Object.freeze({
APARTMENT: 0,
VILLA: 1,
HOUSE: 2,
SWEET: 3,
ROOM: 4,
STUDIO: 5,
OFFICE: 6,
FARMS: 7,
SHOP: 8,
WAREHOUSE: 9,
});
// Map numeric value → Arabic label
@ -14,6 +21,13 @@ const BuildingTypeLabels = Object.freeze({
[BuildingType.APARTMENT]: 'شقة',
[BuildingType.VILLA]: 'فيلا',
[BuildingType.HOUSE]: 'بيت',
[BuildingType.SWEET]: 'سويت',
[BuildingType.ROOM]: 'غرفة',
[BuildingType.STUDIO]: 'استوديو',
[BuildingType.OFFICE]: 'مكتب',
[BuildingType.FARMS]: 'مزرعة',
[BuildingType.SHOP]: 'محل',
[BuildingType.WAREHOUSE]: 'مستودع',
});
// Map numeric value → English key (for UI filters)
@ -21,6 +35,13 @@ const BuildingTypeKeys = Object.freeze({
[BuildingType.APARTMENT]: 'apartment',
[BuildingType.VILLA]: 'villa',
[BuildingType.HOUSE]: 'house',
[BuildingType.SWEET]: 'sweet',
[BuildingType.ROOM]: 'room',
[BuildingType.STUDIO]: 'studio',
[BuildingType.OFFICE]: 'office',
[BuildingType.FARMS]: 'farms',
[BuildingType.SHOP]: 'shop',
[BuildingType.WAREHOUSE]: 'warehouse',
});
// Reverse map: English key → numeric value
@ -28,6 +49,14 @@ const BuildingTypeByKey = Object.freeze({
apartment: BuildingType.APARTMENT,
villa: BuildingType.VILLA,
house: BuildingType.HOUSE,
sweet: BuildingType.SWEET,
suite: BuildingType.SWEET,
room: BuildingType.ROOM,
studio: BuildingType.STUDIO,
office: BuildingType.OFFICE,
farms: BuildingType.FARMS,
shop: BuildingType.SHOP,
warehouse: BuildingType.WAREHOUSE,
});
export { BuildingType, BuildingTypeLabels, BuildingTypeKeys, BuildingTypeByKey };

View File

@ -90,13 +90,15 @@ export default function AddPropertyPage() {
const totalSteps = 4;
const [formData, setFormData] = useState({
propertyType: 'apartment', // apartment, villa, suite, room
propertyType: 'apartment', // apartment, villa, suite, room, studio, office
furnished: false,
bedrooms: 1,
bedrooms: 0,
bathrooms: 1,
livingRooms: 1,
livingRooms: 0,
balconies: 0,
floor: '',
services: {
[PropertyService.ELECTRICITY]: false,
@ -153,7 +155,9 @@ export default function AddPropertyPage() {
{ id: 'apartment', label: 'شقة', icon: Building },
{ id: 'villa', label: 'فيلا', icon: Home },
{ id: 'suite', label: 'سويت', icon: Sofa },
{ id: 'room', label: 'غرفة ضمن شقة', icon: DoorOpen }
{ id: 'room', label: 'غرفة ضمن شقة', icon: DoorOpen },
{ id: 'studio', label: 'استوديو', icon: Layers },
{ id: 'office', label: 'مكتب', icon: Building },
];
const serviceList = [
@ -430,7 +434,7 @@ const handleMapClick = async (coords) => {
};
const decrementBedrooms = () => {
if (formData.bedrooms > 1) {
if (formData.bedrooms > 0) {
setFormData({
...formData,
bedrooms: formData.bedrooms - 1
@ -462,7 +466,7 @@ const handleMapClick = async (coords) => {
};
const decrementLivingRooms = () => {
if (formData.livingRooms > 1) {
if (formData.livingRooms > 0) {
setFormData({
...formData,
livingRooms: formData.livingRooms - 1
@ -470,6 +474,22 @@ const handleMapClick = async (coords) => {
}
};
const incrementBalconies = () => {
setFormData({
...formData,
balconies: formData.balconies + 1
});
};
const decrementBalconies = () => {
if (formData.balconies > 0) {
setFormData({
...formData,
balconies: formData.balconies - 1
});
}
};
const validateStep = () => {
const newErrors = {};
@ -481,15 +501,12 @@ const handleMapClick = async (coords) => {
break;
case 2:
if (!formData.bedrooms) {
newErrors.bedrooms = 'عدد الغرف مطلوب';
if (!formData.floor && formData.floor !== 0) {
newErrors.floor = 'رقم الطابق مطلوب';
}
if (!formData.bathrooms) {
newErrors.bathrooms = 'عدد الحمامات مطلوب';
}
if (!formData.livingRooms) {
newErrors.livingRooms = 'عدد الصالونات مطلوب';
}
break;
case 3:
@ -538,7 +555,18 @@ const handleMapClick = async (coords) => {
console.log('[AddProperty] Building RentPropertyDto payload...');
// Map UI property type to API BuildingType enum
const buildingTypeMap = { apartment: BuildingType.APARTMENT, villa: BuildingType.VILLA, suite: BuildingType.APARTMENT, room: BuildingType.APARTMENT };
const buildingTypeMap = {
apartment: BuildingType.APARTMENT,
villa: BuildingType.VILLA,
suite: BuildingType.SWEET,
sweet: BuildingType.SWEET,
room: BuildingType.ROOM,
studio: BuildingType.STUDIO,
office: BuildingType.OFFICE,
farms: BuildingType.FARMS,
shop: BuildingType.SHOP,
warehouse: BuildingType.WAREHOUSE,
};
// Map offer type to RentType enum: 0=Monthly, 1=Daily
const rentTypeMap = { daily: RentType.DAILY, monthly: RentType.MONTHLY, both: RentType.MONTHLY };
@ -561,6 +589,7 @@ const handleMapClick = async (coords) => {
displayType: formData.offerType === 'both' ? 'Both' : formData.offerType === 'daily' ? 'Daily' : 'Monthly',
propertyCondition: formData.furnished ? 'Furnished' : 'Unfurnished',
photos: imagePreviews.map((_, i) => `photo_${i}.jpg`),
floor: parseInt(formData.floor, 10) || 0,
room: {
areaType: formData.propertyType === 'room' ? 'Shared room' : 'Private room',
peopleAllowed: String(formData.bedrooms),
@ -575,7 +604,9 @@ const handleMapClick = async (coords) => {
visitorsAllowed: true,
quietTimesEnabled: false,
quietTimes: '',
}
},
balconies: formData.balconies || 0,
isOffice: formData.propertyType === 'office',
});
const payload = {
@ -768,10 +799,10 @@ const handleMapClick = async (coords) => {
<p className="text-gray-600">أدخل التفاصيل والخدمات المتاحة</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<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">
عدد الغرف <span className="text-red-500">*</span>
عدد الغرف <span className="text-gray-400 text-xs">(اختياري)</span>
</label>
<div className="flex items-center gap-2">
<button
@ -827,7 +858,7 @@ const handleMapClick = async (coords) => {
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
عدد الصالونات <span className="text-red-500">*</span>
عدد الصالونات <span className="text-gray-400 text-xs">(اختياري)</span>
</label>
<div className="flex items-center gap-2">
<button
@ -852,6 +883,50 @@ const handleMapClick = async (coords) => {
<p className="text-red-500 text-sm mt-1">{errors.livingRooms}</p>
)}
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
رقم الطابق <span className="text-red-500">*</span>
</label>
<input
type="number"
min="0"
value={formData.floor}
onChange={(e) => setFormData({...formData, floor: 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="أدخل رقم الطابق"
/>
{errors.floor && (
<p className="text-red-500 text-sm mt-1">{errors.floor}</p>
)}
</div>
{formData.propertyType === 'office' && (
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
عدد البلكونات (اختياري)
</label>
<div className="flex items-center gap-2">
<button
type="button"
onClick={decrementBalconies}
className="w-10 h-10 bg-gray-100 rounded-lg flex items-center justify-center hover:bg-gray-200"
>
<Minus className="w-4 h-4" />
</button>
<div className="flex-1 text-center font-bold text-xl">
{formData.balconies}
</div>
<button
type="button"
onClick={incrementBalconies}
className="w-10 h-10 bg-gray-100 rounded-lg flex items-center justify-center hover:bg-gray-200"
>
<Plus className="w-4 h-4" />
</button>
</div>
</div>
)}
</div>
<div>