This commit is contained in:
Iliyan Angelov
2025-11-19 12:27:01 +02:00
parent 2043ac897c
commit 34b4c969d4
469 changed files with 26870 additions and 8329 deletions

View File

@@ -5,6 +5,7 @@ export interface LoginCredentials {
email: string;
password: string;
rememberMe?: boolean;
mfaToken?: string;
}
export interface RegisterData {
@@ -19,6 +20,8 @@ export interface AuthResponse {
status?: string;
success?: boolean;
message?: string;
requires_mfa?: boolean;
user_id?: number;
data?: {
token?: string;
refreshToken?: string;
@@ -32,6 +35,11 @@ export interface AuthResponse {
role: string;
createdAt?: string;
};
secret?: string;
qr_code?: string;
backup_codes?: string[];
mfa_enabled?: boolean;
backup_codes_count?: number;
};
}
@@ -153,6 +161,68 @@ const authService = {
);
return response.data;
},
/**
* MFA - Initialize MFA setup
*/
initMFA: async (): Promise<AuthResponse> => {
const response = await apiClient.get<AuthResponse>('/api/auth/mfa/init');
return response.data;
},
/**
* MFA - Enable MFA
*/
enableMFA: async (secret: string, verificationToken: string): Promise<AuthResponse> => {
const response = await apiClient.post<AuthResponse>('/api/auth/mfa/enable', {
secret,
verification_token: verificationToken
});
return response.data;
},
/**
* MFA - Disable MFA
*/
disableMFA: async (): Promise<AuthResponse> => {
const response = await apiClient.post<AuthResponse>('/api/auth/mfa/disable');
return response.data;
},
/**
* MFA - Get MFA status
*/
getMFAStatus: async (): Promise<{ mfa_enabled: boolean; backup_codes_count: number }> => {
const response = await apiClient.get<{ mfa_enabled: boolean; backup_codes_count: number }>('/api/auth/mfa/status');
return response.data;
},
/**
* MFA - Regenerate backup codes
*/
regenerateBackupCodes: async (): Promise<AuthResponse> => {
const response = await apiClient.post<AuthResponse>('/api/auth/mfa/regenerate-backup-codes');
return response.data;
},
/**
* Upload avatar
*/
uploadAvatar: async (file: File): Promise<AuthResponse> => {
const formData = new FormData();
formData.append('image', file);
const response = await apiClient.post<AuthResponse>(
'/api/auth/avatar/upload',
formData,
{
headers: {
'Content-Type': 'multipart/form-data',
},
}
);
return response.data;
},
};
export default authService;

View File

