updates
This commit is contained in:
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"filename": "backup_luxury_hotel_db_20251210_000027.sql",
|
||||||
|
"path": "backups/backup_luxury_hotel_db_20251210_000027.sql",
|
||||||
|
"size_bytes": 462323,
|
||||||
|
"size_mb": 0.44,
|
||||||
|
"created_at": "2025-12-10T00:00:28.460311",
|
||||||
|
"database": "luxury_hotel_db",
|
||||||
|
"status": "success"
|
||||||
|
}
|
||||||
4907
Backend/backups/backup_luxury_hotel_db_20251210_000027.sql
Normal file
4907
Backend/backups/backup_luxury_hotel_db_20251210_000027.sql
Normal file
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -3,6 +3,7 @@ Approval workflow routes.
|
|||||||
"""
|
"""
|
||||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
from sqlalchemy.exc import ProgrammingError
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from ...shared.config.database import get_db
|
from ...shared.config.database import get_db
|
||||||
from ...shared.config.logging_config import get_logger
|
from ...shared.config.logging_config import get_logger
|
||||||
@@ -57,6 +58,13 @@ async def get_pending_approvals(
|
|||||||
})
|
})
|
||||||
except HTTPException:
|
except HTTPException:
|
||||||
raise
|
raise
|
||||||
|
except ProgrammingError as e:
|
||||||
|
# Handle missing table gracefully
|
||||||
|
if "doesn't exist" in str(e) and "approval_requests" in str(e):
|
||||||
|
logger.warning('Approval requests table does not exist. Returning empty list. Run migrations to create the table.')
|
||||||
|
return success_response(data={'approvals': []})
|
||||||
|
logger.error(f'Database error getting pending approvals: {str(e)}', exc_info=True)
|
||||||
|
raise HTTPException(status_code=500, detail='Database error occurred')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f'Error getting pending approvals: {str(e)}', exc_info=True)
|
logger.error(f'Error getting pending approvals: {str(e)}', exc_info=True)
|
||||||
raise HTTPException(status_code=500, detail=str(e))
|
raise HTTPException(status_code=500, detail=str(e))
|
||||||
@@ -88,6 +96,12 @@ async def approve_request(
|
|||||||
)
|
)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
raise HTTPException(status_code=400, detail=str(e))
|
raise HTTPException(status_code=400, detail=str(e))
|
||||||
|
except ProgrammingError as e:
|
||||||
|
if "doesn't exist" in str(e) and "approval_requests" in str(e):
|
||||||
|
logger.warning('Approval requests table does not exist. Run migrations to create the table.')
|
||||||
|
raise HTTPException(status_code=503, detail='Approval system not available. Please run database migrations.')
|
||||||
|
logger.error(f'Database error approving request: {str(e)}', exc_info=True)
|
||||||
|
raise HTTPException(status_code=500, detail='Database error occurred')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f'Error approving request: {str(e)}', exc_info=True)
|
logger.error(f'Error approving request: {str(e)}', exc_info=True)
|
||||||
raise HTTPException(status_code=500, detail=str(e))
|
raise HTTPException(status_code=500, detail=str(e))
|
||||||
@@ -118,6 +132,12 @@ async def reject_request(
|
|||||||
)
|
)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
raise HTTPException(status_code=400, detail=str(e))
|
raise HTTPException(status_code=400, detail=str(e))
|
||||||
|
except ProgrammingError as e:
|
||||||
|
if "doesn't exist" in str(e) and "approval_requests" in str(e):
|
||||||
|
logger.warning('Approval requests table does not exist. Run migrations to create the table.')
|
||||||
|
raise HTTPException(status_code=503, detail='Approval system not available. Please run database migrations.')
|
||||||
|
logger.error(f'Database error rejecting request: {str(e)}', exc_info=True)
|
||||||
|
raise HTTPException(status_code=500, detail='Database error occurred')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f'Error rejecting request: {str(e)}', exc_info=True)
|
logger.error(f'Error rejecting request: {str(e)}', exc_info=True)
|
||||||
raise HTTPException(status_code=500, detail=str(e))
|
raise HTTPException(status_code=500, detail=str(e))
|
||||||
@@ -162,6 +182,12 @@ async def get_my_approval_requests(
|
|||||||
})
|
})
|
||||||
except HTTPException:
|
except HTTPException:
|
||||||
raise
|
raise
|
||||||
|
except ProgrammingError as e:
|
||||||
|
if "doesn't exist" in str(e) and "approval_requests" in str(e):
|
||||||
|
logger.warning('Approval requests table does not exist. Returning empty list. Run migrations to create the table.')
|
||||||
|
return success_response(data={'approvals': []})
|
||||||
|
logger.error(f'Database error getting user approvals: {str(e)}', exc_info=True)
|
||||||
|
raise HTTPException(status_code=500, detail='Database error occurred')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f'Error getting user approvals: {str(e)}', exc_info=True)
|
logger.error(f'Error getting user approvals: {str(e)}', exc_info=True)
|
||||||
raise HTTPException(status_code=500, detail=str(e))
|
raise HTTPException(status_code=500, detail=str(e))
|
||||||
@@ -194,6 +220,12 @@ async def cancel_approval_request(
|
|||||||
return success_response(message='Approval request cancelled successfully')
|
return success_response(message='Approval request cancelled successfully')
|
||||||
except HTTPException:
|
except HTTPException:
|
||||||
raise
|
raise
|
||||||
|
except ProgrammingError as e:
|
||||||
|
if "doesn't exist" in str(e) and "approval_requests" in str(e):
|
||||||
|
logger.warning('Approval requests table does not exist. Run migrations to create the table.')
|
||||||
|
raise HTTPException(status_code=503, detail='Approval system not available. Please run database migrations.')
|
||||||
|
logger.error(f'Database error cancelling approval request: {str(e)}', exc_info=True)
|
||||||
|
raise HTTPException(status_code=500, detail='Database error occurred')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f'Error cancelling approval request: {str(e)}', exc_info=True)
|
logger.error(f'Error cancelling approval request: {str(e)}', exc_info=True)
|
||||||
raise HTTPException(status_code=500, detail=str(e))
|
raise HTTPException(status_code=500, detail=str(e))
|
||||||
|
|||||||
@@ -1,149 +0,0 @@
|
|||||||
# Icon Control Audit Report
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
This document provides a comprehensive audit of icon usage across frontend pages and identifies which icons are controlled from the admin dashboard vs hardcoded.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✅ Pages with Full Admin Control
|
|
||||||
|
|
||||||
### 1. **HomePage** (`Frontend/src/features/content/pages/HomePage.tsx`)
|
|
||||||
**Status: ✅ Fully Controlled**
|
|
||||||
|
|
||||||
All icons are controlled from admin dashboard:
|
|
||||||
- **Features Section** - Icons controlled via `pageContent.features[].icon`
|
|
||||||
- **Luxury Features Section** - Icons controlled via `pageContent.luxury_features[].icon`
|
|
||||||
- **Stats/Achievements Section** - Icons controlled via `pageContent.stats[].icon` (FIXED: now handles lowercase icon names)
|
|
||||||
- **Amenities Section** - Icons controlled via `pageContent.amenities[].icon`
|
|
||||||
- **Awards Section** - Icons controlled via `pageContent.awards[].icon`
|
|
||||||
- **Experiences Section** - Icons controlled via `pageContent.luxury_experiences[].icon`
|
|
||||||
|
|
||||||
**Admin Location:** `PageContentDashboard.tsx` → Home Tab
|
|
||||||
- Features: Line 2179
|
|
||||||
- Luxury Features: Line 1552
|
|
||||||
- Stats: Line 2033
|
|
||||||
- Amenities: Line 1356
|
|
||||||
- Awards: Line 2524
|
|
||||||
- Experiences: Line 2373
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 2. **ServiceDetailPage** (`Frontend/src/features/content/pages/ServiceDetailPage.tsx`)
|
|
||||||
**Status: ✅ Fully Controlled**
|
|
||||||
|
|
||||||
- Service icon comes from `service.icon` field in database
|
|
||||||
- Managed via Service Management admin page
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⚠️ Pages with Partial Admin Control
|
|
||||||
|
|
||||||
### 3. **AboutPage** (`Frontend/src/features/content/pages/AboutPage.tsx`)
|
|
||||||
**Status: ⚠️ Partially Controlled**
|
|
||||||
|
|
||||||
**Controlled Icons:**
|
|
||||||
- ✅ Values Section - Icons controlled via `pageContent.values[].icon` (Admin: Line 3794)
|
|
||||||
- ✅ Features Section - Icons controlled via `pageContent.features[].icon` (Admin: Line 3885)
|
|
||||||
- ✅ Achievements Section - Icons controlled via `pageContent.achievements[].icon` (Admin: Line 4264)
|
|
||||||
|
|
||||||
**Hardcoded Icons:**
|
|
||||||
- ❌ Hero Section - `Hotel` icon (Line 197) - Hardcoded, no admin control
|
|
||||||
- ❌ Contact Info Section - `MapPin`, `Phone`, `Mail` icons (Lines 617, 636, 651) - Hardcoded
|
|
||||||
- ❌ "Learn More" Button - `Hotel` icon (Line 671) - Hardcoded
|
|
||||||
|
|
||||||
**Recommendation:** Add admin controls for:
|
|
||||||
1. Hero section icon (when no hero image is set)
|
|
||||||
2. Contact info section icons (optional, as these are semantic)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 4. **ServicesPage** (`Frontend/src/features/content/pages/ServicesPage.tsx`)
|
|
||||||
**Status: ⚠️ Partially Controlled**
|
|
||||||
|
|
||||||
**Controlled Icons:**
|
|
||||||
- ✅ Service icons come from `service.icon` field in database
|
|
||||||
|
|
||||||
**Hardcoded Icons:**
|
|
||||||
- ❌ Fallback icon - `Award` icon (Line 334) - Used when service has no icon
|
|
||||||
|
|
||||||
**Recommendation:** This is acceptable as a fallback, but could be made configurable.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ❌ Pages with No Admin Control
|
|
||||||
|
|
||||||
### 5. **ContactPage** (`Frontend/src/features/content/pages/ContactPage.tsx`)
|
|
||||||
**Status: ❌ All Icons Hardcoded**
|
|
||||||
|
|
||||||
**Hardcoded Icons:**
|
|
||||||
- ❌ Hero Section - `Mail` icon (Line 191)
|
|
||||||
- ❌ Email Contact Info - `Mail` icon (Line 234)
|
|
||||||
- ❌ Phone Contact Info - `Phone` icon (Line 246)
|
|
||||||
- ❌ Location Contact Info - `MapPin` icon (Line 258)
|
|
||||||
- ❌ Form Field Icons:
|
|
||||||
- `User` icon (Line 333) - Name field
|
|
||||||
- `Mail` icon (Line 361) - Email field
|
|
||||||
- `Phone` icon (Line 387) - Phone field
|
|
||||||
- `MessageSquare` icon (Lines 410, 436) - Subject and Message fields
|
|
||||||
- ❌ Submit Button - `Send` icon (Line 497)
|
|
||||||
|
|
||||||
**Recommendation:** Add admin controls for:
|
|
||||||
1. Hero section icon
|
|
||||||
2. Contact info section icons (Email, Phone, Location)
|
|
||||||
3. Form field icons (optional, as these are semantic UI elements)
|
|
||||||
|
|
||||||
**Admin Location:** `PageContentDashboard.tsx` → Contact Tab (currently no icon controls)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 Summary Statistics
|
|
||||||
|
|
||||||
| Page | Total Icon Usages | Admin Controlled | Hardcoded | Control % |
|
|
||||||
|------|------------------|------------------|-----------|-----------|
|
|
||||||
| HomePage | ~20+ | 20+ | 0 | 100% ✅ |
|
|
||||||
| ServiceDetailPage | 1 | 1 | 0 | 100% ✅ |
|
|
||||||
| AboutPage | 8 | 3 | 5 | 37.5% ⚠️ |
|
|
||||||
| ServicesPage | ~6 | 5 | 1 | 83% ⚠️ |
|
|
||||||
| ContactPage | 8 | 0 | 8 | 0% ❌ |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 Recommendations
|
|
||||||
|
|
||||||
### High Priority
|
|
||||||
1. **ContactPage** - Add icon controls for:
|
|
||||||
- Hero section icon
|
|
||||||
- Contact info section icons (Email, Phone, Location)
|
|
||||||
|
|
||||||
### Medium Priority
|
|
||||||
2. **AboutPage** - Add icon control for:
|
|
||||||
- Hero section icon (when no hero image is set)
|
|
||||||
|
|
||||||
### Low Priority
|
|
||||||
3. **ServicesPage** - Consider making fallback icon configurable
|
|
||||||
4. **ContactPage** - Consider making form field icons configurable (though semantic icons are fine)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🛠️ Implementation Notes
|
|
||||||
|
|
||||||
### Icon Name Handling
|
|
||||||
- Icons in database may be stored as lowercase (e.g., 'users', 'calendar')
|
|
||||||
- Lucide React icons use PascalCase (e.g., 'Users', 'Calendar')
|
|
||||||
- The `getIconComponent` helper function in HomePage.tsx handles this conversion
|
|
||||||
- Consider adding this helper to other pages that need it
|
|
||||||
|
|
||||||
### Admin Icon Picker
|
|
||||||
- IconPicker component is available at: `Frontend/src/features/system/components/IconPicker.tsx`
|
|
||||||
- Already integrated in PageContentDashboard for Home and About pages
|
|
||||||
- Can be easily added to Contact page admin section
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 Notes
|
|
||||||
|
|
||||||
- Most content icons are properly controlled from admin
|
|
||||||
- Hardcoded icons are mostly semantic UI elements (form fields, buttons)
|
|
||||||
- The main gap is the ContactPage which has no icon controls
|
|
||||||
- AboutPage hero section could benefit from icon control when no image is set
|
|
||||||
|
|
||||||
@@ -1,221 +0,0 @@
|
|||||||
# Settings Usage Audit Report
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
This document provides a comprehensive audit of how frontend pages use information from Settings (email, phone, address, currency, etc.) vs hardcoded values.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✅ Pages Using Settings Correctly
|
|
||||||
|
|
||||||
### 1. **Header Component** (`Frontend/src/shared/components/Header.tsx`)
|
|
||||||
**Status: ⚠️ Uses Settings with Hardcoded Fallbacks**
|
|
||||||
|
|
||||||
- ✅ Uses `useCompanySettings()` hook
|
|
||||||
- ✅ Uses `settings.company_phone` and `settings.company_email`
|
|
||||||
- ❌ **Hardcoded fallbacks:**
|
|
||||||
- Phone: `'+1 (234) 567-890'`
|
|
||||||
- Email: `'info@luxuryhotel.com'`
|
|
||||||
- ✅ Uses `settings.company_logo_url`
|
|
||||||
|
|
||||||
**Recommendation:** Remove hardcoded fallbacks or use empty string/null instead.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 2. **Footer Component** (`Frontend/src/shared/components/Footer.tsx`)
|
|
||||||
**Status: ✅ Fully Uses Settings**
|
|
||||||
|
|
||||||
- ✅ Uses `useCompanySettings()` hook
|
|
||||||
- ✅ Uses `settings.company_phone`, `settings.company_email`, `settings.company_address`
|
|
||||||
- ✅ No hardcoded fallbacks (uses `null` if not available)
|
|
||||||
- ✅ Uses `settings.company_logo_url`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 3. **ContactPage** (`Frontend/src/features/content/pages/ContactPage.tsx`)
|
|
||||||
**Status: ⚠️ Uses Settings with Hardcoded Fallback Text**
|
|
||||||
|
|
||||||
- ✅ Uses `useCompanySettings()` hook
|
|
||||||
- ✅ Uses `settings.company_phone`, `settings.company_email`, `settings.company_address`
|
|
||||||
- ❌ **Hardcoded fallback text:**
|
|
||||||
- Phone: `'Available 24/7 for your convenience'` (should be actual phone or null)
|
|
||||||
- Email: `"We'll respond within 24 hours"` (should be actual email or null)
|
|
||||||
- Address: `'Visit us at our hotel reception'` (should be actual address or null)
|
|
||||||
|
|
||||||
**Recommendation:** Use actual values from settings or show nothing if not available.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 4. **AboutPage** (`Frontend/src/features/content/pages/AboutPage.tsx`)
|
|
||||||
**Status: ✅ Fully Uses Settings**
|
|
||||||
|
|
||||||
- ✅ Uses `useCompanySettings()` hook
|
|
||||||
- ✅ Uses `settings.company_phone`, `settings.company_email`, `settings.company_address`
|
|
||||||
- ✅ No hardcoded fallbacks (uses `null` if not available)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 5. **Policy Pages** (Privacy, Terms, Refunds, Cancellation, Accessibility, FAQ)
|
|
||||||
**Status: ✅ Uses Settings for Email**
|
|
||||||
|
|
||||||
- ✅ All use `useCompanySettings()` hook
|
|
||||||
- ✅ Use `settings.company_email` for contact links
|
|
||||||
- ✅ Only show email link if `settings.company_email` exists
|
|
||||||
|
|
||||||
**Pages:**
|
|
||||||
- `PrivacyPolicyPage.tsx`
|
|
||||||
- `TermsPage.tsx`
|
|
||||||
- `RefundsPolicyPage.tsx`
|
|
||||||
- `CancellationPolicyPage.tsx`
|
|
||||||
- `AccessibilityPage.tsx`
|
|
||||||
- `FAQPage.tsx`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 6. **Customer Pages - Currency Usage**
|
|
||||||
**Status: ✅ All Use Currency Context**
|
|
||||||
|
|
||||||
All customer pages use `useFormatCurrency()` hook which uses `CurrencyContext`:
|
|
||||||
- ✅ `BookingDetailPage.tsx`
|
|
||||||
- ✅ `BookingSuccessPage.tsx`
|
|
||||||
- ✅ `MyBookingsPage.tsx`
|
|
||||||
- ✅ `RoomDetailPage.tsx`
|
|
||||||
- ✅ `FullPaymentPage.tsx`
|
|
||||||
- ✅ `PaymentConfirmationPage.tsx`
|
|
||||||
- ✅ `InvoicePage.tsx`
|
|
||||||
- ✅ `GroupBookingPage.tsx`
|
|
||||||
- ✅ `DashboardPage.tsx`
|
|
||||||
|
|
||||||
**Currency Source:** `CurrencyContext` → `localStorage.getItem('currency')` → Falls back to 'VND'
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 7. **Content Pages - Currency Usage**
|
|
||||||
**Status: ✅ All Use Currency Context**
|
|
||||||
|
|
||||||
- ✅ `HomePage.tsx` - Uses `useFormatCurrency()` for service prices
|
|
||||||
- ✅ `ServicesPage.tsx` - Uses `useFormatCurrency()` for service prices
|
|
||||||
- ✅ `ServiceDetailPage.tsx` - Uses `useFormatCurrency()` for service prices
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 8. **PaymentResultPage** (`Frontend/src/pages/customer/PaymentResultPage.tsx`)
|
|
||||||
**Status: ⚠️ Uses Settings with Hardcoded Fallbacks**
|
|
||||||
|
|
||||||
- ✅ Uses `useCompanySettings()` hook
|
|
||||||
- ❌ **Hardcoded fallbacks:**
|
|
||||||
- Email: `'support@hotel.com'`
|
|
||||||
- Phone: `'1900 xxxx'`
|
|
||||||
|
|
||||||
**Recommendation:** Remove hardcoded fallbacks.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 9. **Auth Components**
|
|
||||||
**Status: ⚠️ Mixed Usage**
|
|
||||||
|
|
||||||
**ForgotPasswordModal:**
|
|
||||||
- ✅ Uses `settings.company_email || 'support@hotel.com'` (has fallback)
|
|
||||||
|
|
||||||
**Other Auth Components:**
|
|
||||||
- ❌ Only use placeholder text in form fields (acceptable for UX)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ❌ Pages with Hardcoded Values
|
|
||||||
|
|
||||||
### 1. **PaymentConfirmationPage** (`Frontend/src/pages/customer/PaymentConfirmationPage.tsx`)
|
|
||||||
**Status: ❌ Hardcoded Bank Details**
|
|
||||||
|
|
||||||
**Hardcoded Values:**
|
|
||||||
- Bank: `'Vietcombank (VCB)'`
|
|
||||||
- Account Number: `'0123456789'`
|
|
||||||
- Account Holder: `'KHACH SAN ABC'`
|
|
||||||
|
|
||||||
**Recommendation:** Add bank details to Settings and make them configurable from admin.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 Summary Statistics
|
|
||||||
|
|
||||||
| Category | Total | Uses Settings | Hardcoded Fallbacks | Hardcoded Values |
|
|
||||||
|----------|-------|---------------|---------------------|------------------|
|
|
||||||
| **Email/Phone/Address** | 15+ pages | 12 pages | 3 pages | 0 pages |
|
|
||||||
| **Currency** | 12+ pages | 12 pages | 0 pages | 0 pages |
|
|
||||||
| **Bank Details** | 1 page | 0 pages | 0 pages | 1 page |
|
|
||||||
| **Logo** | 2 components | 2 components | 0 | 0 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 Issues Found
|
|
||||||
|
|
||||||
### High Priority
|
|
||||||
1. **PaymentConfirmationPage** - Bank details are hardcoded
|
|
||||||
- Should be added to Settings
|
|
||||||
- Should be configurable from admin
|
|
||||||
|
|
||||||
### Medium Priority
|
|
||||||
2. **Header Component** - Hardcoded fallback phone/email
|
|
||||||
- Should use empty string or null instead of fake values
|
|
||||||
|
|
||||||
3. **ContactPage** - Hardcoded fallback text instead of actual values
|
|
||||||
- Should show actual phone/email/address or nothing
|
|
||||||
|
|
||||||
4. **PaymentResultPage** - Hardcoded fallback support contact
|
|
||||||
- Should use settings or show nothing
|
|
||||||
|
|
||||||
### Low Priority
|
|
||||||
5. **Auth Components** - Placeholder text in forms (acceptable for UX)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✅ What's Working Well
|
|
||||||
|
|
||||||
1. **Currency System** - Fully centralized via `CurrencyContext`
|
|
||||||
- All pages use `useFormatCurrency()` hook
|
|
||||||
- Currency stored in localStorage
|
|
||||||
- Falls back to 'VND' if not set
|
|
||||||
|
|
||||||
2. **Footer Component** - Perfect implementation
|
|
||||||
- Uses settings without hardcoded fallbacks
|
|
||||||
- Shows nothing if settings not available
|
|
||||||
|
|
||||||
3. **AboutPage** - Perfect implementation
|
|
||||||
- Uses settings without hardcoded fallbacks
|
|
||||||
|
|
||||||
4. **Policy Pages** - Good implementation
|
|
||||||
- Only show email link if available
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🛠️ Recommendations
|
|
||||||
|
|
||||||
### Immediate Actions
|
|
||||||
1. **Add Bank Details to Settings**
|
|
||||||
- Add fields: `bank_name`, `bank_account_number`, `bank_account_holder`
|
|
||||||
- Update PaymentConfirmationPage to use settings
|
|
||||||
- Add admin controls for bank details
|
|
||||||
|
|
||||||
2. **Remove Hardcoded Fallbacks**
|
|
||||||
- Header: Remove `'+1 (234) 567-890'` and `'info@luxuryhotel.com'`
|
|
||||||
- ContactPage: Remove fallback text, show actual values or nothing
|
|
||||||
- PaymentResultPage: Remove `'support@hotel.com'` and `'1900 xxxx'`
|
|
||||||
|
|
||||||
### Future Enhancements
|
|
||||||
3. **Currency Settings Integration**
|
|
||||||
- Consider adding default currency to Company Settings
|
|
||||||
- Allow admin to set default currency for the platform
|
|
||||||
|
|
||||||
4. **Settings Validation**
|
|
||||||
- Add validation to ensure critical settings (email, phone) are set
|
|
||||||
- Show warnings in admin if settings are missing
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 Notes
|
|
||||||
|
|
||||||
- Currency is well-implemented via CurrencyContext
|
|
||||||
- Most pages correctly use `useCompanySettings()` hook
|
|
||||||
- Main issues are hardcoded fallback values that should be removed
|
|
||||||
- Bank details need to be added to settings system
|
|
||||||
- Placeholder text in form fields is acceptable and doesn't need changes
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user