Edit AddProperty
This commit is contained in:
@ -297,6 +297,7 @@ export default function AddPropertyForm({ onClose, onSuccess }) {
|
|||||||
<option value="house">بيت</option>
|
<option value="house">بيت</option>
|
||||||
<option value="villa">فيلا</option>
|
<option value="villa">فيلا</option>
|
||||||
<option value="studio">استوديو</option>
|
<option value="studio">استوديو</option>
|
||||||
|
<option value="office">مكتب</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +1,19 @@
|
|||||||
/**
|
/**
|
||||||
* BuildingType Enum
|
* BuildingType Enum
|
||||||
* Backend values are numeric (0, 1, 2)
|
* Backend values are numeric
|
||||||
* Used in: PropertyInformation.buildingType
|
* Used in: PropertyInformation.buildingType
|
||||||
*/
|
*/
|
||||||
const BuildingType = Object.freeze({
|
const BuildingType = Object.freeze({
|
||||||
APARTMENT: 0,
|
APARTMENT: 0,
|
||||||
VILLA: 1,
|
VILLA: 1,
|
||||||
HOUSE: 2,
|
HOUSE: 2,
|
||||||
|
SWEET: 3,
|
||||||
|
ROOM: 4,
|
||||||
|
STUDIO: 5,
|
||||||
|
OFFICE: 6,
|
||||||
|
FARMS: 7,
|
||||||
|
SHOP: 8,
|
||||||
|
WAREHOUSE: 9,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Map numeric value → Arabic label
|
// Map numeric value → Arabic label
|
||||||
@ -14,6 +21,13 @@ const BuildingTypeLabels = Object.freeze({
|
|||||||
[BuildingType.APARTMENT]: 'شقة',
|
[BuildingType.APARTMENT]: 'شقة',
|
||||||
[BuildingType.VILLA]: 'فيلا',
|
[BuildingType.VILLA]: 'فيلا',
|
||||||
[BuildingType.HOUSE]: 'بيت',
|
[BuildingType.HOUSE]: 'بيت',
|
||||||
|
[BuildingType.SWEET]: 'سويت',
|
||||||
|
[BuildingType.ROOM]: 'غرفة',
|
||||||
|
[BuildingType.STUDIO]: 'استوديو',
|
||||||
|
[BuildingType.OFFICE]: 'مكتب',
|
||||||
|
[BuildingType.FARMS]: 'مزرعة',
|
||||||
|
[BuildingType.SHOP]: 'محل',
|
||||||
|
[BuildingType.WAREHOUSE]: 'مستودع',
|
||||||
});
|
});
|
||||||
|
|
||||||
// Map numeric value → English key (for UI filters)
|
// Map numeric value → English key (for UI filters)
|
||||||
@ -21,6 +35,13 @@ const BuildingTypeKeys = Object.freeze({
|
|||||||
[BuildingType.APARTMENT]: 'apartment',
|
[BuildingType.APARTMENT]: 'apartment',
|
||||||
[BuildingType.VILLA]: 'villa',
|
[BuildingType.VILLA]: 'villa',
|
||||||
[BuildingType.HOUSE]: 'house',
|
[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
|
// Reverse map: English key → numeric value
|
||||||
@ -28,6 +49,14 @@ const BuildingTypeByKey = Object.freeze({
|
|||||||
apartment: BuildingType.APARTMENT,
|
apartment: BuildingType.APARTMENT,
|
||||||
villa: BuildingType.VILLA,
|
villa: BuildingType.VILLA,
|
||||||
house: BuildingType.HOUSE,
|
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 };
|
export { BuildingType, BuildingTypeLabels, BuildingTypeKeys, BuildingTypeByKey };
|
||||||
|
|||||||
@ -90,13 +90,15 @@ export default function AddPropertyPage() {
|
|||||||
const totalSteps = 4;
|
const totalSteps = 4;
|
||||||
|
|
||||||
const [formData, setFormData] = useState({
|
const [formData, setFormData] = useState({
|
||||||
propertyType: 'apartment', // apartment, villa, suite, room
|
propertyType: 'apartment', // apartment, villa, suite, room, studio, office
|
||||||
|
|
||||||
furnished: false,
|
furnished: false,
|
||||||
|
|
||||||
bedrooms: 1,
|
bedrooms: 0,
|
||||||
bathrooms: 1,
|
bathrooms: 1,
|
||||||
livingRooms: 1,
|
livingRooms: 0,
|
||||||
|
balconies: 0,
|
||||||
|
floor: '',
|
||||||
|
|
||||||
services: {
|
services: {
|
||||||
[PropertyService.ELECTRICITY]: false,
|
[PropertyService.ELECTRICITY]: false,
|
||||||
@ -153,7 +155,9 @@ export default function AddPropertyPage() {
|
|||||||
{ id: 'apartment', label: 'شقة', icon: Building },
|
{ id: 'apartment', label: 'شقة', icon: Building },
|
||||||
{ id: 'villa', label: 'فيلا', icon: Home },
|
{ id: 'villa', label: 'فيلا', icon: Home },
|
||||||
{ id: 'suite', label: 'سويت', icon: Sofa },
|
{ 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 = [
|
const serviceList = [
|
||||||
@ -430,7 +434,7 @@ const handleMapClick = async (coords) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const decrementBedrooms = () => {
|
const decrementBedrooms = () => {
|
||||||
if (formData.bedrooms > 1) {
|
if (formData.bedrooms > 0) {
|
||||||
setFormData({
|
setFormData({
|
||||||
...formData,
|
...formData,
|
||||||
bedrooms: formData.bedrooms - 1
|
bedrooms: formData.bedrooms - 1
|
||||||
@ -462,7 +466,7 @@ const handleMapClick = async (coords) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const decrementLivingRooms = () => {
|
const decrementLivingRooms = () => {
|
||||||
if (formData.livingRooms > 1) {
|
if (formData.livingRooms > 0) {
|
||||||
setFormData({
|
setFormData({
|
||||||
...formData,
|
...formData,
|
||||||
livingRooms: formData.livingRooms - 1
|
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 validateStep = () => {
|
||||||
const newErrors = {};
|
const newErrors = {};
|
||||||
|
|
||||||
@ -481,15 +501,12 @@ const handleMapClick = async (coords) => {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
if (!formData.bedrooms) {
|
if (!formData.floor && formData.floor !== 0) {
|
||||||
newErrors.bedrooms = 'عدد الغرف مطلوب';
|
newErrors.floor = 'رقم الطابق مطلوب';
|
||||||
}
|
}
|
||||||
if (!formData.bathrooms) {
|
if (!formData.bathrooms) {
|
||||||
newErrors.bathrooms = 'عدد الحمامات مطلوب';
|
newErrors.bathrooms = 'عدد الحمامات مطلوب';
|
||||||
}
|
}
|
||||||
if (!formData.livingRooms) {
|
|
||||||
newErrors.livingRooms = 'عدد الصالونات مطلوب';
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
@ -538,7 +555,18 @@ const handleMapClick = async (coords) => {
|
|||||||
console.log('[AddProperty] Building RentPropertyDto payload...');
|
console.log('[AddProperty] Building RentPropertyDto payload...');
|
||||||
|
|
||||||
// Map UI property type to API BuildingType enum
|
// 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
|
// Map offer type to RentType enum: 0=Monthly, 1=Daily
|
||||||
const rentTypeMap = { daily: RentType.DAILY, monthly: RentType.MONTHLY, both: RentType.MONTHLY };
|
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',
|
displayType: formData.offerType === 'both' ? 'Both' : formData.offerType === 'daily' ? 'Daily' : 'Monthly',
|
||||||
propertyCondition: formData.furnished ? 'Furnished' : 'Unfurnished',
|
propertyCondition: formData.furnished ? 'Furnished' : 'Unfurnished',
|
||||||
photos: imagePreviews.map((_, i) => `photo_${i}.jpg`),
|
photos: imagePreviews.map((_, i) => `photo_${i}.jpg`),
|
||||||
|
floor: parseInt(formData.floor, 10) || 0,
|
||||||
room: {
|
room: {
|
||||||
areaType: formData.propertyType === 'room' ? 'Shared room' : 'Private room',
|
areaType: formData.propertyType === 'room' ? 'Shared room' : 'Private room',
|
||||||
peopleAllowed: String(formData.bedrooms),
|
peopleAllowed: String(formData.bedrooms),
|
||||||
@ -575,7 +604,9 @@ const handleMapClick = async (coords) => {
|
|||||||
visitorsAllowed: true,
|
visitorsAllowed: true,
|
||||||
quietTimesEnabled: false,
|
quietTimesEnabled: false,
|
||||||
quietTimes: '',
|
quietTimes: '',
|
||||||
}
|
},
|
||||||
|
balconies: formData.balconies || 0,
|
||||||
|
isOffice: formData.propertyType === 'office',
|
||||||
});
|
});
|
||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
@ -768,10 +799,10 @@ const handleMapClick = async (coords) => {
|
|||||||
<p className="text-gray-600">أدخل التفاصيل والخدمات المتاحة</p>
|
<p className="text-gray-600">أدخل التفاصيل والخدمات المتاحة</p>
|
||||||
</div>
|
</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>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<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>
|
</label>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<button
|
<button
|
||||||
@ -827,7 +858,7 @@ const handleMapClick = async (coords) => {
|
|||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<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>
|
</label>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<button
|
<button
|
||||||
@ -852,6 +883,50 @@ const handleMapClick = async (coords) => {
|
|||||||
<p className="text-red-500 text-sm mt-1">{errors.livingRooms}</p>
|
<p className="text-red-500 text-sm mt-1">{errors.livingRooms}</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</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>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
Reference in New Issue
Block a user