@@ -7,7 +7,7 @@ export interface BookingData {
check_out_date: string; // YYYY-MM-DD
guest_count: number;
notes?: string;
payment_method: 'cash' | 'stripe';
payment_method: 'cash' | 'stripe' | 'paypal';
total_price: number;
guest_info: {
full_name: string;
@@ -35,7 +35,7 @@ export interface Booking {
| 'cancelled'
| 'checked_in'
| 'checked_out';
payment_method: 'cash' | 'stripe';
payment_method: 'cash' | 'stripe' | 'paypal';
payment_status:
| 'unpaid'
| 'paid'
@@ -233,16 +233,27 @@ export const checkRoomAvailability = async (
},
}
);
// Handle new response format when roomId is provided
if (response.data?.data?.available !== undefined) {
return {
available: response.data.data.available,
message: response.data.data.message,
};
}
// Fallback for old format
return {
available: true,
message: response.data.message,
message: response.data?.message || 'Room is available',
};
} catch (error: any) {
if (error.response?.status === 409) {
if (error.response?.status === 409 || error.response?.status === 404) {
return {
available: false,
message:
error.response.data.message ||
error.response.data?.message ||
error.response.data?.detail ||
'Room already booked during this time',
};
}

View File

@@ -4,7 +4,7 @@ import apiClient from './apiClient';
export interface PaymentData {
booking_id: number;
amount: number;
payment_method: 'cash' | 'bank_transfer' | 'stripe';
payment_method: 'cash' | 'bank_transfer' | 'stripe' | 'paypal';
transaction_id?: string;
notes?: string;
}
@@ -13,7 +13,7 @@ export interface Payment {
id: number;
booking_id: number;
amount: number;
payment_method: 'cash' | 'bank_transfer' | 'credit_card' | 'debit_card' | 'e_wallet' | 'stripe';
payment_method: 'cash' | 'bank_transfer' | 'credit_card' | 'debit_card' | 'e_wallet' | 'stripe' | 'paypal';
payment_type: 'full' | 'deposit' | 'remaining';
deposit_percentage?: number;
payment_status: 'pending' | 'completed' | 'failed' | 'refunded';
@@ -22,6 +22,14 @@ export interface Payment {
notes?: string;
createdAt: string;
updatedAt: string;
booking?: {
id: number;
booking_number: string;
user?: {
name: string;
email?: string;
};
};
}
export interface BankInfo {
@@ -284,6 +292,79 @@ export const confirmStripePayment = async (
};
};
/**
* Create PayPal order
* POST /api/payments/paypal/create-order
*/
export const createPayPalOrder = async (
bookingId: number,
amount: number,
currency: string = 'USD',
returnUrl?: string,
cancelUrl?: string
): Promise<{
success: boolean;
data: {
order_id: string;
approval_url: string;
status: string;
};
message?: string;
}> => {
const response = await apiClient.post(
'/payments/paypal/create-order',
{
booking_id: bookingId,
amount,
currency,
return_url: returnUrl,
cancel_url: cancelUrl,
}
);
// Map backend response format (status: "success") to frontend format (success: true)
const data = response.data;
return {
success: data.status === "success" || data.success === true,
data: data.data || {},
message: data.message,
};
};
/**
* Capture PayPal payment
* POST /api/payments/paypal/capture
*/
export const capturePayPalPayment = async (
orderId: string,
bookingId: number
): Promise<{
success: boolean;
data: {
payment: Payment;
booking: {
id: number;
booking_number: string;
status: string;
};
};
message?: string;
}> => {
const response = await apiClient.post(
'/payments/paypal/capture',
{
order_id: orderId,
booking_id: bookingId,
}
);
// Map backend response format (status: "success") to frontend format (success: true)
const data = response.data;
return {
success: data.status === "success" || data.success === true,
data: data.data || {},
message: data.message,
};
};
export default {
createPayment,
getPayments,
@@ -295,4 +376,6 @@ export default {
getPaymentsByBookingId,
createStripePaymentIntent,
confirmStripePayment,
createPayPalOrder,
capturePayPalPayment,
};

View File

@@ -36,6 +36,24 @@ export interface UpdateStripeSettingsRequest {
stripe_webhook_secret?: string;
}
export interface PayPalSettingsResponse {
status: string;
data: {
paypal_client_id: string;
paypal_client_secret: string;
paypal_mode: string;
paypal_client_secret_masked: string;
has_client_id: boolean;
has_client_secret: boolean;
};
}
export interface UpdatePayPalSettingsRequest {
paypal_client_id?: string;
paypal_client_secret?: string;
paypal_mode?: string;
}
export interface SmtpSettingsResponse {
status: string;
data: {
@@ -168,6 +186,29 @@ const systemSettingsService = {
return response.data;
},
/**
* Get PayPal settings (Admin only)
*/
getPayPalSettings: async (): Promise<PayPalSettingsResponse> => {
const response = await apiClient.get<PayPalSettingsResponse>(
'/api/admin/system-settings/paypal'
);
return response.data;
},
/**
* Update PayPal settings (Admin only)
*/
updatePayPalSettings: async (
settings: UpdatePayPalSettingsRequest
): Promise<PayPalSettingsResponse> => {
const response = await apiClient.put<PayPalSettingsResponse>(
'/api/admin/system-settings/paypal',
settings
);
return response.data;
},
/**
* Get SMTP settings (Admin only)
*/
@@ -277,6 +318,8 @@ export type {
UpdateCurrencyRequest,
StripeSettingsResponse,
UpdateStripeSettingsRequest,
PayPalSettingsResponse,
UpdatePayPalSettingsRequest,
SmtpSettingsResponse,
UpdateSmtpSettingsRequest,
TestSmtpEmailRequest,