This commit is contained in:
Iliyan Angelov
2025-11-30 22:43:09 +02:00
parent 24b40450dd
commit 39fcfff811
1610 changed files with 5442 additions and 1383 deletions

View File

@@ -8,27 +8,27 @@ import {
} from 'react-router-dom';
import { ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import { LoadingProvider, useNavigationLoading, useLoading } from './contexts/LoadingContext';
import { CookieConsentProvider } from './contexts/CookieConsentContext';
import { CurrencyProvider } from './contexts/CurrencyContext';
import { CompanySettingsProvider } from './contexts/CompanySettingsContext';
import { AuthModalProvider } from './contexts/AuthModalContext';
import { AntibotProvider } from './contexts/AntibotContext';
import OfflineIndicator from './components/common/OfflineIndicator';
import CookieConsentBanner from './components/common/CookieConsentBanner';
import CookiePreferencesModal from './components/common/CookiePreferencesModal';
import AnalyticsLoader from './components/common/AnalyticsLoader';
import Loading from './components/common/Loading';
import Preloader from './components/common/Preloader';
import ScrollToTop from './components/common/ScrollToTop';
import AuthModalManager from './components/modals/AuthModalManager';
import ResetPasswordRouteHandler from './components/auth/ResetPasswordRouteHandler';
import ErrorBoundaryRoute from './components/common/ErrorBoundaryRoute';
import { LoadingProvider, useNavigationLoading, useLoading } from './shared/contexts/LoadingContext';
import { CookieConsentProvider } from './shared/contexts/CookieConsentContext';
import { CurrencyProvider } from './features/payments/contexts/CurrencyContext';
import { CompanySettingsProvider } from './shared/contexts/CompanySettingsContext';
import { AuthModalProvider } from './features/auth/contexts/AuthModalContext';
import { AntibotProvider } from './features/auth/contexts/AntibotContext';
import OfflineIndicator from './shared/components/OfflineIndicator';
import CookieConsentBanner from './shared/components/CookieConsentBanner';
import CookiePreferencesModal from './shared/components/CookiePreferencesModal';
import AnalyticsLoader from './shared/components/AnalyticsLoader';
import Loading from './shared/components/Loading';
import Preloader from './shared/components/Preloader';
import ScrollToTop from './shared/components/ScrollToTop';
import AuthModalManager from './features/auth/components/AuthModalManager';
import ResetPasswordRouteHandler from './features/auth/components/ResetPasswordRouteHandler';
import ErrorBoundaryRoute from './shared/components/ErrorBoundaryRoute';
import useAuthStore from './store/useAuthStore';
import useFavoritesStore from './store/useFavoritesStore';
import { LayoutMain } from './components/layout';
import LayoutMain from './shared/components/LayoutMain';
import AdminLayout from './pages/AdminLayout';
import {
@@ -37,9 +37,9 @@ import {
StaffRoute,
AccountantRoute,
CustomerRoute
} from './components/auth';
} from './features/auth/components';
const HomePage = lazy(() => import('./pages/HomePage'));
const HomePage = lazy(() => import('./features/content/pages/HomePage'));
const DashboardPage = lazy(() => import('./pages/customer/DashboardPage'));
const RoomListPage = lazy(() => import('./pages/customer/RoomListPage'));
const RoomDetailPage = lazy(() => import('./pages/customer/RoomDetailPage'));
@@ -59,16 +59,16 @@ const InvoiceEditPage = lazy(() => import('./pages/admin/InvoiceEditPage'));
const ProfilePage = lazy(() => import('./pages/customer/ProfilePage'));
const LoyaltyPage = lazy(() => import('./pages/customer/LoyaltyPage'));
const GroupBookingPage = lazy(() => import('./pages/customer/GroupBookingPage'));
const AboutPage = lazy(() => import('./pages/AboutPage'));
const ContactPage = lazy(() => import('./pages/ContactPage'));
const PrivacyPolicyPage = lazy(() => import('./pages/PrivacyPolicyPage'));
const TermsPage = lazy(() => import('./pages/TermsPage'));
const RefundsPolicyPage = lazy(() => import('./pages/RefundsPolicyPage'));
const CancellationPolicyPage = lazy(() => import('./pages/CancellationPolicyPage'));
const AccessibilityPage = lazy(() => import('./pages/AccessibilityPage'));
const FAQPage = lazy(() => import('./pages/FAQPage'));
const BlogPage = lazy(() => import('./pages/BlogPage'));
const BlogDetailPage = lazy(() => import('./pages/BlogDetailPage'));
const AboutPage = lazy(() => import('./features/content/pages/AboutPage'));
const ContactPage = lazy(() => import('./features/content/pages/ContactPage'));
const PrivacyPolicyPage = lazy(() => import('./features/content/pages/PrivacyPolicyPage'));
const TermsPage = lazy(() => import('./features/content/pages/TermsPage'));
const RefundsPolicyPage = lazy(() => import('./features/content/pages/RefundsPolicyPage'));
const CancellationPolicyPage = lazy(() => import('./features/content/pages/CancellationPolicyPage'));
const AccessibilityPage = lazy(() => import('./features/content/pages/AccessibilityPage'));
const FAQPage = lazy(() => import('./features/content/pages/FAQPage'));
const BlogPage = lazy(() => import('./features/content/pages/BlogPage'));
const BlogDetailPage = lazy(() => import('./features/content/pages/BlogDetailPage'));
const AdminDashboardPage = lazy(() => import('./pages/admin/DashboardPage'));
const InvoiceManagementPage = lazy(() => import('./pages/admin/InvoiceManagementPage'));
@@ -111,7 +111,7 @@ const AccountantInvoiceManagementPage = lazy(() => import('./pages/accountant/In
const AccountantAnalyticsDashboardPage = lazy(() => import('./pages/accountant/AnalyticsDashboardPage'));
const AccountantLayout = lazy(() => import('./pages/AccountantLayout'));
const NotFoundPage = lazy(() => import('./pages/NotFoundPage'));
const NotFoundPage = lazy(() => import('./shared/pages/NotFoundPage'));
// Component to track navigation changes - must be inside Router
const NavigationTracker: React.FC = () => {

View File

@@ -1,14 +0,0 @@
export { default as EmptyState } from './EmptyState';
export { default as ErrorBoundary } from './ErrorBoundary';
export { default as Loading } from './Loading';
export { default as OptimizedImage } from './OptimizedImage';
export { default as Pagination } from './Pagination';
export { default as PaymentMethodSelector } from './PaymentMethodSelector';
export { default as PaymentStatusBadge } from './PaymentStatusBadge';
export { default as ConfirmationDialog } from './ConfirmationDialog';
export { default as GlobalLoading } from './GlobalLoading';
export { default as OfflineIndicator } from './OfflineIndicator';
export { default as Skeleton } from './Skeleton';
export { default as ScrollToTop } from './ScrollToTop';
export { default as ExportButton } from './ExportButton';

View File

@@ -0,0 +1,249 @@
/**
* AI Assistant Widget Component
* Provides an AI-powered chat interface for hotel management queries
*/
import React, { useState, useRef, useEffect } from 'react';
import { Send, Bot, X, Minimize2, Maximize2, Loader2 } from 'lucide-react';
import { chatWithAI, AIChatResponse } from '../services/aiAssistantService';
import { toast } from 'react-toastify';
interface Message {
id: string;
role: 'user' | 'assistant';
content: string;
timestamp: Date;
intent?: string;
}
interface AIAssistantWidgetProps {
className?: string;
}
const AIAssistantWidget: React.FC<AIAssistantWidgetProps> = ({ className = '' }) => {
const [isOpen, setIsOpen] = useState(false);
const [isMinimized, setIsMinimized] = useState(false);
const [messages, setMessages] = useState<Message[]>([
{
id: '1',
role: 'assistant',
content: 'Hello! I\'m your AI assistant. I can help you with questions about rooms, bookings, invoices, payments, and chat messages. How can I assist you today?',
timestamp: new Date(),
},
]);
const [inputValue, setInputValue] = useState('');
const [isLoading, setIsLoading] = useState(false);
const messagesEndRef = useRef<HTMLDivElement>(null);
const inputRef = useRef<HTMLInputElement>(null);
const scrollToBottom = () => {
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
};
useEffect(() => {
scrollToBottom();
}, [messages]);
useEffect(() => {
if (isOpen && inputRef.current) {
inputRef.current.focus();
}
}, [isOpen]);
const handleSend = async () => {
if (!inputValue.trim() || isLoading) return;
const userMessage: Message = {
id: Date.now().toString(),
role: 'user',
content: inputValue.trim(),
timestamp: new Date(),
};
setMessages((prev) => [...prev, userMessage]);
setInputValue('');
setIsLoading(true);
try {
const response: AIChatResponse = await chatWithAI(userMessage.content);
const assistantMessage: Message = {
id: (Date.now() + 1).toString(),
role: 'assistant',
content: response.response,
timestamp: new Date(),
intent: response.intent,
};
setMessages((prev) => [...prev, assistantMessage]);
} catch (error: any) {
console.error('AI Assistant Error:', error);
// Extract error message
let errorMessage = 'I apologize, but I encountered an error. Please try again.';
if (error.response) {
// Server responded with error
const detail = error.response.data?.detail || error.response.data?.message;
if (detail) {
errorMessage = `Error: ${detail}`;
toast.error(detail);
} else {
toast.error(`Error ${error.response.status}: ${error.response.statusText}`);
}
} else if (error.request) {
// Request made but no response
errorMessage = 'Unable to connect to the server. Please check your connection.';
toast.error('Connection error. Please check your network.');
} else {
// Something else happened
errorMessage = `Error: ${error.message || 'Unknown error'}`;
toast.error(error.message || 'An unexpected error occurred');
}
const errorMsg: Message = {
id: (Date.now() + 1).toString(),
role: 'assistant',
content: errorMessage,
timestamp: new Date(),
};
setMessages((prev) => [...prev, errorMsg]);
} finally {
setIsLoading(false);
}
};
const handleKeyPress = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
handleSend();
}
};
const clearChat = () => {
setMessages([
{
id: '1',
role: 'assistant',
content: 'Hello! I\'m your AI assistant. How can I help you today?',
timestamp: new Date(),
},
]);
};
if (!isOpen) {
return (
<button
onClick={() => setIsOpen(true)}
className={`fixed bottom-6 right-6 w-14 h-14 bg-gradient-to-r from-amber-500 to-amber-600 text-white rounded-full shadow-2xl hover:from-amber-600 hover:to-amber-700 transition-all duration-300 flex items-center justify-center z-50 ${className}`}
aria-label="Open AI Assistant"
>
<Bot className="w-6 h-6" />
</button>
);
}
return (
<div
className={`fixed bottom-6 right-6 w-96 ${isMinimized ? 'h-16' : 'h-[600px]'} bg-white rounded-2xl shadow-2xl border border-slate-200 flex flex-col z-50 transition-all duration-300 ${className}`}
>
{/* Header */}
<div className="bg-gradient-to-r from-slate-900 via-slate-800 to-slate-900 px-4 py-3 rounded-t-2xl flex items-center justify-between">
<div className="flex items-center gap-2">
<Bot className="w-5 h-5 text-amber-400" />
<h3 className="text-white font-semibold">AI Assistant</h3>
</div>
<div className="flex items-center gap-2">
<button
onClick={clearChat}
className="text-amber-200 hover:text-white text-xs px-2 py-1 rounded hover:bg-slate-700/50 transition-colors"
>
Clear
</button>
<button
onClick={() => setIsMinimized(!isMinimized)}
className="text-amber-200 hover:text-white p-1.5 rounded hover:bg-slate-700/50 transition-colors"
aria-label={isMinimized ? 'Maximize' : 'Minimize'}
>
{isMinimized ? <Maximize2 className="w-4 h-4" /> : <Minimize2 className="w-4 h-4" />}
</button>
<button
onClick={() => setIsOpen(false)}
className="text-amber-200 hover:text-white p-1.5 rounded hover:bg-slate-700/50 transition-colors"
aria-label="Close"
>
<X className="w-4 h-4" />
</button>
</div>
</div>
{!isMinimized && (
<>
{/* Messages */}
<div className="flex-1 overflow-y-auto p-4 space-y-4 bg-gradient-to-b from-slate-50 to-white">
{messages.map((message) => (
<div
key={message.id}
className={`flex ${message.role === 'user' ? 'justify-end' : 'justify-start'}`}
>
<div
className={`max-w-[80%] rounded-2xl px-4 py-2 ${
message.role === 'user'
? 'bg-gradient-to-r from-amber-500 to-amber-600 text-white'
: 'bg-white border border-slate-200 text-slate-700 shadow-sm'
}`}
>
<p className="text-sm whitespace-pre-wrap">{message.content}</p>
{message.intent && message.role === 'assistant' && (
<p className="text-xs opacity-70 mt-1">Intent: {message.intent}</p>
)}
</div>
</div>
))}
{isLoading && (
<div className="flex justify-start">
<div className="bg-white border border-slate-200 rounded-2xl px-4 py-2 shadow-sm">
<Loader2 className="w-4 h-4 animate-spin text-amber-500" />
</div>
</div>
)}
<div ref={messagesEndRef} />
</div>
{/* Input */}
<div className="border-t border-slate-200 p-4 bg-white rounded-b-2xl">
<div className="flex gap-2">
<input
ref={inputRef}
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
onKeyPress={handleKeyPress}
placeholder="Ask about rooms, bookings, invoices..."
className="flex-1 px-4 py-2 border-2 border-slate-200 rounded-xl focus:border-amber-400 focus:ring-4 focus:ring-amber-100 transition-all duration-200 text-slate-700"
disabled={isLoading}
/>
<button
onClick={handleSend}
disabled={!inputValue.trim() || isLoading}
className="px-4 py-2 bg-gradient-to-r from-amber-500 to-amber-600 text-white rounded-xl hover:from-amber-600 hover:to-amber-700 disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-200 shadow-lg hover:shadow-xl flex items-center justify-center"
>
{isLoading ? (
<Loader2 className="w-5 h-5 animate-spin" />
) : (
<Send className="w-5 h-5" />
)}
</button>
</div>
<p className="text-xs text-slate-500 mt-2">
Try: "Which rooms are occupied?" or "Show me booking BK12345"
</p>
</div>
</>
)}
</div>
);
};
export default AIAssistantWidget;

View File

@@ -0,0 +1,169 @@
/**
* AI Assistant Service
* Handles communication with the AI assistant backend
*/
import apiClient from '../../../shared/services/apiClient';
export interface AIChatRequest {
message: string;
context?: Record<string, any>;
}
export interface AIChatResponse {
response: string;
intent: string;
data_used: Record<string, any>;
timestamp: string;
user_role?: string; // Added: user role information
}
export interface SystemStatus {
user_role?: string; // Added: user role information
timestamp: string;
room_status: {
total_rooms: number;
available: number;
occupied: number;
maintenance?: number;
cleaning?: number;
occupancy_rate: number;
rooms_with_active_bookings?: number;
};
booking_summary?: {
upcoming_checkins: number;
upcoming_checkouts: number;
active_bookings: number;
pending_bookings: number;
};
user_bookings?: Array<{
booking_number: string;
status: string;
check_in: string;
check_out: string;
total_price: number;
room_number?: string;
room_type?: string;
}>;
payment_summary?: {
total_revenue: number;
pending_amount: number;
completed_payments: number;
};
invoice_summary?: {
total_invoices: number;
overdue_invoices: number;
status_breakdown?: Record<string, number>;
};
user_invoices?: Array<{
invoice_number: string;
status: string;
total_amount: number;
balance_due: number;
due_date: string;
booking_number?: string;
}>;
user_payments?: Array<{
id: number;
amount: number;
payment_method: string;
payment_status: string;
payment_date: string;
booking_number?: string;
}>;
unanswered_chats?: Array<{
chat_id: number;
visitor_name: string;
last_message: string;
waiting_hours: number;
}>;
room_problems?: Array<{
room_number: string;
issue_type: string;
description: string;
}>;
application_knowledge?: {
features: string[];
role_info: Record<string, any>;
};
}
export interface OccupiedRoom {
room_number: string;
room_type: string;
floor: number;
booking_id: number;
guest_name: string;
check_in: string;
check_out: string;
}
/**
* Send a message to the AI assistant
*/
export const chatWithAI = async (
message: string,
context?: Record<string, any>
): Promise<AIChatResponse> => {
const response = await apiClient.post<{ status: string; data: AIChatResponse }>(
'/ai-assistant/chat',
{ message, context }
);
return response.data.data;
};
/**
* Get comprehensive system status
*/
export const getAIStatus = async (): Promise<SystemStatus> => {
const response = await apiClient.get<{ status: string; data: SystemStatus }>(
'/ai-assistant/status'
);
return response.data.data;
};
/**
* Get list of occupied rooms
*/
export const getOccupiedRooms = async (
roomNumber?: string
): Promise<OccupiedRoom[]> => {
const response = await apiClient.get<{ status: string; data: { rooms: OccupiedRoom[] } }>(
'/ai-assistant/rooms/occupied',
{ params: roomNumber ? { room_number: roomNumber } : {} }
);
return response.data.data.rooms;
};
/**
* Get rooms with problems
*/
export const getRoomProblems = async (): Promise<Array<{
room_number: string;
issue_type: string;
description: string;
}>> => {
const response = await apiClient.get<{ status: string; data: { problems: any[] } }>(
'/ai-assistant/rooms/problems'
);
return response.data.data.problems;
};
/**
* Get unanswered chat messages
*/
export const getUnansweredChats = async (
hours: number = 24
): Promise<Array<{
chat_id: number;
visitor_name: string;
last_message: string;
waiting_hours: number;
}>> => {
const response = await apiClient.get<{ status: string; data: { chats: any[] } }>(
'/ai-assistant/chats/unanswered',
{ params: { hours } }
);
return response.data.data.chats;
};

View File

@@ -6,8 +6,8 @@ import {
Square,
} from 'lucide-react';
import { toast } from 'react-toastify';
import { exportData } from '../../utils/exportUtils';
import analyticsService from '../../services/api/analyticsService';
import { exportData } from '../../../shared/utils/exportUtils';
import analyticsService from '../services/analyticsService';
interface ReportMetric {
id: string;

View File

@@ -1,4 +1,4 @@
import apiClient from './apiClient';
import apiClient from '../../../shared/services/apiClient';
// ==================== REVENUE ANALYTICS ====================

View File

@@ -1,4 +1,4 @@
import apiClient from './apiClient';
import apiClient from '../../../shared/services/apiClient';
export interface AuditLog {
id: number;

View File

@@ -1,4 +1,4 @@
import apiClient from './apiClient';
import apiClient from '../../../shared/services/apiClient';
export interface CustomerDashboardStats {
total_bookings: number;

View File

@@ -1,4 +1,4 @@
import apiClient from './apiClient';
import apiClient from '../../../shared/services/apiClient';
export interface ReportData {
total_bookings: number;

View File

@@ -1,7 +1,7 @@
import React, { useEffect } from 'react';
import { Navigate } from 'react-router-dom';
import useAuthStore from '../../store/useAuthStore';
import { useAuthModal } from '../../contexts/AuthModalContext';
import useAuthStore from '../../../store/useAuthStore';
import { useAuthModal } from '../contexts/AuthModalContext';
interface AccountantRouteProps {
children: React.ReactNode;

View File

@@ -1,7 +1,7 @@
import React, { useEffect } from 'react';
import { Navigate } from 'react-router-dom';
import useAuthStore from '../../store/useAuthStore';
import { useAuthModal } from '../../contexts/AuthModalContext';
import useAuthStore from '../../../store/useAuthStore';
import { useAuthModal } from '../contexts/AuthModalContext';
interface AdminRouteProps {
children: React.ReactNode;

View File

@@ -1,10 +1,10 @@
import React, { useEffect } from 'react';
import { useAuthModal } from '../../contexts/AuthModalContext';
import { useAuthModal } from '../contexts/AuthModalContext';
import LoginModal from './LoginModal';
import RegisterModal from './RegisterModal';
import ForgotPasswordModal from './ForgotPasswordModal';
import ResetPasswordModal from './ResetPasswordModal';
import useAuthStore from '../../store/useAuthStore';
import useAuthStore from '../../../store/useAuthStore';
const AuthModalManager: React.FC = () => {
const { isOpen, modalType, resetPasswordParams, openModal } = useAuthModal();

View File

@@ -1,7 +1,7 @@
import React, { useEffect } from 'react';
import { Navigate } from 'react-router-dom';
import useAuthStore from '../../store/useAuthStore';
import { useAuthModal } from '../../contexts/AuthModalContext';
import useAuthStore from '../../../store/useAuthStore';
import { useAuthModal } from '../contexts/AuthModalContext';
interface CustomerRouteProps {
children: React.ReactNode;

View File

@@ -2,12 +2,12 @@ import React, { useState, useEffect } from 'react';
import { useForm } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import { X, Mail, ArrowLeft, Send, Loader2, CheckCircle } from 'lucide-react';
import useAuthStore from '../../store/useAuthStore';
import { forgotPasswordSchema, ForgotPasswordFormData } from '../../utils/validationSchemas';
import { useCompanySettings } from '../../contexts/CompanySettingsContext';
import { useAuthModal } from '../../contexts/AuthModalContext';
import { useAntibotForm } from '../../hooks/useAntibotForm';
import HoneypotField from '../common/HoneypotField';
import useAuthStore from '../../../store/useAuthStore';
import { forgotPasswordSchema, ForgotPasswordFormData } from '../../../shared/utils/validationSchemas';
import { useCompanySettings } from '../../../shared/contexts/CompanySettingsContext';
import { useAuthModal } from '../contexts/AuthModalContext';
import { useAntibotForm } from '../hooks/useAntibotForm';
import HoneypotField from '../../../shared/components/HoneypotField';
import { toast } from 'react-toastify';
const ForgotPasswordModal: React.FC = () => {

View File

@@ -2,16 +2,16 @@ import React, { useState, useEffect } from 'react';
import { useForm } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import { X, Eye, EyeOff, LogIn, Loader2, Mail, Lock, Shield, ArrowLeft } from 'lucide-react';
import useAuthStore from '../../store/useAuthStore';
import { loginSchema, LoginFormData } from '../../utils/validationSchemas';
import { useCompanySettings } from '../../contexts/CompanySettingsContext';
import { useAuthModal } from '../../contexts/AuthModalContext';
import useAuthStore from '../../../store/useAuthStore';
import { loginSchema, LoginFormData } from '../../../shared/utils/validationSchemas';
import { useCompanySettings } from '../../../shared/contexts/CompanySettingsContext';
import { useAuthModal } from '../contexts/AuthModalContext';
import * as yup from 'yup';
import { toast } from 'react-toastify';
import Recaptcha from '../common/Recaptcha';
import { recaptchaService } from '../../services/api/systemSettingsService';
import { useAntibotForm } from '../../hooks/useAntibotForm';
import HoneypotField from '../common/HoneypotField';
import Recaptcha from '../../../shared/components/Recaptcha';
import { recaptchaService } from '../../../features/system/services/systemSettingsService';
import { useAntibotForm } from '../hooks/useAntibotForm';
import HoneypotField from '../../../shared/components/HoneypotField';
const mfaTokenSchema = yup.object().shape({
mfaToken: yup

View File

@@ -1,6 +1,6 @@
import React, { useEffect } from 'react';
import useAuthStore from '../../store/useAuthStore';
import { useAuthModal } from '../../contexts/AuthModalContext';
import useAuthStore from '../../../store/useAuthStore';
import { useAuthModal } from '../contexts/AuthModalContext';
interface ProtectedRouteProps {
children: React.ReactNode;

View File

@@ -2,15 +2,15 @@ import React, { useState, useEffect } from 'react';
import { useForm } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import { X, Eye, EyeOff, UserPlus, Loader2, Mail, Lock, User, Phone, CheckCircle2, XCircle } from 'lucide-react';
import useAuthStore from '../../store/useAuthStore';
import { registerSchema, RegisterFormData } from '../../utils/validationSchemas';
import { useCompanySettings } from '../../contexts/CompanySettingsContext';
import { useAuthModal } from '../../contexts/AuthModalContext';
import useAuthStore from '../../../store/useAuthStore';
import { registerSchema, RegisterFormData } from '../../../shared/utils/validationSchemas';
import { useCompanySettings } from '../../../shared/contexts/CompanySettingsContext';
import { useAuthModal } from '../contexts/AuthModalContext';
import { toast } from 'react-toastify';
import Recaptcha from '../common/Recaptcha';
import { recaptchaService } from '../../services/api/systemSettingsService';
import { useAntibotForm } from '../../hooks/useAntibotForm';
import HoneypotField from '../common/HoneypotField';
import Recaptcha from '../../../shared/components/Recaptcha';
import { recaptchaService } from '../../system/services/systemSettingsService';
import { useAntibotForm } from '../hooks/useAntibotForm';
import HoneypotField from '../../../shared/components/HoneypotField';
const PasswordRequirement: React.FC<{ met: boolean; text: string }> = ({ met, text }) => (
<div className="flex items-center gap-1.5 sm:gap-2 text-[10px] sm:text-xs font-light">

View File

@@ -2,10 +2,10 @@ import React, { useState, useEffect } from 'react';
import { useForm } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import { X, Eye, EyeOff, Lock, Loader2, CheckCircle2, XCircle, AlertCircle, KeyRound } from 'lucide-react';
import useAuthStore from '../../store/useAuthStore';
import { resetPasswordSchema, ResetPasswordFormData } from '../../utils/validationSchemas';
import { useCompanySettings } from '../../contexts/CompanySettingsContext';
import { useAuthModal } from '../../contexts/AuthModalContext';
import useAuthStore from '../../../store/useAuthStore';
import { resetPasswordSchema, ResetPasswordFormData } from '../../../shared/utils/validationSchemas';
import { useCompanySettings } from '../../../shared/contexts/CompanySettingsContext';
import { useAuthModal } from '../contexts/AuthModalContext';
const PasswordRequirement: React.FC<{ met: boolean; text: string }> = ({ met, text }) => (
<div className="flex items-center gap-1.5 sm:gap-2 text-[10px] sm:text-xs">

View File

@@ -1,6 +1,6 @@
import { useEffect } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { useAuthModal } from '../../contexts/AuthModalContext';
import { useAuthModal } from '../contexts/AuthModalContext';
const ResetPasswordRouteHandler: React.FC = () => {
const { token } = useParams<{ token: string }>();

View File

@@ -1,7 +1,7 @@
import React, { useEffect } from 'react';
import { Navigate } from 'react-router-dom';
import useAuthStore from '../../store/useAuthStore';
import { useAuthModal } from '../../contexts/AuthModalContext';
import useAuthStore from '../../../store/useAuthStore';
import { useAuthModal } from '../contexts/AuthModalContext';
interface StaffRouteProps {
children: React.ReactNode;

View File

@@ -8,7 +8,7 @@ import {
clearRateLimit,
getFingerprintHash,
type AntibotValidationResult,
} from '../utils/antibot';
} from '../../../shared/utils/antibot';
interface AntibotContextType {
timing: FormTiming;

View File

@@ -1,4 +1,4 @@
import apiClient from './apiClient';
import apiClient from '../../../shared/services/apiClient';
export interface LoginCredentials {
email: string;

View File

@@ -0,0 +1,3 @@
// Auth services
export * from './authService';
export * from './userService';

View File

@@ -1,4 +1,4 @@
import apiClient from './apiClient';
import apiClient from '../../../shared/services/apiClient';
export interface User {
id: number;

View File

@@ -1,8 +1,8 @@
import React, { useState } from 'react';
import { X, AlertTriangle, XCircle, Loader2, Info } from 'lucide-react';
import { cancelBooking, type Booking } from '../../services/api/bookingService';
import { cancelBooking, type Booking } from '../services/bookingService';
import { toast } from 'react-toastify';
import { useFormatCurrency } from '../../hooks/useFormatCurrency';
import { useFormatCurrency } from '../../payments/hooks/useFormatCurrency';
interface CancelBookingModalProps {
isOpen: boolean;

View File

@@ -18,28 +18,29 @@ import {
Receipt,
} from 'lucide-react';
import { toast } from 'react-toastify';
import { getRoomById, getRoomBookedDates, type Room } from '../../services/api/roomService';
import { getRoomById, getRoomBookedDates, type Room } from '../../rooms/services/roomService';
import {
createBooking,
checkRoomAvailability,
type BookingData,
} from '../../services/api/bookingService';
import { serviceService, Service, promotionService, Promotion } from '../../services/api';
import useAuthStore from '../../store/useAuthStore';
} from '../services/bookingService';
import serviceService, { Service } from '../../hotel_services/services/serviceService';
import promotionService, { Promotion } from '../../loyalty/services/promotionService';
import useAuthStore from '../../../store/useAuthStore';
import {
bookingValidationSchema,
type BookingFormData,
} from '../../validators/bookingValidator';
import { useFormatCurrency } from '../../hooks/useFormatCurrency';
import { formatDateLocal } from '../../utils/format';
import Recaptcha from '../common/Recaptcha';
import { recaptchaService } from '../../services/api/systemSettingsService';
import StripePaymentModal from '../payments/StripePaymentModal';
import PayPalPaymentModal from '../payments/PayPalPaymentModal';
import CashPaymentModal from '../payments/CashPaymentModal';
import InvoiceInfoModal from '../booking/InvoiceInfoModal';
import { useAntibotForm } from '../../hooks/useAntibotForm';
import HoneypotField from '../common/HoneypotField';
} from '../../../shared/utils/bookingValidator';
import { useFormatCurrency } from '../../payments/hooks/useFormatCurrency';
import { formatDateLocal } from '../../../shared/utils/format';
import Recaptcha from '../../../shared/components/Recaptcha';
import { recaptchaService } from '../../../features/system/services/systemSettingsService';
import StripePaymentModal from '../../payments/components/StripePaymentModal';
import PayPalPaymentModal from '../../payments/components/PayPalPaymentModal';
import CashPaymentModal from '../../payments/components/CashPaymentModal';
import InvoiceInfoModal from './InvoiceInfoModal';
import { useAntibotForm } from '../../auth/hooks/useAntibotForm';
import HoneypotField from '../../../shared/components/HoneypotField';
interface LuxuryBookingModalProps {
roomId: number;
@@ -443,7 +444,7 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
if (createdBookingId) {
// Check booking status before showing success toast
try {
const { getBookingById } = await import('../../services/api/bookingService');
const { getBookingById } = await import('../services/bookingService');
const bookingResponse = await getBookingById(createdBookingId);
if (bookingResponse.success && bookingResponse.data?.booking) {
const booking = bookingResponse.data.booking;

View File

@@ -1,4 +1,4 @@
import apiClient from './apiClient';
import apiClient from '../../../shared/services/apiClient';
export interface BookingData {
room_id: number;

View File

@@ -1,4 +1,4 @@
import apiClient from './apiClient';
import apiClient from '../../../shared/services/apiClient';
export interface RoomBlock {
room_type_id: number;

View File

@@ -10,10 +10,10 @@ import {
} from 'lucide-react';
import * as LucideIcons from 'lucide-react';
import { Link } from 'react-router-dom';
import { pageContentService } from '../services/api';
import type { PageContent } from '../services/api/pageContentService';
import { useCompanySettings } from '../contexts/CompanySettingsContext';
import { createSanitizedHtml } from '../utils/htmlSanitizer';
import pageContentService from '../services/pageContentService';
import type { PageContent } from '../services/pageContentService';
import { useCompanySettings } from '../../../shared/contexts/CompanySettingsContext';
import { createSanitizedHtml } from '../../../shared/utils/htmlSanitizer';
const AboutPage: React.FC = () => {
const { settings } = useCompanySettings();

View File

@@ -1,11 +1,11 @@
import React, { useState, useEffect } from 'react';
import { Accessibility, ArrowLeft } from 'lucide-react';
import { Link } from 'react-router-dom';
import { pageContentService } from '../services/api';
import type { PageContent } from '../services/api/pageContentService';
import { useCompanySettings } from '../contexts/CompanySettingsContext';
import Loading from '../components/common/Loading';
import { createSanitizedHtml } from '../utils/htmlSanitizer';
import pageContentService from '../services/pageContentService';
import type { PageContent } from '../services/pageContentService';
import { useCompanySettings } from '../../../shared/contexts/CompanySettingsContext';
import Loading from '../../../shared/components/Loading';
import { createSanitizedHtml } from '../../../shared/utils/htmlSanitizer';
const AccessibilityPage: React.FC = () => {
const { settings } = useCompanySettings();

View File

@@ -1,9 +1,9 @@
import React, { useState, useEffect } from 'react';
import { useParams, Link, useNavigate } from 'react-router-dom';
import { Calendar, User, Tag, ArrowLeft, Eye, Share2, ArrowRight } from 'lucide-react';
import { blogService, BlogPost } from '../services/api';
import Loading from '../components/common/Loading';
import { createSanitizedHtml } from '../utils/htmlSanitizer';
import blogService, { BlogPost } from '../services/blogService';
import Loading from '../../../shared/components/Loading';
import { createSanitizedHtml } from '../../../shared/utils/htmlSanitizer';
const BlogDetailPage: React.FC = () => {
const { slug } = useParams<{ slug: string }>();

View File

@@ -1,9 +1,9 @@
import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import { Calendar, User, Tag, Search, ArrowRight, Eye, Sparkles, BookOpen } from 'lucide-react';
import { blogService, BlogPost } from '../services/api';
import Loading from '../components/common/Loading';
import Pagination from '../components/common/Pagination';
import blogService, { BlogPost } from '../services/blogService';
import Loading from '../../../shared/components/Loading';
import Pagination from '../../../shared/components/Pagination';
const BlogPage: React.FC = () => {
const [posts, setPosts] = useState<BlogPost[]>([]);

View File

@@ -1,11 +1,10 @@
import React, { useState, useEffect } from 'react';
import { XCircle, ArrowLeft } from 'lucide-react';
import { Link } from 'react-router-dom';
import { pageContentService } from '../services/api';
import type { PageContent } from '../services/api/pageContentService';
import { useCompanySettings } from '../contexts/CompanySettingsContext';
import Loading from '../components/common/Loading';
import { createSanitizedHtml } from '../utils/htmlSanitizer';
import pageContentService, { PageContent } from '../services/pageContentService';
import { useCompanySettings } from '../../../shared/contexts/CompanySettingsContext';
import Loading from '../../../shared/components/Loading';
import { createSanitizedHtml } from '../../../shared/utils/htmlSanitizer';
const CancellationPolicyPage: React.FC = () => {
const { settings } = useCompanySettings();

View File

@@ -1,15 +1,15 @@
import React, { useState, useEffect } from 'react';
import { Mail, Phone, MapPin, Send, User, MessageSquare } from 'lucide-react';
import { submitContactForm } from '../services/api/contactService';
import { pageContentService } from '../services/api';
import type { PageContent } from '../services/api/pageContentService';
import { useCompanySettings } from '../contexts/CompanySettingsContext';
import { submitContactForm } from '../services/contactService';
import pageContentService from '../services/pageContentService';
import type { PageContent } from '../services/pageContentService';
import { useCompanySettings } from '../../../shared/contexts/CompanySettingsContext';
import { toast } from 'react-toastify';
import Recaptcha from '../components/common/Recaptcha';
import { recaptchaService } from '../services/api/systemSettingsService';
import ChatWidget from '../components/chat/ChatWidget';
import { useAntibotForm } from '../hooks/useAntibotForm';
import HoneypotField from '../components/common/HoneypotField';
import Recaptcha from '../../../shared/components/Recaptcha';
import { recaptchaService } from '../../../features/system/services/systemSettingsService';
import ChatWidget from '../../notifications/components/ChatWidget';
import { useAntibotForm } from '../../../features/auth/hooks/useAntibotForm';
import HoneypotField from '../../../shared/components/HoneypotField';
const ContactPage: React.FC = () => {
const { settings } = useCompanySettings();

View File

@@ -1,11 +1,11 @@
import React, { useState, useEffect } from 'react';
import { HelpCircle, ArrowLeft } from 'lucide-react';
import { Link } from 'react-router-dom';
import { pageContentService } from '../services/api';
import type { PageContent } from '../services/api/pageContentService';
import { useCompanySettings } from '../contexts/CompanySettingsContext';
import Loading from '../components/common/Loading';
import { createSanitizedHtml } from '../utils/htmlSanitizer';
import pageContentService from '../services/pageContentService';
import type { PageContent } from '../services/pageContentService';
import { useCompanySettings } from '../../../shared/contexts/CompanySettingsContext';
import Loading from '../../../shared/components/Loading';
import { createSanitizedHtml } from '../../../shared/utils/htmlSanitizer';
const FAQPage: React.FC = () => {
const { settings } = useCompanySettings();

View File

@@ -15,15 +15,13 @@ import {
RoomCardSkeleton,
RoomCarousel,
SearchRoomForm,
} from '../components/rooms';
import {
bannerService,
roomService,
pageContentService
} from '../services/api';
import type { Banner } from '../services/api/bannerService';
import type { Room } from '../services/api/roomService';
import type { PageContent } from '../services/api/pageContentService';
} from '../../rooms/components';
import bannerService from '../services/bannerService';
import roomService from '../../rooms/services/roomService';
import pageContentService from '../services/pageContentService';
import type { Banner } from '../services/bannerService';
import type { Room } from '../../rooms/services/roomService';
import type { PageContent } from '../services/pageContentService';
const HomePage: React.FC = () => {
const [banners, setBanners] = useState<Banner[]>([]);

View File

@@ -1,11 +1,11 @@
import React, { useState, useEffect } from 'react';
import { Shield, ArrowLeft } from 'lucide-react';
import { Link } from 'react-router-dom';
import { pageContentService } from '../services/api';
import type { PageContent } from '../services/api/pageContentService';
import { useCompanySettings } from '../contexts/CompanySettingsContext';
import Loading from '../components/common/Loading';
import { createSanitizedHtml } from '../utils/htmlSanitizer';
import pageContentService from '../services/pageContentService';
import type { PageContent } from '../services/pageContentService';
import { useCompanySettings } from '../../../shared/contexts/CompanySettingsContext';
import Loading from '../../../shared/components/Loading';
import { createSanitizedHtml } from '../../../shared/utils/htmlSanitizer';
const PrivacyPolicyPage: React.FC = () => {
const { settings } = useCompanySettings();

View File

@@ -1,11 +1,11 @@
import React, { useState, useEffect } from 'react';
import { RefreshCw, ArrowLeft } from 'lucide-react';
import { Link } from 'react-router-dom';
import { pageContentService } from '../services/api';
import type { PageContent } from '../services/api/pageContentService';
import { useCompanySettings } from '../contexts/CompanySettingsContext';
import Loading from '../components/common/Loading';
import { createSanitizedHtml } from '../utils/htmlSanitizer';
import pageContentService from '../services/pageContentService';
import type { PageContent } from '../services/pageContentService';
import { useCompanySettings } from '../../../shared/contexts/CompanySettingsContext';
import Loading from '../../../shared/components/Loading';
import { createSanitizedHtml } from '../../../shared/utils/htmlSanitizer';
const RefundsPolicyPage: React.FC = () => {
const { settings } = useCompanySettings();

View File

@@ -1,11 +1,11 @@
import React, { useState, useEffect } from 'react';
import { Scale, ArrowLeft } from 'lucide-react';
import { Link } from 'react-router-dom';
import { pageContentService } from '../services/api';
import type { PageContent } from '../services/api/pageContentService';
import { useCompanySettings } from '../contexts/CompanySettingsContext';
import Loading from '../components/common/Loading';
import { createSanitizedHtml } from '../utils/htmlSanitizer';
import pageContentService from '../services/pageContentService';
import type { PageContent } from '../services/pageContentService';
import { useCompanySettings } from '../../../shared/contexts/CompanySettingsContext';
import Loading from '../../../shared/components/Loading';
import { createSanitizedHtml } from '../../../shared/utils/htmlSanitizer';
const TermsPage: React.FC = () => {
const { settings } = useCompanySettings();

View File

@@ -1,4 +1,4 @@
import apiClient from './apiClient';
import apiClient from '../../../shared/services/apiClient';
export type CookiePolicySettings = {
analytics_enabled: boolean;

View File

@@ -1,4 +1,4 @@
import apiClient from './apiClient';
import apiClient from '../../../shared/services/apiClient';
export interface Banner {
id: number;

View File

@@ -1,4 +1,4 @@
import apiClient from './apiClient';
import apiClient from '../../../shared/services/apiClient';
export interface BlogSection {
type: 'hero' | 'text' | 'image' | 'gallery' | 'quote' | 'features' | 'cta' | 'video';

View File

@@ -1,4 +1,4 @@
import apiClient from './apiClient';
import apiClient from '../../../shared/services/apiClient';
export interface ContactFormData {
name: string;

View File

@@ -1,4 +1,4 @@
import apiClient from './apiClient';
import apiClient from '../../../shared/services/apiClient';
export type PageType = 'home' | 'contact' | 'about' | 'footer' | 'seo' | 'privacy' | 'terms' | 'refunds' | 'cancellation' | 'accessibility' | 'faq';

View File

@@ -1,4 +1,4 @@
import apiClient from './apiClient';
import apiClient from '../../../shared/services/apiClient';
export type CookieCategoryPreferences = {
necessary: boolean;

View File

@@ -1,4 +1,4 @@
import apiClient from './apiClient';
import apiClient from '../../../shared/services/apiClient';
export interface GuestPreference {
preferred_room_location?: string;

View File

@@ -1,10 +1,12 @@
import React, { useState, useEffect } from 'react';
import { X, Search, Calendar, Users, DollarSign, CreditCard, FileText, User } from 'lucide-react';
import { bookingService, roomService, userService } from '../../services/api';
import type { Room } from '../../services/api/roomService';
import type { User as UserType } from '../../services/api/userService';
import bookingService from '../../bookings/services/bookingService';
import roomService from '../../rooms/services/roomService';
import userService from '../../auth/services/userService';
import type { Room } from '../../rooms/services/roomService';
import type { User as UserType } from '../../auth/services/userService';
import { toast } from 'react-toastify';
import { useFormatCurrency } from '../../hooks/useFormatCurrency';
import { useFormatCurrency } from '../../payments/hooks/useFormatCurrency';
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';

View File

@@ -1,8 +1,9 @@
import React, { useState, useEffect } from 'react';
import { X, Plus, Trash2, Calendar, DollarSign, FileText, Building2, Loader2 } from 'lucide-react';
import { groupBookingService, roomService, Room } from '../../services/api';
import groupBookingService from '../../bookings/services/groupBookingService';
import roomService, { Room } from '../../rooms/services/roomService';
import { toast } from 'react-toastify';
import { useFormatCurrency } from '../../hooks/useFormatCurrency';
import { useFormatCurrency } from '../../payments/hooks/useFormatCurrency';
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';

View File

@@ -9,12 +9,12 @@ import {
Clock,
} from 'lucide-react';
import { toast } from 'react-toastify';
import Loading from '../common/Loading';
import Pagination from '../common/Pagination';
import advancedRoomService, { HousekeepingTask, ChecklistItem } from '../../services/api/advancedRoomService';
import { roomService, Room } from '../../services/api';
import { userService, User as UserType } from '../../services/api';
import useAuthStore from '../../store/useAuthStore';
import Loading from '../../../shared/components/Loading';
import Pagination from '../../../shared/components/Pagination';
import advancedRoomService, { HousekeepingTask, ChecklistItem } from '../../rooms/services/advancedRoomService';
import roomService, { Room } from '../../rooms/services/roomService';
import userService, { User as UserType } from '../../auth/services/userService';
import useAuthStore from '../../../store/useAuthStore';
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';

View File

@@ -11,16 +11,16 @@ import {
Star,
} from 'lucide-react';
import { toast } from 'react-toastify';
import Loading from '../common/Loading';
import Pagination from '../common/Pagination';
import Loading from '../../../shared/components/Loading';
import Pagination from '../../../shared/components/Pagination';
import advancedRoomService, {
RoomInspection,
InspectionChecklistItem,
Issue,
} from '../../services/api/advancedRoomService';
import { roomService, Room } from '../../services/api';
import { userService, User as UserType } from '../../services/api';
import useAuthStore from '../../store/useAuthStore';
} from '../../rooms/services/advancedRoomService';
import roomService, { Room } from '../../rooms/services/roomService';
import userService, { User as UserType } from '../../auth/services/userService';
import useAuthStore from '../../../store/useAuthStore';
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';

View File

@@ -8,12 +8,12 @@ import {
CheckCircle,
} from 'lucide-react';
import { toast } from 'react-toastify';
import Loading from '../common/Loading';
import Pagination from '../common/Pagination';
import advancedRoomService, { MaintenanceRecord } from '../../services/api/advancedRoomService';
import { roomService, Room } from '../../services/api';
import { userService, User as UserType } from '../../services/api';
import useAuthStore from '../../store/useAuthStore';
import Loading from '../../../shared/components/Loading';
import Pagination from '../../../shared/components/Pagination';
import advancedRoomService, { MaintenanceRecord } from '../../rooms/services/advancedRoomService';
import roomService, { Room } from '../../rooms/services/roomService';
import userService, { User as UserType } from '../../auth/services/userService';
import useAuthStore from '../../../store/useAuthStore';
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';

View File

@@ -1,4 +1,4 @@
import apiClient from './apiClient';
import apiClient from '../../../shared/services/apiClient';
export interface Service {
id: number;

View File

@@ -1,4 +1,4 @@
import apiClient from './apiClient';
import apiClient from '../../../shared/services/apiClient';
export interface LoyaltyTier {
id: number;

View File

@@ -1,4 +1,4 @@
import apiClient from './apiClient';
import apiClient from '../../../shared/services/apiClient';
export type PackageStatus = 'active' | 'inactive' | 'scheduled' | 'expired';
export type PackageItemType = 'room' | 'service' | 'breakfast' | 'activity' | 'amenity' | 'discount';

View File

@@ -1,4 +1,4 @@
import apiClient from './apiClient';
import apiClient from '../../../shared/services/apiClient';
export interface Promotion {
id: number;

View File

@@ -1,10 +1,11 @@
import React, { useState, useEffect, useRef } from 'react';
import { MessageCircle, X, Send, Minimize2, Maximize2, Clock } from 'lucide-react';
import { chatService, contactService, type Chat, type ChatMessage, type ContactFormData } from '../../services/api';
import useAuthStore from '../../store/useAuthStore';
import { useCompanySettings } from '../../contexts/CompanySettingsContext';
import chatService, { type Chat, type ChatMessage } from '../services/chatService';
import contactService, { type ContactFormData } from '../../content/services/contactService';
import useAuthStore from '../../../store/useAuthStore';
import { useCompanySettings } from '../../../shared/contexts/CompanySettingsContext';
import { toast } from 'react-toastify';
import ConfirmationDialog from '../common/ConfirmationDialog';
import ConfirmationDialog from '../../../shared/components/ConfirmationDialog';
interface ChatWidgetProps {
onClose?: () => void;

View File

@@ -1,9 +1,9 @@
import React, { useState, useEffect, useRef } from 'react';
import { Bell } from 'lucide-react';
import { toast } from 'react-toastify';
import notificationService, { Notification } from '../../services/api/notificationService';
import { formatDate } from '../../utils/format';
import useAuthStore from '../../store/useAuthStore';
import notificationService, { Notification } from '../services/notificationService';
import { formatDate } from '../../../shared/utils/format';
import useAuthStore from '../../../store/useAuthStore';
const InAppNotificationBell: React.FC = () => {
const { isAuthenticated, token, isLoading } = useAuthStore();

View File

@@ -1,8 +1,8 @@
import React, { useState, useEffect } from 'react';
import { Bell, Mail, MessageSquare, Smartphone, Save } from 'lucide-react';
import { toast } from 'react-toastify';
import { Loading } from '../common';
import notificationService, { NotificationPreferences as NotificationPreferencesType } from '../../services/api/notificationService';
import Loading from '../../../shared/components/Loading';
import notificationService, { NotificationPreferences as NotificationPreferencesType } from '../services/notificationService';
const NotificationPreferences: React.FC = () => {
const [preferences, setPreferences] = useState<NotificationPreferencesType | null>(null);

View File

@@ -1,7 +1,7 @@
import React, { useState, useEffect } from 'react';
import { X, Plus } from 'lucide-react';
import { toast } from 'react-toastify';
import notificationService, { NotificationTemplate } from '../../services/api/notificationService';
import notificationService, { NotificationTemplate } from '../services/notificationService';
interface NotificationTemplatesModalProps {
onClose: () => void;

View File

@@ -1,7 +1,7 @@
import React, { useState, useEffect } from 'react';
import { X } from 'lucide-react';
import { toast } from 'react-toastify';
import notificationService from '../../services/api/notificationService';
import notificationService from '../services/notificationService';
interface SendNotificationModalProps {
onClose: () => void;

View File

@@ -2,9 +2,9 @@ import React, { useEffect, useState } from 'react';
import { Bell } from 'lucide-react';
import { useNavigate } from 'react-router-dom';
import { toast } from 'react-toastify';
import useAuthStore from '../../store/useAuthStore';
import { type Chat } from '../../services/api';
import { useChatNotifications } from '../../contexts/ChatNotificationContext';
import useAuthStore from '../../../store/useAuthStore';
import { type Chat } from '../services/chatService';
import { useChatNotifications } from '../contexts/ChatNotificationContext';
const StaffChatNotification: React.FC = () => {
const [notificationWs, setNotificationWs] = useState<WebSocket | null>(null);

View File

@@ -1,6 +1,6 @@
import React, { createContext, useContext, useState, ReactNode, useEffect } from 'react';
import useAuthStore from '../store/useAuthStore';
import { chatService } from '../services/api';
import useAuthStore from '../../../store/useAuthStore';
import chatService from '../services/chatService';
interface ChatNotificationContextType {
unreadCount: number;

View File

@@ -1,4 +1,4 @@
import apiClient from './apiClient';
import apiClient from '../../../shared/services/apiClient';
export interface Chat {
id: number;

View File

@@ -1,4 +1,4 @@
import apiClient from './apiClient';
import apiClient from '../../../shared/services/apiClient';
export interface Campaign {
id: number;

View File

@@ -1,4 +1,4 @@
import apiClient from './apiClient';
import apiClient from '../../../shared/services/apiClient';
export interface Notification {
id: number;

View File

@@ -1,8 +1,8 @@
import React, { useState, useEffect } from 'react';
import { createBoricaPayment } from '../../services/api/paymentService';
import { createBoricaPayment } from '../services/paymentService';
import { X, Loader2, AlertCircle, CreditCard } from 'lucide-react';
import { toast } from 'react-toastify';
import { useFormatCurrency } from '../../hooks/useFormatCurrency';
import { useFormatCurrency } from '../hooks/useFormatCurrency';
interface BoricaPaymentModalProps {
isOpen: boolean;

View File

@@ -1,6 +1,6 @@
import React, { useState } from 'react';
import { X, CheckCircle, CreditCard } from 'lucide-react';
import { useFormatCurrency } from '../../hooks/useFormatCurrency';
import { useFormatCurrency } from '../hooks/useFormatCurrency';
import DepositPaymentModal from './DepositPaymentModal';
interface CashPaymentModalProps {

View File

@@ -8,13 +8,13 @@ import {
Loader2,
} from 'lucide-react';
import { toast } from 'react-toastify';
import { getBookingById, type Booking } from '../../services/api/bookingService';
import CancelBookingModal from '../booking/CancelBookingModal';
import { getBookingById, type Booking } from '../../bookings/services/bookingService';
import CancelBookingModal from '../../bookings/components/CancelBookingModal';
import {
getPaymentsByBookingId,
type Payment,
} from '../../services/api/paymentService';
import { useFormatCurrency } from '../../hooks/useFormatCurrency';
} from '../services/paymentService';
import { useFormatCurrency } from '../hooks/useFormatCurrency';
import StripePaymentModal from './StripePaymentModal';
import PayPalPaymentModal from './PayPalPaymentModal';

View File

@@ -1,8 +1,8 @@
import React, { useState, useEffect } from 'react';
import { createPayPalOrder } from '../../services/api/paymentService';
import { createPayPalOrder } from '../services/paymentService';
import { X, Loader2, AlertCircle } from 'lucide-react';
import { toast } from 'react-toastify';
import { useFormatCurrency } from '../../hooks/useFormatCurrency';
import { useFormatCurrency } from '../hooks/useFormatCurrency';
interface PayPalPaymentModalProps {
isOpen: boolean;

View File

@@ -1,7 +1,7 @@
import React, { useState, useEffect } from 'react';
import { createPayPalOrder } from '../../services/api/paymentService';
import { createPayPalOrder } from '../services/paymentService';
import { Loader2, AlertCircle } from 'lucide-react';
import { useFormatCurrency } from '../../hooks/useFormatCurrency';
import { useFormatCurrency } from '../hooks/useFormatCurrency';
interface PayPalPaymentWrapperProps {
bookingId: number;

View File

@@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react';
import { loadStripe, StripeElementsOptions } from '@stripe/stripe-js';
import { Elements } from '@stripe/react-stripe-js';
import StripePaymentForm from './StripePaymentForm';
import { createStripePaymentIntent, confirmStripePayment } from '../../services/api/paymentService';
import { createStripePaymentIntent, confirmStripePayment } from '../services/paymentService';
import { X, Loader2, AlertCircle } from 'lucide-react';
import { toast } from 'react-toastify';

View File

@@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react';
import { loadStripe, StripeElementsOptions } from '@stripe/stripe-js';
import { Elements } from '@stripe/react-stripe-js';
import StripePaymentForm from './StripePaymentForm';
import { createStripePaymentIntent, confirmStripePayment } from '../../services/api/paymentService';
import { createStripePaymentIntent, confirmStripePayment } from '../services/paymentService';
import { Loader2, AlertCircle } from 'lucide-react';
interface StripePaymentWrapperProps {

View File

@@ -5,8 +5,8 @@ import React, {
useState,
ReactNode,
} from 'react';
import { CURRENCY } from '../utils/constants';
import systemSettingsService from '../services/api/systemSettingsService';
import { CURRENCY } from '../../../shared/utils/constants';
import systemSettingsService from '../../../features/system/services/systemSettingsService';
type CurrencyContextValue = {
currency: string;

View File

@@ -1,6 +1,6 @@
import { useMemo } from 'react';
import { useCurrency } from '../contexts/CurrencyContext';
import { formatCurrency as formatCurrencyUtil } from '../utils/format';
import { formatCurrency as formatCurrencyUtil } from '../../../shared/utils/format';
export const useFormatCurrency = () => {
const { currency } = useCurrency();

View File

@@ -1,4 +1,4 @@
import apiClient from './apiClient';
import apiClient from '../../../shared/services/apiClient';
export interface InvoiceItem {
id: number;

View File

@@ -1,4 +1,4 @@
import apiClient from './apiClient';
import apiClient from '../../../shared/services/apiClient';
export interface PaymentData {
booking_id: number;

View File

@@ -1,5 +1,5 @@
import apiClient from './apiClient';
import type { Room } from './roomService';
import apiClient from '../../../shared/services/apiClient';
import type { Room } from '../../rooms/services/roomService';
export interface Favorite {
id: number;

View File

@@ -1,4 +1,4 @@
import apiClient from './apiClient';
import apiClient from '../../../shared/services/apiClient';
export interface Review {
id: number;

View File

@@ -1,6 +1,6 @@
import React, { useState, useEffect } from 'react';
import { ChevronLeft, ChevronRight } from 'lucide-react';
import type { Banner } from '../../services/api/bannerService';
import type { Banner } from '../../content/services/bannerService';
interface BannerCarouselProps {
banners: Banner[];

View File

@@ -1,7 +1,7 @@
import React, { useState } from 'react';
import { Heart } from 'lucide-react';
import useFavoritesStore from '../../store/useFavoritesStore';
import useAuthStore from '../../store/useAuthStore';
import useFavoritesStore from '../../../store/useFavoritesStore';
import useAuthStore from '../../../store/useAuthStore';
interface FavoriteButtonProps {
roomId: number;

Some files were not shown because too many files have changed in this diff Show More