Add enums, AuthService, and integrate backend registration endpoints
All checks were successful
Build frontend / build (push) Successful in 57s
All checks were successful
Build frontend / build (push) Successful in 57s
- Add separate enum files: BuildingType, PropertyStatus, BookingStatus, CommissionType, IdentityType, UserRole, City, LoginMethod, OwnerType, CustomerType - Add AuthService (addToken/getToken/deleteToken) - Update api.js: use AuthService, add Owner/Add and Customer/Add endpoints - Update login page to use AuthService for token storage - Rewrite owner register: 3-step flow with OwnerType dropdown, backend integration, OTP verification - Rewrite tenant register: 2-step flow with CustomerType dropdown, backend integration, OTP verification - Update homepage and property detail to use enums instead of hardcoded maps - Update AddPropertyForm to import from enums directly - Add console logs and status toasts linked to API response messages
This commit is contained in:
38
app/enums/BookingStatus.js
Normal file
38
app/enums/BookingStatus.js
Normal file
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* BookingStatus Enum
|
||||
* Backend values are strings
|
||||
* Used in: Reservation workflow
|
||||
*/
|
||||
const BookingStatus = Object.freeze({
|
||||
PENDING: 'pending',
|
||||
OWNER_APPROVED: 'owner_approved',
|
||||
ADMIN_APPROVED: 'admin_approved',
|
||||
ACTIVE: 'active',
|
||||
COMPLETED: 'completed',
|
||||
REJECTED: 'rejected',
|
||||
CANCELLED: 'cancelled',
|
||||
});
|
||||
|
||||
// Map status → Arabic label
|
||||
const BookingStatusLabels = Object.freeze({
|
||||
[BookingStatus.PENDING]: 'بانتظار الموافقة',
|
||||
[BookingStatus.OWNER_APPROVED]: 'موافقة المالك',
|
||||
[BookingStatus.ADMIN_APPROVED]: 'موافقة الإدارة',
|
||||
[BookingStatus.ACTIVE]: 'إيجار نشط',
|
||||
[BookingStatus.COMPLETED]: 'منتهي',
|
||||
[BookingStatus.REJECTED]: 'مرفوض',
|
||||
[BookingStatus.CANCELLED]: 'ملغي',
|
||||
});
|
||||
|
||||
// Map status → color class (Tailwind bg)
|
||||
const BookingStatusColors = Object.freeze({
|
||||
[BookingStatus.PENDING]: 'yellow',
|
||||
[BookingStatus.OWNER_APPROVED]: 'blue',
|
||||
[BookingStatus.ADMIN_APPROVED]: 'green',
|
||||
[BookingStatus.ACTIVE]: 'purple',
|
||||
[BookingStatus.COMPLETED]: 'gray',
|
||||
[BookingStatus.REJECTED]: 'red',
|
||||
[BookingStatus.CANCELLED]: 'red',
|
||||
});
|
||||
|
||||
export { BookingStatus, BookingStatusLabels, BookingStatusColors };
|
||||
33
app/enums/BuildingType.js
Normal file
33
app/enums/BuildingType.js
Normal file
@ -0,0 +1,33 @@
|
||||
/**
|
||||
* BuildingType Enum
|
||||
* Backend values are numeric (0, 1, 2)
|
||||
* Used in: PropertyInformation.buildingType
|
||||
*/
|
||||
const BuildingType = Object.freeze({
|
||||
APARTMENT: 0,
|
||||
VILLA: 1,
|
||||
HOUSE: 2,
|
||||
});
|
||||
|
||||
// Map numeric value → Arabic label
|
||||
const BuildingTypeLabels = Object.freeze({
|
||||
[BuildingType.APARTMENT]: 'شقة',
|
||||
[BuildingType.VILLA]: 'فيلا',
|
||||
[BuildingType.HOUSE]: 'بيت',
|
||||
});
|
||||
|
||||
// Map numeric value → English key (for UI filters)
|
||||
const BuildingTypeKeys = Object.freeze({
|
||||
[BuildingType.APARTMENT]: 'apartment',
|
||||
[BuildingType.VILLA]: 'villa',
|
||||
[BuildingType.HOUSE]: 'house',
|
||||
});
|
||||
|
||||
// Reverse map: English key → numeric value
|
||||
const BuildingTypeByKey = Object.freeze({
|
||||
apartment: BuildingType.APARTMENT,
|
||||
villa: BuildingType.VILLA,
|
||||
house: BuildingType.HOUSE,
|
||||
});
|
||||
|
||||
export { BuildingType, BuildingTypeLabels, BuildingTypeKeys, BuildingTypeByKey };
|
||||
38
app/enums/City.js
Normal file
38
app/enums/City.js
Normal file
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* City Enum
|
||||
* Syrian cities used in property locations
|
||||
* Used in: Property search filters, location display
|
||||
*/
|
||||
const City = Object.freeze({
|
||||
DAMASCUS: 'دمشق',
|
||||
ALEPPO: 'حلب',
|
||||
HOMS: 'حمص',
|
||||
LATAKIA: 'اللاذقية',
|
||||
DARAA: 'درعا',
|
||||
TARTOUS: 'طرطوس',
|
||||
SUWEIDA: 'السويداء',
|
||||
DEIR_EZZOR: 'دير الزور',
|
||||
RAQQA: 'الرقة',
|
||||
IDLIB: 'إدلب',
|
||||
HASAKAH: 'الحسكة',
|
||||
QAMISHLI: 'القامشلي',
|
||||
RURAL_DAMASCUS: 'ريف دمشق',
|
||||
});
|
||||
|
||||
// All cities as a flat array
|
||||
const CitiesList = Object.freeze(Object.values(City));
|
||||
|
||||
/**
|
||||
* Extract city name from a full address string
|
||||
* @param {string} address
|
||||
* @returns {string}
|
||||
*/
|
||||
function extractCity(address) {
|
||||
if (!address) return '';
|
||||
for (const city of CitiesList) {
|
||||
if (address.includes(city)) return city;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
export { City, CitiesList, extractCity };
|
||||
19
app/enums/CommissionType.js
Normal file
19
app/enums/CommissionType.js
Normal file
@ -0,0 +1,19 @@
|
||||
/**
|
||||
* CommissionType Enum
|
||||
* Defines who pays the platform commission
|
||||
* Used in: Property pricing, booking financials
|
||||
*/
|
||||
const CommissionType = Object.freeze({
|
||||
FROM_OWNER: 'from_owner',
|
||||
FROM_TENANT: 'from_tenant',
|
||||
FROM_BOTH: 'from_both',
|
||||
});
|
||||
|
||||
// Map type → Arabic label
|
||||
const CommissionTypeLabels = Object.freeze({
|
||||
[CommissionType.FROM_OWNER]: 'من المالك',
|
||||
[CommissionType.FROM_TENANT]: 'من المستأجر',
|
||||
[CommissionType.FROM_BOTH]: 'من الاثنين',
|
||||
});
|
||||
|
||||
export { CommissionType, CommissionTypeLabels };
|
||||
17
app/enums/CustomerType.js
Normal file
17
app/enums/CustomerType.js
Normal file
@ -0,0 +1,17 @@
|
||||
/**
|
||||
* CustomerType Enum
|
||||
* Backend values for customer sub-types
|
||||
* Used in: Customer registration (Customer/Add)
|
||||
*/
|
||||
const CustomerType = Object.freeze({
|
||||
PERSONAL: 'Personal',
|
||||
FAMILY: 'Family',
|
||||
});
|
||||
|
||||
// Map value → Arabic label
|
||||
const CustomerTypeLabels = Object.freeze({
|
||||
[CustomerType.PERSONAL]: 'شخصي',
|
||||
[CustomerType.FAMILY]: 'عائلي',
|
||||
});
|
||||
|
||||
export { CustomerType, CustomerTypeLabels };
|
||||
23
app/enums/IdentityType.js
Normal file
23
app/enums/IdentityType.js
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* IdentityType Enum
|
||||
* Tenant identity document type
|
||||
* Used in: Property booking, allowedIdentities filter
|
||||
*/
|
||||
const IdentityType = Object.freeze({
|
||||
SYRIAN: 'syrian',
|
||||
PASSPORT: 'passport',
|
||||
});
|
||||
|
||||
// Map type → Arabic label
|
||||
const IdentityTypeLabels = Object.freeze({
|
||||
[IdentityType.SYRIAN]: 'هوية سورية',
|
||||
[IdentityType.PASSPORT]: 'جواز سفر',
|
||||
});
|
||||
|
||||
// Map type → flag emoji
|
||||
const IdentityTypeFlags = Object.freeze({
|
||||
[IdentityType.SYRIAN]: '🇸🇾',
|
||||
[IdentityType.PASSPORT]: '🛂',
|
||||
});
|
||||
|
||||
export { IdentityType, IdentityTypeLabels, IdentityTypeFlags };
|
||||
11
app/enums/LoginMethod.js
Normal file
11
app/enums/LoginMethod.js
Normal file
@ -0,0 +1,11 @@
|
||||
/**
|
||||
* LoginMethod Enum
|
||||
* Authentication method type
|
||||
* Used in: Login page, OTP verification
|
||||
*/
|
||||
const LoginMethod = Object.freeze({
|
||||
EMAIL: 'email',
|
||||
PHONE: 'phone',
|
||||
});
|
||||
|
||||
export { LoginMethod };
|
||||
17
app/enums/OwnerType.js
Normal file
17
app/enums/OwnerType.js
Normal file
@ -0,0 +1,17 @@
|
||||
/**
|
||||
* OwnerType Enum
|
||||
* Backend values for owner sub-types
|
||||
* Used in: Owner registration (Owner/Add)
|
||||
*/
|
||||
const OwnerType = Object.freeze({
|
||||
PERSON: 'peerson',
|
||||
REAL_ESTATE_AGENCY: 'RealEstateAgency',
|
||||
});
|
||||
|
||||
// Map value → Arabic label
|
||||
const OwnerTypeLabels = Object.freeze({
|
||||
[OwnerType.PERSON]: 'شخص',
|
||||
[OwnerType.REAL_ESTATE_AGENCY]: 'وكالة عقارية',
|
||||
});
|
||||
|
||||
export { OwnerType, OwnerTypeLabels };
|
||||
33
app/enums/PropertyStatus.js
Normal file
33
app/enums/PropertyStatus.js
Normal file
@ -0,0 +1,33 @@
|
||||
/**
|
||||
* PropertyStatus Enum
|
||||
* Backend values are numeric (0, 1, 2)
|
||||
* Used in: PropertyInformation.status
|
||||
*/
|
||||
const PropertyStatus = Object.freeze({
|
||||
AVAILABLE: 0,
|
||||
BOOKED: 1,
|
||||
MAINTENANCE: 2,
|
||||
});
|
||||
|
||||
// Map numeric value → Arabic label
|
||||
const PropertyStatusLabels = Object.freeze({
|
||||
[PropertyStatus.AVAILABLE]: 'متاح',
|
||||
[PropertyStatus.BOOKED]: 'محجوز',
|
||||
[PropertyStatus.MAINTENANCE]: 'صيانة',
|
||||
});
|
||||
|
||||
// Map numeric value → English key (for UI filters)
|
||||
const PropertyStatusKeys = Object.freeze({
|
||||
[PropertyStatus.AVAILABLE]: 'available',
|
||||
[PropertyStatus.BOOKED]: 'booked',
|
||||
[PropertyStatus.MAINTENANCE]: 'maintenance',
|
||||
});
|
||||
|
||||
// Reverse map: English key → numeric value
|
||||
const PropertyStatusByKey = Object.freeze({
|
||||
available: PropertyStatus.AVAILABLE,
|
||||
booked: PropertyStatus.BOOKED,
|
||||
maintenance: PropertyStatus.MAINTENANCE,
|
||||
});
|
||||
|
||||
export { PropertyStatus, PropertyStatusLabels, PropertyStatusKeys, PropertyStatusByKey };
|
||||
26
app/enums/UserRole.js
Normal file
26
app/enums/UserRole.js
Normal file
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* UserRole Enum
|
||||
* User account roles in the system
|
||||
* Used in: JWT payload, registration, routing
|
||||
*/
|
||||
const UserRole = Object.freeze({
|
||||
OWNER: 'owner',
|
||||
TENANT: 'tenant',
|
||||
ADMIN: 'admin',
|
||||
});
|
||||
|
||||
// Map role → Arabic label
|
||||
const UserRoleLabels = Object.freeze({
|
||||
[UserRole.OWNER]: 'مالك عقار',
|
||||
[UserRole.TENANT]: 'مستأجر',
|
||||
[UserRole.ADMIN]: 'مدير النظام',
|
||||
});
|
||||
|
||||
// Map role → color theme (used in UI)
|
||||
const UserRoleColors = Object.freeze({
|
||||
[UserRole.OWNER]: 'amber',
|
||||
[UserRole.TENANT]: 'blue',
|
||||
[UserRole.ADMIN]: 'red',
|
||||
});
|
||||
|
||||
export { UserRole, UserRoleLabels, UserRoleColors };
|
||||
15
app/enums/index.js
Normal file
15
app/enums/index.js
Normal file
@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Enums Index
|
||||
* Central export for all enum modules
|
||||
*/
|
||||
|
||||
export { BuildingType, BuildingTypeLabels, BuildingTypeKeys, BuildingTypeByKey } from './BuildingType';
|
||||
export { PropertyStatus, PropertyStatusLabels, PropertyStatusKeys, PropertyStatusByKey } from './PropertyStatus';
|
||||
export { BookingStatus, BookingStatusLabels, BookingStatusColors } from './BookingStatus';
|
||||
export { CommissionType, CommissionTypeLabels } from './CommissionType';
|
||||
export { IdentityType, IdentityTypeLabels, IdentityTypeFlags } from './IdentityType';
|
||||
export { UserRole, UserRoleLabels, UserRoleColors } from './UserRole';
|
||||
export { City, CitiesList, extractCity } from './City';
|
||||
export { LoginMethod } from './LoginMethod';
|
||||
export { OwnerType, OwnerTypeLabels } from './OwnerType';
|
||||
export { CustomerType, CustomerTypeLabels } from './CustomerType';
|
||||
Reference in New Issue
Block a user