This commit is contained in:
129
app/utils/api.js
129
app/utils/api.js
@ -453,6 +453,10 @@ import AuthService from '../services/AuthService';
|
||||
|
||||
const API_BASE = process.env.NEXT_PUBLIC_API_URL || 'https://45.93.137.91.nip.io/api';
|
||||
|
||||
function isFormData(value) {
|
||||
return typeof FormData !== 'undefined' && value instanceof FormData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic API fetch — attaches auth token, unwraps { data } envelope
|
||||
*/
|
||||
@ -460,14 +464,24 @@ async function apiFetch(endpoint, options = {}) {
|
||||
const token = AuthService.getToken();
|
||||
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
...(token && { Authorization: `Bearer ${token}` }),
|
||||
...options.headers,
|
||||
...(options.headers || {}),
|
||||
};
|
||||
|
||||
const hasBody = options.body != null;
|
||||
const bodyIsFormData = isFormData(options.body);
|
||||
|
||||
if (hasBody && !bodyIsFormData && !headers['Content-Type'] && !headers['content-type']) {
|
||||
headers['Content-Type'] = 'application/json';
|
||||
}
|
||||
|
||||
const res = await fetch(`${API_BASE}${endpoint}`, {
|
||||
...options,
|
||||
headers,
|
||||
body:
|
||||
hasBody && !bodyIsFormData && typeof options.body !== 'string'
|
||||
? JSON.stringify(options.body)
|
||||
: options.body,
|
||||
});
|
||||
|
||||
if (!res.ok && res.status !== 206) {
|
||||
@ -493,7 +507,13 @@ 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 = { 'Content-Type': 'application/json' };
|
||||
const headers = {};
|
||||
|
||||
const bodyIsFormData = isFormData(body);
|
||||
if (!bodyIsFormData) {
|
||||
headers['Content-Type'] = 'application/json';
|
||||
}
|
||||
|
||||
if (token) {
|
||||
headers['Authorization'] = `Bearer ${token}`;
|
||||
}
|
||||
@ -501,11 +521,12 @@ async function authFetch(endpoint, body, token = null) {
|
||||
const res = await fetch(`${API_BASE}${endpoint}`, {
|
||||
method: 'POST',
|
||||
headers,
|
||||
body: JSON.stringify(body),
|
||||
body: bodyIsFormData ? body : JSON.stringify(body),
|
||||
});
|
||||
|
||||
const text = await res.text();
|
||||
let data = null;
|
||||
|
||||
try {
|
||||
data = text ? JSON.parse(text) : null;
|
||||
if (data && typeof data === 'object' && 'data' in data) {
|
||||
@ -515,7 +536,7 @@ async function authFetch(endpoint, body, token = null) {
|
||||
data = text;
|
||||
}
|
||||
|
||||
const message = (typeof data === 'object' && data?.message) ? data.message : null;
|
||||
const message = typeof data === 'object' && data?.message ? data.message : null;
|
||||
|
||||
return { status: res.status, data, ok: res.ok || res.status === 206, message };
|
||||
}
|
||||
@ -547,7 +568,7 @@ export async function getSaleProperties() {
|
||||
export async function getSaleProperty(id) {
|
||||
const items = await apiFetch('/SaleProperties/GetSaleProperties');
|
||||
if (!Array.isArray(items)) return items;
|
||||
return items.find(p => p.id == id) || items[0];
|
||||
return items.find((p) => p.id == id) || items[0];
|
||||
}
|
||||
|
||||
// ─── Properties (generic) ───
|
||||
@ -596,15 +617,13 @@ export async function checkAvailability(propertyId, fromDate = null, toDate = nu
|
||||
}
|
||||
|
||||
export async function bookReservation(propertyInfoId, startDate, endDate) {
|
||||
const payload = {
|
||||
propertyInfoId,
|
||||
startDate,
|
||||
endDate,
|
||||
};
|
||||
|
||||
return apiFetch('/Reservations/BookReservation/book', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload),
|
||||
body: {
|
||||
propertyInfoId,
|
||||
startDate,
|
||||
endDate,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@ -627,34 +646,34 @@ export async function getOwnerByUserId(userId) {
|
||||
// ─── Properties ───
|
||||
|
||||
export async function getMyRentListings() {
|
||||
return apiFetch(`/RentProperties/GetMyRentListings`);
|
||||
return apiFetch('/RentProperties/GetMyRentListings');
|
||||
}
|
||||
|
||||
export async function addRentProperty(data) {
|
||||
return apiFetch('/RentProperties/AddRentProperty', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
body: data,
|
||||
});
|
||||
}
|
||||
|
||||
export async function editRentProperty(id, data) {
|
||||
return apiFetch(`/RentProperties/EditRentProperty/${id}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(data),
|
||||
body: data,
|
||||
});
|
||||
}
|
||||
|
||||
export async function editSaleProperty(id, data) {
|
||||
return apiFetch(`/SaleProperties/EditSaleProperty/${id}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(data),
|
||||
body: data,
|
||||
});
|
||||
}
|
||||
|
||||
export async function addSaleProperty(data) {
|
||||
return apiFetch('/SaleProperties/AddSaleProperty', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
body: data,
|
||||
});
|
||||
}
|
||||
|
||||
@ -677,6 +696,7 @@ export async function getCurrencies() {
|
||||
export async function uploadPicture(file) {
|
||||
const formData = new FormData();
|
||||
formData.append('image', file);
|
||||
|
||||
const token = AuthService.getToken();
|
||||
|
||||
const res = await fetch(`${API_BASE}/Files/UploadPicture`, {
|
||||
@ -702,8 +722,13 @@ export async function uploadPicture(file) {
|
||||
// ─── Auth: Registration ───
|
||||
|
||||
async function multipartAuthFetch(endpoint, formData) {
|
||||
const token = AuthService.getToken();
|
||||
|
||||
const res = await fetch(`${API_BASE}${endpoint}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
...(token && { Authorization: `Bearer ${token}` }),
|
||||
},
|
||||
body: formData,
|
||||
});
|
||||
|
||||
@ -729,8 +754,7 @@ export async function addOwner(data, frontImage = null, backImage = null, licens
|
||||
formData.append('LastName', data.lastName || data.LastName || '');
|
||||
formData.append('Email', data.email || data.Email || '');
|
||||
|
||||
const phoneValue =
|
||||
data.phone || data.phoneNumber || data.Phone || data.PhoneNumber || '';
|
||||
const phoneValue = data.phone || data.phoneNumber || data.Phone || data.PhoneNumber || '';
|
||||
const whatsappValue =
|
||||
data.whatsAppNumber || data.whatsapp || data.WhatsAppNumber || data.WhatsApp || '';
|
||||
|
||||
@ -842,7 +866,7 @@ export async function getUserNotifications() {
|
||||
export async function confirmDepositPayment(bookingId) {
|
||||
return apiFetch('/Reservations/ConfirmDepositPayment', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ bookingId }),
|
||||
body: { bookingId },
|
||||
});
|
||||
}
|
||||
|
||||
@ -890,7 +914,7 @@ export async function adminConfirmDeposit(reservationId, adminId, comment = null
|
||||
export async function updateBookingStatus(bookingId, status) {
|
||||
return apiFetch('/Reservations/UpdateStatus', {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify({ bookingId, status }),
|
||||
body: { bookingId, status },
|
||||
});
|
||||
}
|
||||
|
||||
@ -903,7 +927,7 @@ export async function getOwnerReservationRequests() {
|
||||
export async function getOwnerReservationsByStatuses(filterStatuses) {
|
||||
return apiFetch('/Reservations/GetAllReservationsByStateForOwner', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ filterStatuses }),
|
||||
body: { filterStatuses },
|
||||
});
|
||||
}
|
||||
|
||||
@ -922,14 +946,16 @@ export async function ownerConfirmReservation(id) {
|
||||
export async function payDeposit(data) {
|
||||
return apiFetch('/Reservations/PayDeposit/pay-deposit', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
body: data,
|
||||
});
|
||||
}
|
||||
|
||||
// ─── Owner Contact & Stats ───
|
||||
|
||||
export async function getOwnerContactInformation(propertyInformationId) {
|
||||
return apiFetch(`/Owner/GetOwnerContactInformation?propertyInformationId=${propertyInformationId}`);
|
||||
return apiFetch(
|
||||
`/Owner/GetOwnerContactInformation?propertyInformationId=${propertyInformationId}`
|
||||
);
|
||||
}
|
||||
|
||||
export async function getOwnerStatistics() {
|
||||
@ -940,28 +966,42 @@ export async function getOwnerStatistics() {
|
||||
|
||||
export async function registerRealEstateAgent(formData) {
|
||||
const token = AuthService.getToken();
|
||||
|
||||
const res = await fetch(`${API_BASE}/RealEstateAgent/Add`, {
|
||||
method: 'POST',
|
||||
headers: { ...(token && { Authorization: `Bearer ${token}` }) },
|
||||
headers: {
|
||||
...(token && { Authorization: `Bearer ${token}` }),
|
||||
},
|
||||
body: formData,
|
||||
});
|
||||
|
||||
const text = await res.text();
|
||||
let data = null;
|
||||
|
||||
try {
|
||||
data = text ? JSON.parse(text) : null;
|
||||
if (data && typeof data === 'object' && 'data' in data) data = data.data;
|
||||
} catch {
|
||||
data = text;
|
||||
}
|
||||
return { status: res.status, data, ok: res.ok || res.status === 206, message: data?.message };
|
||||
|
||||
return {
|
||||
status: res.status,
|
||||
data,
|
||||
ok: res.ok || res.status === 206,
|
||||
message: data?.message || (typeof data === 'string' ? data : null),
|
||||
};
|
||||
}
|
||||
|
||||
// ─── Change Password ───
|
||||
|
||||
export async function changePassword(oldPassword, newPassword) {
|
||||
return apiFetch(`/User/ChangePassword?oldPassword=${encodeURIComponent(oldPassword)}&newPassword=${encodeURIComponent(newPassword)}`, {
|
||||
method: 'PUT',
|
||||
});
|
||||
return apiFetch(
|
||||
`/User/ChangePassword?oldPassword=${encodeURIComponent(oldPassword)}&newPassword=${encodeURIComponent(newPassword)}`,
|
||||
{
|
||||
method: 'PUT',
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// ─── Forget Password (OTP flow) ───
|
||||
@ -971,9 +1011,12 @@ export async function requestForgetPasswordOtp(email) {
|
||||
}
|
||||
|
||||
export async function verifyForgetPasswordOtp(email, code, newPassword) {
|
||||
return apiFetch(`/User/VerifyForgetPasswordOTP?email=${encodeURIComponent(email)}&code=${encodeURIComponent(code)}&newPassword=${encodeURIComponent(newPassword)}`, {
|
||||
method: 'POST',
|
||||
});
|
||||
return apiFetch(
|
||||
`/User/VerifyForgetPasswordOTP?email=${encodeURIComponent(email)}&code=${encodeURIComponent(code)}&newPassword=${encodeURIComponent(newPassword)}`,
|
||||
{
|
||||
method: 'POST',
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// ─── Reset Password (token flow) ───
|
||||
@ -995,7 +1038,7 @@ export async function deleteMyAccount(password) {
|
||||
export async function setFCMToken(token, deviceType = 2) {
|
||||
return apiFetch('/User/SetFCMToken', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ token, deviceType }),
|
||||
body: { token, deviceType },
|
||||
});
|
||||
}
|
||||
|
||||
@ -1003,7 +1046,9 @@ export async function setFCMToken(token, deviceType = 2) {
|
||||
|
||||
export async function filterRentProperties(params = {}) {
|
||||
const qs = new URLSearchParams();
|
||||
Object.entries(params).forEach(([k, v]) => { if (v != null && v !== '') qs.set(k, v); });
|
||||
Object.entries(params).forEach(([k, v]) => {
|
||||
if (v != null && v !== '') qs.set(k, v);
|
||||
});
|
||||
const query = qs.toString();
|
||||
return apiFetch(`/RentProperties/FilterRentProperties${query ? `?${query}` : ''}`);
|
||||
}
|
||||
@ -1013,35 +1058,35 @@ export async function filterRentProperties(params = {}) {
|
||||
export async function submitReport(subject, body) {
|
||||
return apiFetch('/Reports', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ subject, body }),
|
||||
body: { subject, body },
|
||||
});
|
||||
}
|
||||
|
||||
export async function submitReservationReport(data) {
|
||||
return apiFetch('/ReservationReports', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
body: data,
|
||||
});
|
||||
}
|
||||
|
||||
export async function updateReservationReport(id, data) {
|
||||
return apiFetch(`/ReservationReports/${id}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(data),
|
||||
body: data,
|
||||
});
|
||||
}
|
||||
|
||||
export async function submitSaleReport(data) {
|
||||
return apiFetch('/SaleReports', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
body: data,
|
||||
});
|
||||
}
|
||||
|
||||
export async function updateSaleReport(id, data) {
|
||||
return apiFetch(`/SaleReports/${id}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(data),
|
||||
body: data,
|
||||
});
|
||||
}
|
||||
|
||||
@ -1050,6 +1095,6 @@ export async function updateSaleReport(id, data) {
|
||||
export async function addTerm(name, description) {
|
||||
return apiFetch('/Terms', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ name, description }),
|
||||
body: { name, description },
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user