From b818d645a990ba04cc922d5d8e2a2deb3e6a200c Mon Sep 17 00:00:00 2001 From: Iliyan Angelov Date: Sun, 7 Dec 2025 20:36:17 +0200 Subject: [PATCH] updates --- .../system_settings_routes.cpython-312.pyc | Bin 81691 -> 88156 bytes .../system/routes/system_settings_routes.py | 174 ++ Frontend/src/App.tsx | 11 +- .../auth/components/ForgotPasswordModal.tsx | 24 +- .../features/auth/components/LoginModal.tsx | 14 +- .../auth/components/RegisterModal.tsx | 18 +- .../auth/components/ResetPasswordModal.tsx | 18 +- .../auth/pages/HousekeepingLoginPage.tsx | 14 +- .../bookings/components/InvoiceInfoModal.tsx | 20 +- .../components/LuxuryBookingModal.tsx | 102 +- .../content/components/PartnersCarousel.tsx | 16 +- .../src/features/content/pages/AboutPage.tsx | 160 +- .../content/pages/AccessibilityPage.tsx | 24 +- .../features/content/pages/BlogDetailPage.tsx | 48 +- .../src/features/content/pages/BlogPage.tsx | 74 +- .../content/pages/CancellationPolicyPage.tsx | 24 +- .../features/content/pages/ContactPage.tsx | 120 +- .../src/features/content/pages/FAQPage.tsx | 24 +- .../src/features/content/pages/HomePage.tsx | 178 +- .../content/pages/PrivacyPolicyPage.tsx | 26 +- .../content/pages/RefundsPolicyPage.tsx | 24 +- .../content/pages/ServiceDetailPage.tsx | 96 +- .../features/content/pages/ServicesPage.tsx | 76 +- .../src/features/content/pages/TermsPage.tsx | 24 +- .../notifications/components/ChatWidget.tsx | 46 +- .../components/BoricaPaymentModal.tsx | 20 +- .../payments/components/CashPaymentModal.tsx | 14 +- .../components/DepositPaymentModal.tsx | 48 +- .../components/PayPalPaymentModal.tsx | 12 +- .../components/PayPalPaymentWrapper.tsx | 16 +- .../payments/components/StripePaymentForm.tsx | 10 +- .../components/StripePaymentModal.tsx | 10 +- .../rooms/components/BannerCarousel.tsx | 10 +- .../features/rooms/components/Pagination.tsx | 12 +- .../features/rooms/components/RatingStars.tsx | 2 +- .../rooms/components/ReviewSection.tsx | 32 +- .../features/rooms/components/RoomCard.tsx | 22 +- .../rooms/components/RoomCardSkeleton.tsx | 6 +- .../rooms/components/RoomCarousel.tsx | 16 +- .../features/rooms/components/RoomFilter.tsx | 98 +- .../rooms/components/SearchRoomForm.tsx | 6 +- .../system/services/systemSettingsService.ts | 43 +- Frontend/src/pages/HousekeepingLayout.tsx | 10 +- Frontend/src/pages/accountant/ProfilePage.tsx | 94 +- .../admin/AdvancedRoomManagementPage.tsx | 80 +- .../pages/admin/AnalyticsDashboardPage.tsx | 291 +-- Frontend/src/pages/admin/AuditLogsPage.tsx | 472 ----- .../src/pages/admin/BannerManagementPage.tsx | 8 +- .../src/pages/admin/BlogManagementPage.tsx | 86 +- .../src/pages/admin/BusinessDashboardPage.tsx | 1587 ----------------- .../pages/admin/ComplaintManagementPage.tsx | 14 +- .../pages/admin/ComplianceReportingPage.tsx | 8 +- .../src/pages/admin/CookieSettingsPage.tsx | 4 +- .../src/pages/admin/CurrencySettingsPage.tsx | 4 +- .../pages/admin/FinancialAuditTrailPage.tsx | 10 +- .../src/pages/admin/InvoiceManagementPage.tsx | 1 - Frontend/src/pages/admin/ProfilePage.tsx | 94 +- .../pages/admin/PromotionsManagementPage.tsx | 859 +++++++++ .../pages/admin/ReceptionDashboardPage.tsx | 28 +- Frontend/src/pages/admin/ReportsPage.tsx | 379 ---- Frontend/src/pages/admin/SettingsPage.tsx | 246 ++- .../src/pages/customer/BoricaReturnPage.tsx | 14 +- Frontend/src/pages/customer/ComplaintPage.tsx | 16 +- .../src/pages/customer/FullPaymentPage.tsx | 62 +- .../src/pages/customer/GuestRequestsPage.tsx | 18 +- .../src/pages/customer/PayPalCancelPage.tsx | 8 +- .../src/pages/customer/PayPalReturnPage.tsx | 20 +- Frontend/src/pages/customer/ProfilePage.tsx | 94 +- .../src/pages/customer/RoomDetailPage.tsx | 108 +- Frontend/src/pages/customer/RoomListPage.tsx | 66 +- .../src/pages/housekeeping/DashboardPage.tsx | 114 +- .../src/pages/housekeeping/ProfilePage.tsx | 76 +- .../src/pages/housekeeping/ShiftViewPage.tsx | 10 +- .../src/pages/staff/ChatManagementPage.tsx | 34 +- Frontend/src/pages/staff/ProfilePage.tsx | 94 +- .../pages/staff/ReceptionDashboardPage.tsx | 82 +- Frontend/src/routes/adminRoutes.tsx | 4 +- .../shared/components/ConfirmationDialog.tsx | 18 +- .../shared/components/CookieConsentBanner.tsx | 24 +- .../components/CookiePreferencesLink.tsx | 2 +- .../components/CookiePreferencesModal.tsx | 24 +- .../shared/components/CurrencySelector.tsx | 4 +- Frontend/src/shared/components/Footer.tsx | 102 +- Frontend/src/shared/components/Header.tsx | 582 +++--- Frontend/src/shared/components/Navbar.tsx | 232 ++- .../shared/components/OfflineIndicator.tsx | 16 +- .../src/shared/components/SidebarAdmin.tsx | 12 +- Frontend/src/shared/contexts/ThemeContext.tsx | 162 ++ Frontend/src/shared/pages/NotFoundPage.tsx | 16 +- Frontend/src/styles/index.css | 165 +- Frontend/tailwind.config.js | 7 +- 91 files changed, 3692 insertions(+), 4501 deletions(-) delete mode 100644 Frontend/src/pages/admin/AuditLogsPage.tsx delete mode 100644 Frontend/src/pages/admin/BusinessDashboardPage.tsx create mode 100644 Frontend/src/pages/admin/PromotionsManagementPage.tsx delete mode 100644 Frontend/src/pages/admin/ReportsPage.tsx create mode 100644 Frontend/src/shared/contexts/ThemeContext.tsx diff --git a/Backend/src/system/routes/__pycache__/system_settings_routes.cpython-312.pyc b/Backend/src/system/routes/__pycache__/system_settings_routes.cpython-312.pyc index 8bc550029166ecb7d2bec63ff49a24c28f26d06b..10f7bfa2a5fbe3102891f7e07bb15c6ef5858fc1 100644 GIT binary patch delta 4536 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 delta 598 zcmYk2-D?v;6vcD5$xOO6p{P(xh}KdeEozjQfC_d6QM1LmDx!!I;_gU8#oD`hiGonf zn<$i(4&tjIMWKGs9VPft9~7&t6s%(K!ABK@{sW40^VDIvoIUfKbMMUeN3pyAqR9`5 zgc;GRY2_;6{>kJ9<97Swj1>=hj4mh!j@cc|#96|w#~u)-*O^1K7krEF3Kk4An2q;o zZV_^+BO>SZh_sgy<^|>ruR2i-R(Ka2rL>fzDI%iYu~md!$()y<7EWp&Hvnesetvw|u$kj+9Hja8XoCqoRhP-Ui3=$ zP1c&RX;%D_xKuuWQF!=?T#ulSq^^-#luvBf$(FV8ldE4gWZPg!bq~XU0Za0L1BFg{ kcBI=O4T{V1jsxkA-&*T0;{Ro8&H-R;D^~RW*;4@j0a!w#x&QzG diff --git a/Backend/src/system/routes/system_settings_routes.py b/Backend/src/system/routes/system_settings_routes.py index a7c22c81..f9c5a1f2 100644 --- a/Backend/src/system/routes/system_settings_routes.py +++ b/Backend/src/system/routes/system_settings_routes.py @@ -1846,6 +1846,180 @@ async def upload_company_favicon( logger.error(f"Error uploading favicon: {e}", exc_info=True) raise HTTPException(status_code=500, detail=str(e)) +class UpdateThemeSettingsRequest(BaseModel): + theme_primary_color: Optional[str] = None + theme_primary_light: Optional[str] = None + theme_primary_dark: Optional[str] = None + theme_primary_accent: Optional[str] = None + +@router.get("/theme") +async def get_theme_settings( + db: Session = Depends(get_db) +): + """Get current theme color settings""" + try: + setting_keys = [ + "theme_primary_color", + "theme_primary_light", + "theme_primary_dark", + "theme_primary_accent", + ] + + settings_dict = {} + for key in setting_keys: + setting = db.query(SystemSettings).filter( + SystemSettings.key == key + ).first() + if setting: + settings_dict[key] = setting.value + else: + settings_dict[key] = None + + # Get updated_at and updated_by from any theme setting + theme_setting = db.query(SystemSettings).filter( + SystemSettings.key == "theme_primary_color" + ).first() + + updated_at = None + updated_by = None + if theme_setting: + updated_at = theme_setting.updated_at.isoformat() if theme_setting.updated_at else None + updated_by = theme_setting.updated_by.full_name if theme_setting.updated_by else None + + return { + "status": "success", + "data": { + "theme_primary_color": settings_dict.get("theme_primary_color", "#d4af37"), + "theme_primary_light": settings_dict.get("theme_primary_light", "#f5d76e"), + "theme_primary_dark": settings_dict.get("theme_primary_dark", "#c9a227"), + "theme_primary_accent": settings_dict.get("theme_primary_accent", "#e8c547"), + "updated_at": updated_at, + "updated_by": updated_by, + } + } + except Exception as e: + logger.error(f"Error getting theme settings: {e}", exc_info=True) + raise HTTPException(status_code=500, detail=str(e)) + +@router.put("/theme") +async def update_theme_settings( + request_data: UpdateThemeSettingsRequest, + request: Request, + current_user: User = Depends(authorize_roles("admin")), + db: Session = Depends(get_db) +): + """Update theme color settings (admin only)""" + import re + + client_ip = request.client.host if request.client else None + user_agent = request.headers.get('User-Agent') + request_id = getattr(request.state, 'request_id', None) + + try: + # Validate hex color format + hex_color_pattern = re.compile(r'^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$') + + db_settings = {} + + if request_data.theme_primary_color is not None: + if not hex_color_pattern.match(request_data.theme_primary_color): + raise HTTPException( + status_code=400, + detail="Invalid theme_primary_color format. Must be a valid hex color (e.g., #d4af37)" + ) + db_settings["theme_primary_color"] = request_data.theme_primary_color + + if request_data.theme_primary_light is not None: + if not hex_color_pattern.match(request_data.theme_primary_light): + raise HTTPException( + status_code=400, + detail="Invalid theme_primary_light format. Must be a valid hex color (e.g., #f5d76e)" + ) + db_settings["theme_primary_light"] = request_data.theme_primary_light + + if request_data.theme_primary_dark is not None: + if not hex_color_pattern.match(request_data.theme_primary_dark): + raise HTTPException( + status_code=400, + detail="Invalid theme_primary_dark format. Must be a valid hex color (e.g., #c9a227)" + ) + db_settings["theme_primary_dark"] = request_data.theme_primary_dark + + if request_data.theme_primary_accent is not None: + if not hex_color_pattern.match(request_data.theme_primary_accent): + raise HTTPException( + status_code=400, + detail="Invalid theme_primary_accent format. Must be a valid hex color (e.g., #e8c547)" + ) + db_settings["theme_primary_accent"] = request_data.theme_primary_accent + + # Update or create settings + for key, value in db_settings.items(): + setting = db.query(SystemSettings).filter( + SystemSettings.key == key + ).first() + + if setting: + setting.value = value + setting.updated_at = datetime.utcnow() + setting.updated_by_id = current_user.id + else: + setting = SystemSettings( + key=key, + value=value, + updated_by_id=current_user.id + ) + db.add(setting) + + db.commit() + + # Get updated settings + updated_settings = {} + for key in ["theme_primary_color", "theme_primary_light", "theme_primary_dark", "theme_primary_accent"]: + setting = db.query(SystemSettings).filter( + SystemSettings.key == key + ).first() + if setting: + updated_settings[key] = setting.value + else: + # Return defaults if not set + defaults = { + "theme_primary_color": "#d4af37", + "theme_primary_light": "#f5d76e", + "theme_primary_dark": "#c9a227", + "theme_primary_accent": "#e8c547", + } + updated_settings[key] = defaults.get(key) + + theme_setting = db.query(SystemSettings).filter( + SystemSettings.key == "theme_primary_color" + ).first() + + updated_at = None + updated_by = None + if theme_setting: + updated_at = theme_setting.updated_at.isoformat() if theme_setting.updated_at else None + updated_by = theme_setting.updated_by.full_name if theme_setting.updated_by else None + + return { + "status": "success", + "message": "Theme settings updated successfully", + "data": { + "theme_primary_color": updated_settings.get("theme_primary_color", "#d4af37"), + "theme_primary_light": updated_settings.get("theme_primary_light", "#f5d76e"), + "theme_primary_dark": updated_settings.get("theme_primary_dark", "#c9a227"), + "theme_primary_accent": updated_settings.get("theme_primary_accent", "#e8c547"), + "updated_at": updated_at, + "updated_by": updated_by, + } + } + except HTTPException: + raise + except Exception as e: + db.rollback() + logger.error(f"Error updating theme settings: {e}", exc_info=True) + raise HTTPException(status_code=500, detail=str(e)) + @router.get("/recaptcha") async def get_recaptcha_settings( db: Session = Depends(get_db) diff --git a/Frontend/src/App.tsx b/Frontend/src/App.tsx index d4b11d73..399678ff 100644 --- a/Frontend/src/App.tsx +++ b/Frontend/src/App.tsx @@ -12,6 +12,7 @@ import { LoadingProvider, useNavigationLoading, useLoading } from './shared/cont import { CookieConsentProvider } from './shared/contexts/CookieConsentContext'; import { CurrencyProvider } from './features/payments/contexts/CurrencyContext'; import { CompanySettingsProvider } from './shared/contexts/CompanySettingsContext'; +import { ThemeProvider } from './shared/contexts/ThemeContext'; import { AuthModalProvider } from './features/auth/contexts/AuthModalContext'; import { AntibotProvider } from './features/auth/contexts/AntibotContext'; import { RoomProvider } from './features/rooms/contexts/RoomContext'; @@ -91,7 +92,7 @@ const GroupBookingManagementPage = lazy(() => import('./pages/admin/GroupBooking const AdminBookingManagementPage = lazy(() => import('./pages/admin/BookingManagementPage')); const PageContentDashboardPage = lazy(() => import('./pages/admin/PageContentDashboard')); const AnalyticsDashboardPage = lazy(() => import('./pages/admin/AnalyticsDashboardPage')); -const BusinessDashboardPage = lazy(() => import('./pages/admin/BusinessDashboardPage')); +const PromotionsManagementPage = lazy(() => import('./pages/admin/PromotionsManagementPage')); const SettingsPage = lazy(() => import('./pages/admin/SettingsPage')); const TaskManagementPage = lazy(() => import('./pages/admin/TaskManagementPage')); const WorkflowManagementPage = lazy(() => import('./pages/admin/WorkflowManagementPage')); @@ -249,7 +250,8 @@ function App() { - + + @@ -600,8 +602,8 @@ function App() { element={} /> } + path="promotions" + element={} /> + diff --git a/Frontend/src/features/auth/components/ForgotPasswordModal.tsx b/Frontend/src/features/auth/components/ForgotPasswordModal.tsx index a525ad37..a7515d56 100644 --- a/Frontend/src/features/auth/components/ForgotPasswordModal.tsx +++ b/Frontend/src/features/auth/components/ForgotPasswordModal.tsx @@ -93,7 +93,7 @@ const ForgotPasswordModal: React.FC = () => {
{/* Modal */} -
+
{/* Close button */}
@@ -172,7 +172,7 @@ const ForgotPasswordModal: React.FC = () => { setIsSuccess(false); clearError(); }} - className="w-full flex items-center justify-center py-2.5 sm:py-3 px-4 border border-gray-300 rounded-lg text-xs sm:text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[#d4af37] transition-colors" + className="w-full flex items-center justify-center py-2.5 sm:py-3 px-4 border border-gray-300 rounded-lg text-xs sm:text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[var(--luxury-gold)] transition-colors" > Resend Email @@ -180,7 +180,7 @@ const ForgotPasswordModal: React.FC = () => { @@ -286,7 +286,7 @@ const ForgotPasswordModal: React.FC = () => { If you're having trouble resetting your password, please contact our support team via email{' '}
{supportEmail} @@ -295,7 +295,7 @@ const ForgotPasswordModal: React.FC = () => { {' '}or hotline{' '} {supportPhone} diff --git a/Frontend/src/features/auth/components/LoginModal.tsx b/Frontend/src/features/auth/components/LoginModal.tsx index 6a0f20cf..9dd80fd4 100644 --- a/Frontend/src/features/auth/components/LoginModal.tsx +++ b/Frontend/src/features/auth/components/LoginModal.tsx @@ -376,7 +376,7 @@ const LoginModal: React.FC = () => {
{/* Modal */} -
+
{/* Close button */} @@ -633,7 +633,7 @@ const LoginModal: React.FC = () => { Don't have an account?{' '} diff --git a/Frontend/src/features/auth/components/RegisterModal.tsx b/Frontend/src/features/auth/components/RegisterModal.tsx index e4f841e9..a0466901 100644 --- a/Frontend/src/features/auth/components/RegisterModal.tsx +++ b/Frontend/src/features/auth/components/RegisterModal.tsx @@ -15,11 +15,11 @@ import HoneypotField from '../../../shared/components/HoneypotField'; const PasswordRequirement: React.FC<{ met: boolean; text: string }> = ({ met, text }) => (
{met ? ( - + ) : ( )} - + {text}
@@ -165,7 +165,7 @@ const RegisterModal: React.FC = () => {
{/* Modal */} -
+
{/* Close button */} diff --git a/Frontend/src/features/auth/components/ResetPasswordModal.tsx b/Frontend/src/features/auth/components/ResetPasswordModal.tsx index 10227440..471e2f74 100644 --- a/Frontend/src/features/auth/components/ResetPasswordModal.tsx +++ b/Frontend/src/features/auth/components/ResetPasswordModal.tsx @@ -132,7 +132,7 @@ const ResetPasswordModal: React.FC = ({ token }) => {
{/* Modal */} -
+
{/* Close button */} {!isSuccess && (
@@ -212,7 +212,7 @@ const ResetPasswordModal: React.FC = ({ token }) => { closeModal(); openModal('login'); }} - className="inline-flex items-center justify-center w-full py-2.5 sm:py-3 px-4 border border-transparent rounded-lg text-xs sm:text-sm font-medium text-white bg-gradient-to-r from-[#d4af37] to-[#c9a227] hover:from-[#f5d76e] hover:to-[#d4af37] focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[#d4af37] transition-colors" + className="inline-flex items-center justify-center w-full py-2.5 sm:py-3 px-4 border border-transparent rounded-lg text-xs sm:text-sm font-medium text-white bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[var(--luxury-gold)] transition-colors" > Login Now @@ -267,7 +267,7 @@ const ResetPasswordModal: React.FC = ({ token }) => { className={`block w-full pl-9 sm:pl-10 pr-9 sm:pr-10 py-2.5 sm:py-3 border rounded-lg focus:outline-none focus:ring-2 transition-colors text-sm sm:text-base luxury-input ${ errors.password ? 'border-red-300 focus:ring-red-500' - : 'border-gray-300 focus:ring-[#d4af37]' + : 'border-gray-300 focus:ring-[var(--luxury-gold)]' }`} placeholder="••••••••" /> @@ -330,7 +330,7 @@ const ResetPasswordModal: React.FC = ({ token }) => { className={`block w-full pl-9 sm:pl-10 pr-9 sm:pr-10 py-2.5 sm:py-3 border rounded-lg focus:outline-none focus:ring-2 transition-colors text-sm sm:text-base luxury-input ${ errors.confirmPassword ? 'border-red-300 focus:ring-red-500' - : 'border-gray-300 focus:ring-[#d4af37]' + : 'border-gray-300 focus:ring-[var(--luxury-gold)]' }`} placeholder="••••••••" /> @@ -356,7 +356,7 @@ const ResetPasswordModal: React.FC = ({ token }) => { diff --git a/Frontend/src/features/auth/pages/HousekeepingLoginPage.tsx b/Frontend/src/features/auth/pages/HousekeepingLoginPage.tsx index 5605b5fa..9b56abe9 100644 --- a/Frontend/src/features/auth/pages/HousekeepingLoginPage.tsx +++ b/Frontend/src/features/auth/pages/HousekeepingLoginPage.tsx @@ -345,7 +345,7 @@ const HousekeepingLoginPage: React.FC = () => {
-
+
{settings.company_logo_url ? ( { autoComplete="one-time-code" maxLength={8} className={`w-full pl-10 pr-4 py-3 border rounded-lg text-center tracking-widest ${ - mfaErrors.mfaToken ? 'border-red-300 focus:ring-red-500' : 'border-gray-300 focus:ring-[#d4af37]' + mfaErrors.mfaToken ? 'border-red-300 focus:ring-red-500' : 'border-gray-300 focus:ring-[var(--luxury-gold)]' }`} placeholder="000000" /> @@ -402,7 +402,7 @@ const HousekeepingLoginPage: React.FC = () => { @@ -73,7 +73,7 @@ const InvoiceInfoModal: React.FC = ({
@@ -85,7 +85,7 @@ const InvoiceInfoModal: React.FC = ({