forked from amer2004/SweetHome
fixing add property
This commit is contained in:
@ -227,7 +227,6 @@ export default function AddPropertyPage() {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// Fetch available currencies
|
||||
getCurrencies().then((data) => {
|
||||
if (Array.isArray(data) && data.length > 0) {
|
||||
setCurrencies(data);
|
||||
@ -351,6 +350,7 @@ const response = await fetch(
|
||||
toast.success(t('toast.locationConfirmed'), { id: 'location' });
|
||||
}
|
||||
};
|
||||
|
||||
const handleMarkerDragEnd = async (lat, lng) => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
@ -370,6 +370,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const confirmLocation = () => {
|
||||
if (selectedLocation) {
|
||||
setFormData({
|
||||
@ -414,7 +415,6 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Show preview
|
||||
const reader = new FileReader();
|
||||
reader.onloadend = () => {
|
||||
setImagePreviews(prev => [...prev, reader.result]);
|
||||
@ -426,7 +426,6 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
images: [...prev.images, file]
|
||||
}));
|
||||
|
||||
// Upload to server immediately
|
||||
try {
|
||||
const path = await uploadPicture(file);
|
||||
setUploadedImagePaths(prev => [...prev, path]);
|
||||
@ -648,7 +647,6 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
return;
|
||||
}
|
||||
|
||||
// Map UI property type to API BuildingType enum
|
||||
const buildingTypeMap = { apartment: BuildingType.APARTMENT, villa: BuildingType.VILLA, sweet: BuildingType.SWEET, suite: BuildingType.SWEET, room: BuildingType.ROOM, studio: BuildingType.STUDIO, office: BuildingType.OFFICE, farms: BuildingType.FARMS, shop: BuildingType.SHOP, warehouse: BuildingType.WAREHOUSE };
|
||||
|
||||
const selectedServices = Object.entries(formData.services)
|
||||
@ -750,7 +748,7 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
currencyId: selectedCurrencyId,
|
||||
rentType: rentTypeMap[formData.offerType] ?? RentType.MONTHLY,
|
||||
type: formData.furnished ? RentPropertyType.FURNISHED : RentPropertyType.UNFURNISHED,
|
||||
allowedPaymentPeriod: formData.allowedPaymentPeriod || '',
|
||||
allowedPaymentPeriod: formData.allowedPaymentPeriod || '1.00:00:00',
|
||||
});
|
||||
const res = await addRentProperty(payload);
|
||||
toast.success(t('toast.rentPropertySuccess'));
|
||||
@ -1226,7 +1224,6 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* 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">{t('addProperty.customTermsTitle')}</p>
|
||||
<div className="flex gap-2">
|
||||
@ -1360,7 +1357,6 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Currency dropdown */}
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
{t('addProperty.currencyLabel')} <span className="text-red-500">*</span>
|
||||
@ -1375,7 +1371,6 @@ const handleMarkerDragEnd = async (lat, lng) => {
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{/* Price and deposit fields - conditional on offerType */}
|
||||
{errors.offerType && (
|
||||
<p className="text-red-500 text-sm mt-1">{errors.offerType}</p>
|
||||
)}
|
||||
|
||||
120
app/utils/api.js
120
app/utils/api.js
@ -39,9 +39,6 @@ function buildApiUrl(base, endpoint) {
|
||||
return `${base.replace(/\/$/, "")}${endpoint.startsWith("/") ? endpoint : `/${endpoint}`}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic API fetch — attaches auth token, unwraps { data } envelope
|
||||
*/
|
||||
async function apiFetch(endpoint, options = {}) {
|
||||
const token = AuthService.getToken();
|
||||
|
||||
@ -103,9 +100,6 @@ async function apiFetch(endpoint, options = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Auth fetch — returns full { status, data, ok } for status-code handling
|
||||
*/
|
||||
async function authFetch(endpoint, body, token = null) {
|
||||
const headers = {};
|
||||
|
||||
@ -193,8 +187,6 @@ async function reportFetch(endpoint, body) {
|
||||
};
|
||||
}
|
||||
|
||||
// ─── Rent Properties ───
|
||||
|
||||
export async function getRentProperties() {
|
||||
return apiFetch("/RentProperties/GetRentProperties");
|
||||
}
|
||||
@ -213,8 +205,6 @@ export async function getRentPropertyLocations(params = {}) {
|
||||
);
|
||||
}
|
||||
|
||||
// ─── Sale Properties ───
|
||||
|
||||
export async function getSaleProperties() {
|
||||
return apiFetch("/SaleProperties/GetSaleProperties");
|
||||
}
|
||||
@ -225,14 +215,10 @@ export async function getSaleProperty(id) {
|
||||
return items.find((p) => p.id == id) || items[0];
|
||||
}
|
||||
|
||||
// ─── Properties (generic) ───
|
||||
|
||||
export async function getProperty(id) {
|
||||
return apiFetch(`/Properties/Get/${id}`);
|
||||
}
|
||||
|
||||
// ─── Recommendations ───
|
||||
|
||||
export async function getRecommendations() {
|
||||
return apiFetch("/Recommendations/GetRecommendations");
|
||||
}
|
||||
@ -241,8 +227,6 @@ export async function getTopRecommendations(count = 10) {
|
||||
return apiFetch(`/Recommendations/GetTopRecommendations?count=${count}`);
|
||||
}
|
||||
|
||||
// ─── Reservations ───
|
||||
|
||||
export async function getAvailableDateRanges(
|
||||
propertyId,
|
||||
fromDate = null,
|
||||
@ -291,8 +275,6 @@ export async function bookReservation(propertyInfoId, startDate, endDate) {
|
||||
});
|
||||
}
|
||||
|
||||
// ─── Terms ───
|
||||
|
||||
export async function getARTerms() {
|
||||
return apiFetch("/Configuration/GetARTerms");
|
||||
}
|
||||
@ -301,8 +283,6 @@ export async function getENTerms() {
|
||||
return apiFetch("/Configuration/GetENTerms");
|
||||
}
|
||||
|
||||
// ─── Profile ───
|
||||
|
||||
export async function getCustomerByUserId(userId) {
|
||||
return apiFetch(`/Customer/GetByUserId/${userId}`);
|
||||
}
|
||||
@ -311,69 +291,34 @@ export async function getOwnerByUserId(userId) {
|
||||
return apiFetch(`/Owner/GetByUserId/${userId}`);
|
||||
}
|
||||
|
||||
// ─── Properties ───
|
||||
|
||||
export async function getMyRentListings() {
|
||||
return apiFetch("/RentProperties/GetMyRentListings");
|
||||
}
|
||||
|
||||
function normalizeLocationValue(value) {
|
||||
if (value === null || value === undefined || value === "") return "";
|
||||
|
||||
const normalizedValue = String(value).trim();
|
||||
const map = {
|
||||
"دمشق": "Damascus",
|
||||
"حلب": "Aleppo",
|
||||
"حمص": "Homs",
|
||||
"اللاذقية": "Latakia",
|
||||
"درعا": "Daraa",
|
||||
"طرطوس": "Tartous",
|
||||
"السويداء": "Suweida",
|
||||
"دير الزور": "DeirEzzor",
|
||||
"الرقة": "Raqqa",
|
||||
"إدلب": "Idlib",
|
||||
"الحسكة": "Hasakah",
|
||||
"القامشلي": "Qamishli",
|
||||
"ريف دمشق": "RuralDamascus",
|
||||
Damascus: "Damascus",
|
||||
Aleppo: "Aleppo",
|
||||
Homs: "Homs",
|
||||
Latakia: "Latakia",
|
||||
Daraa: "Daraa",
|
||||
Tartous: "Tartous",
|
||||
Sweida: "Suweida",
|
||||
DeirEzzor: "DeirEzzor",
|
||||
Raqqa: "Raqqa",
|
||||
Idlib: "Idlib",
|
||||
Hasakah: "Hasakah",
|
||||
Qamishli: "Qamishli",
|
||||
RuralDamascus: "RuralDamascus",
|
||||
};
|
||||
|
||||
return map[normalizedValue] ?? normalizedValue;
|
||||
}
|
||||
|
||||
export function buildRentPropertyPayload(data = {}) {
|
||||
const propertyInformation = data?.propertyInformation || {};
|
||||
|
||||
const rawCityValue =
|
||||
data?.city ??
|
||||
data?.governorate ??
|
||||
propertyInformation?.city ??
|
||||
propertyInformation?.governorate ??
|
||||
"";
|
||||
const normalizedCityValue = normalizeLocationValue(rawCityValue);
|
||||
1;
|
||||
|
||||
const cityInt = parseInt(rawCityValue, 10) || 1;
|
||||
|
||||
const documentTypeValue =
|
||||
data?.documentType ?? propertyInformation?.documentType ?? "";
|
||||
data?.documentType ?? propertyInformation?.documentType ?? 1;
|
||||
|
||||
return {
|
||||
...data,
|
||||
city: normalizedCityValue,
|
||||
governorate: normalizedCityValue,
|
||||
city: cityInt,
|
||||
governorate: cityInt,
|
||||
documentType: documentTypeValue,
|
||||
propertyInformation: {
|
||||
...propertyInformation,
|
||||
city: normalizedCityValue,
|
||||
governorate: normalizeLocationValue(propertyInformation?.governorate ?? normalizedCityValue),
|
||||
city: cityInt,
|
||||
governorate: cityInt,
|
||||
documentType: documentTypeValue,
|
||||
},
|
||||
};
|
||||
@ -382,14 +327,14 @@ export function buildRentPropertyPayload(data = {}) {
|
||||
export async function addRentProperty(data) {
|
||||
return apiFetch("/RentProperties/AddRentProperty", {
|
||||
method: "POST",
|
||||
body: { rentPropertyDto: buildRentPropertyPayload(data) },
|
||||
body: buildRentPropertyPayload(data),
|
||||
});
|
||||
}
|
||||
|
||||
export async function editRentProperty(id, data) {
|
||||
return apiFetch(`/RentProperties/EditRentProperty/${id}`, {
|
||||
method: "PUT",
|
||||
body: { rentPropertyDto: buildRentPropertyPayload(data) },
|
||||
body: buildRentPropertyPayload(data),
|
||||
});
|
||||
}
|
||||
|
||||
@ -429,8 +374,6 @@ export async function updateSalePropertyStatus(id, status) {
|
||||
});
|
||||
}
|
||||
|
||||
// ─── Currencies ───
|
||||
|
||||
export async function getCurrencies() {
|
||||
return apiFetch("/Currency/GetAll");
|
||||
}
|
||||
@ -439,8 +382,6 @@ export async function getPaymentTypes() {
|
||||
return apiFetch("/PaymentType/GetAll");
|
||||
}
|
||||
|
||||
// ─── Files ───
|
||||
|
||||
export async function uploadPicture(file) {
|
||||
const formData = new FormData();
|
||||
formData.append("image", file);
|
||||
@ -474,8 +415,6 @@ export async function uploadPicture(file) {
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Auth: Registration ───
|
||||
|
||||
async function multipartAuthFetch(endpoint, formData) {
|
||||
const token = AuthService.getToken();
|
||||
|
||||
@ -571,8 +510,6 @@ export async function addCustomer(data, frontImage = null, backImage = null) {
|
||||
return multipartAuthFetch("/Customer/Add", formData);
|
||||
}
|
||||
|
||||
// ─── Auth: Login ───
|
||||
|
||||
export async function loginWithEmail(credential, password) {
|
||||
return authFetch("/Auth/LogInWithEmail", {
|
||||
credential,
|
||||
@ -591,8 +528,6 @@ export async function loginWithPhone(credential, password) {
|
||||
});
|
||||
}
|
||||
|
||||
// ─── Auth: OTP ───
|
||||
|
||||
export async function sendEmailOTP() {
|
||||
return apiFetch("/Auth/SendEmailOTP", { method: "POST" });
|
||||
}
|
||||
@ -619,8 +554,6 @@ export async function verifyPhone(code) {
|
||||
);
|
||||
}
|
||||
|
||||
// ─── Helpers ───
|
||||
|
||||
export function isEmail(value) {
|
||||
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
|
||||
}
|
||||
@ -629,8 +562,6 @@ export function isPhoneNumber(value) {
|
||||
return /^\+?\d{7,15}$/.test(value.replace(/[\s\-()]/g, ""));
|
||||
}
|
||||
|
||||
// ─── Favorites ───
|
||||
|
||||
export async function getUserFavoriteProperties() {
|
||||
return apiFetch("/FavoriteProperty/GetUserFavoriteProperties");
|
||||
}
|
||||
@ -649,8 +580,6 @@ export async function getUserNotifications() {
|
||||
return apiFetch("/Notifications/GetUserNotifications");
|
||||
}
|
||||
|
||||
// ─── Booking/Reservation Management ───
|
||||
|
||||
export async function confirmDepositPayment(bookingId) {
|
||||
return apiFetch("/Reservations/ConfirmDepositPayment", {
|
||||
method: "POST",
|
||||
@ -706,8 +635,6 @@ export async function updateBookingStatus(bookingId, status) {
|
||||
});
|
||||
}
|
||||
|
||||
// ─── Owner / Reservations ───
|
||||
|
||||
export async function getOwnerReservationRequests() {
|
||||
return apiFetch("/Reservations/GetOwnerResevationRequests");
|
||||
}
|
||||
@ -729,8 +656,6 @@ export async function ownerConfirmReservation(id) {
|
||||
});
|
||||
}
|
||||
|
||||
// ─── Payments ───
|
||||
|
||||
export async function getMyTransaction() {
|
||||
return apiFetch("/Customer/GetMyTransaction");
|
||||
}
|
||||
@ -754,7 +679,6 @@ export async function payDeposit(data) {
|
||||
formData.append("Comment", "");
|
||||
}
|
||||
|
||||
// صورة الوصل لطريقة الدفع Haram
|
||||
if (data.paymentImage) {
|
||||
formData.append("TransactionType", data.paymentImage);
|
||||
formData.append("paymentImage", data.paymentImage);
|
||||
@ -766,8 +690,6 @@ export async function payDeposit(data) {
|
||||
});
|
||||
}
|
||||
|
||||
// ─── Owner Contact & Stats ───
|
||||
|
||||
export async function getOwnerContactInformation(propertyInformationId) {
|
||||
return apiFetch(
|
||||
`/Owner/GetOwnerContactInformation?propertyInformationId=${propertyInformationId}`,
|
||||
@ -778,8 +700,6 @@ export async function getOwnerStatistics() {
|
||||
return apiFetch("/Statistics/GetOwnerStatistics");
|
||||
}
|
||||
|
||||
// ─── Agent Registration ───
|
||||
|
||||
export async function registerRealEstateAgent(formData) {
|
||||
const token = AuthService.getToken();
|
||||
|
||||
@ -811,8 +731,6 @@ export async function registerRealEstateAgent(formData) {
|
||||
};
|
||||
}
|
||||
|
||||
// ─── Change Password ───
|
||||
|
||||
export async function changePassword(oldPassword, newPassword) {
|
||||
return apiFetch(
|
||||
`/User/ChangePassword?oldPassword=${encodeURIComponent(oldPassword)}&newPassword=${encodeURIComponent(newPassword)}`,
|
||||
@ -822,8 +740,6 @@ export async function changePassword(oldPassword, newPassword) {
|
||||
);
|
||||
}
|
||||
|
||||
// ─── Forget Password (OTP flow) ───
|
||||
|
||||
export async function requestForgetPasswordOtp(email) {
|
||||
return apiFetch(`/User/ForgetPassword?email=${encodeURIComponent(email)}`, {
|
||||
method: "POST",
|
||||
@ -839,14 +755,10 @@ export async function verifyForgetPasswordOtp(email, code, newPassword) {
|
||||
);
|
||||
}
|
||||
|
||||
// ─── Reset Password (token flow) ───
|
||||
|
||||
export async function resetPassword(token) {
|
||||
return apiFetch(`/Auth/ResetPassword?token=${encodeURIComponent(token)}`);
|
||||
}
|
||||
|
||||
// ─── Delete Account ───
|
||||
|
||||
export async function deleteMyAccount(password) {
|
||||
return apiFetch(
|
||||
`/User/DeleteMyAccount?password=${encodeURIComponent(password)}`,
|
||||
@ -856,8 +768,6 @@ export async function deleteMyAccount(password) {
|
||||
);
|
||||
}
|
||||
|
||||
// ─── Set FCM Token ───
|
||||
|
||||
export async function setFCMToken(token, deviceType = 2) {
|
||||
return apiFetch("/User/SetFCMToken", {
|
||||
method: "POST",
|
||||
@ -865,8 +775,6 @@ export async function setFCMToken(token, deviceType = 2) {
|
||||
});
|
||||
}
|
||||
|
||||
// ─── Filter Rent Properties ───
|
||||
|
||||
export async function filterRentProperties(params = {}) {
|
||||
const qs = new URLSearchParams();
|
||||
Object.entries(params).forEach(([k, v]) => {
|
||||
@ -878,8 +786,6 @@ export async function filterRentProperties(params = {}) {
|
||||
);
|
||||
}
|
||||
|
||||
// ─── Reports ───
|
||||
|
||||
export async function sendGeneralReport(subject, reportBody) {
|
||||
return reportFetch("/Reports/SendGeneralReport", {
|
||||
subject,
|
||||
@ -922,8 +828,6 @@ export async function updateSaleReport(id, data) {
|
||||
});
|
||||
}
|
||||
|
||||
// ─── Terms (Add or Update) ───
|
||||
|
||||
export async function addOrUpdateTerms(terms) {
|
||||
return apiFetch("/Terms/AddOrUpdateTerms", {
|
||||
method: "POST",
|
||||
|
||||
Reference in New Issue
Block a user