This commit is contained in:
Iliyan Angelov
2025-12-07 20:36:17 +02:00
parent 876af48145
commit b818d645a9
91 changed files with 3692 additions and 4501 deletions

View File

@@ -1846,6 +1846,180 @@ async def upload_company_favicon(
logger.error(f"Error uploading favicon: {e}", exc_info=True) logger.error(f"Error uploading favicon: {e}", exc_info=True)
raise HTTPException(status_code=500, detail=str(e)) 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") @router.get("/recaptcha")
async def get_recaptcha_settings( async def get_recaptcha_settings(
db: Session = Depends(get_db) db: Session = Depends(get_db)

View File

@@ -12,6 +12,7 @@ import { LoadingProvider, useNavigationLoading, useLoading } from './shared/cont
import { CookieConsentProvider } from './shared/contexts/CookieConsentContext'; import { CookieConsentProvider } from './shared/contexts/CookieConsentContext';
import { CurrencyProvider } from './features/payments/contexts/CurrencyContext'; import { CurrencyProvider } from './features/payments/contexts/CurrencyContext';
import { CompanySettingsProvider } from './shared/contexts/CompanySettingsContext'; import { CompanySettingsProvider } from './shared/contexts/CompanySettingsContext';
import { ThemeProvider } from './shared/contexts/ThemeContext';
import { AuthModalProvider } from './features/auth/contexts/AuthModalContext'; import { AuthModalProvider } from './features/auth/contexts/AuthModalContext';
import { AntibotProvider } from './features/auth/contexts/AntibotContext'; import { AntibotProvider } from './features/auth/contexts/AntibotContext';
import { RoomProvider } from './features/rooms/contexts/RoomContext'; 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 AdminBookingManagementPage = lazy(() => import('./pages/admin/BookingManagementPage'));
const PageContentDashboardPage = lazy(() => import('./pages/admin/PageContentDashboard')); const PageContentDashboardPage = lazy(() => import('./pages/admin/PageContentDashboard'));
const AnalyticsDashboardPage = lazy(() => import('./pages/admin/AnalyticsDashboardPage')); 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 SettingsPage = lazy(() => import('./pages/admin/SettingsPage'));
const TaskManagementPage = lazy(() => import('./pages/admin/TaskManagementPage')); const TaskManagementPage = lazy(() => import('./pages/admin/TaskManagementPage'));
const WorkflowManagementPage = lazy(() => import('./pages/admin/WorkflowManagementPage')); const WorkflowManagementPage = lazy(() => import('./pages/admin/WorkflowManagementPage'));
@@ -249,7 +250,8 @@ function App() {
<LoadingProvider> <LoadingProvider>
<CookieConsentProvider> <CookieConsentProvider>
<CurrencyProvider> <CurrencyProvider>
<CompanySettingsProvider> <ThemeProvider>
<CompanySettingsProvider>
<AntibotProvider> <AntibotProvider>
<AuthModalProvider> <AuthModalProvider>
<StepUpAuthProvider> <StepUpAuthProvider>
@@ -600,8 +602,8 @@ function App() {
element={<UserManagementPage />} element={<UserManagementPage />}
/> />
<Route <Route
path="business" path="promotions"
element={<BusinessDashboardPage />} element={<PromotionsManagementPage />}
/> />
<Route <Route
path="reception" path="reception"
@@ -974,6 +976,7 @@ function App() {
</AuthModalProvider> </AuthModalProvider>
</AntibotProvider> </AntibotProvider>
</CompanySettingsProvider> </CompanySettingsProvider>
</ThemeProvider>
</CurrencyProvider> </CurrencyProvider>
</CookieConsentProvider> </CookieConsentProvider>
</LoadingProvider> </LoadingProvider>

View File

@@ -93,7 +93,7 @@ const ForgotPasswordModal: React.FC = () => {
<div className="absolute inset-0 bg-black/60 backdrop-blur-sm" /> <div className="absolute inset-0 bg-black/60 backdrop-blur-sm" />
{/* Modal */} {/* Modal */}
<div className="relative w-full max-w-md max-h-[95vh] overflow-y-auto bg-gradient-to-br from-gray-50 via-white to-gray-50 rounded-lg shadow-2xl border border-[#d4af37]/20"> <div className="relative w-full max-w-md max-h-[95vh] overflow-y-auto bg-gradient-to-br from-gray-50 via-white to-gray-50 rounded-lg shadow-2xl border border-[var(--luxury-gold)]/20">
{/* Close button */} {/* Close button */}
<button <button
onClick={closeModal} onClick={closeModal}
@@ -117,13 +117,13 @@ const ForgotPasswordModal: React.FC = () => {
style={{ filter: 'drop-shadow(0 4px 6px rgba(0,0,0,0.1))' }} style={{ filter: 'drop-shadow(0 4px 6px rgba(0,0,0,0.1))' }}
/> />
) : ( ) : (
<div className="relative p-2.5 sm:p-3 bg-gradient-to-br from-[#d4af37] to-[#c9a227] rounded-full shadow-lg shadow-[#d4af37]/30"> <div className="relative p-2.5 sm:p-3 bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] rounded-full shadow-lg shadow-[var(--luxury-gold)]/30">
<Mail className="w-6 h-6 sm:w-8 sm:h-8 text-[#0f0f0f] relative z-10" /> <Mail className="w-6 h-6 sm:w-8 sm:h-8 text-[#0f0f0f] relative z-10" />
</div> </div>
)} )}
</div> </div>
{settings.company_tagline && ( {settings.company_tagline && (
<p className="text-[10px] sm:text-xs text-[#d4af37] uppercase tracking-[1.5px] sm:tracking-[2px] mb-1 sm:mb-2 font-light"> <p className="text-[10px] sm:text-xs text-[var(--luxury-gold)] uppercase tracking-[1.5px] sm:tracking-[2px] mb-1 sm:mb-2 font-light">
{settings.company_tagline} {settings.company_tagline}
</p> </p>
)} )}
@@ -150,7 +150,7 @@ const ForgotPasswordModal: React.FC = () => {
<p className="text-xs sm:text-sm text-gray-600"> <p className="text-xs sm:text-sm text-gray-600">
We have sent a password reset link to We have sent a password reset link to
</p> </p>
<p className="text-xs sm:text-sm font-medium text-[#d4af37] break-all"> <p className="text-xs sm:text-sm font-medium text-[var(--luxury-gold)] break-all">
{submittedEmail} {submittedEmail}
</p> </p>
</div> </div>
@@ -172,7 +172,7 @@ const ForgotPasswordModal: React.FC = () => {
setIsSuccess(false); setIsSuccess(false);
clearError(); 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"
> >
<Mail className="-ml-1 mr-2 h-4 w-4 sm:h-5 sm:w-5" /> <Mail className="-ml-1 mr-2 h-4 w-4 sm:h-5 sm:w-5" />
Resend Email Resend Email
@@ -180,7 +180,7 @@ const ForgotPasswordModal: React.FC = () => {
<button <button
onClick={() => openModal('login')} onClick={() => openModal('login')}
className="w-full flex items-center justify-center 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="w-full flex items-center justify-center 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"
> >
<ArrowLeft className="-ml-1 mr-2 h-4 w-4 sm:h-5 sm:w-5" /> <ArrowLeft className="-ml-1 mr-2 h-4 w-4 sm:h-5 sm:w-5" />
Back to Login Back to Login
@@ -220,7 +220,7 @@ const ForgotPasswordModal: React.FC = () => {
className={`block w-full pl-9 sm:pl-10 pr-3 py-2.5 sm:py-3 border rounded-lg focus:outline-none focus:ring-2 transition-colors text-sm sm:text-base luxury-input ${ className={`block w-full pl-9 sm:pl-10 pr-3 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.email errors.email
? 'border-red-300 focus:ring-red-500' ? 'border-red-300 focus:ring-red-500'
: 'border-gray-300 focus:ring-[#d4af37]' : 'border-gray-300 focus:ring-[var(--luxury-gold)]'
}`} }`}
placeholder="email@example.com" placeholder="email@example.com"
/> />
@@ -235,7 +235,7 @@ const ForgotPasswordModal: React.FC = () => {
<button <button
type="submit" type="submit"
disabled={isLoading} disabled={isLoading}
className="w-full flex items-center justify-center py-2.5 sm:py-3 px-4 border border-transparent rounded-lg shadow-sm 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] disabled:opacity-50 disabled:cursor-not-allowed transition-colors" className="w-full flex items-center justify-center py-2.5 sm:py-3 px-4 border border-transparent rounded-lg shadow-sm 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)] disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
> >
{isLoading ? ( {isLoading ? (
<> <>
@@ -254,7 +254,7 @@ const ForgotPasswordModal: React.FC = () => {
<button <button
type="button" type="button"
onClick={() => openModal('login')} onClick={() => openModal('login')}
className="inline-flex items-center text-xs sm:text-sm font-medium text-[#d4af37] hover:text-[#c9a227] transition-colors" className="inline-flex items-center text-xs sm:text-sm font-medium text-[var(--luxury-gold)] hover:text-[var(--luxury-gold-dark)] transition-colors"
> >
<ArrowLeft className="mr-1 h-3.5 w-3.5 sm:h-4 sm:w-4" /> <ArrowLeft className="mr-1 h-3.5 w-3.5 sm:h-4 sm:w-4" />
Back to Login Back to Login
@@ -269,7 +269,7 @@ const ForgotPasswordModal: React.FC = () => {
Don't have an account?{' '} Don't have an account?{' '}
<button <button
onClick={() => openModal('register')} onClick={() => openModal('register')}
className="font-medium text-[#d4af37] hover:text-[#c9a227] transition-colors" className="font-medium text-[var(--luxury-gold)] hover:text-[var(--luxury-gold-dark)] transition-colors"
> >
Register now Register now
</button> </button>
@@ -286,7 +286,7 @@ const ForgotPasswordModal: React.FC = () => {
If you're having trouble resetting your password, please contact our support team via email{' '} If you're having trouble resetting your password, please contact our support team via email{' '}
<a <a
href={`mailto:${supportEmail}`} href={`mailto:${supportEmail}`}
className="text-[#d4af37] hover:underline break-all" className="text-[var(--luxury-gold)] hover:underline break-all"
> >
{supportEmail} {supportEmail}
</a> </a>
@@ -295,7 +295,7 @@ const ForgotPasswordModal: React.FC = () => {
{' '}or hotline{' '} {' '}or hotline{' '}
<a <a
href={`tel:${supportPhone.replace(/\s+/g, '').replace(/[()]/g, '')}`} href={`tel:${supportPhone.replace(/\s+/g, '').replace(/[()]/g, '')}`}
className="text-[#d4af37] hover:underline" className="text-[var(--luxury-gold)] hover:underline"
> >
{supportPhone} {supportPhone}
</a> </a>

View File

@@ -376,7 +376,7 @@ const LoginModal: React.FC = () => {
<div className="absolute inset-0 bg-black/60 backdrop-blur-sm" /> <div className="absolute inset-0 bg-black/60 backdrop-blur-sm" />
{/* Modal */} {/* Modal */}
<div className="relative w-full max-w-md max-h-[95vh] overflow-y-auto bg-gradient-to-br from-gray-50 via-white to-gray-50 rounded-lg shadow-2xl border border-[#d4af37]/20"> <div className="relative w-full max-w-md max-h-[95vh] overflow-y-auto bg-gradient-to-br from-gray-50 via-white to-gray-50 rounded-lg shadow-2xl border border-[var(--luxury-gold)]/20">
{/* Close button */} {/* Close button */}
<button <button
onClick={closeModal} onClick={closeModal}
@@ -400,13 +400,13 @@ const LoginModal: React.FC = () => {
style={{ filter: 'drop-shadow(0 4px 6px rgba(0,0,0,0.1))' }} style={{ filter: 'drop-shadow(0 4px 6px rgba(0,0,0,0.1))' }}
/> />
) : ( ) : (
<div className="relative p-2.5 sm:p-3 bg-gradient-to-br from-[#d4af37] to-[#c9a227] rounded-full shadow-lg shadow-[#d4af37]/30"> <div className="relative p-2.5 sm:p-3 bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] rounded-full shadow-lg shadow-[var(--luxury-gold)]/30">
<Shield className="w-6 h-6 sm:w-8 sm:h-8 text-[#0f0f0f] relative z-10" /> <Shield className="w-6 h-6 sm:w-8 sm:h-8 text-[#0f0f0f] relative z-10" />
</div> </div>
)} )}
</div> </div>
{settings.company_tagline && ( {settings.company_tagline && (
<p className="text-[10px] sm:text-xs text-[#d4af37] uppercase tracking-[1.5px] sm:tracking-[2px] mb-1 sm:mb-2 font-light"> <p className="text-[10px] sm:text-xs text-[var(--luxury-gold)] uppercase tracking-[1.5px] sm:tracking-[2px] mb-1 sm:mb-2 font-light">
{settings.company_tagline} {settings.company_tagline}
</p> </p>
)} )}
@@ -555,7 +555,7 @@ const LoginModal: React.FC = () => {
<button <button
type="button" type="button"
onClick={() => setShowPassword(!showPassword)} onClick={() => setShowPassword(!showPassword)}
className="absolute inset-y-0 right-0 pr-3 flex items-center transition-colors hover:text-[#d4af37]" className="absolute inset-y-0 right-0 pr-3 flex items-center transition-colors hover:text-[var(--luxury-gold)]"
> >
{showPassword ? ( {showPassword ? (
<EyeOff className="h-4 w-4 sm:h-5 sm:w-5 text-gray-400" /> <EyeOff className="h-4 w-4 sm:h-5 sm:w-5 text-gray-400" />
@@ -577,7 +577,7 @@ const LoginModal: React.FC = () => {
{...register('rememberMe')} {...register('rememberMe')}
id="rememberMe" id="rememberMe"
type="checkbox" type="checkbox"
className="h-4 w-4 text-[#d4af37] focus:ring-[#d4af37]/50 border-gray-300 rounded-sm cursor-pointer accent-[#d4af37]" className="h-4 w-4 text-[var(--luxury-gold)] focus:ring-[var(--luxury-gold)]/50 border-gray-300 rounded-sm cursor-pointer accent-[var(--luxury-gold)]"
/> />
<label htmlFor="rememberMe" className="ml-2 block text-xs sm:text-sm text-gray-700 cursor-pointer font-light tracking-wide"> <label htmlFor="rememberMe" className="ml-2 block text-xs sm:text-sm text-gray-700 cursor-pointer font-light tracking-wide">
Remember me Remember me
@@ -587,7 +587,7 @@ const LoginModal: React.FC = () => {
<button <button
type="button" type="button"
onClick={() => openModal('forgot-password')} onClick={() => openModal('forgot-password')}
className="text-xs sm:text-sm font-medium text-[#d4af37] hover:text-[#c9a227] transition-colors tracking-wide" className="text-xs sm:text-sm font-medium text-[var(--luxury-gold)] hover:text-[var(--luxury-gold-dark)] transition-colors tracking-wide"
> >
Forgot password? Forgot password?
</button> </button>
@@ -633,7 +633,7 @@ const LoginModal: React.FC = () => {
Don't have an account?{' '} Don't have an account?{' '}
<button <button
onClick={() => openModal('register')} onClick={() => openModal('register')}
className="font-medium text-[#d4af37] hover:text-[#c9a227] transition-colors" className="font-medium text-[var(--luxury-gold)] hover:text-[var(--luxury-gold-dark)] transition-colors"
> >
Register now Register now
</button> </button>

View File

@@ -15,11 +15,11 @@ import HoneypotField from '../../../shared/components/HoneypotField';
const PasswordRequirement: React.FC<{ met: boolean; text: string }> = ({ met, text }) => ( 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"> <div className="flex items-center gap-1.5 sm:gap-2 text-[10px] sm:text-xs font-light">
{met ? ( {met ? (
<CheckCircle2 className="h-3.5 w-3.5 sm:h-4 sm:w-4 text-[#d4af37] flex-shrink-0" /> <CheckCircle2 className="h-3.5 w-3.5 sm:h-4 sm:w-4 text-[var(--luxury-gold)] flex-shrink-0" />
) : ( ) : (
<XCircle className="h-3.5 w-3.5 sm:h-4 sm:w-4 text-gray-300 flex-shrink-0" /> <XCircle className="h-3.5 w-3.5 sm:h-4 sm:w-4 text-gray-300 flex-shrink-0" />
)} )}
<span className={met ? 'text-[#c9a227] font-medium' : 'text-gray-500'}> <span className={met ? 'text-[var(--luxury-gold-dark)] font-medium' : 'text-gray-500'}>
{text} {text}
</span> </span>
</div> </div>
@@ -165,7 +165,7 @@ const RegisterModal: React.FC = () => {
<div className="absolute inset-0 bg-black/60 backdrop-blur-sm" /> <div className="absolute inset-0 bg-black/60 backdrop-blur-sm" />
{/* Modal */} {/* Modal */}
<div className="relative w-full max-w-md max-h-[95vh] overflow-y-auto bg-gradient-to-br from-gray-50 via-white to-gray-50 rounded-lg shadow-2xl border border-[#d4af37]/20"> <div className="relative w-full max-w-md max-h-[95vh] overflow-y-auto bg-gradient-to-br from-gray-50 via-white to-gray-50 rounded-lg shadow-2xl border border-[var(--luxury-gold)]/20">
{/* Close button */} {/* Close button */}
<button <button
onClick={closeModal} onClick={closeModal}
@@ -189,13 +189,13 @@ const RegisterModal: React.FC = () => {
style={{ filter: 'drop-shadow(0 4px 6px rgba(0,0,0,0.1))' }} style={{ filter: 'drop-shadow(0 4px 6px rgba(0,0,0,0.1))' }}
/> />
) : ( ) : (
<div className="relative p-2.5 sm:p-3 bg-gradient-to-br from-[#d4af37] to-[#c9a227] rounded-full shadow-lg shadow-[#d4af37]/30"> <div className="relative p-2.5 sm:p-3 bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] rounded-full shadow-lg shadow-[var(--luxury-gold)]/30">
<UserPlus className="w-6 h-6 sm:w-8 sm:h-8 text-[#0f0f0f] relative z-10" /> <UserPlus className="w-6 h-6 sm:w-8 sm:h-8 text-[#0f0f0f] relative z-10" />
</div> </div>
)} )}
</div> </div>
{settings.company_tagline && ( {settings.company_tagline && (
<p className="text-[10px] sm:text-xs text-[#d4af37] uppercase tracking-[1.5px] sm:tracking-[2px] mb-1 sm:mb-2 font-light"> <p className="text-[10px] sm:text-xs text-[var(--luxury-gold)] uppercase tracking-[1.5px] sm:tracking-[2px] mb-1 sm:mb-2 font-light">
{settings.company_tagline} {settings.company_tagline}
</p> </p>
)} )}
@@ -322,7 +322,7 @@ const RegisterModal: React.FC = () => {
<button <button
type="button" type="button"
onClick={() => setShowPassword(!showPassword)} onClick={() => setShowPassword(!showPassword)}
className="absolute inset-y-0 right-0 pr-3 flex items-center transition-colors hover:text-[#d4af37]" className="absolute inset-y-0 right-0 pr-3 flex items-center transition-colors hover:text-[var(--luxury-gold)]"
> >
{showPassword ? ( {showPassword ? (
<EyeOff className="h-4 w-4 sm:h-5 sm:w-5 text-gray-400" /> <EyeOff className="h-4 w-4 sm:h-5 sm:w-5 text-gray-400" />
@@ -344,7 +344,7 @@ const RegisterModal: React.FC = () => {
<div <div
className={`h-full transition-all duration-300 ${ className={`h-full transition-all duration-300 ${
passwordStrength.strength >= 4 passwordStrength.strength >= 4
? 'bg-[#d4af37]' ? 'bg-[var(--luxury-gold)]'
: passwordStrength.strength >= 3 : passwordStrength.strength >= 3
? 'bg-yellow-500' ? 'bg-yellow-500'
: 'bg-red-500' : 'bg-red-500'
@@ -389,7 +389,7 @@ const RegisterModal: React.FC = () => {
<button <button
type="button" type="button"
onClick={() => setShowConfirmPassword(!showConfirmPassword)} onClick={() => setShowConfirmPassword(!showConfirmPassword)}
className="absolute inset-y-0 right-0 pr-3 flex items-center transition-colors hover:text-[#d4af37]" className="absolute inset-y-0 right-0 pr-3 flex items-center transition-colors hover:text-[var(--luxury-gold)]"
> >
{showConfirmPassword ? ( {showConfirmPassword ? (
<EyeOff className="h-4 w-4 sm:h-5 sm:w-5 text-gray-400" /> <EyeOff className="h-4 w-4 sm:h-5 sm:w-5 text-gray-400" />
@@ -443,7 +443,7 @@ const RegisterModal: React.FC = () => {
Already have an account?{' '} Already have an account?{' '}
<button <button
onClick={() => openModal('login')} onClick={() => openModal('login')}
className="font-medium text-[#d4af37] hover:text-[#c9a227] transition-colors" className="font-medium text-[var(--luxury-gold)] hover:text-[var(--luxury-gold-dark)] transition-colors"
> >
Login now Login now
</button> </button>

View File

@@ -132,7 +132,7 @@ const ResetPasswordModal: React.FC<ResetPasswordModalProps> = ({ token }) => {
<div className="absolute inset-0 bg-black/60 backdrop-blur-sm" /> <div className="absolute inset-0 bg-black/60 backdrop-blur-sm" />
{/* Modal */} {/* Modal */}
<div className="relative w-full max-w-md max-h-[95vh] overflow-y-auto bg-gradient-to-br from-gray-50 via-white to-gray-50 rounded-lg shadow-2xl border border-[#d4af37]/20"> <div className="relative w-full max-w-md max-h-[95vh] overflow-y-auto bg-gradient-to-br from-gray-50 via-white to-gray-50 rounded-lg shadow-2xl border border-[var(--luxury-gold)]/20">
{/* Close button */} {/* Close button */}
{!isSuccess && ( {!isSuccess && (
<button <button
@@ -158,13 +158,13 @@ const ResetPasswordModal: React.FC<ResetPasswordModalProps> = ({ token }) => {
style={{ filter: 'drop-shadow(0 4px 6px rgba(0,0,0,0.1))' }} style={{ filter: 'drop-shadow(0 4px 6px rgba(0,0,0,0.1))' }}
/> />
) : ( ) : (
<div className="relative p-2.5 sm:p-3 bg-gradient-to-br from-[#d4af37] to-[#c9a227] rounded-full shadow-lg shadow-[#d4af37]/30"> <div className="relative p-2.5 sm:p-3 bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] rounded-full shadow-lg shadow-[var(--luxury-gold)]/30">
<KeyRound className="w-6 h-6 sm:w-8 sm:h-8 text-[#0f0f0f] relative z-10" /> <KeyRound className="w-6 h-6 sm:w-8 sm:h-8 text-[#0f0f0f] relative z-10" />
</div> </div>
)} )}
</div> </div>
{settings.company_tagline && ( {settings.company_tagline && (
<p className="text-[10px] sm:text-xs text-[#d4af37] uppercase tracking-[1.5px] sm:tracking-[2px] mb-1 sm:mb-2 font-light"> <p className="text-[10px] sm:text-xs text-[var(--luxury-gold)] uppercase tracking-[1.5px] sm:tracking-[2px] mb-1 sm:mb-2 font-light">
{settings.company_tagline} {settings.company_tagline}
</p> </p>
)} )}
@@ -203,7 +203,7 @@ const ResetPasswordModal: React.FC<ResetPasswordModalProps> = ({ token }) => {
Redirecting to login... Redirecting to login...
</p> </p>
<div className="mt-2 flex justify-center"> <div className="mt-2 flex justify-center">
<Loader2 className="animate-spin h-4 w-4 sm:h-5 sm:w-5 text-[#d4af37]" /> <Loader2 className="animate-spin h-4 w-4 sm:h-5 sm:w-5 text-[var(--luxury-gold)]" />
</div> </div>
</div> </div>
@@ -212,7 +212,7 @@ const ResetPasswordModal: React.FC<ResetPasswordModalProps> = ({ token }) => {
closeModal(); closeModal();
openModal('login'); 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"
> >
<KeyRound className="-ml-1 mr-2 h-4 w-4 sm:h-5 sm:w-5" /> <KeyRound className="-ml-1 mr-2 h-4 w-4 sm:h-5 sm:w-5" />
Login Now Login Now
@@ -267,7 +267,7 @@ const ResetPasswordModal: React.FC<ResetPasswordModalProps> = ({ 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 ${ 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 errors.password
? 'border-red-300 focus:ring-red-500' ? 'border-red-300 focus:ring-red-500'
: 'border-gray-300 focus:ring-[#d4af37]' : 'border-gray-300 focus:ring-[var(--luxury-gold)]'
}`} }`}
placeholder="••••••••" placeholder="••••••••"
/> />
@@ -330,7 +330,7 @@ const ResetPasswordModal: React.FC<ResetPasswordModalProps> = ({ 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 ${ 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 errors.confirmPassword
? 'border-red-300 focus:ring-red-500' ? 'border-red-300 focus:ring-red-500'
: 'border-gray-300 focus:ring-[#d4af37]' : 'border-gray-300 focus:ring-[var(--luxury-gold)]'
}`} }`}
placeholder="••••••••" placeholder="••••••••"
/> />
@@ -356,7 +356,7 @@ const ResetPasswordModal: React.FC<ResetPasswordModalProps> = ({ token }) => {
<button <button
type="submit" type="submit"
disabled={isLoading} disabled={isLoading}
className="w-full flex items-center justify-center py-2.5 sm:py-3 px-4 border border-transparent rounded-lg shadow-sm 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] disabled:opacity-50 disabled:cursor-not-allowed transition-colors" className="w-full flex items-center justify-center py-2.5 sm:py-3 px-4 border border-transparent rounded-lg shadow-sm 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)] disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
> >
{isLoading ? ( {isLoading ? (
<> <>
@@ -375,7 +375,7 @@ const ResetPasswordModal: React.FC<ResetPasswordModalProps> = ({ token }) => {
<button <button
type="button" type="button"
onClick={() => openModal('login')} onClick={() => openModal('login')}
className="text-xs sm:text-sm font-medium text-[#d4af37] hover:text-[#c9a227] transition-colors" className="text-xs sm:text-sm font-medium text-[var(--luxury-gold)] hover:text-[var(--luxury-gold-dark)] transition-colors"
> >
Back to Login Back to Login
</button> </button>

View File

@@ -345,7 +345,7 @@ const HousekeepingLoginPage: React.FC = () => {
<div className="min-h-screen bg-gradient-to-br from-gray-50 via-white to-gray-50 flex items-center justify-center p-4"> <div className="min-h-screen bg-gradient-to-br from-gray-50 via-white to-gray-50 flex items-center justify-center p-4">
<div className="w-full max-w-md"> <div className="w-full max-w-md">
<div className="bg-white rounded-2xl shadow-2xl border border-gray-200/50 overflow-hidden"> <div className="bg-white rounded-2xl shadow-2xl border border-gray-200/50 overflow-hidden">
<div className="bg-gradient-to-r from-[#d4af37] via-[#c9a227] to-[#d4af37] p-6 sm:p-8 text-center"> <div className="bg-gradient-to-r from-[var(--luxury-gold)] via-[var(--luxury-gold-dark)] to-[var(--luxury-gold)] p-6 sm:p-8 text-center">
<div className="flex justify-center mb-4"> <div className="flex justify-center mb-4">
{settings.company_logo_url ? ( {settings.company_logo_url ? (
<img <img
@@ -389,7 +389,7 @@ const HousekeepingLoginPage: React.FC = () => {
autoComplete="one-time-code" autoComplete="one-time-code"
maxLength={8} maxLength={8}
className={`w-full pl-10 pr-4 py-3 border rounded-lg text-center tracking-widest ${ 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" placeholder="000000"
/> />
@@ -402,7 +402,7 @@ const HousekeepingLoginPage: React.FC = () => {
<button <button
type="submit" type="submit"
disabled={isLoading} disabled={isLoading}
className="w-full bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-white py-3 px-4 rounded-lg font-semibold hover:from-[#f5d76e] hover:to-[#d4af37] transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center" className="w-full bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-white py-3 px-4 rounded-lg font-semibold hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center"
> >
{isLoading ? ( {isLoading ? (
<> <>
@@ -461,7 +461,7 @@ const HousekeepingLoginPage: React.FC = () => {
type="email" type="email"
autoComplete="email" autoComplete="email"
className={`w-full pl-10 pr-4 py-3 border rounded-lg ${ className={`w-full pl-10 pr-4 py-3 border rounded-lg ${
errors.email ? 'border-red-300 focus:ring-red-500' : 'border-gray-300 focus:ring-[#d4af37]' errors.email ? 'border-red-300 focus:ring-red-500' : 'border-gray-300 focus:ring-[var(--luxury-gold)]'
}`} }`}
placeholder="email@example.com" placeholder="email@example.com"
/> />
@@ -485,7 +485,7 @@ const HousekeepingLoginPage: React.FC = () => {
type={showPassword ? 'text' : 'password'} type={showPassword ? 'text' : 'password'}
autoComplete="current-password" autoComplete="current-password"
className={`w-full pl-10 pr-10 py-3 border rounded-lg ${ className={`w-full pl-10 pr-10 py-3 border rounded-lg ${
errors.password ? 'border-red-300 focus:ring-red-500' : 'border-gray-300 focus:ring-[#d4af37]' errors.password ? 'border-red-300 focus:ring-red-500' : 'border-gray-300 focus:ring-[var(--luxury-gold)]'
}`} }`}
placeholder="••••••••" placeholder="••••••••"
/> />
@@ -511,7 +511,7 @@ const HousekeepingLoginPage: React.FC = () => {
{...register('rememberMe')} {...register('rememberMe')}
id="rememberMe" id="rememberMe"
type="checkbox" type="checkbox"
className="h-4 w-4 text-[#d4af37] focus:ring-[#d4af37] border-gray-300 rounded" className="h-4 w-4 text-[var(--luxury-gold)] focus:ring-[var(--luxury-gold)] border-gray-300 rounded"
/> />
<label htmlFor="rememberMe" className="ml-2 block text-sm text-gray-700"> <label htmlFor="rememberMe" className="ml-2 block text-sm text-gray-700">
Remember me Remember me
@@ -535,7 +535,7 @@ const HousekeepingLoginPage: React.FC = () => {
<button <button
type="submit" type="submit"
disabled={isLoading} disabled={isLoading}
className="w-full bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-white py-3 px-4 rounded-lg font-semibold hover:from-[#f5d76e] hover:to-[#d4af37] transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center" className="w-full bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-white py-3 px-4 rounded-lg font-semibold hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center"
> >
{isLoading ? ( {isLoading ? (
<> <>

View File

@@ -44,19 +44,19 @@ const InvoiceInfoModal: React.FC<InvoiceInfoModalProps> = ({
className="fixed inset-0 bg-black/90 backdrop-blur-sm" className="fixed inset-0 bg-black/90 backdrop-blur-sm"
onClick={onClose} onClick={onClose}
/> />
<div className="relative w-full max-w-lg max-h-[95vh] bg-gradient-to-br from-[#0a0a0a] via-[#1a1a1a] to-[#0a0a0a] rounded-xl sm:rounded-2xl border border-[#d4af37]/30 shadow-2xl shadow-[#d4af37]/20 overflow-hidden flex flex-col"> <div className="relative w-full max-w-lg max-h-[95vh] bg-gradient-to-br from-[#0a0a0a] via-[#1a1a1a] to-[#0a0a0a] rounded-xl sm:rounded-2xl border border-[var(--luxury-gold)]/30 shadow-2xl shadow-[var(--luxury-gold)]/20 overflow-hidden flex flex-col">
{/* Header */} {/* Header */}
<div className="px-3 sm:px-4 md:px-6 py-3 sm:py-4 border-b border-[#d4af37]/20 bg-gradient-to-r from-[#1a1a1a] to-[#0a0a0a] flex-shrink-0"> <div className="px-3 sm:px-4 md:px-6 py-3 sm:py-4 border-b border-[var(--luxury-gold)]/20 bg-gradient-to-r from-[#1a1a1a] to-[#0a0a0a] flex-shrink-0">
<div className="flex items-center justify-between gap-2"> <div className="flex items-center justify-between gap-2">
<div className="flex items-center gap-2 min-w-0 flex-1"> <div className="flex items-center gap-2 min-w-0 flex-1">
<Building2 className="w-4 h-4 sm:w-5 sm:h-5 text-[#d4af37] flex-shrink-0" /> <Building2 className="w-4 h-4 sm:w-5 sm:h-5 text-[var(--luxury-gold)] flex-shrink-0" />
<h2 className="text-base sm:text-lg md:text-xl font-serif font-bold text-white tracking-tight truncate"> <h2 className="text-base sm:text-lg md:text-xl font-serif font-bold text-white tracking-tight truncate">
Invoice Information Invoice Information
</h2> </h2>
</div> </div>
<button <button
onClick={onClose} onClick={onClose}
className="p-1.5 sm:p-2 hover:bg-[#d4af37]/10 rounded-lg transition-colors text-gray-400 hover:text-white flex-shrink-0" className="p-1.5 sm:p-2 hover:bg-[var(--luxury-gold)]/10 rounded-lg transition-colors text-gray-400 hover:text-white flex-shrink-0"
> >
<X className="w-4 h-4 sm:w-5 sm:h-5" /> <X className="w-4 h-4 sm:w-5 sm:h-5" />
</button> </button>
@@ -73,7 +73,7 @@ const InvoiceInfoModal: React.FC<InvoiceInfoModalProps> = ({
<input <input
{...register('company_name')} {...register('company_name')}
type="text" type="text"
className="w-full px-3 py-2 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white text-sm focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37]" className="w-full px-3 py-2 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white text-sm focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)]"
placeholder="Company Name" placeholder="Company Name"
/> />
</div> </div>
@@ -85,7 +85,7 @@ const InvoiceInfoModal: React.FC<InvoiceInfoModalProps> = ({
<textarea <textarea
{...register('company_address')} {...register('company_address')}
rows={3} rows={3}
className="w-full px-3 py-2 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white text-sm focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37] resize-none" className="w-full px-3 py-2 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white text-sm focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)] resize-none"
placeholder="Company Address" placeholder="Company Address"
/> />
</div> </div>
@@ -98,7 +98,7 @@ const InvoiceInfoModal: React.FC<InvoiceInfoModalProps> = ({
<input <input
{...register('company_tax_id')} {...register('company_tax_id')}
type="text" type="text"
className="w-full px-3 py-2 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white text-sm focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37]" className="w-full px-3 py-2 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white text-sm focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)]"
placeholder="Tax ID" placeholder="Tax ID"
/> />
</div> </div>
@@ -110,7 +110,7 @@ const InvoiceInfoModal: React.FC<InvoiceInfoModalProps> = ({
<input <input
{...register('customer_tax_id')} {...register('customer_tax_id')}
type="text" type="text"
className="w-full px-3 py-2 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white text-sm focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37]" className="w-full px-3 py-2 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white text-sm focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)]"
placeholder="Tax ID" placeholder="Tax ID"
/> />
</div> </div>
@@ -118,7 +118,7 @@ const InvoiceInfoModal: React.FC<InvoiceInfoModalProps> = ({
</div> </div>
{/* Footer */} {/* Footer */}
<div className="mt-4 sm:mt-6 flex items-center justify-end gap-2 sm:gap-3 pt-3 sm:pt-4 border-t border-[#d4af37]/20 flex-shrink-0"> <div className="mt-4 sm:mt-6 flex items-center justify-end gap-2 sm:gap-3 pt-3 sm:pt-4 border-t border-[var(--luxury-gold)]/20 flex-shrink-0">
<button <button
type="button" type="button"
onClick={onClose} onClick={onClose}
@@ -128,7 +128,7 @@ const InvoiceInfoModal: React.FC<InvoiceInfoModalProps> = ({
</button> </button>
<button <button
type="submit" type="submit"
className="px-4 sm:px-6 py-2 bg-[#d4af37] text-black font-semibold rounded-lg hover:bg-[#c9a227] transition-all flex items-center gap-1.5 sm:gap-2 text-sm sm:text-base min-h-[44px]" className="px-4 sm:px-6 py-2 bg-[var(--luxury-gold)] text-black font-semibold rounded-lg hover:bg-[var(--luxury-gold-dark)] transition-all flex items-center gap-1.5 sm:gap-2 text-sm sm:text-base min-h-[44px]"
> >
<Save className="w-3.5 h-3.5 sm:w-4 sm:h-4" /> <Save className="w-3.5 h-3.5 sm:w-4 sm:h-4" />
<span>Save</span> <span>Save</span>

View File

@@ -514,9 +514,9 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
className="fixed inset-0 bg-black/80 backdrop-blur-sm" className="fixed inset-0 bg-black/80 backdrop-blur-sm"
onClick={onClose} onClick={onClose}
/> />
<div className="relative w-full max-w-4xl max-h-[95vh] bg-gradient-to-br from-[#0a0a0a] via-[#1a1a1a] to-[#0a0a0a] rounded-xl sm:rounded-2xl border border-[#d4af37]/30 shadow-2xl shadow-[#d4af37]/20 overflow-hidden flex flex-col"> <div className="relative w-full max-w-4xl max-h-[95vh] bg-gradient-to-br from-[#0a0a0a] via-[#1a1a1a] to-[#0a0a0a] rounded-xl sm:rounded-2xl border border-[var(--luxury-gold)]/30 shadow-2xl shadow-[var(--luxury-gold)]/20 overflow-hidden flex flex-col">
{/* Header */} {/* Header */}
<div className="relative px-3 sm:px-4 md:px-6 py-3 sm:py-4 border-b border-[#d4af37]/20 bg-gradient-to-r from-[#1a1a1a] to-[#0a0a0a] flex-shrink-0"> <div className="relative px-3 sm:px-4 md:px-6 py-3 sm:py-4 border-b border-[var(--luxury-gold)]/20 bg-gradient-to-r from-[#1a1a1a] to-[#0a0a0a] flex-shrink-0">
<div className="flex items-center justify-between gap-2"> <div className="flex items-center justify-between gap-2">
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
<h2 className="text-base sm:text-lg md:text-xl lg:text-2xl font-serif font-bold text-white tracking-tight truncate"> <h2 className="text-base sm:text-lg md:text-xl lg:text-2xl font-serif font-bold text-white tracking-tight truncate">
@@ -528,7 +528,7 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
</div> </div>
<button <button
onClick={onClose} onClick={onClose}
className="p-1.5 sm:p-2 hover:bg-[#d4af37]/10 rounded-lg transition-colors text-gray-400 hover:text-white flex-shrink-0" className="p-1.5 sm:p-2 hover:bg-[var(--luxury-gold)]/10 rounded-lg transition-colors text-gray-400 hover:text-white flex-shrink-0"
> >
<X className="w-4 h-4 sm:w-5 sm:h-5" /> <X className="w-4 h-4 sm:w-5 sm:h-5" />
</button> </button>
@@ -545,7 +545,7 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
<div <div
className={`flex items-center justify-center w-6 h-6 sm:w-7 sm:h-7 md:w-8 md:h-8 rounded-full border-2 transition-all flex-shrink-0 ${ className={`flex items-center justify-center w-6 h-6 sm:w-7 sm:h-7 md:w-8 md:h-8 rounded-full border-2 transition-all flex-shrink-0 ${
isActive isActive
? 'bg-[#d4af37] border-[#d4af37] text-black' ? 'bg-[var(--luxury-gold)] border-[var(--luxury-gold)] text-black'
: isCompleted : isCompleted
? 'bg-green-500/20 border-green-500 text-green-400' ? 'bg-green-500/20 border-green-500 text-green-400'
: 'bg-transparent border-gray-600 text-gray-500' : 'bg-transparent border-gray-600 text-gray-500'
@@ -561,7 +561,7 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
</div> </div>
<span <span
className={`ml-1 sm:ml-2 text-[10px] sm:text-xs font-medium hidden md:block truncate ${ className={`ml-1 sm:ml-2 text-[10px] sm:text-xs font-medium hidden md:block truncate ${
isActive ? 'text-[#d4af37]' : isCompleted ? 'text-green-400' : 'text-gray-500' isActive ? 'text-[var(--luxury-gold)]' : isCompleted ? 'text-green-400' : 'text-gray-500'
}`} }`}
> >
{step.label} {step.label}
@@ -585,7 +585,7 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
<div className="h-full overflow-y-auto"> <div className="h-full overflow-y-auto">
{loading ? ( {loading ? (
<div className="flex items-center justify-center py-12"> <div className="flex items-center justify-center py-12">
<Loader2 className="w-8 h-8 animate-spin text-[#d4af37]" /> <Loader2 className="w-8 h-8 animate-spin text-[var(--luxury-gold)]" />
</div> </div>
) : ( ) : (
<form onSubmit={handleSubmit(onSubmit)} className="space-y-6 relative"> <form onSubmit={handleSubmit(onSubmit)} className="space-y-6 relative">
@@ -602,13 +602,13 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
<div className="space-y-4"> <div className="space-y-4">
<div> <div>
<h3 className="text-lg font-serif font-semibold text-white mb-4 flex items-center gap-2"> <h3 className="text-lg font-serif font-semibold text-white mb-4 flex items-center gap-2">
<Calendar className="w-5 h-5 text-[#d4af37]" /> <Calendar className="w-5 h-5 text-[var(--luxury-gold)]" />
Select Dates Select Dates
</h3> </h3>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4"> <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div> <div>
<label className="block text-xs font-medium text-gray-300 mb-2"> <label className="block text-xs font-medium text-gray-300 mb-2">
Check-in Date <span className="text-[#d4af37]">*</span> Check-in Date <span className="text-[var(--luxury-gold)]">*</span>
</label> </label>
<Controller <Controller
control={control} control={control}
@@ -631,7 +631,7 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
} }
field.onChange(date); field.onChange(date);
}} }}
className="w-full px-3 py-2 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white text-sm focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37]" className="w-full px-3 py-2 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white text-sm focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)]"
wrapperClassName="w-full" wrapperClassName="w-full"
/> />
)} )}
@@ -642,7 +642,7 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
</div> </div>
<div> <div>
<label className="block text-xs font-medium text-gray-300 mb-2"> <label className="block text-xs font-medium text-gray-300 mb-2">
Check-out Date <span className="text-[#d4af37]">*</span> Check-out Date <span className="text-[var(--luxury-gold)]">*</span>
</label> </label>
<Controller <Controller
control={control} control={control}
@@ -668,7 +668,7 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
} }
field.onChange(date); field.onChange(date);
}} }}
className="w-full px-3 py-2 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white text-sm focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37]" className="w-full px-3 py-2 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white text-sm focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)]"
wrapperClassName="w-full" wrapperClassName="w-full"
/> />
)} )}
@@ -679,10 +679,10 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
</div> </div>
</div> </div>
{checkInDate && checkOutDate && ( {checkInDate && checkOutDate && (
<div className="mt-4 p-3 bg-[#d4af37]/10 border border-[#d4af37]/20 rounded-lg"> <div className="mt-4 p-3 bg-[var(--luxury-gold)]/10 border border-[var(--luxury-gold)]/20 rounded-lg">
<p className="text-sm text-gray-300"> <p className="text-sm text-gray-300">
<span className="text-[#d4af37] font-semibold">{numberOfNights}</span> night{numberOfNights !== 1 ? 's' : ''} <span className="text-[var(--luxury-gold)] font-semibold">{numberOfNights}</span> night{numberOfNights !== 1 ? 's' : ''}
<span className="text-[#d4af37] font-semibold ml-1">{formatCurrency(roomTotal)}</span> <span className="text-[var(--luxury-gold)] font-semibold ml-1">{formatCurrency(roomTotal)}</span>
</p> </p>
</div> </div>
)} )}
@@ -695,18 +695,18 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
<div className="space-y-4"> <div className="space-y-4">
<div> <div>
<h3 className="text-lg font-serif font-semibold text-white mb-4 flex items-center gap-2"> <h3 className="text-lg font-serif font-semibold text-white mb-4 flex items-center gap-2">
<Users className="w-5 h-5 text-[#d4af37]" /> <Users className="w-5 h-5 text-[var(--luxury-gold)]" />
Guest Information Guest Information
</h3> </h3>
<div className="space-y-4"> <div className="space-y-4">
<div> <div>
<label className="block text-xs font-medium text-gray-300 mb-2"> <label className="block text-xs font-medium text-gray-300 mb-2">
Full Name <span className="text-[#d4af37]">*</span> Full Name <span className="text-[var(--luxury-gold)]">*</span>
</label> </label>
<input <input
{...register('fullName')} {...register('fullName')}
type="text" type="text"
className="w-full px-3 py-2 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white text-sm focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37]" className="w-full px-3 py-2 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white text-sm focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)]"
placeholder="John Doe" placeholder="John Doe"
/> />
{errors.fullName && ( {errors.fullName && (
@@ -716,12 +716,12 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4"> <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div> <div>
<label className="block text-xs font-medium text-gray-300 mb-2"> <label className="block text-xs font-medium text-gray-300 mb-2">
Email <span className="text-[#d4af37]">*</span> Email <span className="text-[var(--luxury-gold)]">*</span>
</label> </label>
<input <input
{...register('email')} {...register('email')}
type="email" type="email"
className="w-full px-3 py-2 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white text-sm focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37]" className="w-full px-3 py-2 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white text-sm focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)]"
placeholder="email@example.com" placeholder="email@example.com"
/> />
{errors.email && ( {errors.email && (
@@ -730,12 +730,12 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
</div> </div>
<div> <div>
<label className="block text-xs font-medium text-gray-300 mb-2"> <label className="block text-xs font-medium text-gray-300 mb-2">
Phone <span className="text-[#d4af37]">*</span> Phone <span className="text-[var(--luxury-gold)]">*</span>
</label> </label>
<input <input
{...register('phone')} {...register('phone')}
type="tel" type="tel"
className="w-full px-3 py-2 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white text-sm focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37]" className="w-full px-3 py-2 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white text-sm focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)]"
placeholder="0123456789" placeholder="0123456789"
/> />
{errors.phone && ( {errors.phone && (
@@ -745,14 +745,14 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
</div> </div>
<div> <div>
<label className="block text-xs font-medium text-gray-300 mb-2"> <label className="block text-xs font-medium text-gray-300 mb-2">
Number of Guests <span className="text-[#d4af37]">*</span> Number of Guests <span className="text-[var(--luxury-gold)]">*</span>
</label> </label>
<input <input
{...register('guestCount')} {...register('guestCount')}
type="number" type="number"
min="1" min="1"
max={room?.capacity || room?.room_type?.capacity || 10} max={room?.capacity || room?.room_type?.capacity || 10}
className="w-full px-3 py-2 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white text-sm focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37]" className="w-full px-3 py-2 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white text-sm focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)]"
/> />
{errors.guestCount && ( {errors.guestCount && (
<p className="text-xs text-red-400 mt-1">{errors.guestCount.message}</p> <p className="text-xs text-red-400 mt-1">{errors.guestCount.message}</p>
@@ -765,7 +765,7 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
<textarea <textarea
{...register('notes')} {...register('notes')}
rows={2} rows={2}
className="w-full px-3 py-2 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white text-sm focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37] resize-none" className="w-full px-3 py-2 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white text-sm focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)] resize-none"
placeholder="Any special requests..." placeholder="Any special requests..."
/> />
</div> </div>
@@ -779,7 +779,7 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
<div className="space-y-4"> <div className="space-y-4">
<div> <div>
<h3 className="text-lg font-serif font-semibold text-white mb-4 flex items-center gap-2"> <h3 className="text-lg font-serif font-semibold text-white mb-4 flex items-center gap-2">
<Sparkles className="w-5 h-5 text-[#d4af37]" /> <Sparkles className="w-5 h-5 text-[var(--luxury-gold)]" />
Additional Services Additional Services
</h3> </h3>
{services.length > 0 ? ( {services.length > 0 ? (
@@ -790,7 +790,7 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
return ( return (
<div <div
key={service.id} key={service.id}
className="p-3 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg" className="p-3 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg"
> >
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div className="flex-1"> <div className="flex-1">
@@ -815,7 +815,7 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
} }
}} }}
disabled={quantity === 0} disabled={quantity === 0}
className="w-7 h-7 flex items-center justify-center bg-[#1a1a1a] border border-[#d4af37]/20 rounded text-[#d4af37] hover:bg-[#d4af37]/10 disabled:opacity-50" className="w-7 h-7 flex items-center justify-center bg-[#1a1a1a] border border-[var(--luxury-gold)]/20 rounded text-[var(--luxury-gold)] hover:bg-[var(--luxury-gold)]/10 disabled:opacity-50"
> >
<Minus className="w-3.5 h-3.5" /> <Minus className="w-3.5 h-3.5" />
</button> </button>
@@ -833,13 +833,13 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
)); ));
} }
}} }}
className="w-7 h-7 flex items-center justify-center bg-[#1a1a1a] border border-[#d4af37]/20 rounded text-[#d4af37] hover:bg-[#d4af37]/10" className="w-7 h-7 flex items-center justify-center bg-[#1a1a1a] border border-[var(--luxury-gold)]/20 rounded text-[var(--luxury-gold)] hover:bg-[var(--luxury-gold)]/10"
> >
<Plus className="w-3.5 h-3.5" /> <Plus className="w-3.5 h-3.5" />
</button> </button>
</div> </div>
{quantity > 0 && ( {quantity > 0 && (
<span className="text-sm font-semibold text-[#d4af37] w-20 text-right"> <span className="text-sm font-semibold text-[var(--luxury-gold)] w-20 text-right">
{formatCurrency(service.price * quantity)} {formatCurrency(service.price * quantity)}
</span> </span>
)} )}
@@ -854,7 +854,7 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
)} )}
{/* Promotion Code */} {/* Promotion Code */}
<div className="mt-6 pt-6 border-t border-[#d4af37]/20"> <div className="mt-6 pt-6 border-t border-[var(--luxury-gold)]/20">
<h4 className="text-sm font-semibold text-white mb-3">Promotion Code</h4> <h4 className="text-sm font-semibold text-white mb-3">Promotion Code</h4>
{!selectedPromotion ? ( {!selectedPromotion ? (
<div className="flex gap-2"> <div className="flex gap-2">
@@ -866,14 +866,14 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
setPromotionError(null); setPromotionError(null);
}} }}
placeholder="Enter code" placeholder="Enter code"
className="flex-1 px-3 py-2 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white text-sm focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37]" className="flex-1 px-3 py-2 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white text-sm focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)]"
disabled={validatingPromotion || subtotal === 0} disabled={validatingPromotion || subtotal === 0}
/> />
<button <button
type="button" type="button"
onClick={handleValidatePromotion} onClick={handleValidatePromotion}
disabled={validatingPromotion || !promotionCode.trim() || subtotal === 0} disabled={validatingPromotion || !promotionCode.trim() || subtotal === 0}
className="px-4 py-2 bg-[#d4af37] text-black font-semibold rounded-lg hover:bg-[#c9a227] disabled:opacity-50 disabled:cursor-not-allowed text-sm" className="px-4 py-2 bg-[var(--luxury-gold)] text-black font-semibold rounded-lg hover:bg-[var(--luxury-gold-dark)] disabled:opacity-50 disabled:cursor-not-allowed text-sm"
> >
{validatingPromotion ? <Loader2 className="w-4 h-4 animate-spin" /> : 'Apply'} {validatingPromotion ? <Loader2 className="w-4 h-4 animate-spin" /> : 'Apply'}
</button> </button>
@@ -897,9 +897,9 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
</div> </div>
{/* Referral Code */} {/* Referral Code */}
<div className="mt-6 pt-6 border-t border-[#d4af37]/20"> <div className="mt-6 pt-6 border-t border-[var(--luxury-gold)]/20">
<div className="flex items-center gap-2 mb-3"> <div className="flex items-center gap-2 mb-3">
<Users className="w-4 h-4 text-[#d4af37]" /> <Users className="w-4 h-4 text-[var(--luxury-gold)]" />
<h4 className="text-sm font-semibold text-white">Referral Code (Optional)</h4> <h4 className="text-sm font-semibold text-white">Referral Code (Optional)</h4>
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
@@ -911,7 +911,7 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
setReferralError(null); setReferralError(null);
}} }}
placeholder="Enter referral code from a friend" placeholder="Enter referral code from a friend"
className="w-full px-3 py-2 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white text-sm focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37]" className="w-full px-3 py-2 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white text-sm focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)]"
/> />
{referralCode && ( {referralCode && (
<p className="text-xs text-gray-400"> <p className="text-xs text-gray-400">
@@ -930,51 +930,51 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
<div className="space-y-4"> <div className="space-y-4">
<div> <div>
<h3 className="text-lg font-serif font-semibold text-white mb-4 flex items-center gap-2"> <h3 className="text-lg font-serif font-semibold text-white mb-4 flex items-center gap-2">
<CreditCard className="w-5 h-5 text-[#d4af37]" /> <CreditCard className="w-5 h-5 text-[var(--luxury-gold)]" />
Payment Method Payment Method
</h3> </h3>
<div className="space-y-3"> <div className="space-y-3">
<label className="flex items-start p-4 bg-[#0a0a0a] border-2 border-[#d4af37]/20 rounded-lg cursor-pointer hover:border-[#d4af37]/40 transition-all"> <label className="flex items-start p-4 bg-[#0a0a0a] border-2 border-[var(--luxury-gold)]/20 rounded-lg cursor-pointer hover:border-[var(--luxury-gold)]/40 transition-all">
<input <input
{...register('paymentMethod')} {...register('paymentMethod')}
type="radio" type="radio"
value="cash" value="cash"
className="mt-1 mr-3 w-4 h-4 text-[#d4af37] border-[#d4af37]/30 focus:ring-[#d4af37]/50" className="mt-1 mr-3 w-4 h-4 text-[var(--luxury-gold)] border-[var(--luxury-gold)]/30 focus:ring-[var(--luxury-gold)]/50"
/> />
<div className="flex-1"> <div className="flex-1">
<div className="flex items-center gap-2 mb-1"> <div className="flex items-center gap-2 mb-1">
<CreditCard className="w-4 h-4 text-[#d4af37]" /> <CreditCard className="w-4 h-4 text-[var(--luxury-gold)]" />
<span className="font-semibold text-white text-sm">Pay on Arrival</span> <span className="font-semibold text-white text-sm">Pay on Arrival</span>
<span className="text-xs bg-orange-500/20 text-orange-300 px-2 py-0.5 rounded">20% deposit</span> <span className="text-xs bg-orange-500/20 text-orange-300 px-2 py-0.5 rounded">20% deposit</span>
</div> </div>
<p className="text-xs text-gray-400">Pay 20% deposit now, remaining on arrival</p> <p className="text-xs text-gray-400">Pay 20% deposit now, remaining on arrival</p>
</div> </div>
</label> </label>
<label className="flex items-start p-4 bg-[#0a0a0a] border-2 border-[#d4af37]/20 rounded-lg cursor-pointer hover:border-[#d4af37]/40 transition-all"> <label className="flex items-start p-4 bg-[#0a0a0a] border-2 border-[var(--luxury-gold)]/20 rounded-lg cursor-pointer hover:border-[var(--luxury-gold)]/40 transition-all">
<input <input
{...register('paymentMethod')} {...register('paymentMethod')}
type="radio" type="radio"
value="stripe" value="stripe"
className="mt-1 mr-3 w-4 h-4 text-[#d4af37] border-[#d4af37]/30 focus:ring-[#d4af37]/50" className="mt-1 mr-3 w-4 h-4 text-[var(--luxury-gold)] border-[var(--luxury-gold)]/30 focus:ring-[var(--luxury-gold)]/50"
/> />
<div className="flex-1"> <div className="flex-1">
<div className="flex items-center gap-2 mb-1"> <div className="flex items-center gap-2 mb-1">
<CreditCard className="w-4 h-4 text-[#d4af37]" /> <CreditCard className="w-4 h-4 text-[var(--luxury-gold)]" />
<span className="font-semibold text-white text-sm">Credit/Debit Card</span> <span className="font-semibold text-white text-sm">Credit/Debit Card</span>
</div> </div>
<p className="text-xs text-gray-400">Secure payment via Stripe</p> <p className="text-xs text-gray-400">Secure payment via Stripe</p>
</div> </div>
</label> </label>
<label className="flex items-start p-4 bg-[#0a0a0a] border-2 border-[#d4af37]/20 rounded-lg cursor-pointer hover:border-[#d4af37]/40 transition-all"> <label className="flex items-start p-4 bg-[#0a0a0a] border-2 border-[var(--luxury-gold)]/20 rounded-lg cursor-pointer hover:border-[var(--luxury-gold)]/40 transition-all">
<input <input
{...register('paymentMethod')} {...register('paymentMethod')}
type="radio" type="radio"
value="paypal" value="paypal"
className="mt-1 mr-3 w-4 h-4 text-[#d4af37] border-[#d4af37]/30 focus:ring-[#d4af37]/50" className="mt-1 mr-3 w-4 h-4 text-[var(--luxury-gold)] border-[var(--luxury-gold)]/30 focus:ring-[var(--luxury-gold)]/50"
/> />
<div className="flex-1"> <div className="flex-1">
<div className="flex items-center gap-2 mb-1"> <div className="flex items-center gap-2 mb-1">
<CreditCard className="w-4 h-4 text-[#d4af37]" /> <CreditCard className="w-4 h-4 text-[var(--luxury-gold)]" />
<span className="font-semibold text-white text-sm">PayPal</span> <span className="font-semibold text-white text-sm">PayPal</span>
</div> </div>
<p className="text-xs text-gray-400">Pay securely with PayPal</p> <p className="text-xs text-gray-400">Pay securely with PayPal</p>
@@ -987,7 +987,7 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
<button <button
type="button" type="button"
onClick={() => setShowInvoiceModal(true)} onClick={() => setShowInvoiceModal(true)}
className="flex items-center gap-2 px-4 py-2 text-sm text-[#d4af37] hover:text-[#f5d76e] transition-colors" className="flex items-center gap-2 px-4 py-2 text-sm text-[var(--luxury-gold)] hover:text-[var(--luxury-gold-light)] transition-colors"
> >
<Receipt className="w-4 h-4" /> <Receipt className="w-4 h-4" />
Add Invoice Information (Optional) Add Invoice Information (Optional)
@@ -995,7 +995,7 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
</div> </div>
{/* Summary */} {/* Summary */}
<div className="mt-6 p-4 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg"> <div className="mt-6 p-4 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg">
<div className="space-y-2 text-sm"> <div className="space-y-2 text-sm">
<div className="flex justify-between text-gray-300"> <div className="flex justify-between text-gray-300">
<span>Room ({numberOfNights} nights)</span> <span>Room ({numberOfNights} nights)</span>
@@ -1013,7 +1013,7 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
<span>-{formatCurrency(promotionDiscount)}</span> <span>-{formatCurrency(promotionDiscount)}</span>
</div> </div>
)} )}
<div className="flex justify-between text-lg font-bold text-[#d4af37] pt-2 border-t border-[#d4af37]/20"> <div className="flex justify-between text-lg font-bold text-[var(--luxury-gold)] pt-2 border-t border-[var(--luxury-gold)]/20">
<span>Total</span> <span>Total</span>
<span>{formatCurrency(totalPrice)}</span> <span>{formatCurrency(totalPrice)}</span>
</div> </div>
@@ -1057,7 +1057,7 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
</div> </div>
{/* Footer */} {/* Footer */}
<div className="px-3 sm:px-4 md:px-6 py-3 sm:py-4 border-t border-[#d4af37]/20 bg-gradient-to-r from-[#1a1a1a] to-[#0a0a0a] flex-shrink-0"> <div className="px-3 sm:px-4 md:px-6 py-3 sm:py-4 border-t border-[var(--luxury-gold)]/20 bg-gradient-to-r from-[#1a1a1a] to-[#0a0a0a] flex-shrink-0">
<div className="flex items-center justify-between gap-2 sm:gap-3"> <div className="flex items-center justify-between gap-2 sm:gap-3">
<button <button
onClick={currentStep === 'dates' ? onClose : handleBack} onClick={currentStep === 'dates' ? onClose : handleBack}
@@ -1071,7 +1071,7 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
<button <button
onClick={handleNext} onClick={handleNext}
disabled={!canGoToNextStep()} disabled={!canGoToNextStep()}
className="px-4 sm:px-6 py-2 bg-[#d4af37] text-black font-semibold rounded-lg hover:bg-[#c9a227] disabled:opacity-50 disabled:cursor-not-allowed transition-all flex items-center gap-1.5 sm:gap-2 text-xs sm:text-sm sm:text-base min-h-[44px]" className="px-4 sm:px-6 py-2 bg-[var(--luxury-gold)] text-black font-semibold rounded-lg hover:bg-[var(--luxury-gold-dark)] disabled:opacity-50 disabled:cursor-not-allowed transition-all flex items-center gap-1.5 sm:gap-2 text-xs sm:text-sm sm:text-base min-h-[44px]"
> >
<span>Next</span> <span>Next</span>
<ArrowRight className="w-3.5 h-3.5 sm:w-4 sm:h-4" /> <ArrowRight className="w-3.5 h-3.5 sm:w-4 sm:h-4" />
@@ -1102,7 +1102,7 @@ const LuxuryBookingModal: React.FC<LuxuryBookingModalProps> = ({
})(); })();
}} }}
disabled={submitting || !paymentMethodForm} disabled={submitting || !paymentMethodForm}
className="px-4 sm:px-6 py-2 bg-[#d4af37] text-black font-semibold rounded-lg hover:bg-[#c9a227] disabled:opacity-50 disabled:cursor-not-allowed transition-all flex items-center gap-1.5 sm:gap-2 text-xs sm:text-sm sm:text-base min-h-[44px]" className="px-4 sm:px-6 py-2 bg-[var(--luxury-gold)] text-black font-semibold rounded-lg hover:bg-[var(--luxury-gold-dark)] disabled:opacity-50 disabled:cursor-not-allowed transition-all flex items-center gap-1.5 sm:gap-2 text-xs sm:text-sm sm:text-base min-h-[44px]"
> >
{submitting ? ( {submitting ? (
<> <>

View File

@@ -223,11 +223,11 @@ const PartnersCarousel: React.FC<PartnersCarouselProps> = ({
disabled={currentIndex === 0} disabled={currentIndex === 0}
className="absolute left-0 top-1/2 -translate-y-1/2 z-10 className="absolute left-0 top-1/2 -translate-y-1/2 z-10
w-10 h-10 sm:w-12 sm:h-12 w-10 h-10 sm:w-12 sm:h-12
bg-gradient-to-r from-[#d4af37] to-[#c9a227] bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]
text-white rounded-full text-white rounded-full
flex items-center justify-center flex items-center justify-center
shadow-lg shadow-[#d4af37]/40 shadow-lg shadow-[var(--luxury-gold)]/40
hover:shadow-xl hover:shadow-[#d4af37]/50 hover:shadow-xl hover:shadow-[var(--luxury-gold)]/50
hover:scale-110 hover:scale-110
active:scale-95 active:scale-95
transition-all duration-300 transition-all duration-300
@@ -243,11 +243,11 @@ const PartnersCarousel: React.FC<PartnersCarouselProps> = ({
disabled={currentIndex >= maxIndex} disabled={currentIndex >= maxIndex}
className="absolute right-0 top-1/2 -translate-y-1/2 z-10 className="absolute right-0 top-1/2 -translate-y-1/2 z-10
w-10 h-10 sm:w-12 sm:h-12 w-10 h-10 sm:w-12 sm:h-12
bg-gradient-to-r from-[#d4af37] to-[#c9a227] bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]
text-white rounded-full text-white rounded-full
flex items-center justify-center flex items-center justify-center
shadow-lg shadow-[#d4af37]/40 shadow-lg shadow-[var(--luxury-gold)]/40
hover:shadow-xl hover:shadow-[#d4af37]/50 hover:shadow-xl hover:shadow-[var(--luxury-gold)]/50
hover:scale-110 hover:scale-110
active:scale-95 active:scale-95
transition-all duration-300 transition-all duration-300
@@ -270,8 +270,8 @@ const PartnersCarousel: React.FC<PartnersCarouselProps> = ({
className={`transition-all duration-300 rounded-full className={`transition-all duration-300 rounded-full
${ ${
index === currentIndex index === currentIndex
? 'w-8 h-2 sm:w-10 sm:h-2.5 bg-gradient-to-r from-[#d4af37] to-[#c9a227] shadow-lg shadow-[#d4af37]/40' ? 'w-8 h-2 sm:w-10 sm:h-2.5 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] shadow-lg shadow-[var(--luxury-gold)]/40'
: 'w-2 h-2 sm:w-2.5 sm:h-2.5 bg-gray-300 hover:bg-[#d4af37]/50' : 'w-2 h-2 sm:w-2.5 sm:h-2.5 bg-gray-300 hover:bg-[var(--luxury-gold)]/50'
} }
`} `}
aria-label={`Go to partners slide ${index + 1}`} aria-label={`Go to partners slide ${index + 1}`}

View File

@@ -178,7 +178,7 @@ const AboutPage: React.FC = () => {
className="w-full h-full object-cover scale-105 transition-transform duration-[20s] ease-out hover:scale-100" className="w-full h-full object-cover scale-105 transition-transform duration-[20s] ease-out hover:scale-100"
/> />
<div className="absolute inset-0 bg-gradient-to-b from-black/70 via-black/50 to-black/70"></div> <div className="absolute inset-0 bg-gradient-to-b from-black/70 via-black/50 to-black/70"></div>
<div className="absolute inset-0 bg-gradient-to-r from-[#d4af37]/10 via-transparent to-[#d4af37]/10"></div> <div className="absolute inset-0 bg-gradient-to-r from-[var(--luxury-gold)]/10 via-transparent to-[var(--luxury-gold)]/10"></div>
</div> </div>
)} )}
{!pageContent?.about_hero_image && ( {!pageContent?.about_hero_image && (
@@ -192,8 +192,8 @@ const AboutPage: React.FC = () => {
{!pageContent?.about_hero_image && ( {!pageContent?.about_hero_image && (
<div className="flex justify-center mb-8"> <div className="flex justify-center mb-8">
<div className="relative"> <div className="relative">
<div className="absolute inset-0 bg-gradient-to-br from-[#d4af37] via-[#f5d76e] to-[#d4af37] rounded-full blur-3xl opacity-40 animate-pulse"></div> <div className="absolute inset-0 bg-gradient-to-br from-[var(--luxury-gold)] via-[var(--luxury-gold-light)] to-[var(--luxury-gold)] rounded-full blur-3xl opacity-40 animate-pulse"></div>
<div className="relative bg-gradient-to-br from-[#d4af37] to-[#c9a227] p-6 rounded-2xl shadow-2xl shadow-[#d4af37]/30"> <div className="relative bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] p-6 rounded-2xl shadow-2xl shadow-[var(--luxury-gold)]/30">
<Hotel className="w-12 h-12 md:w-16 md:h-16 text-white drop-shadow-lg" /> <Hotel className="w-12 h-12 md:w-16 md:h-16 text-white drop-shadow-lg" />
</div> </div>
</div> </div>
@@ -201,11 +201,11 @@ const AboutPage: React.FC = () => {
)} )}
<div className="mb-6"> <div className="mb-6">
<div className="inline-block mb-4"> <div className="inline-block mb-4">
<div className="h-px w-20 bg-gradient-to-r from-transparent via-[#d4af37] to-transparent mx-auto"></div> <div className="h-px w-20 bg-gradient-to-r from-transparent via-[var(--luxury-gold)] to-transparent mx-auto"></div>
</div> </div>
</div> </div>
<h1 className="text-5xl md:text-6xl lg:text-7xl font-serif font-light mb-6 tracking-[0.02em] leading-tight"> <h1 className="text-5xl md:text-6xl lg:text-7xl font-serif font-light mb-6 tracking-[0.02em] leading-tight">
<span className="bg-gradient-to-b from-white via-[#f5d76e] to-[#d4af37] bg-clip-text text-transparent drop-shadow-2xl"> <span className="bg-gradient-to-b from-white via-[var(--luxury-gold-light)] to-[var(--luxury-gold)] bg-clip-text text-transparent drop-shadow-2xl">
{pageContent?.title || 'About Luxury Hotel'} {pageContent?.title || 'About Luxury Hotel'}
</span> </span>
</h1> </h1>
@@ -214,7 +214,7 @@ const AboutPage: React.FC = () => {
</p> </p>
<div className="mt-8"> <div className="mt-8">
<div className="inline-block"> <div className="inline-block">
<div className="h-px w-20 bg-gradient-to-r from-transparent via-[#d4af37] to-transparent mx-auto"></div> <div className="h-px w-20 bg-gradient-to-r from-transparent via-[var(--luxury-gold)] to-transparent mx-auto"></div>
</div> </div>
</div> </div>
</div> </div>
@@ -223,20 +223,20 @@ const AboutPage: React.FC = () => {
{} {}
<section className="py-20 md:py-28 bg-white relative overflow-hidden"> <section className="py-20 md:py-28 bg-white relative overflow-hidden">
<div className="absolute top-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-[#d4af37]/30 to-transparent"></div> <div className="absolute top-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-[var(--luxury-gold)]/30 to-transparent"></div>
<div className="container mx-auto px-4 sm:px-6 lg:px-8"> <div className="container mx-auto px-4 sm:px-6 lg:px-8">
<div className="max-w-5xl mx-auto"> <div className="max-w-5xl mx-auto">
<div className="text-center mb-16"> <div className="text-center mb-16">
<div className="inline-block mb-4"> <div className="inline-block mb-4">
<span className="text-sm font-semibold text-[#d4af37] tracking-[0.2em] uppercase">Our Heritage</span> <span className="text-sm font-semibold text-[var(--luxury-gold)] tracking-[0.2em] uppercase">Our Heritage</span>
</div> </div>
<h2 className="text-4xl md:text-5xl lg:text-6xl font-serif font-light text-gray-900 mb-6 tracking-tight"> <h2 className="text-4xl md:text-5xl lg:text-6xl font-serif font-light text-gray-900 mb-6 tracking-tight">
Our Story Our Story
</h2> </h2>
<div className="flex items-center justify-center gap-4 mb-6"> <div className="flex items-center justify-center gap-4 mb-6">
<div className="h-px w-12 bg-gradient-to-r from-transparent to-[#d4af37]"></div> <div className="h-px w-12 bg-gradient-to-r from-transparent to-[var(--luxury-gold)]"></div>
<div className="w-2 h-2 bg-[#d4af37] rounded-full"></div> <div className="w-2 h-2 bg-[var(--luxury-gold)] rounded-full"></div>
<div className="h-px w-12 bg-gradient-to-l from-transparent to-[#d4af37]"></div> <div className="h-px w-12 bg-gradient-to-l from-transparent to-[var(--luxury-gold)]"></div>
</div> </div>
</div> </div>
<div className="prose prose-lg md:prose-xl max-w-none text-gray-700 leading-relaxed space-y-8"> <div className="prose prose-lg md:prose-xl max-w-none text-gray-700 leading-relaxed space-y-8">
@@ -247,7 +247,7 @@ const AboutPage: React.FC = () => {
/> />
) : ( ) : (
<> <>
<p className="text-lg md:text-xl leading-relaxed font-light tracking-wide first-letter:text-5xl first-letter:font-serif first-letter:text-[#d4af37] first-letter:float-left first-letter:mr-2 first-letter:leading-none"> <p className="text-lg md:text-xl leading-relaxed font-light tracking-wide first-letter:text-5xl first-letter:font-serif first-letter:text-[var(--luxury-gold)] first-letter:float-left first-letter:mr-2 first-letter:leading-none">
Welcome to Luxury Hotel, where timeless elegance meets modern sophistication. Welcome to Luxury Hotel, where timeless elegance meets modern sophistication.
Since our founding, we have been dedicated to providing exceptional hospitality Since our founding, we have been dedicated to providing exceptional hospitality
and creating unforgettable memories for our guests. and creating unforgettable memories for our guests.
@@ -267,7 +267,7 @@ const AboutPage: React.FC = () => {
</div> </div>
</div> </div>
</div> </div>
<div className="absolute bottom-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-[#d4af37]/30 to-transparent"></div> <div className="absolute bottom-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-[var(--luxury-gold)]/30 to-transparent"></div>
</section> </section>
{} {}
@@ -278,33 +278,33 @@ const AboutPage: React.FC = () => {
<div className="max-w-7xl mx-auto"> <div className="max-w-7xl mx-auto">
<div className="text-center mb-16"> <div className="text-center mb-16">
<div className="inline-block mb-4"> <div className="inline-block mb-4">
<span className="text-sm font-semibold text-[#d4af37] tracking-[0.2em] uppercase">Core Principles</span> <span className="text-sm font-semibold text-[var(--luxury-gold)] tracking-[0.2em] uppercase">Core Principles</span>
</div> </div>
<h2 className="text-4xl md:text-5xl lg:text-6xl font-serif font-light text-gray-900 mb-6 tracking-tight"> <h2 className="text-4xl md:text-5xl lg:text-6xl font-serif font-light text-gray-900 mb-6 tracking-tight">
Our Values Our Values
</h2> </h2>
<div className="flex items-center justify-center gap-4 mb-6"> <div className="flex items-center justify-center gap-4 mb-6">
<div className="h-px w-12 bg-gradient-to-r from-transparent to-[#d4af37]"></div> <div className="h-px w-12 bg-gradient-to-r from-transparent to-[var(--luxury-gold)]"></div>
<div className="w-2 h-2 bg-[#d4af37] rounded-full"></div> <div className="w-2 h-2 bg-[var(--luxury-gold)] rounded-full"></div>
<div className="h-px w-12 bg-gradient-to-l from-transparent to-[#d4af37]"></div> <div className="h-px w-12 bg-gradient-to-l from-transparent to-[var(--luxury-gold)]"></div>
</div> </div>
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 lg:gap-8"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 lg:gap-8">
{values.map((value, index) => ( {values.map((value, index) => (
<div <div
key={value.title} key={value.title}
className="group relative bg-white/80 backdrop-blur-sm p-8 rounded-2xl shadow-lg hover:shadow-2xl transition-all duration-500 border border-gray-100 hover:border-[#d4af37]/30 hover:-translate-y-2" className="group relative bg-white/80 backdrop-blur-sm p-8 rounded-2xl shadow-lg hover:shadow-2xl transition-all duration-500 border border-gray-100 hover:border-[var(--luxury-gold)]/30 hover:-translate-y-2"
style={{ animationDelay: `${index * 0.1}s` }} style={{ animationDelay: `${index * 0.1}s` }}
> >
<div className="absolute top-0 right-0 w-32 h-32 bg-gradient-to-br from-[#d4af37]/5 to-transparent rounded-bl-full opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div> <div className="absolute top-0 right-0 w-32 h-32 bg-gradient-to-br from-[var(--luxury-gold)]/5 to-transparent rounded-bl-full opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
<div className="relative"> <div className="relative">
<div className="w-16 h-16 bg-gradient-to-br from-[#d4af37] via-[#f5d76e] to-[#d4af37] rounded-xl flex items-center justify-center mb-6 shadow-lg shadow-[#d4af37]/20 group-hover:scale-110 group-hover:rotate-3 transition-transform duration-500"> <div className="w-16 h-16 bg-gradient-to-br from-[var(--luxury-gold)] via-[var(--luxury-gold-light)] to-[var(--luxury-gold)] rounded-xl flex items-center justify-center mb-6 shadow-lg shadow-[var(--luxury-gold)]/20 group-hover:scale-110 group-hover:rotate-3 transition-transform duration-500">
{(() => { {(() => {
const ValueIcon = getIconComponent(value.icon); const ValueIcon = getIconComponent(value.icon);
return <ValueIcon className="w-8 h-8 text-white drop-shadow-md" />; return <ValueIcon className="w-8 h-8 text-white drop-shadow-md" />;
})()} })()}
</div> </div>
<h3 className="text-xl md:text-2xl font-serif font-semibold text-gray-900 mb-3 group-hover:text-[#d4af37] transition-colors duration-300"> <h3 className="text-xl md:text-2xl font-serif font-semibold text-gray-900 mb-3 group-hover:text-[var(--luxury-gold)] transition-colors duration-300">
{value.title} {value.title}
</h3> </h3>
<p className="text-gray-600 leading-relaxed font-light text-sm md:text-base"> <p className="text-gray-600 leading-relaxed font-light text-sm md:text-base">
@@ -327,15 +327,15 @@ const AboutPage: React.FC = () => {
<div className="max-w-7xl mx-auto"> <div className="max-w-7xl mx-auto">
<div className="text-center mb-16"> <div className="text-center mb-16">
<div className="inline-block mb-4"> <div className="inline-block mb-4">
<span className="text-sm font-semibold text-[#d4af37] tracking-[0.2em] uppercase">Excellence Defined</span> <span className="text-sm font-semibold text-[var(--luxury-gold)] tracking-[0.2em] uppercase">Excellence Defined</span>
</div> </div>
<h2 className="text-4xl md:text-5xl lg:text-6xl font-serif font-light text-gray-900 mb-6 tracking-tight"> <h2 className="text-4xl md:text-5xl lg:text-6xl font-serif font-light text-gray-900 mb-6 tracking-tight">
Why Choose Us Why Choose Us
</h2> </h2>
<div className="flex items-center justify-center gap-4 mb-6"> <div className="flex items-center justify-center gap-4 mb-6">
<div className="h-px w-12 bg-gradient-to-r from-transparent to-[#d4af37]"></div> <div className="h-px w-12 bg-gradient-to-r from-transparent to-[var(--luxury-gold)]"></div>
<div className="w-2 h-2 bg-[#d4af37] rounded-full"></div> <div className="w-2 h-2 bg-[var(--luxury-gold)] rounded-full"></div>
<div className="h-px w-12 bg-gradient-to-l from-transparent to-[#d4af37]"></div> <div className="h-px w-12 bg-gradient-to-l from-transparent to-[var(--luxury-gold)]"></div>
</div> </div>
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 lg:gap-12"> <div className="grid grid-cols-1 md:grid-cols-3 gap-8 lg:gap-12">
@@ -347,12 +347,12 @@ const AboutPage: React.FC = () => {
className="group text-center p-8 relative" className="group text-center p-8 relative"
style={{ animationDelay: `${index * 0.1}s` }} style={{ animationDelay: `${index * 0.1}s` }}
> >
<div className="absolute inset-0 bg-gradient-to-br from-[#d4af37]/5 to-transparent rounded-3xl opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div> <div className="absolute inset-0 bg-gradient-to-br from-[var(--luxury-gold)]/5 to-transparent rounded-3xl opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
<div className="relative"> <div className="relative">
<div className="w-20 h-20 bg-gradient-to-br from-[#d4af37] via-[#f5d76e] to-[#d4af37] rounded-2xl flex items-center justify-center mx-auto mb-6 shadow-xl shadow-[#d4af37]/30 group-hover:scale-110 group-hover:shadow-2xl group-hover:shadow-[#d4af37]/40 transition-all duration-500"> <div className="w-20 h-20 bg-gradient-to-br from-[var(--luxury-gold)] via-[var(--luxury-gold-light)] to-[var(--luxury-gold)] rounded-2xl flex items-center justify-center mx-auto mb-6 shadow-xl shadow-[var(--luxury-gold)]/30 group-hover:scale-110 group-hover:shadow-2xl group-hover:shadow-[var(--luxury-gold)]/40 transition-all duration-500">
<FeatureIcon className="w-10 h-10 text-white drop-shadow-lg" /> <FeatureIcon className="w-10 h-10 text-white drop-shadow-lg" />
</div> </div>
<h3 className="text-xl md:text-2xl font-serif font-semibold text-gray-900 mb-4 group-hover:text-[#d4af37] transition-colors duration-300"> <h3 className="text-xl md:text-2xl font-serif font-semibold text-gray-900 mb-4 group-hover:text-[var(--luxury-gold)] transition-colors duration-300">
{feature.title} {feature.title}
</h3> </h3>
<p className="text-gray-600 leading-relaxed font-light text-sm md:text-base"> <p className="text-gray-600 leading-relaxed font-light text-sm md:text-base">
@@ -377,11 +377,11 @@ const AboutPage: React.FC = () => {
<div className="container mx-auto px-4 sm:px-6 lg:px-8 relative z-10"> <div className="container mx-auto px-4 sm:px-6 lg:px-8 relative z-10">
<div className="max-w-7xl mx-auto grid grid-cols-1 md:grid-cols-2 gap-8 lg:gap-12"> <div className="max-w-7xl mx-auto grid grid-cols-1 md:grid-cols-2 gap-8 lg:gap-12">
{pageContent.mission && ( {pageContent.mission && (
<div className="group relative bg-white/95 backdrop-blur-sm p-10 md:p-12 rounded-2xl shadow-2xl border border-[#d4af37]/20 hover:border-[#d4af37]/40 transition-all duration-500 hover:shadow-[#d4af37]/20 hover:-translate-y-1"> <div className="group relative bg-white/95 backdrop-blur-sm p-10 md:p-12 rounded-2xl shadow-2xl border border-[var(--luxury-gold)]/20 hover:border-[var(--luxury-gold)]/40 transition-all duration-500 hover:shadow-[var(--luxury-gold)]/20 hover:-translate-y-1">
<div className="absolute top-0 right-0 w-40 h-40 bg-gradient-to-br from-[#d4af37]/10 to-transparent rounded-bl-full opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div> <div className="absolute top-0 right-0 w-40 h-40 bg-gradient-to-br from-[var(--luxury-gold)]/10 to-transparent rounded-bl-full opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
<div className="relative"> <div className="relative">
<div className="flex items-center gap-3 mb-6"> <div className="flex items-center gap-3 mb-6">
<div className="w-1 h-12 bg-gradient-to-b from-[#d4af37] to-[#f5d76e] rounded-full"></div> <div className="w-1 h-12 bg-gradient-to-b from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] rounded-full"></div>
<h2 className="text-3xl md:text-4xl font-serif font-light text-gray-900">Our Mission</h2> <h2 className="text-3xl md:text-4xl font-serif font-light text-gray-900">Our Mission</h2>
</div> </div>
<p className="text-gray-700 leading-relaxed text-base md:text-lg font-light tracking-wide">{pageContent.mission}</p> <p className="text-gray-700 leading-relaxed text-base md:text-lg font-light tracking-wide">{pageContent.mission}</p>
@@ -389,11 +389,11 @@ const AboutPage: React.FC = () => {
</div> </div>
)} )}
{pageContent.vision && ( {pageContent.vision && (
<div className="group relative bg-white/95 backdrop-blur-sm p-10 md:p-12 rounded-2xl shadow-2xl border border-[#d4af37]/20 hover:border-[#d4af37]/40 transition-all duration-500 hover:shadow-[#d4af37]/20 hover:-translate-y-1"> <div className="group relative bg-white/95 backdrop-blur-sm p-10 md:p-12 rounded-2xl shadow-2xl border border-[var(--luxury-gold)]/20 hover:border-[var(--luxury-gold)]/40 transition-all duration-500 hover:shadow-[var(--luxury-gold)]/20 hover:-translate-y-1">
<div className="absolute top-0 right-0 w-40 h-40 bg-gradient-to-br from-[#d4af37]/10 to-transparent rounded-bl-full opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div> <div className="absolute top-0 right-0 w-40 h-40 bg-gradient-to-br from-[var(--luxury-gold)]/10 to-transparent rounded-bl-full opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
<div className="relative"> <div className="relative">
<div className="flex items-center gap-3 mb-6"> <div className="flex items-center gap-3 mb-6">
<div className="w-1 h-12 bg-gradient-to-b from-[#d4af37] to-[#f5d76e] rounded-full"></div> <div className="w-1 h-12 bg-gradient-to-b from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] rounded-full"></div>
<h2 className="text-3xl md:text-4xl font-serif font-light text-gray-900">Our Vision</h2> <h2 className="text-3xl md:text-4xl font-serif font-light text-gray-900">Our Vision</h2>
</div> </div>
<p className="text-gray-700 leading-relaxed text-base md:text-lg font-light tracking-wide">{pageContent.vision}</p> <p className="text-gray-700 leading-relaxed text-base md:text-lg font-light tracking-wide">{pageContent.vision}</p>
@@ -412,24 +412,24 @@ const AboutPage: React.FC = () => {
<div className="max-w-7xl mx-auto"> <div className="max-w-7xl mx-auto">
<div className="text-center mb-16"> <div className="text-center mb-16">
<div className="inline-block mb-4"> <div className="inline-block mb-4">
<span className="text-sm font-semibold text-[#d4af37] tracking-[0.2em] uppercase">Meet The Experts</span> <span className="text-sm font-semibold text-[var(--luxury-gold)] tracking-[0.2em] uppercase">Meet The Experts</span>
</div> </div>
<h2 className="text-4xl md:text-5xl lg:text-6xl font-serif font-light text-gray-900 mb-6 tracking-tight"> <h2 className="text-4xl md:text-5xl lg:text-6xl font-serif font-light text-gray-900 mb-6 tracking-tight">
Our Team Our Team
</h2> </h2>
<div className="flex items-center justify-center gap-4 mb-6"> <div className="flex items-center justify-center gap-4 mb-6">
<div className="h-px w-12 bg-gradient-to-r from-transparent to-[#d4af37]"></div> <div className="h-px w-12 bg-gradient-to-r from-transparent to-[var(--luxury-gold)]"></div>
<div className="w-2 h-2 bg-[#d4af37] rounded-full"></div> <div className="w-2 h-2 bg-[var(--luxury-gold)] rounded-full"></div>
<div className="h-px w-12 bg-gradient-to-l from-transparent to-[#d4af37]"></div> <div className="h-px w-12 bg-gradient-to-l from-transparent to-[var(--luxury-gold)]"></div>
</div> </div>
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 lg:gap-10"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 lg:gap-10">
{team.map((member: any, index: number) => ( {team.map((member: any, index: number) => (
<div <div
key={index} key={index}
className="group relative bg-white rounded-2xl shadow-xl overflow-hidden hover:shadow-2xl transition-all duration-500 border border-gray-100 hover:border-[#d4af37]/30 hover:-translate-y-2" className="group relative bg-white rounded-2xl shadow-xl overflow-hidden hover:shadow-2xl transition-all duration-500 border border-gray-100 hover:border-[var(--luxury-gold)]/30 hover:-translate-y-2"
> >
<div className="absolute inset-0 bg-gradient-to-br from-[#d4af37]/5 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500 z-10"></div> <div className="absolute inset-0 bg-gradient-to-br from-[var(--luxury-gold)]/5 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500 z-10"></div>
{member.image && ( {member.image && (
<div className="relative overflow-hidden h-72"> <div className="relative overflow-hidden h-72">
<img <img
@@ -441,8 +441,8 @@ const AboutPage: React.FC = () => {
</div> </div>
)} )}
<div className="p-8 relative z-10"> <div className="p-8 relative z-10">
<h3 className="text-2xl font-serif font-semibold text-gray-900 mb-2 group-hover:text-[#d4af37] transition-colors duration-300">{member.name}</h3> <h3 className="text-2xl font-serif font-semibold text-gray-900 mb-2 group-hover:text-[var(--luxury-gold)] transition-colors duration-300">{member.name}</h3>
<p className="text-[#d4af37] font-medium mb-4 text-sm tracking-wide uppercase">{member.role}</p> <p className="text-[var(--luxury-gold)] font-medium mb-4 text-sm tracking-wide uppercase">{member.role}</p>
{member.bio && <p className="text-gray-600 text-sm mb-6 leading-relaxed font-light">{member.bio}</p>} {member.bio && <p className="text-gray-600 text-sm mb-6 leading-relaxed font-light">{member.bio}</p>}
{member.social_links && ( {member.social_links && (
<div className="flex gap-4 pt-4 border-t border-gray-100"> <div className="flex gap-4 pt-4 border-t border-gray-100">
@@ -451,7 +451,7 @@ const AboutPage: React.FC = () => {
href={member.social_links.linkedin} href={member.social_links.linkedin}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
className="w-10 h-10 rounded-full bg-gray-100 flex items-center justify-center text-gray-600 hover:bg-[#d4af37] hover:text-white transition-all duration-300 group-hover:scale-110" className="w-10 h-10 rounded-full bg-gray-100 flex items-center justify-center text-gray-600 hover:bg-[var(--luxury-gold)] hover:text-white transition-all duration-300 group-hover:scale-110"
> >
<Linkedin className="w-5 h-5" /> <Linkedin className="w-5 h-5" />
</a> </a>
@@ -461,7 +461,7 @@ const AboutPage: React.FC = () => {
href={member.social_links.twitter} href={member.social_links.twitter}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
className="w-10 h-10 rounded-full bg-gray-100 flex items-center justify-center text-gray-600 hover:bg-[#d4af37] hover:text-white transition-all duration-300 group-hover:scale-110" className="w-10 h-10 rounded-full bg-gray-100 flex items-center justify-center text-gray-600 hover:bg-[var(--luxury-gold)] hover:text-white transition-all duration-300 group-hover:scale-110"
> >
<Twitter className="w-5 h-5" /> <Twitter className="w-5 h-5" />
</a> </a>
@@ -485,30 +485,30 @@ const AboutPage: React.FC = () => {
<div className="max-w-6xl mx-auto"> <div className="max-w-6xl mx-auto">
<div className="text-center mb-16"> <div className="text-center mb-16">
<div className="inline-block mb-4"> <div className="inline-block mb-4">
<span className="text-sm font-semibold text-[#d4af37] tracking-[0.2em] uppercase">Our Journey</span> <span className="text-sm font-semibold text-[var(--luxury-gold)] tracking-[0.2em] uppercase">Our Journey</span>
</div> </div>
<h2 className="text-4xl md:text-5xl lg:text-6xl font-serif font-light text-gray-900 mb-6 tracking-tight"> <h2 className="text-4xl md:text-5xl lg:text-6xl font-serif font-light text-gray-900 mb-6 tracking-tight">
Our History Our History
</h2> </h2>
<div className="flex items-center justify-center gap-4 mb-6"> <div className="flex items-center justify-center gap-4 mb-6">
<div className="h-px w-12 bg-gradient-to-r from-transparent to-[#d4af37]"></div> <div className="h-px w-12 bg-gradient-to-r from-transparent to-[var(--luxury-gold)]"></div>
<div className="w-2 h-2 bg-[#d4af37] rounded-full"></div> <div className="w-2 h-2 bg-[var(--luxury-gold)] rounded-full"></div>
<div className="h-px w-12 bg-gradient-to-l from-transparent to-[#d4af37]"></div> <div className="h-px w-12 bg-gradient-to-l from-transparent to-[var(--luxury-gold)]"></div>
</div> </div>
</div> </div>
<div className="relative"> <div className="relative">
<div className="absolute left-8 md:left-1/2 transform md:-translate-x-1/2 w-1 h-full bg-gradient-to-b from-[#d4af37] via-[#f5d76e] to-[#d4af37] shadow-lg"></div> <div className="absolute left-8 md:left-1/2 transform md:-translate-x-1/2 w-1 h-full bg-gradient-to-b from-[var(--luxury-gold)] via-[var(--luxury-gold-light)] to-[var(--luxury-gold)] shadow-lg"></div>
<div className="space-y-12 md:space-y-16"> <div className="space-y-12 md:space-y-16">
{timeline.map((event: any, index: number) => ( {timeline.map((event: any, index: number) => (
<div key={index} className={`relative flex items-center ${index % 2 === 0 ? 'md:flex-row' : 'md:flex-row-reverse'}`}> <div key={index} className={`relative flex items-center ${index % 2 === 0 ? 'md:flex-row' : 'md:flex-row-reverse'}`}>
<div className="absolute left-6 md:left-1/2 transform md:-translate-x-1/2 w-6 h-6 bg-gradient-to-br from-[#d4af37] to-[#c9a227] rounded-full border-4 border-white shadow-xl z-10 group-hover:scale-125 transition-transform duration-300"></div> <div className="absolute left-6 md:left-1/2 transform md:-translate-x-1/2 w-6 h-6 bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] rounded-full border-4 border-white shadow-xl z-10 group-hover:scale-125 transition-transform duration-300"></div>
<div className={`ml-20 md:ml-0 md:w-5/12 ${index % 2 === 0 ? 'md:mr-auto md:pr-8' : 'md:ml-auto md:pl-8'}`}> <div className={`ml-20 md:ml-0 md:w-5/12 ${index % 2 === 0 ? 'md:mr-auto md:pr-8' : 'md:ml-auto md:pl-8'}`}>
<div className="group bg-white/90 backdrop-blur-sm p-8 rounded-2xl shadow-xl hover:shadow-2xl transition-all duration-500 border border-gray-100 hover:border-[#d4af37]/30"> <div className="group bg-white/90 backdrop-blur-sm p-8 rounded-2xl shadow-xl hover:shadow-2xl transition-all duration-500 border border-gray-100 hover:border-[var(--luxury-gold)]/30">
<div className="flex items-center gap-3 mb-4"> <div className="flex items-center gap-3 mb-4">
<div className="text-[#d4af37] font-bold text-2xl md:text-3xl font-serif">{event.year}</div> <div className="text-[var(--luxury-gold)] font-bold text-2xl md:text-3xl font-serif">{event.year}</div>
<div className="h-px flex-1 bg-gradient-to-r from-[#d4af37] to-transparent"></div> <div className="h-px flex-1 bg-gradient-to-r from-[var(--luxury-gold)] to-transparent"></div>
</div> </div>
<h3 className="text-2xl md:text-3xl font-serif font-semibold text-gray-900 mb-3 group-hover:text-[#d4af37] transition-colors duration-300">{event.title}</h3> <h3 className="text-2xl md:text-3xl font-serif font-semibold text-gray-900 mb-3 group-hover:text-[var(--luxury-gold)] transition-colors duration-300">{event.title}</h3>
<p className="text-gray-600 leading-relaxed font-light mb-4">{event.description}</p> <p className="text-gray-600 leading-relaxed font-light mb-4">{event.description}</p>
{event.image && ( {event.image && (
<div className="mt-6 overflow-hidden rounded-xl"> <div className="mt-6 overflow-hidden rounded-xl">
@@ -538,15 +538,15 @@ const AboutPage: React.FC = () => {
<div className="max-w-7xl mx-auto"> <div className="max-w-7xl mx-auto">
<div className="text-center mb-16"> <div className="text-center mb-16">
<div className="inline-block mb-4"> <div className="inline-block mb-4">
<span className="text-sm font-semibold text-[#d4af37] tracking-[0.2em] uppercase">Recognition</span> <span className="text-sm font-semibold text-[var(--luxury-gold)] tracking-[0.2em] uppercase">Recognition</span>
</div> </div>
<h2 className="text-4xl md:text-5xl lg:text-6xl font-serif font-light text-gray-900 mb-6 tracking-tight"> <h2 className="text-4xl md:text-5xl lg:text-6xl font-serif font-light text-gray-900 mb-6 tracking-tight">
Achievements & Awards Achievements & Awards
</h2> </h2>
<div className="flex items-center justify-center gap-4 mb-6"> <div className="flex items-center justify-center gap-4 mb-6">
<div className="h-px w-12 bg-gradient-to-r from-transparent to-[#d4af37]"></div> <div className="h-px w-12 bg-gradient-to-r from-transparent to-[var(--luxury-gold)]"></div>
<div className="w-2 h-2 bg-[#d4af37] rounded-full"></div> <div className="w-2 h-2 bg-[var(--luxury-gold)] rounded-full"></div>
<div className="h-px w-12 bg-gradient-to-l from-transparent to-[#d4af37]"></div> <div className="h-px w-12 bg-gradient-to-l from-transparent to-[var(--luxury-gold)]"></div>
</div> </div>
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 lg:gap-10"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 lg:gap-10">
@@ -555,19 +555,19 @@ const AboutPage: React.FC = () => {
return ( return (
<div <div
key={index} key={index}
className="group relative bg-gradient-to-br from-white to-slate-50 p-8 rounded-2xl shadow-xl hover:shadow-2xl transition-all duration-500 border border-gray-100 hover:border-[#d4af37]/40 hover:-translate-y-2" className="group relative bg-gradient-to-br from-white to-slate-50 p-8 rounded-2xl shadow-xl hover:shadow-2xl transition-all duration-500 border border-gray-100 hover:border-[var(--luxury-gold)]/40 hover:-translate-y-2"
> >
<div className="absolute top-0 right-0 w-32 h-32 bg-gradient-to-br from-[#d4af37]/10 to-transparent rounded-bl-full opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div> <div className="absolute top-0 right-0 w-32 h-32 bg-gradient-to-br from-[var(--luxury-gold)]/10 to-transparent rounded-bl-full opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
<div className="relative"> <div className="relative">
<div className="flex items-center gap-4 mb-6"> <div className="flex items-center gap-4 mb-6">
<div className="w-16 h-16 bg-gradient-to-br from-[#d4af37] via-[#f5d76e] to-[#d4af37] rounded-xl flex items-center justify-center shadow-lg shadow-[#d4af37]/20 group-hover:scale-110 group-hover:rotate-3 transition-transform duration-500"> <div className="w-16 h-16 bg-gradient-to-br from-[var(--luxury-gold)] via-[var(--luxury-gold-light)] to-[var(--luxury-gold)] rounded-xl flex items-center justify-center shadow-lg shadow-[var(--luxury-gold)]/20 group-hover:scale-110 group-hover:rotate-3 transition-transform duration-500">
<AchievementIcon className="w-8 h-8 text-white drop-shadow-md" /> <AchievementIcon className="w-8 h-8 text-white drop-shadow-md" />
</div> </div>
{achievement.year && ( {achievement.year && (
<div className="text-[#d4af37] font-bold text-2xl font-serif">{achievement.year}</div> <div className="text-[var(--luxury-gold)] font-bold text-2xl font-serif">{achievement.year}</div>
)} )}
</div> </div>
<h3 className="text-xl md:text-2xl font-serif font-semibold text-gray-900 mb-3 group-hover:text-[#d4af37] transition-colors duration-300">{achievement.title}</h3> <h3 className="text-xl md:text-2xl font-serif font-semibold text-gray-900 mb-3 group-hover:text-[var(--luxury-gold)] transition-colors duration-300">{achievement.title}</h3>
<p className="text-gray-600 text-sm md:text-base leading-relaxed font-light mb-4">{achievement.description}</p> <p className="text-gray-600 text-sm md:text-base leading-relaxed font-light mb-4">{achievement.description}</p>
{achievement.image && ( {achievement.image && (
<div className="mt-6 overflow-hidden rounded-xl"> <div className="mt-6 overflow-hidden rounded-xl">
@@ -595,15 +595,15 @@ const AboutPage: React.FC = () => {
<div className="max-w-6xl mx-auto"> <div className="max-w-6xl mx-auto">
<div className="text-center mb-16"> <div className="text-center mb-16">
<div className="inline-block mb-4"> <div className="inline-block mb-4">
<span className="text-sm font-semibold text-[#d4af37] tracking-[0.2em] uppercase">Connect With Us</span> <span className="text-sm font-semibold text-[var(--luxury-gold)] tracking-[0.2em] uppercase">Connect With Us</span>
</div> </div>
<h2 className="text-4xl md:text-5xl lg:text-6xl font-serif font-light text-gray-900 mb-6 tracking-tight"> <h2 className="text-4xl md:text-5xl lg:text-6xl font-serif font-light text-gray-900 mb-6 tracking-tight">
Get In Touch Get In Touch
</h2> </h2>
<div className="flex items-center justify-center gap-4 mb-6"> <div className="flex items-center justify-center gap-4 mb-6">
<div className="h-px w-12 bg-gradient-to-r from-transparent to-[#d4af37]"></div> <div className="h-px w-12 bg-gradient-to-r from-transparent to-[var(--luxury-gold)]"></div>
<div className="w-2 h-2 bg-[#d4af37] rounded-full"></div> <div className="w-2 h-2 bg-[var(--luxury-gold)] rounded-full"></div>
<div className="h-px w-12 bg-gradient-to-l from-transparent to-[#d4af37]"></div> <div className="h-px w-12 bg-gradient-to-l from-transparent to-[var(--luxury-gold)]"></div>
</div> </div>
<p className="text-gray-600 mt-6 text-lg font-light max-w-2xl mx-auto"> <p className="text-gray-600 mt-6 text-lg font-light max-w-2xl mx-auto">
We'd love to hear from you. Contact us for reservations or inquiries. We'd love to hear from you. Contact us for reservations or inquiries.
@@ -612,11 +612,11 @@ const AboutPage: React.FC = () => {
{(displayAddress || displayPhone || displayEmail) && ( {(displayAddress || displayPhone || displayEmail) && (
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 lg:gap-10 mb-16"> <div className="grid grid-cols-1 md:grid-cols-3 gap-8 lg:gap-10 mb-16">
{displayAddress && ( {displayAddress && (
<div className="group text-center p-8 bg-white/80 backdrop-blur-sm rounded-2xl shadow-xl hover:shadow-2xl transition-all duration-500 border border-gray-100 hover:border-[#d4af37]/40 hover:-translate-y-2"> <div className="group text-center p-8 bg-white/80 backdrop-blur-sm rounded-2xl shadow-xl hover:shadow-2xl transition-all duration-500 border border-gray-100 hover:border-[var(--luxury-gold)]/40 hover:-translate-y-2">
<div className="w-16 h-16 bg-gradient-to-br from-[#d4af37] via-[#f5d76e] to-[#d4af37] rounded-2xl flex items-center justify-center mx-auto mb-6 shadow-lg shadow-[#d4af37]/20 group-hover:scale-110 group-hover:rotate-3 transition-transform duration-500"> <div className="w-16 h-16 bg-gradient-to-br from-[var(--luxury-gold)] via-[var(--luxury-gold-light)] to-[var(--luxury-gold)] rounded-2xl flex items-center justify-center mx-auto mb-6 shadow-lg shadow-[var(--luxury-gold)]/20 group-hover:scale-110 group-hover:rotate-3 transition-transform duration-500">
<MapPin className="w-8 h-8 text-white drop-shadow-md" /> <MapPin className="w-8 h-8 text-white drop-shadow-md" />
</div> </div>
<h3 className="text-xl font-serif font-semibold text-gray-900 mb-4 group-hover:text-[#d4af37] transition-colors duration-300"> <h3 className="text-xl font-serif font-semibold text-gray-900 mb-4 group-hover:text-[var(--luxury-gold)] transition-colors duration-300">
Address Address
</h3> </h3>
<p className="text-gray-600 leading-relaxed font-light"> <p className="text-gray-600 leading-relaxed font-light">
@@ -631,30 +631,30 @@ const AboutPage: React.FC = () => {
</div> </div>
)} )}
{displayPhone && ( {displayPhone && (
<div className="group text-center p-8 bg-white/80 backdrop-blur-sm rounded-2xl shadow-xl hover:shadow-2xl transition-all duration-500 border border-gray-100 hover:border-[#d4af37]/40 hover:-translate-y-2" style={{ animationDelay: '0.1s' }}> <div className="group text-center p-8 bg-white/80 backdrop-blur-sm rounded-2xl shadow-xl hover:shadow-2xl transition-all duration-500 border border-gray-100 hover:border-[var(--luxury-gold)]/40 hover:-translate-y-2" style={{ animationDelay: '0.1s' }}>
<div className="w-16 h-16 bg-gradient-to-br from-[#d4af37] via-[#f5d76e] to-[#d4af37] rounded-2xl flex items-center justify-center mx-auto mb-6 shadow-lg shadow-[#d4af37]/20 group-hover:scale-110 group-hover:rotate-3 transition-transform duration-500"> <div className="w-16 h-16 bg-gradient-to-br from-[var(--luxury-gold)] via-[var(--luxury-gold-light)] to-[var(--luxury-gold)] rounded-2xl flex items-center justify-center mx-auto mb-6 shadow-lg shadow-[var(--luxury-gold)]/20 group-hover:scale-110 group-hover:rotate-3 transition-transform duration-500">
<Phone className="w-8 h-8 text-white drop-shadow-md" /> <Phone className="w-8 h-8 text-white drop-shadow-md" />
</div> </div>
<h3 className="text-xl font-serif font-semibold text-gray-900 mb-4 group-hover:text-[#d4af37] transition-colors duration-300"> <h3 className="text-xl font-serif font-semibold text-gray-900 mb-4 group-hover:text-[var(--luxury-gold)] transition-colors duration-300">
Phone Phone
</h3> </h3>
<p className="text-gray-600 font-light"> <p className="text-gray-600 font-light">
<a href={`tel:${displayPhone.replace(/\s+/g, '').replace(/[()]/g, '')}`} className="hover:text-[#d4af37] transition-colors duration-300"> <a href={`tel:${displayPhone.replace(/\s+/g, '').replace(/[()]/g, '')}`} className="hover:text-[var(--luxury-gold)] transition-colors duration-300">
{displayPhone} {displayPhone}
</a> </a>
</p> </p>
</div> </div>
)} )}
{displayEmail && ( {displayEmail && (
<div className="group text-center p-8 bg-white/80 backdrop-blur-sm rounded-2xl shadow-xl hover:shadow-2xl transition-all duration-500 border border-gray-100 hover:border-[#d4af37]/40 hover:-translate-y-2" style={{ animationDelay: '0.2s' }}> <div className="group text-center p-8 bg-white/80 backdrop-blur-sm rounded-2xl shadow-xl hover:shadow-2xl transition-all duration-500 border border-gray-100 hover:border-[var(--luxury-gold)]/40 hover:-translate-y-2" style={{ animationDelay: '0.2s' }}>
<div className="w-16 h-16 bg-gradient-to-br from-[#d4af37] via-[#f5d76e] to-[#d4af37] rounded-2xl flex items-center justify-center mx-auto mb-6 shadow-lg shadow-[#d4af37]/20 group-hover:scale-110 group-hover:rotate-3 transition-transform duration-500"> <div className="w-16 h-16 bg-gradient-to-br from-[var(--luxury-gold)] via-[var(--luxury-gold-light)] to-[var(--luxury-gold)] rounded-2xl flex items-center justify-center mx-auto mb-6 shadow-lg shadow-[var(--luxury-gold)]/20 group-hover:scale-110 group-hover:rotate-3 transition-transform duration-500">
<Mail className="w-8 h-8 text-white drop-shadow-md" /> <Mail className="w-8 h-8 text-white drop-shadow-md" />
</div> </div>
<h3 className="text-xl font-serif font-semibold text-gray-900 mb-4 group-hover:text-[#d4af37] transition-colors duration-300"> <h3 className="text-xl font-serif font-semibold text-gray-900 mb-4 group-hover:text-[var(--luxury-gold)] transition-colors duration-300">
Email Email
</h3> </h3>
<p className="text-gray-600 font-light"> <p className="text-gray-600 font-light">
<a href={`mailto:${displayEmail}`} className="hover:text-[#d4af37] transition-colors duration-300"> <a href={`mailto:${displayEmail}`} className="hover:text-[var(--luxury-gold)] transition-colors duration-300">
{displayEmail} {displayEmail}
</a> </a>
</p> </p>
@@ -665,11 +665,11 @@ const AboutPage: React.FC = () => {
<div className="text-center"> <div className="text-center">
<Link <Link
to="/rooms" to="/rooms"
className="group inline-flex items-center space-x-3 px-10 py-4 bg-gradient-to-r from-[#d4af37] via-[#f5d76e] to-[#d4af37] text-white rounded-xl hover:shadow-2xl hover:shadow-[#d4af37]/40 transition-all duration-500 font-medium text-lg tracking-wide relative overflow-hidden" className="group inline-flex items-center space-x-3 px-10 py-4 bg-gradient-to-r from-[var(--luxury-gold)] via-[var(--luxury-gold-light)] to-[var(--luxury-gold)] text-white rounded-xl hover:shadow-2xl hover:shadow-[var(--luxury-gold)]/40 transition-all duration-500 font-medium text-lg tracking-wide relative overflow-hidden"
> >
<span className="relative z-10">Explore Our Rooms</span> <span className="relative z-10">Explore Our Rooms</span>
<Hotel className="w-5 h-5 relative z-10 group-hover:translate-x-1 transition-transform duration-300" /> <Hotel className="w-5 h-5 relative z-10 group-hover:translate-x-1 transition-transform duration-300" />
<div className="absolute inset-0 bg-gradient-to-r from-[#f5d76e] to-[#d4af37] opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div> <div className="absolute inset-0 bg-gradient-to-r from-[var(--luxury-gold-light)] to-[var(--luxury-gold)] opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
</Link> </Link>
</div> </div>
</div> </div>

View File

@@ -94,12 +94,12 @@ const AccessibilityPage: React.FC = () => {
}} }}
> >
<div className="text-center"> <div className="text-center">
<Accessibility className="w-16 h-16 text-[#d4af37]/50 mx-auto mb-4" /> <Accessibility className="w-16 h-16 text-[var(--luxury-gold)]/50 mx-auto mb-4" />
<h1 className="text-2xl font-elegant font-bold text-white mb-2">Accessibility</h1> <h1 className="text-2xl font-elegant font-bold text-white mb-2">Accessibility</h1>
<p className="text-gray-400">This page is currently unavailable.</p> <p className="text-gray-400">This page is currently unavailable.</p>
<Link <Link
to="/" to="/"
className="inline-flex items-center gap-2 text-[#d4af37]/80 hover:text-[#d4af37] mt-6 transition-all duration-300" className="inline-flex items-center gap-2 text-[var(--luxury-gold)]/80 hover:text-[var(--luxury-gold)] mt-6 transition-all duration-300"
> >
<ArrowLeft className="w-4 h-4" /> <ArrowLeft className="w-4 h-4" />
<span>Back to Home</span> <span>Back to Home</span>
@@ -123,17 +123,17 @@ const AccessibilityPage: React.FC = () => {
<div className="w-full px-3 sm:px-4 md:px-6 lg:px-8 py-8 sm:py-12 max-w-5xl mx-auto"> <div className="w-full px-3 sm:px-4 md:px-6 lg:px-8 py-8 sm:py-12 max-w-5xl mx-auto">
<Link <Link
to="/" to="/"
className="inline-flex items-center gap-2 text-[#d4af37]/80 hover:text-[#d4af37] mb-6 transition-all duration-300 group font-light tracking-wide text-xs sm:text-sm" className="inline-flex items-center gap-2 text-[var(--luxury-gold)]/80 hover:text-[var(--luxury-gold)] mb-6 transition-all duration-300 group font-light tracking-wide text-xs sm:text-sm"
> >
<ArrowLeft className="w-4 h-4 group-hover:-translate-x-1 transition-transform" /> <ArrowLeft className="w-4 h-4 group-hover:-translate-x-1 transition-transform" />
<span>Back to Home</span> <span>Back to Home</span>
</Link> </Link>
<div className="mb-8 sm:mb-12 text-center"> <div className="mb-8 sm:mb-12 text-center">
<div className="inline-flex items-center justify-center w-16 h-16 sm:w-20 sm:h-20 mb-4 sm:mb-6 bg-gradient-to-br from-[#d4af37]/20 to-[#c9a227]/10 rounded-full border border-[#d4af37]/30"> <div className="inline-flex items-center justify-center w-16 h-16 sm:w-20 sm:h-20 mb-4 sm:mb-6 bg-gradient-to-br from-[var(--luxury-gold)]/20 to-[var(--luxury-gold-dark)]/10 rounded-full border border-[var(--luxury-gold)]/30">
<Accessibility className="w-8 h-8 sm:w-10 sm:h-10 text-[#d4af37]" /> <Accessibility className="w-8 h-8 sm:w-10 sm:h-10 text-[var(--luxury-gold)]" />
</div> </div>
<h1 className="text-3xl sm:text-4xl lg:text-5xl font-elegant font-bold text-white mb-3 sm:mb-4 tracking-tight leading-tight bg-gradient-to-r from-white via-[#d4af37] to-white bg-clip-text text-transparent"> <h1 className="text-3xl sm:text-4xl lg:text-5xl font-elegant font-bold text-white mb-3 sm:mb-4 tracking-tight leading-tight bg-gradient-to-r from-white via-[var(--luxury-gold)] to-white bg-clip-text text-transparent">
{pageContent.title || 'Accessibility'} {pageContent.title || 'Accessibility'}
</h1> </h1>
{pageContent.subtitle && ( {pageContent.subtitle && (
@@ -143,18 +143,18 @@ const AccessibilityPage: React.FC = () => {
)} )}
</div> </div>
<div className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-xl border border-[#d4af37]/20 backdrop-blur-xl shadow-2xl shadow-[#d4af37]/5 p-6 sm:p-8 lg:p-12"> <div className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-xl border border-[var(--luxury-gold)]/20 backdrop-blur-xl shadow-2xl shadow-[var(--luxury-gold)]/5 p-6 sm:p-8 lg:p-12">
<div <div
className="prose prose-invert prose-lg max-w-none text-gray-300 className="prose prose-invert prose-lg max-w-none text-gray-300
prose-headings:text-white prose-headings:font-elegant prose-headings:font-semibold prose-headings:text-white prose-headings:font-elegant prose-headings:font-semibold
prose-h2:text-2xl prose-h2:mt-8 prose-h2:mb-4 prose-h2:border-b prose-h2:border-[#d4af37]/20 prose-h2:pb-2 prose-h2:text-2xl prose-h2:mt-8 prose-h2:mb-4 prose-h2:border-b prose-h2:border-[var(--luxury-gold)]/20 prose-h2:pb-2
prose-p:text-gray-300 prose-p:font-light prose-p:leading-relaxed prose-p:mb-4 prose-p:text-gray-300 prose-p:font-light prose-p:leading-relaxed prose-p:mb-4
prose-ul:text-gray-300 prose-ul:font-light prose-ul:my-4 prose-ul:text-gray-300 prose-ul:font-light prose-ul:my-4
prose-li:text-gray-300 prose-li:mb-2 prose-li:ml-4 prose-li:text-gray-300 prose-li:mb-2 prose-li:ml-4
prose-strong:text-[#d4af37] prose-strong:font-medium prose-strong:text-[var(--luxury-gold)] prose-strong:font-medium
prose-a:text-[#d4af37] prose-a:no-underline hover:prose-a:underline prose-a:text-[var(--luxury-gold)] prose-a:no-underline hover:prose-a:underline
[&_*]:text-gray-300 [&_h1]:text-white [&_h2]:text-white [&_h3]:text-white [&_h4]:text-white [&_h5]:text-white [&_h6]:text-white [&_*]:text-gray-300 [&_h1]:text-white [&_h2]:text-white [&_h3]:text-white [&_h4]:text-white [&_h5]:text-white [&_h6]:text-white
[&_strong]:text-[#d4af37] [&_b]:text-[#d4af37] [&_a]:text-[#d4af37]" [&_strong]:text-[var(--luxury-gold)] [&_b]:text-[var(--luxury-gold)] [&_a]:text-[var(--luxury-gold)]"
style={{ color: '#d1d5db' }} style={{ color: '#d1d5db' }}
dangerouslySetInnerHTML={createSanitizedHtml( dangerouslySetInnerHTML={createSanitizedHtml(
pageContent.content || pageContent.description || '<p style="color: #d1d5db;">No content available.</p>' pageContent.content || pageContent.description || '<p style="color: #d1d5db;">No content available.</p>'
@@ -166,7 +166,7 @@ const AccessibilityPage: React.FC = () => {
<div className="mt-8 text-center"> <div className="mt-8 text-center">
<p className="text-sm text-gray-400 font-light"> <p className="text-sm text-gray-400 font-light">
For accessibility inquiries, contact us at{' '} For accessibility inquiries, contact us at{' '}
<a href={`mailto:${settings.company_email}`} className="text-[#d4af37] hover:underline"> <a href={`mailto:${settings.company_email}`} className="text-[var(--luxury-gold)] hover:underline">
{settings.company_email} {settings.company_email}
</a> </a>
</p> </p>

View File

@@ -111,7 +111,7 @@ const BlogDetailPage: React.FC = () => {
<div className="min-h-screen bg-gradient-to-b from-[#0f0f0f] via-[#1a1a1a] to-black text-white flex items-center justify-center"> <div className="min-h-screen bg-gradient-to-b from-[#0f0f0f] via-[#1a1a1a] to-black text-white flex items-center justify-center">
<div className="text-center"> <div className="text-center">
<h1 className="text-2xl font-bold mb-4">Post not found</h1> <h1 className="text-2xl font-bold mb-4">Post not found</h1>
<Link to="/blog" className="text-[#d4af37] hover:underline"> <Link to="/blog" className="text-[var(--luxury-gold)] hover:underline">
Back to Blog Back to Blog
</Link> </Link>
</div> </div>
@@ -140,7 +140,7 @@ const BlogDetailPage: React.FC = () => {
{/* Back Button */} {/* Back Button */}
<Link <Link
to="/blog" to="/blog"
className="inline-flex items-center gap-2 text-gray-400 hover:text-[#d4af37] transition-colors mb-8" className="inline-flex items-center gap-2 text-gray-400 hover:text-[var(--luxury-gold)] transition-colors mb-8"
> >
<ArrowLeft className="w-4 h-4" /> <ArrowLeft className="w-4 h-4" />
<span>Back to Blog</span> <span>Back to Blog</span>
@@ -154,7 +154,7 @@ const BlogDetailPage: React.FC = () => {
<Link <Link
key={tag} key={tag}
to={`/blog?tag=${encodeURIComponent(tag)}`} to={`/blog?tag=${encodeURIComponent(tag)}`}
className="inline-flex items-center gap-1 px-3 py-1 bg-[#d4af37]/10 text-[#d4af37] rounded-full text-sm font-medium hover:bg-[#d4af37]/20 transition-colors" className="inline-flex items-center gap-1 px-3 py-1 bg-[var(--luxury-gold)]/10 text-[var(--luxury-gold)] rounded-full text-sm font-medium hover:bg-[var(--luxury-gold)]/20 transition-colors"
> >
<Tag className="w-3 h-3" /> <Tag className="w-3 h-3" />
{tag} {tag}
@@ -173,7 +173,7 @@ const BlogDetailPage: React.FC = () => {
</p> </p>
)} )}
<div className="flex flex-wrap items-center gap-6 text-sm text-gray-400 pb-6 border-b border-[#d4af37]/20"> <div className="flex flex-wrap items-center gap-6 text-sm text-gray-400 pb-6 border-b border-[var(--luxury-gold)]/20">
{post.published_at && ( {post.published_at && (
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Calendar className="w-4 h-4" /> <Calendar className="w-4 h-4" />
@@ -192,7 +192,7 @@ const BlogDetailPage: React.FC = () => {
</div> </div>
<button <button
onClick={handleShare} onClick={handleShare}
className="flex items-center gap-2 text-[#d4af37] hover:text-[#f5d76e] transition-colors" className="flex items-center gap-2 text-[var(--luxury-gold)] hover:text-[var(--luxury-gold-light)] transition-colors"
> >
<Share2 className="w-4 h-4" /> <Share2 className="w-4 h-4" />
<span>Share</span> <span>Share</span>
@@ -203,17 +203,17 @@ const BlogDetailPage: React.FC = () => {
{/* Article Content */} {/* Article Content */}
<article className="prose prose-invert prose-lg max-w-none mb-12 <article className="prose prose-invert prose-lg max-w-none mb-12
prose-headings:text-white prose-headings:font-elegant prose-headings:font-semibold prose-headings:text-white prose-headings:font-elegant prose-headings:font-semibold
prose-h2:text-3xl prose-h2:mt-12 prose-h2:mb-6 prose-h2:border-b prose-h2:border-[#d4af37]/20 prose-h2:pb-3 prose-h2:text-3xl prose-h2:mt-12 prose-h2:mb-6 prose-h2:border-b prose-h2:border-[var(--luxury-gold)]/20 prose-h2:pb-3
prose-h3:text-2xl prose-h3:mt-8 prose-h3:mb-4 prose-h3:text-2xl prose-h3:mt-8 prose-h3:mb-4
prose-p:text-gray-300 prose-p:font-light prose-p:leading-relaxed prose-p:mb-6 prose-p:text-gray-300 prose-p:font-light prose-p:leading-relaxed prose-p:mb-6
prose-ul:text-gray-300 prose-ul:font-light prose-ul:my-6 prose-ul:text-gray-300 prose-ul:font-light prose-ul:my-6
prose-ol:text-gray-300 prose-ol:font-light prose-ol:my-6 prose-ol:text-gray-300 prose-ol:font-light prose-ol:my-6
prose-li:text-gray-300 prose-li:mb-2 prose-li:text-gray-300 prose-li:mb-2
prose-strong:text-[#d4af37] prose-strong:font-medium prose-strong:text-[var(--luxury-gold)] prose-strong:font-medium
prose-a:text-[#d4af37] prose-a:no-underline hover:prose-a:underline prose-a:text-[var(--luxury-gold)] prose-a:no-underline hover:prose-a:underline
prose-img:rounded-xl prose-img:shadow-2xl prose-img:rounded-xl prose-img:shadow-2xl
[&_*]:text-gray-300 [&_h1]:text-white [&_h2]:text-white [&_h3]:text-white [&_h4]:text-white [&_*]:text-gray-300 [&_h1]:text-white [&_h2]:text-white [&_h3]:text-white [&_h4]:text-white
[&_strong]:text-[#d4af37] [&_b]:text-[#d4af37] [&_a]:text-[#d4af37]" [&_strong]:text-[var(--luxury-gold)] [&_b]:text-[var(--luxury-gold)] [&_a]:text-[var(--luxury-gold)]"
> >
<div <div
dangerouslySetInnerHTML={createSanitizedHtml( dangerouslySetInnerHTML={createSanitizedHtml(
@@ -231,7 +231,7 @@ const BlogDetailPage: React.FC = () => {
<div key={index}> <div key={index}>
{/* Hero Section */} {/* Hero Section */}
{section.type === 'hero' && ( {section.type === 'hero' && (
<div className="relative rounded-3xl overflow-hidden border-2 border-[#d4af37]/20 shadow-2xl"> <div className="relative rounded-3xl overflow-hidden border-2 border-[var(--luxury-gold)]/20 shadow-2xl">
{section.image && ( {section.image && (
<div className="absolute inset-0"> <div className="absolute inset-0">
<img src={section.image} alt={section.title} className="w-full h-full object-cover" /> <img src={section.image} alt={section.title} className="w-full h-full object-cover" />
@@ -255,7 +255,7 @@ const BlogDetailPage: React.FC = () => {
{/* Text Section */} {/* Text Section */}
{section.type === 'text' && ( {section.type === 'text' && (
<div className={`bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] rounded-3xl border-2 border-[#d4af37]/20 p-8 md:p-12 shadow-xl ${ <div className={`bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] rounded-3xl border-2 border-[var(--luxury-gold)]/20 p-8 md:p-12 shadow-xl ${
section.alignment === 'center' ? 'text-center' : section.alignment === 'right' ? 'text-right' : 'text-left' section.alignment === 'center' ? 'text-center' : section.alignment === 'right' ? 'text-right' : 'text-left'
}`}> }`}>
{section.title && ( {section.title && (
@@ -274,10 +274,10 @@ const BlogDetailPage: React.FC = () => {
{/* Image Section */} {/* Image Section */}
{section.type === 'image' && section.image && ( {section.type === 'image' && section.image && (
<div className="rounded-3xl overflow-hidden border-2 border-[#d4af37]/20 shadow-2xl"> <div className="rounded-3xl overflow-hidden border-2 border-[var(--luxury-gold)]/20 shadow-2xl">
<img src={section.image} alt={section.title || 'Blog image'} className="w-full h-auto" /> <img src={section.image} alt={section.title || 'Blog image'} className="w-full h-auto" />
{section.title && ( {section.title && (
<div className="bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] px-6 py-4 border-t border-[#d4af37]/20"> <div className="bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] px-6 py-4 border-t border-[var(--luxury-gold)]/20">
<p className="text-gray-400 text-sm font-light italic text-center">{section.title}</p> <p className="text-gray-400 text-sm font-light italic text-center">{section.title}</p>
</div> </div>
)} )}
@@ -288,7 +288,7 @@ const BlogDetailPage: React.FC = () => {
{section.type === 'gallery' && section.images && section.images.length > 0 && ( {section.type === 'gallery' && section.images && section.images.length > 0 && (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{section.images.map((img, imgIndex) => ( {section.images.map((img, imgIndex) => (
<div key={imgIndex} className="rounded-2xl overflow-hidden border-2 border-[#d4af37]/20 shadow-xl group hover:border-[#d4af37]/50 transition-all"> <div key={imgIndex} className="rounded-2xl overflow-hidden border-2 border-[var(--luxury-gold)]/20 shadow-xl group hover:border-[var(--luxury-gold)]/50 transition-all">
<img src={img} alt={`Gallery image ${imgIndex + 1}`} className="w-full h-64 object-cover group-hover:scale-110 transition-transform duration-500" /> <img src={img} alt={`Gallery image ${imgIndex + 1}`} className="w-full h-64 object-cover group-hover:scale-110 transition-transform duration-500" />
</div> </div>
))} ))}
@@ -297,15 +297,15 @@ const BlogDetailPage: React.FC = () => {
{/* Quote Section */} {/* Quote Section */}
{section.type === 'quote' && ( {section.type === 'quote' && (
<div className="relative bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] rounded-3xl border-2 border-[#d4af37]/30 p-8 md:p-12 shadow-2xl"> <div className="relative bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] rounded-3xl border-2 border-[var(--luxury-gold)]/30 p-8 md:p-12 shadow-2xl">
<div className="absolute top-6 left-6 text-6xl text-[#d4af37]/20 font-serif">"</div> <div className="absolute top-6 left-6 text-6xl text-[var(--luxury-gold)]/20 font-serif">"</div>
{section.quote && ( {section.quote && (
<blockquote className="text-2xl md:text-3xl font-serif font-light text-white italic mb-6 relative z-10 pl-8"> <blockquote className="text-2xl md:text-3xl font-serif font-light text-white italic mb-6 relative z-10 pl-8">
{section.quote} {section.quote}
</blockquote> </blockquote>
)} )}
{section.author && ( {section.author && (
<cite className="text-[#d4af37] text-lg font-medium not-italic block text-right"> <cite className="text-[var(--luxury-gold)] text-lg font-medium not-italic block text-right">
— {section.author} — {section.author}
</cite> </cite>
)} )}
@@ -316,7 +316,7 @@ const BlogDetailPage: React.FC = () => {
{section.type === 'features' && section.features && ( {section.type === 'features' && section.features && (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{section.features.map((feature, featIndex) => ( {section.features.map((feature, featIndex) => (
<div key={featIndex} className="bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] rounded-2xl border-2 border-[#d4af37]/20 p-6 shadow-xl hover:border-[#d4af37]/50 transition-all"> <div key={featIndex} className="bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] rounded-2xl border-2 border-[var(--luxury-gold)]/20 p-6 shadow-xl hover:border-[var(--luxury-gold)]/50 transition-all">
{feature.icon && ( {feature.icon && (
<div className="text-4xl mb-4">{feature.icon}</div> <div className="text-4xl mb-4">{feature.icon}</div>
)} )}
@@ -329,7 +329,7 @@ const BlogDetailPage: React.FC = () => {
{/* CTA Section */} {/* CTA Section */}
{section.type === 'cta' && ( {section.type === 'cta' && (
<div className="relative bg-gradient-to-br from-[#d4af37]/10 via-[#c9a227]/5 to-[#d4af37]/10 rounded-3xl border-2 border-[#d4af37]/30 p-8 md:p-12 text-center shadow-2xl"> <div className="relative bg-gradient-to-br from-[var(--luxury-gold)]/10 via-[var(--luxury-gold-dark)]/5 to-[var(--luxury-gold)]/10 rounded-3xl border-2 border-[var(--luxury-gold)]/30 p-8 md:p-12 text-center shadow-2xl">
{section.title && ( {section.title && (
<h3 className="text-3xl md:text-4xl font-serif font-bold text-white mb-4"> <h3 className="text-3xl md:text-4xl font-serif font-bold text-white mb-4">
{section.title} {section.title}
@@ -343,7 +343,7 @@ const BlogDetailPage: React.FC = () => {
{section.cta_text && section.cta_link && ( {section.cta_text && section.cta_link && (
<a <a
href={section.cta_link} href={section.cta_link}
className="inline-flex items-center gap-3 px-8 py-4 bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-[#0f0f0f] font-semibold rounded-xl hover:from-[#f5d76e] hover:to-[#d4af37] transition-all shadow-lg hover:shadow-xl hover:scale-105" className="inline-flex items-center gap-3 px-8 py-4 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-[#0f0f0f] font-semibold rounded-xl hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] transition-all shadow-lg hover:shadow-xl hover:scale-105"
> >
{section.cta_text} {section.cta_text}
<ArrowRight className="w-5 h-5" /> <ArrowRight className="w-5 h-5" />
@@ -354,7 +354,7 @@ const BlogDetailPage: React.FC = () => {
{/* Video Section */} {/* Video Section */}
{section.type === 'video' && section.video_url && ( {section.type === 'video' && section.video_url && (
<div className="rounded-3xl overflow-hidden border-2 border-[#d4af37]/20 shadow-2xl bg-black"> <div className="rounded-3xl overflow-hidden border-2 border-[var(--luxury-gold)]/20 shadow-2xl bg-black">
<div className="aspect-video"> <div className="aspect-video">
<iframe <iframe
src={section.video_url.replace('watch?v=', 'embed/').replace('vimeo.com/', 'player.vimeo.com/video/')} src={section.video_url.replace('watch?v=', 'embed/').replace('vimeo.com/', 'player.vimeo.com/video/')}
@@ -372,14 +372,14 @@ const BlogDetailPage: React.FC = () => {
{/* Related Posts */} {/* Related Posts */}
{relatedPosts.length > 0 && ( {relatedPosts.length > 0 && (
<div className="mt-16 pt-12 border-t border-[#d4af37]/20"> <div className="mt-16 pt-12 border-t border-[var(--luxury-gold)]/20">
<h2 className="text-2xl sm:text-3xl font-bold text-white mb-8">Related Posts</h2> <h2 className="text-2xl sm:text-3xl font-bold text-white mb-8">Related Posts</h2>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6"> <div className="grid grid-cols-1 md:grid-cols-3 gap-6">
{relatedPosts.map((relatedPost) => ( {relatedPosts.map((relatedPost) => (
<Link <Link
key={relatedPost.id} key={relatedPost.id}
to={`/blog/${relatedPost.slug}`} to={`/blog/${relatedPost.slug}`}
className="group bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] rounded-xl border border-[#d4af37]/20 overflow-hidden hover:border-[#d4af37]/50 transition-all duration-300" className="group bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] rounded-xl border border-[var(--luxury-gold)]/20 overflow-hidden hover:border-[var(--luxury-gold)]/50 transition-all duration-300"
> >
{relatedPost.featured_image && ( {relatedPost.featured_image && (
<div className="relative h-40 overflow-hidden"> <div className="relative h-40 overflow-hidden">
@@ -391,7 +391,7 @@ const BlogDetailPage: React.FC = () => {
</div> </div>
)} )}
<div className="p-4"> <div className="p-4">
<h3 className="text-lg font-bold text-white mb-2 group-hover:text-[#d4af37] transition-colors line-clamp-2"> <h3 className="text-lg font-bold text-white mb-2 group-hover:text-[var(--luxury-gold)] transition-colors line-clamp-2">
{relatedPost.title} {relatedPost.title}
</h3> </h3>
{relatedPost.excerpt && ( {relatedPost.excerpt && (

View File

@@ -70,41 +70,41 @@ const BlogPage: React.FC = () => {
return ( return (
<div className="min-h-screen bg-gradient-to-b from-[#0f0f0f] via-[#1a1a1a] to-[#0f0f0f] w-full" style={{ width: '100vw', position: 'relative', left: '50%', right: '50%', marginLeft: '-50vw', marginRight: '-50vw', marginTop: '-1.5rem', marginBottom: '-1.5rem' }}> <div className="min-h-screen bg-gradient-to-b from-[#0f0f0f] via-[#1a1a1a] to-[#0f0f0f] w-full" style={{ width: '100vw', position: 'relative', left: '50%', right: '50%', marginLeft: '-50vw', marginRight: '-50vw', marginTop: '-1.5rem', marginBottom: '-1.5rem' }}>
{/* Hero Section */} {/* Hero Section */}
<div className="w-full bg-gradient-to-br from-[#1a1a1a] via-[#0f0f0f] to-[#1a1a1a] border-b border-[#d4af37]/10 pt-6 sm:pt-7 md:pt-8 overflow-hidden relative"> <div className="w-full bg-gradient-to-br from-[#1a1a1a] via-[#0f0f0f] to-[#1a1a1a] border-b border-[var(--luxury-gold)]/10 pt-6 sm:pt-7 md:pt-8 overflow-hidden relative">
{/* Background Effects */} {/* Background Effects */}
<div className="absolute inset-0 opacity-10"> <div className="absolute inset-0 opacity-10">
<div className="absolute top-10 left-10 w-32 sm:w-48 h-32 sm:h-48 bg-[#d4af37] rounded-full blur-3xl"></div> <div className="absolute top-10 left-10 w-32 sm:w-48 h-32 sm:h-48 bg-[var(--luxury-gold)] rounded-full blur-3xl"></div>
<div className="absolute bottom-10 right-10 w-40 sm:w-64 h-40 sm:h-64 bg-[#c9a227] rounded-full blur-3xl"></div> <div className="absolute bottom-10 right-10 w-40 sm:w-64 h-40 sm:h-64 bg-[var(--luxury-gold-dark)] rounded-full blur-3xl"></div>
</div> </div>
<div className="absolute top-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-[#d4af37]/50 to-transparent"></div> <div className="absolute top-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-[var(--luxury-gold)]/50 to-transparent"></div>
<div className="w-full max-w-[1920px] mx-auto px-3 sm:px-4 md:px-6 lg:px-8 xl:px-12 2xl:px-16 3xl:px-20 py-4 sm:py-5 md:py-6 relative z-10"> <div className="w-full max-w-[1920px] mx-auto px-3 sm:px-4 md:px-6 lg:px-8 xl:px-12 2xl:px-16 3xl:px-20 py-4 sm:py-5 md:py-6 relative z-10">
<div className="max-w-2xl mx-auto text-center px-2"> <div className="max-w-2xl mx-auto text-center px-2">
<div className="flex justify-center mb-2 sm:mb-3 md:mb-4"> <div className="flex justify-center mb-2 sm:mb-3 md:mb-4">
<div className="relative group"> <div className="relative group">
<div className="absolute inset-0 bg-gradient-to-br from-[#d4af37] via-[#f5d76e] to-[#c9a227] rounded-xl blur-lg opacity-40 group-hover:opacity-60 transition-opacity duration-500"></div> <div className="absolute inset-0 bg-gradient-to-br from-[var(--luxury-gold)] via-[var(--luxury-gold-light)] to-[var(--luxury-gold-dark)] rounded-xl blur-lg opacity-40 group-hover:opacity-60 transition-opacity duration-500"></div>
<div className="relative p-2 sm:p-2.5 md:p-3 bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-lg border-2 border-[#d4af37]/40 backdrop-blur-sm shadow-xl shadow-[#d4af37]/20 group-hover:border-[#d4af37]/60 transition-all duration-300"> <div className="relative p-2 sm:p-2.5 md:p-3 bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-lg border-2 border-[var(--luxury-gold)]/40 backdrop-blur-sm shadow-xl shadow-[var(--luxury-gold)]/20 group-hover:border-[var(--luxury-gold)]/60 transition-all duration-300">
<BookOpen className="w-5 h-5 sm:w-6 sm:h-6 md:w-7 md:h-7 text-[#d4af37] drop-shadow-lg" /> <BookOpen className="w-5 h-5 sm:w-6 sm:h-6 md:w-7 md:h-7 text-[var(--luxury-gold)] drop-shadow-lg" />
</div> </div>
</div> </div>
</div> </div>
<h1 className="text-2xl xs:text-3xl sm:text-4xl md:text-5xl font-serif font-semibold mb-2 sm:mb-3 tracking-tight leading-tight px-2"> <h1 className="text-2xl xs:text-3xl sm:text-4xl md:text-5xl font-serif font-semibold mb-2 sm:mb-3 tracking-tight leading-tight px-2">
<span className="bg-gradient-to-r from-white via-[#d4af37] to-white bg-clip-text text-transparent"> <span className="bg-gradient-to-r from-white via-[var(--luxury-gold)] to-white bg-clip-text text-transparent">
Our Blog Our Blog
</span> </span>
</h1> </h1>
<div className="w-12 sm:w-16 md:w-20 h-0.5 bg-gradient-to-r from-transparent via-[#d4af37] to-transparent mx-auto mb-2 sm:mb-3"></div> <div className="w-12 sm:w-16 md:w-20 h-0.5 bg-gradient-to-r from-transparent via-[var(--luxury-gold)] to-transparent mx-auto mb-2 sm:mb-3"></div>
<p className="text-sm sm:text-base md:text-lg text-gray-300 font-light leading-relaxed max-w-xl mx-auto tracking-wide px-2 sm:px-4"> <p className="text-sm sm:text-base md:text-lg text-gray-300 font-light leading-relaxed max-w-xl mx-auto tracking-wide px-2 sm:px-4">
Discover stories, insights, and updates from our luxury hotel Discover stories, insights, and updates from our luxury hotel
</p> </p>
<div className="mt-4 flex items-center justify-center gap-2 text-[#d4af37]/60"> <div className="mt-4 flex items-center justify-center gap-2 text-[var(--luxury-gold)]/60">
<Sparkles className="w-4 h-4 animate-pulse" /> <Sparkles className="w-4 h-4 animate-pulse" />
<span className="text-xs sm:text-sm font-light tracking-wider uppercase">Premium Content</span> <span className="text-xs sm:text-sm font-light tracking-wider uppercase">Premium Content</span>
<Sparkles className="w-4 h-4 animate-pulse" style={{ animationDelay: '0.5s' }} /> <Sparkles className="w-4 h-4 animate-pulse" style={{ animationDelay: '0.5s' }} />
</div> </div>
</div> </div>
</div> </div>
<div className="absolute bottom-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-[#d4af37]/30 to-transparent"></div> <div className="absolute bottom-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-[var(--luxury-gold)]/30 to-transparent"></div>
</div> </div>
{/* Main Content - Full Width */} {/* Main Content - Full Width */}
@@ -114,9 +114,9 @@ const BlogPage: React.FC = () => {
<div className="mb-12 sm:mb-16"> <div className="mb-12 sm:mb-16">
<div className="flex flex-col lg:flex-row gap-6 mb-8"> <div className="flex flex-col lg:flex-row gap-6 mb-8">
<div className="flex-1 relative group"> <div className="flex-1 relative group">
<div className="absolute inset-0 bg-gradient-to-r from-[#d4af37]/10 to-transparent rounded-xl blur-xl opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div> <div className="absolute inset-0 bg-gradient-to-r from-[var(--luxury-gold)]/10 to-transparent rounded-xl blur-xl opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
<div className="relative"> <div className="relative">
<Search className="absolute left-5 top-1/2 transform -translate-y-1/2 text-[#d4af37] w-5 h-5 z-10" /> <Search className="absolute left-5 top-1/2 transform -translate-y-1/2 text-[var(--luxury-gold)] w-5 h-5 z-10" />
<input <input
type="text" type="text"
placeholder="Search blog posts..." placeholder="Search blog posts..."
@@ -125,7 +125,7 @@ const BlogPage: React.FC = () => {
setSearchTerm(e.target.value); setSearchTerm(e.target.value);
setCurrentPage(1); setCurrentPage(1);
}} }}
className="w-full pl-14 pr-5 py-4 bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] border border-[#d4af37]/20 rounded-xl text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37]/50 transition-all duration-300 backdrop-blur-sm font-light" className="w-full pl-14 pr-5 py-4 bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] border border-[var(--luxury-gold)]/20 rounded-xl text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)]/50 transition-all duration-300 backdrop-blur-sm font-light"
/> />
</div> </div>
</div> </div>
@@ -147,8 +147,8 @@ const BlogPage: React.FC = () => {
{/* Blog Posts Grid - Luxury Design */} {/* Blog Posts Grid - Luxury Design */}
{posts.length === 0 ? ( {posts.length === 0 ? (
<div className="text-center py-20"> <div className="text-center py-20">
<div className="inline-flex items-center justify-center w-20 h-20 rounded-full bg-[#d4af37]/10 mb-6"> <div className="inline-flex items-center justify-center w-20 h-20 rounded-full bg-[var(--luxury-gold)]/10 mb-6">
<BookOpen className="w-10 h-10 text-[#d4af37]" /> <BookOpen className="w-10 h-10 text-[var(--luxury-gold)]" />
</div> </div>
<p className="text-gray-400 text-xl font-light">No blog posts found</p> <p className="text-gray-400 text-xl font-light">No blog posts found</p>
<p className="text-gray-500 text-sm mt-2">Try adjusting your search or filters</p> <p className="text-gray-500 text-sm mt-2">Try adjusting your search or filters</p>
@@ -160,12 +160,12 @@ const BlogPage: React.FC = () => {
<Link <Link
key={post.id} key={post.id}
to={`/blog/${post.slug}`} to={`/blog/${post.slug}`}
className="group relative bg-gradient-to-br from-[#1a1a1a] via-[#0f0f0f] to-[#0a0a0a] rounded-3xl border-2 border-[#d4af37]/20 overflow-hidden hover:border-[#d4af37]/60 transition-all duration-700 hover:shadow-2xl hover:shadow-[#d4af37]/30 hover:-translate-y-3" className="group relative bg-gradient-to-br from-[#1a1a1a] via-[#0f0f0f] to-[#0a0a0a] rounded-3xl border-2 border-[var(--luxury-gold)]/20 overflow-hidden hover:border-[var(--luxury-gold)]/60 transition-all duration-700 hover:shadow-2xl hover:shadow-[var(--luxury-gold)]/30 hover:-translate-y-3"
style={{ animationDelay: `${index * 50}ms` }} style={{ animationDelay: `${index * 50}ms` }}
> >
{/* Premium Glow Effects */} {/* Premium Glow Effects */}
<div className="absolute inset-0 bg-gradient-to-br from-[#d4af37]/0 via-[#d4af37]/0 to-[#d4af37]/0 group-hover:from-[#d4af37]/10 group-hover:via-[#d4af37]/5 group-hover:to-[#d4af37]/10 transition-all duration-700 rounded-3xl blur-2xl opacity-0 group-hover:opacity-100"></div> <div className="absolute inset-0 bg-gradient-to-br from-[var(--luxury-gold)]/0 via-[var(--luxury-gold)]/0 to-[var(--luxury-gold)]/0 group-hover:from-[var(--luxury-gold)]/10 group-hover:via-[var(--luxury-gold)]/5 group-hover:to-[var(--luxury-gold)]/10 transition-all duration-700 rounded-3xl blur-2xl opacity-0 group-hover:opacity-100"></div>
<div className="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-transparent via-[#d4af37]/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div> <div className="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-transparent via-[var(--luxury-gold)]/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
{/* Content */} {/* Content */}
<div className="relative z-10"> <div className="relative z-10">
@@ -179,15 +179,15 @@ const BlogPage: React.FC = () => {
/> />
{/* Premium Badge Overlay */} {/* Premium Badge Overlay */}
<div className="absolute top-6 left-6 z-20"> <div className="absolute top-6 left-6 z-20">
<div className="bg-gradient-to-br from-[#d4af37]/20 to-[#c9a227]/10 backdrop-blur-md rounded-2xl px-4 py-2 border border-[#d4af37]/40 shadow-xl"> <div className="bg-gradient-to-br from-[var(--luxury-gold)]/20 to-[var(--luxury-gold-dark)]/10 backdrop-blur-md rounded-2xl px-4 py-2 border border-[var(--luxury-gold)]/40 shadow-xl">
<div className="flex items-center gap-2 text-[#d4af37]"> <div className="flex items-center gap-2 text-[var(--luxury-gold)]">
<Eye className="w-4 h-4" /> <Eye className="w-4 h-4" />
<span className="text-sm font-semibold">{post.views_count}</span> <span className="text-sm font-semibold">{post.views_count}</span>
</div> </div>
</div> </div>
</div> </div>
{/* Luxury Corner Accent */} {/* Luxury Corner Accent */}
<div className="absolute top-0 right-0 w-32 h-32 bg-gradient-to-br from-[#d4af37]/20 to-transparent rounded-bl-full opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div> <div className="absolute top-0 right-0 w-32 h-32 bg-gradient-to-br from-[var(--luxury-gold)]/20 to-transparent rounded-bl-full opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
</div> </div>
)} )}
<div className="p-8"> <div className="p-8">
@@ -196,7 +196,7 @@ const BlogPage: React.FC = () => {
{post.tags.slice(0, 2).map((tag) => ( {post.tags.slice(0, 2).map((tag) => (
<span <span
key={tag} key={tag}
className="inline-flex items-center gap-1.5 px-4 py-1.5 bg-gradient-to-br from-[#d4af37]/15 to-[#d4af37]/5 text-[#d4af37] rounded-full text-xs font-semibold border border-[#d4af37]/30 backdrop-blur-sm shadow-lg" className="inline-flex items-center gap-1.5 px-4 py-1.5 bg-gradient-to-br from-[var(--luxury-gold)]/15 to-[var(--luxury-gold)]/5 text-[var(--luxury-gold)] rounded-full text-xs font-semibold border border-[var(--luxury-gold)]/30 backdrop-blur-sm shadow-lg"
> >
<Tag className="w-3 h-3" /> <Tag className="w-3 h-3" />
{tag} {tag}
@@ -204,7 +204,7 @@ const BlogPage: React.FC = () => {
))} ))}
</div> </div>
)} )}
<h2 className="text-2xl sm:text-3xl font-serif font-bold text-white mb-4 group-hover:text-[#d4af37] transition-colors duration-500 line-clamp-2 leading-tight tracking-tight"> <h2 className="text-2xl sm:text-3xl font-serif font-bold text-white mb-4 group-hover:text-[var(--luxury-gold)] transition-colors duration-500 line-clamp-2 leading-tight tracking-tight">
{post.title} {post.title}
</h2> </h2>
{post.excerpt && ( {post.excerpt && (
@@ -212,28 +212,28 @@ const BlogPage: React.FC = () => {
{post.excerpt} {post.excerpt}
</p> </p>
)} )}
<div className="flex items-center justify-between text-sm text-gray-400 pt-6 border-t border-[#d4af37]/20 mb-6"> <div className="flex items-center justify-between text-sm text-gray-400 pt-6 border-t border-[var(--luxury-gold)]/20 mb-6">
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
{post.published_at && ( {post.published_at && (
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Calendar className="w-4 h-4 text-[#d4af37]" /> <Calendar className="w-4 h-4 text-[var(--luxury-gold)]" />
<span className="font-light">{formatDate(post.published_at)}</span> <span className="font-light">{formatDate(post.published_at)}</span>
</div> </div>
)} )}
</div> </div>
{post.author_name && ( {post.author_name && (
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<User className="w-4 h-4 text-[#d4af37]" /> <User className="w-4 h-4 text-[var(--luxury-gold)]" />
<span className="font-light">{post.author_name}</span> <span className="font-light">{post.author_name}</span>
</div> </div>
)} )}
</div> </div>
<div className="flex items-center justify-between pt-4 border-t border-[#d4af37]/10"> <div className="flex items-center justify-between pt-4 border-t border-[var(--luxury-gold)]/10">
<div className="flex items-center gap-3 text-[#d4af37] group-hover:gap-4 transition-all duration-300"> <div className="flex items-center gap-3 text-[var(--luxury-gold)] group-hover:gap-4 transition-all duration-300">
<span className="text-sm font-semibold tracking-wide uppercase">Read Article</span> <span className="text-sm font-semibold tracking-wide uppercase">Read Article</span>
<ArrowRight className="w-5 h-5 group-hover:translate-x-2 transition-transform duration-300" /> <ArrowRight className="w-5 h-5 group-hover:translate-x-2 transition-transform duration-300" />
</div> </div>
<div className="w-12 h-0.5 bg-gradient-to-r from-[#d4af37] to-transparent group-hover:w-20 transition-all duration-500"></div> <div className="w-12 h-0.5 bg-gradient-to-r from-[var(--luxury-gold)] to-transparent group-hover:w-20 transition-all duration-500"></div>
</div> </div>
</div> </div>
</div> </div>
@@ -259,9 +259,9 @@ const BlogPage: React.FC = () => {
<div className="lg:col-span-3"> <div className="lg:col-span-3">
{allTags.length > 0 && ( {allTags.length > 0 && (
<div className="sticky top-8"> <div className="sticky top-8">
<div className="bg-gradient-to-br from-[#1a1a1a] via-[#0f0f0f] to-[#0a0a0a] rounded-3xl border-2 border-[#d4af37]/20 p-8 backdrop-blur-xl shadow-2xl"> <div className="bg-gradient-to-br from-[#1a1a1a] via-[#0f0f0f] to-[#0a0a0a] rounded-3xl border-2 border-[var(--luxury-gold)]/20 p-8 backdrop-blur-xl shadow-2xl">
<div className="flex items-center gap-3 mb-6 pb-6 border-b border-[#d4af37]/20"> <div className="flex items-center gap-3 mb-6 pb-6 border-b border-[var(--luxury-gold)]/20">
<div className="w-1 h-8 bg-gradient-to-b from-[#d4af37] to-[#c9a227] rounded-full"></div> <div className="w-1 h-8 bg-gradient-to-b from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] rounded-full"></div>
<h3 className="text-xl font-serif font-bold text-white">Filter by Tags</h3> <h3 className="text-xl font-serif font-bold text-white">Filter by Tags</h3>
</div> </div>
<div className="space-y-3"> <div className="space-y-3">
@@ -272,8 +272,8 @@ const BlogPage: React.FC = () => {
}} }}
className={`group relative w-full text-left px-5 py-4 rounded-2xl text-sm font-medium transition-all duration-300 overflow-hidden ${ className={`group relative w-full text-left px-5 py-4 rounded-2xl text-sm font-medium transition-all duration-300 overflow-hidden ${
selectedTag === null selectedTag === null
? 'bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-[#0f0f0f] shadow-lg shadow-[#d4af37]/40' ? 'bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-[#0f0f0f] shadow-lg shadow-[var(--luxury-gold)]/40'
: 'bg-gradient-to-br from-[#0f0f0f] to-[#0a0a0a] text-gray-300 border-2 border-[#d4af37]/20 hover:border-[#d4af37]/50 hover:text-[#d4af37] hover:bg-[#1a1a1a]' : 'bg-gradient-to-br from-[#0f0f0f] to-[#0a0a0a] text-gray-300 border-2 border-[var(--luxury-gold)]/20 hover:border-[var(--luxury-gold)]/50 hover:text-[var(--luxury-gold)] hover:bg-[#1a1a1a]'
}`} }`}
> >
<span className="relative z-10 flex items-center gap-2"> <span className="relative z-10 flex items-center gap-2">
@@ -293,8 +293,8 @@ const BlogPage: React.FC = () => {
}} }}
className={`group relative w-full text-left px-5 py-4 rounded-2xl text-sm font-medium transition-all duration-300 overflow-hidden ${ className={`group relative w-full text-left px-5 py-4 rounded-2xl text-sm font-medium transition-all duration-300 overflow-hidden ${
selectedTag === tag selectedTag === tag
? 'bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-[#0f0f0f] shadow-lg shadow-[#d4af37]/40' ? 'bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-[#0f0f0f] shadow-lg shadow-[var(--luxury-gold)]/40'
: 'bg-gradient-to-br from-[#0f0f0f] to-[#0a0a0a] text-gray-300 border-2 border-[#d4af37]/20 hover:border-[#d4af37]/50 hover:text-[#d4af37] hover:bg-[#1a1a1a]' : 'bg-gradient-to-br from-[#0f0f0f] to-[#0a0a0a] text-gray-300 border-2 border-[var(--luxury-gold)]/20 hover:border-[var(--luxury-gold)]/50 hover:text-[var(--luxury-gold)] hover:bg-[#1a1a1a]'
}`} }`}
> >
<span className="relative z-10 flex items-center gap-2"> <span className="relative z-10 flex items-center gap-2">

View File

@@ -94,12 +94,12 @@ const CancellationPolicyPage: React.FC = () => {
}} }}
> >
<div className="text-center"> <div className="text-center">
<XCircle className="w-16 h-16 text-[#d4af37]/50 mx-auto mb-4" /> <XCircle className="w-16 h-16 text-[var(--luxury-gold)]/50 mx-auto mb-4" />
<h1 className="text-2xl font-elegant font-bold text-white mb-2">Cancellation Policy</h1> <h1 className="text-2xl font-elegant font-bold text-white mb-2">Cancellation Policy</h1>
<p className="text-gray-400">This page is currently unavailable.</p> <p className="text-gray-400">This page is currently unavailable.</p>
<Link <Link
to="/" to="/"
className="inline-flex items-center gap-2 text-[#d4af37]/80 hover:text-[#d4af37] mt-6 transition-all duration-300" className="inline-flex items-center gap-2 text-[var(--luxury-gold)]/80 hover:text-[var(--luxury-gold)] mt-6 transition-all duration-300"
> >
<ArrowLeft className="w-4 h-4" /> <ArrowLeft className="w-4 h-4" />
<span>Back to Home</span> <span>Back to Home</span>
@@ -123,17 +123,17 @@ const CancellationPolicyPage: React.FC = () => {
<div className="w-full px-3 sm:px-4 md:px-6 lg:px-8 py-8 sm:py-12 max-w-5xl mx-auto"> <div className="w-full px-3 sm:px-4 md:px-6 lg:px-8 py-8 sm:py-12 max-w-5xl mx-auto">
<Link <Link
to="/" to="/"
className="inline-flex items-center gap-2 text-[#d4af37]/80 hover:text-[#d4af37] mb-6 transition-all duration-300 group font-light tracking-wide text-xs sm:text-sm" className="inline-flex items-center gap-2 text-[var(--luxury-gold)]/80 hover:text-[var(--luxury-gold)] mb-6 transition-all duration-300 group font-light tracking-wide text-xs sm:text-sm"
> >
<ArrowLeft className="w-4 h-4 group-hover:-translate-x-1 transition-transform" /> <ArrowLeft className="w-4 h-4 group-hover:-translate-x-1 transition-transform" />
<span>Back to Home</span> <span>Back to Home</span>
</Link> </Link>
<div className="mb-8 sm:mb-12 text-center"> <div className="mb-8 sm:mb-12 text-center">
<div className="inline-flex items-center justify-center w-16 h-16 sm:w-20 sm:h-20 mb-4 sm:mb-6 bg-gradient-to-br from-[#d4af37]/20 to-[#c9a227]/10 rounded-full border border-[#d4af37]/30"> <div className="inline-flex items-center justify-center w-16 h-16 sm:w-20 sm:h-20 mb-4 sm:mb-6 bg-gradient-to-br from-[var(--luxury-gold)]/20 to-[var(--luxury-gold-dark)]/10 rounded-full border border-[var(--luxury-gold)]/30">
<XCircle className="w-8 h-8 sm:w-10 sm:h-10 text-[#d4af37]" /> <XCircle className="w-8 h-8 sm:w-10 sm:h-10 text-[var(--luxury-gold)]" />
</div> </div>
<h1 className="text-3xl sm:text-4xl lg:text-5xl font-elegant font-bold text-white mb-3 sm:mb-4 tracking-tight leading-tight bg-gradient-to-r from-white via-[#d4af37] to-white bg-clip-text text-transparent"> <h1 className="text-3xl sm:text-4xl lg:text-5xl font-elegant font-bold text-white mb-3 sm:mb-4 tracking-tight leading-tight bg-gradient-to-r from-white via-[var(--luxury-gold)] to-white bg-clip-text text-transparent">
{pageContent.title || 'Cancellation Policy'} {pageContent.title || 'Cancellation Policy'}
</h1> </h1>
{pageContent.subtitle && ( {pageContent.subtitle && (
@@ -143,18 +143,18 @@ const CancellationPolicyPage: React.FC = () => {
)} )}
</div> </div>
<div className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-xl border border-[#d4af37]/20 backdrop-blur-xl shadow-2xl shadow-[#d4af37]/5 p-6 sm:p-8 lg:p-12"> <div className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-xl border border-[var(--luxury-gold)]/20 backdrop-blur-xl shadow-2xl shadow-[var(--luxury-gold)]/5 p-6 sm:p-8 lg:p-12">
<div <div
className="prose prose-invert prose-lg max-w-none text-gray-300 className="prose prose-invert prose-lg max-w-none text-gray-300
prose-headings:text-white prose-headings:font-elegant prose-headings:font-semibold prose-headings:text-white prose-headings:font-elegant prose-headings:font-semibold
prose-h2:text-2xl prose-h2:mt-8 prose-h2:mb-4 prose-h2:border-b prose-h2:border-[#d4af37]/20 prose-h2:pb-2 prose-h2:text-2xl prose-h2:mt-8 prose-h2:mb-4 prose-h2:border-b prose-h2:border-[var(--luxury-gold)]/20 prose-h2:pb-2
prose-p:text-gray-300 prose-p:font-light prose-p:leading-relaxed prose-p:mb-4 prose-p:text-gray-300 prose-p:font-light prose-p:leading-relaxed prose-p:mb-4
prose-ul:text-gray-300 prose-ul:font-light prose-ul:my-4 prose-ul:text-gray-300 prose-ul:font-light prose-ul:my-4
prose-li:text-gray-300 prose-li:mb-2 prose-li:ml-4 prose-li:text-gray-300 prose-li:mb-2 prose-li:ml-4
prose-strong:text-[#d4af37] prose-strong:font-medium prose-strong:text-[var(--luxury-gold)] prose-strong:font-medium
prose-a:text-[#d4af37] prose-a:no-underline hover:prose-a:underline prose-a:text-[var(--luxury-gold)] prose-a:no-underline hover:prose-a:underline
[&_*]:text-gray-300 [&_h1]:text-white [&_h2]:text-white [&_h3]:text-white [&_h4]:text-white [&_h5]:text-white [&_h6]:text-white [&_*]:text-gray-300 [&_h1]:text-white [&_h2]:text-white [&_h3]:text-white [&_h4]:text-white [&_h5]:text-white [&_h6]:text-white
[&_strong]:text-[#d4af37] [&_b]:text-[#d4af37] [&_a]:text-[#d4af37]" [&_strong]:text-[var(--luxury-gold)] [&_b]:text-[var(--luxury-gold)] [&_a]:text-[var(--luxury-gold)]"
style={{ color: '#d1d5db' }} style={{ color: '#d1d5db' }}
dangerouslySetInnerHTML={createSanitizedHtml( dangerouslySetInnerHTML={createSanitizedHtml(
pageContent.content || pageContent.description || '<p style="color: #d1d5db;">No content available.</p>' pageContent.content || pageContent.description || '<p style="color: #d1d5db;">No content available.</p>'
@@ -166,7 +166,7 @@ const CancellationPolicyPage: React.FC = () => {
<div className="mt-8 text-center"> <div className="mt-8 text-center">
<p className="text-sm text-gray-400 font-light"> <p className="text-sm text-gray-400 font-light">
For questions about cancellations, contact us at{' '} For questions about cancellations, contact us at{' '}
<a href={`mailto:${settings.company_email}`} className="text-[#d4af37] hover:underline"> <a href={`mailto:${settings.company_email}`} className="text-[var(--luxury-gold)] hover:underline">
{settings.company_email} {settings.company_email}
</a> </a>
</p> </p>

View File

@@ -174,36 +174,36 @@ const ContactPage: React.FC = () => {
return ( return (
<div className="min-h-screen bg-gradient-to-b from-[#0f0f0f] via-[#1a1a1a] to-[#0f0f0f] w-full" style={{ width: '100vw', position: 'relative', left: '50%', right: '50%', marginLeft: '-50vw', marginRight: '-50vw', marginTop: '-1.5rem', marginBottom: '-1.5rem' }}> <div className="min-h-screen bg-gradient-to-b from-[#0f0f0f] via-[#1a1a1a] to-[#0f0f0f] w-full" style={{ width: '100vw', position: 'relative', left: '50%', right: '50%', marginLeft: '-50vw', marginRight: '-50vw', marginTop: '-1.5rem', marginBottom: '-1.5rem' }}>
{} {}
<div className="w-full bg-gradient-to-br from-[#1a1a1a] via-[#0f0f0f] to-[#1a1a1a] border-b border-[#d4af37]/10 pt-6 sm:pt-7 md:pt-8 overflow-hidden relative"> <div className="w-full bg-gradient-to-br from-[#1a1a1a] via-[#0f0f0f] to-[#1a1a1a] border-b border-[var(--luxury-gold)]/10 pt-6 sm:pt-7 md:pt-8 overflow-hidden relative">
{} {}
<div className="absolute inset-0 opacity-10"> <div className="absolute inset-0 opacity-10">
<div className="absolute top-10 left-10 w-32 sm:w-48 h-32 sm:h-48 bg-[#d4af37] rounded-full blur-3xl"></div> <div className="absolute top-10 left-10 w-32 sm:w-48 h-32 sm:h-48 bg-[var(--luxury-gold)] rounded-full blur-3xl"></div>
<div className="absolute bottom-10 right-10 w-40 sm:w-64 h-40 sm:h-64 bg-[#c9a227] rounded-full blur-3xl"></div> <div className="absolute bottom-10 right-10 w-40 sm:w-64 h-40 sm:h-64 bg-[var(--luxury-gold-dark)] rounded-full blur-3xl"></div>
</div> </div>
<div className="absolute top-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-[#d4af37]/50 to-transparent"></div> <div className="absolute top-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-[var(--luxury-gold)]/50 to-transparent"></div>
<div className="w-full max-w-[1920px] mx-auto px-3 sm:px-4 md:px-6 lg:px-8 xl:px-12 2xl:px-16 3xl:px-20 py-4 sm:py-5 md:py-6 relative z-10"> <div className="w-full max-w-[1920px] mx-auto px-3 sm:px-4 md:px-6 lg:px-8 xl:px-12 2xl:px-16 3xl:px-20 py-4 sm:py-5 md:py-6 relative z-10">
<div className="max-w-2xl mx-auto text-center px-2"> <div className="max-w-2xl mx-auto text-center px-2">
<div className="flex justify-center mb-2 sm:mb-3 md:mb-4"> <div className="flex justify-center mb-2 sm:mb-3 md:mb-4">
<div className="relative group"> <div className="relative group">
<div className="absolute inset-0 bg-gradient-to-br from-[#d4af37] via-[#f5d76e] to-[#c9a227] rounded-xl blur-lg opacity-40 group-hover:opacity-60 transition-opacity duration-500"></div> <div className="absolute inset-0 bg-gradient-to-br from-[var(--luxury-gold)] via-[var(--luxury-gold-light)] to-[var(--luxury-gold-dark)] rounded-xl blur-lg opacity-40 group-hover:opacity-60 transition-opacity duration-500"></div>
<div className="relative p-2 sm:p-2.5 md:p-3 bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-lg border-2 border-[#d4af37]/40 backdrop-blur-sm shadow-xl shadow-[#d4af37]/20 group-hover:border-[#d4af37]/60 transition-all duration-300"> <div className="relative p-2 sm:p-2.5 md:p-3 bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-lg border-2 border-[var(--luxury-gold)]/40 backdrop-blur-sm shadow-xl shadow-[var(--luxury-gold)]/20 group-hover:border-[var(--luxury-gold)]/60 transition-all duration-300">
<Mail className="w-5 h-5 sm:w-6 sm:h-6 md:w-7 md:h-7 text-[#d4af37] drop-shadow-lg" /> <Mail className="w-5 h-5 sm:w-6 sm:h-6 md:w-7 md:h-7 text-[var(--luxury-gold)] drop-shadow-lg" />
</div> </div>
</div> </div>
</div> </div>
<h1 className="text-2xl xs:text-3xl sm:text-4xl md:text-5xl font-serif font-semibold mb-2 sm:mb-3 tracking-tight leading-tight px-2"> <h1 className="text-2xl xs:text-3xl sm:text-4xl md:text-5xl font-serif font-semibold mb-2 sm:mb-3 tracking-tight leading-tight px-2">
<span className="bg-gradient-to-r from-white via-[#d4af37] to-white bg-clip-text text-transparent"> <span className="bg-gradient-to-r from-white via-[var(--luxury-gold)] to-white bg-clip-text text-transparent">
{pageContent?.title || 'Contact Us'} {pageContent?.title || 'Contact Us'}
</span> </span>
</h1> </h1>
<div className="w-12 sm:w-16 md:w-20 h-0.5 bg-gradient-to-r from-transparent via-[#d4af37] to-transparent mx-auto mb-2 sm:mb-3"></div> <div className="w-12 sm:w-16 md:w-20 h-0.5 bg-gradient-to-r from-transparent via-[var(--luxury-gold)] to-transparent mx-auto mb-2 sm:mb-3"></div>
<p className="text-sm sm:text-base md:text-lg text-gray-300 font-light leading-relaxed max-w-xl mx-auto tracking-wide px-2 sm:px-4"> <p className="text-sm sm:text-base md:text-lg text-gray-300 font-light leading-relaxed max-w-xl mx-auto tracking-wide px-2 sm:px-4">
{pageContent?.subtitle || pageContent?.description || "Experience the pinnacle of hospitality. We're here to make your stay extraordinary."} {pageContent?.subtitle || pageContent?.description || "Experience the pinnacle of hospitality. We're here to make your stay extraordinary."}
</p> </p>
</div> </div>
</div> </div>
<div className="absolute bottom-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-[#d4af37]/30 to-transparent"></div> <div className="absolute bottom-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-[var(--luxury-gold)]/30 to-transparent"></div>
</div> </div>
{} {}
@@ -213,15 +213,15 @@ const ContactPage: React.FC = () => {
{} {}
<div className="lg:col-span-4"> <div className="lg:col-span-4">
<div className="bg-gradient-to-br from-[#1a1a1a] via-[#0f0f0f] to-[#0a0a0a] <div className="bg-gradient-to-br from-[#1a1a1a] via-[#0f0f0f] to-[#0a0a0a]
rounded-xl sm:rounded-2xl border-2 border-[#d4af37]/30 p-5 sm:p-6 md:p-8 lg:p-10 rounded-xl sm:rounded-2xl border-2 border-[var(--luxury-gold)]/30 p-5 sm:p-6 md:p-8 lg:p-10
shadow-2xl shadow-[#d4af37]/10 backdrop-blur-xl shadow-2xl shadow-[var(--luxury-gold)]/10 backdrop-blur-xl
relative overflow-hidden h-full group hover:border-[#d4af37]/50 transition-all duration-500"> relative overflow-hidden h-full group hover:border-[var(--luxury-gold)]/50 transition-all duration-500">
{} {}
<div className="absolute inset-0 bg-gradient-to-br from-[#d4af37]/5 via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div> <div className="absolute inset-0 bg-gradient-to-br from-[var(--luxury-gold)]/5 via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
<div className="relative z-10"> <div className="relative z-10">
<div className="flex items-center gap-2 sm:gap-3 mb-6 sm:mb-7 md:mb-8"> <div className="flex items-center gap-2 sm:gap-3 mb-6 sm:mb-7 md:mb-8">
<div className="w-0.5 sm:w-1 h-6 sm:h-8 bg-gradient-to-b from-[#d4af37] to-[#c9a227] rounded-full"></div> <div className="w-0.5 sm:w-1 h-6 sm:h-8 bg-gradient-to-b from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] rounded-full"></div>
<h2 className="text-xl sm:text-2xl md:text-3xl font-serif font-semibold <h2 className="text-xl sm:text-2xl md:text-3xl font-serif font-semibold
text-white tracking-tight"> text-white tracking-tight">
Get in Touch Get in Touch
@@ -230,35 +230,35 @@ const ContactPage: React.FC = () => {
<div className="space-y-5 sm:space-y-6 md:space-y-7"> <div className="space-y-5 sm:space-y-6 md:space-y-7">
<div className="flex items-start gap-3 sm:gap-4 md:gap-5 group/item hover:translate-x-1 transition-transform duration-300"> <div className="flex items-start gap-3 sm:gap-4 md:gap-5 group/item hover:translate-x-1 transition-transform duration-300">
<div className="p-2.5 sm:p-3 md:p-4 bg-gradient-to-br from-[#d4af37]/20 to-[#d4af37]/10 rounded-lg sm:rounded-xl border border-[#d4af37]/40 flex-shrink-0 group-hover/item:bg-gradient-to-br group-hover/item:from-[#d4af37]/30 group-hover/item:to-[#d4af37]/20 group-hover/item:border-[#d4af37]/60 transition-all duration-300 shadow-lg shadow-[#d4af37]/10"> <div className="p-2.5 sm:p-3 md:p-4 bg-gradient-to-br from-[var(--luxury-gold)]/20 to-[var(--luxury-gold)]/10 rounded-lg sm:rounded-xl border border-[var(--luxury-gold)]/40 flex-shrink-0 group-hover/item:bg-gradient-to-br group-hover/item:from-[var(--luxury-gold)]/30 group-hover/item:to-[var(--luxury-gold)]/20 group-hover/item:border-[var(--luxury-gold)]/60 transition-all duration-300 shadow-lg shadow-[var(--luxury-gold)]/10">
<Mail className="w-5 h-5 sm:w-6 sm:h-6 text-[#d4af37] drop-shadow-lg" /> <Mail className="w-5 h-5 sm:w-6 sm:h-6 text-[var(--luxury-gold)] drop-shadow-lg" />
</div> </div>
<div> <div>
<h3 className="text-sm sm:text-base font-medium text-[#d4af37] mb-1 sm:mb-2 tracking-wide">Email</h3> <h3 className="text-sm sm:text-base font-medium text-[var(--luxury-gold)] mb-1 sm:mb-2 tracking-wide">Email</h3>
<a href={`mailto:${displayEmail}`} className="text-gray-300 font-light text-xs sm:text-sm leading-relaxed hover:text-[#d4af37] transition-colors"> <a href={`mailto:${displayEmail}`} className="text-gray-300 font-light text-xs sm:text-sm leading-relaxed hover:text-[var(--luxury-gold)] transition-colors">
{displayEmail} {displayEmail}
</a> </a>
</div> </div>
</div> </div>
<div className="flex items-start gap-3 sm:gap-4 md:gap-5 group/item hover:translate-x-1 transition-transform duration-300"> <div className="flex items-start gap-3 sm:gap-4 md:gap-5 group/item hover:translate-x-1 transition-transform duration-300">
<div className="p-2.5 sm:p-3 md:p-4 bg-gradient-to-br from-[#d4af37]/20 to-[#d4af37]/10 rounded-lg sm:rounded-xl border border-[#d4af37]/40 flex-shrink-0 group-hover/item:bg-gradient-to-br group-hover/item:from-[#d4af37]/30 group-hover/item:to-[#d4af37]/20 group-hover/item:border-[#d4af37]/60 transition-all duration-300 shadow-lg shadow-[#d4af37]/10"> <div className="p-2.5 sm:p-3 md:p-4 bg-gradient-to-br from-[var(--luxury-gold)]/20 to-[var(--luxury-gold)]/10 rounded-lg sm:rounded-xl border border-[var(--luxury-gold)]/40 flex-shrink-0 group-hover/item:bg-gradient-to-br group-hover/item:from-[var(--luxury-gold)]/30 group-hover/item:to-[var(--luxury-gold)]/20 group-hover/item:border-[var(--luxury-gold)]/60 transition-all duration-300 shadow-lg shadow-[var(--luxury-gold)]/10">
<Phone className="w-5 h-5 sm:w-6 sm:h-6 text-[#d4af37] drop-shadow-lg" /> <Phone className="w-5 h-5 sm:w-6 sm:h-6 text-[var(--luxury-gold)] drop-shadow-lg" />
</div> </div>
<div> <div>
<h3 className="text-sm sm:text-base font-medium text-[#d4af37] mb-1 sm:mb-2 tracking-wide">Phone</h3> <h3 className="text-sm sm:text-base font-medium text-[var(--luxury-gold)] mb-1 sm:mb-2 tracking-wide">Phone</h3>
<a href={`tel:${displayPhone.replace(/\s+/g, '').replace(/[()]/g, '')}`} className="text-gray-300 font-light text-xs sm:text-sm leading-relaxed hover:text-[#d4af37] transition-colors"> <a href={`tel:${displayPhone.replace(/\s+/g, '').replace(/[()]/g, '')}`} className="text-gray-300 font-light text-xs sm:text-sm leading-relaxed hover:text-[var(--luxury-gold)] transition-colors">
{displayPhone} {displayPhone}
</a> </a>
</div> </div>
</div> </div>
<div className="flex items-start gap-3 sm:gap-4 md:gap-5 group/item hover:translate-x-1 transition-transform duration-300"> <div className="flex items-start gap-3 sm:gap-4 md:gap-5 group/item hover:translate-x-1 transition-transform duration-300">
<div className="p-2.5 sm:p-3 md:p-4 bg-gradient-to-br from-[#d4af37]/20 to-[#d4af37]/10 rounded-lg sm:rounded-xl border border-[#d4af37]/40 flex-shrink-0 group-hover/item:bg-gradient-to-br group-hover/item:from-[#d4af37]/30 group-hover/item:to-[#d4af37]/20 group-hover/item:border-[#d4af37]/60 transition-all duration-300 shadow-lg shadow-[#d4af37]/10"> <div className="p-2.5 sm:p-3 md:p-4 bg-gradient-to-br from-[var(--luxury-gold)]/20 to-[var(--luxury-gold)]/10 rounded-lg sm:rounded-xl border border-[var(--luxury-gold)]/40 flex-shrink-0 group-hover/item:bg-gradient-to-br group-hover/item:from-[var(--luxury-gold)]/30 group-hover/item:to-[var(--luxury-gold)]/20 group-hover/item:border-[var(--luxury-gold)]/60 transition-all duration-300 shadow-lg shadow-[var(--luxury-gold)]/10">
<MapPin className="w-5 h-5 sm:w-6 sm:h-6 text-[#d4af37] drop-shadow-lg" /> <MapPin className="w-5 h-5 sm:w-6 sm:h-6 text-[var(--luxury-gold)] drop-shadow-lg" />
</div> </div>
<div> <div>
<h3 className="text-sm sm:text-base font-medium text-[#d4af37] mb-1 sm:mb-2 tracking-wide">Location</h3> <h3 className="text-sm sm:text-base font-medium text-[var(--luxury-gold)] mb-1 sm:mb-2 tracking-wide">Location</h3>
<p className="text-gray-300 font-light text-xs sm:text-sm leading-relaxed whitespace-pre-line"> <p className="text-gray-300 font-light text-xs sm:text-sm leading-relaxed whitespace-pre-line">
{displayAddress} {displayAddress}
</p> </p>
@@ -268,11 +268,11 @@ const ContactPage: React.FC = () => {
{} {}
{pageContent?.map_url && ( {pageContent?.map_url && (
<div className="mt-6 sm:mt-7 md:mt-8 pt-6 sm:pt-7 md:pt-8 border-t border-[#d4af37]/30"> <div className="mt-6 sm:mt-7 md:mt-8 pt-6 sm:pt-7 md:pt-8 border-t border-[var(--luxury-gold)]/30">
<h3 className="text-sm sm:text-base font-medium text-[#d4af37] mb-3 sm:mb-4 tracking-wide"> <h3 className="text-sm sm:text-base font-medium text-[var(--luxury-gold)] mb-3 sm:mb-4 tracking-wide">
Find Us Find Us
</h3> </h3>
<div className="relative rounded-lg overflow-hidden border-2 border-[#d4af37]/30 shadow-lg shadow-[#d4af37]/10 group hover:border-[#d4af37]/50 transition-all duration-300"> <div className="relative rounded-lg overflow-hidden border-2 border-[var(--luxury-gold)]/30 shadow-lg shadow-[var(--luxury-gold)]/10 group hover:border-[var(--luxury-gold)]/50 transition-all duration-300">
<iframe <iframe
src={pageContent.map_url} src={pageContent.map_url}
width="100%" width="100%"
@@ -288,7 +288,7 @@ const ContactPage: React.FC = () => {
</div> </div>
)} )}
<div className="mt-5 sm:mt-6 md:mt-7 pt-5 sm:pt-6 md:pt-7 border-t border-[#d4af37]/30"> <div className="mt-5 sm:mt-6 md:mt-7 pt-5 sm:pt-6 md:pt-7 border-t border-[var(--luxury-gold)]/30">
<p className="text-gray-400 font-light text-xs sm:text-sm leading-relaxed tracking-wide"> <p className="text-gray-400 font-light text-xs sm:text-sm leading-relaxed tracking-wide">
{pageContent?.content || "Our team is here to help you with any questions about your stay, bookings, or special requests. We're committed to exceeding your expectations."} {pageContent?.content || "Our team is here to help you with any questions about your stay, bookings, or special requests. We're committed to exceeding your expectations."}
</p> </p>
@@ -300,17 +300,17 @@ const ContactPage: React.FC = () => {
{} {}
<div className="lg:col-span-8"> <div className="lg:col-span-8">
<div className="bg-gradient-to-br from-[#1a1a1a] via-[#0f0f0f] to-[#0a0a0a] <div className="bg-gradient-to-br from-[#1a1a1a] via-[#0f0f0f] to-[#0a0a0a]
rounded-xl sm:rounded-2xl border-2 border-[#d4af37]/30 p-5 sm:p-6 md:p-8 lg:p-10 rounded-xl sm:rounded-2xl border-2 border-[var(--luxury-gold)]/30 p-5 sm:p-6 md:p-8 lg:p-10
shadow-2xl shadow-[#d4af37]/10 backdrop-blur-xl shadow-2xl shadow-[var(--luxury-gold)]/10 backdrop-blur-xl
relative overflow-hidden"> relative overflow-hidden">
{} {}
<div className="absolute inset-0 opacity-5"> <div className="absolute inset-0 opacity-5">
<div className="absolute top-0 right-0 w-48 sm:w-64 md:w-96 h-48 sm:h-64 md:h-96 bg-[#d4af37] rounded-full blur-3xl"></div> <div className="absolute top-0 right-0 w-48 sm:w-64 md:w-96 h-48 sm:h-64 md:h-96 bg-[var(--luxury-gold)] rounded-full blur-3xl"></div>
</div> </div>
<div className="relative z-10"> <div className="relative z-10">
<div className="flex items-center gap-2 sm:gap-3 mb-6 sm:mb-7 md:mb-8"> <div className="flex items-center gap-2 sm:gap-3 mb-6 sm:mb-7 md:mb-8">
<div className="w-0.5 sm:w-1 h-6 sm:h-8 bg-gradient-to-b from-[#d4af37] to-[#c9a227] rounded-full"></div> <div className="w-0.5 sm:w-1 h-6 sm:h-8 bg-gradient-to-b from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] rounded-full"></div>
<h2 className="text-xl sm:text-2xl md:text-3xl font-serif font-semibold <h2 className="text-xl sm:text-2xl md:text-3xl font-serif font-semibold
text-white tracking-tight"> text-white tracking-tight">
Send Us a Message Send Us a Message
@@ -330,8 +330,8 @@ const ContactPage: React.FC = () => {
<div> <div>
<label htmlFor="name" className="block text-xs sm:text-sm font-medium text-gray-300 mb-2 sm:mb-3 tracking-wide"> <label htmlFor="name" className="block text-xs sm:text-sm font-medium text-gray-300 mb-2 sm:mb-3 tracking-wide">
<span className="flex items-center gap-1.5 sm:gap-2"> <span className="flex items-center gap-1.5 sm:gap-2">
<User className="w-3.5 h-3.5 sm:w-4 sm:h-4 text-[#d4af37] drop-shadow-lg" /> <User className="w-3.5 h-3.5 sm:w-4 sm:h-4 text-[var(--luxury-gold)] drop-shadow-lg" />
Full Name <span className="text-[#d4af37] font-semibold">*</span> Full Name <span className="text-[var(--luxury-gold)] font-semibold">*</span>
</span> </span>
</label> </label>
<input <input
@@ -342,9 +342,9 @@ const ContactPage: React.FC = () => {
onChange={handleChange} onChange={handleChange}
className={`w-full px-4 sm:px-5 py-3 sm:py-4 bg-gradient-to-br from-[#0f0f0f] to-[#0a0a0a] border-2 rounded-lg className={`w-full px-4 sm:px-5 py-3 sm:py-4 bg-gradient-to-br from-[#0f0f0f] to-[#0a0a0a] border-2 rounded-lg
text-white text-sm sm:text-base placeholder-gray-500/60 text-white text-sm sm:text-base placeholder-gray-500/60
focus:outline-none focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37] focus:shadow-lg focus:shadow-[#d4af37]/20 focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)] focus:shadow-lg focus:shadow-[var(--luxury-gold)]/20
transition-all duration-300 hover:border-[#d4af37]/40 transition-all duration-300 hover:border-[var(--luxury-gold)]/40
${errors.name ? 'border-red-500/50 focus:border-red-500 focus:ring-red-500/50' : 'border-[#d4af37]/30'}`} ${errors.name ? 'border-red-500/50 focus:border-red-500 focus:ring-red-500/50' : 'border-[var(--luxury-gold)]/30'}`}
placeholder="Enter your full name" placeholder="Enter your full name"
/> />
{errors.name && ( {errors.name && (
@@ -358,8 +358,8 @@ const ContactPage: React.FC = () => {
<div> <div>
<label htmlFor="email" className="block text-xs sm:text-sm font-medium text-gray-300 mb-2 sm:mb-3 tracking-wide"> <label htmlFor="email" className="block text-xs sm:text-sm font-medium text-gray-300 mb-2 sm:mb-3 tracking-wide">
<span className="flex items-center gap-1.5 sm:gap-2"> <span className="flex items-center gap-1.5 sm:gap-2">
<Mail className="w-3.5 h-3.5 sm:w-4 sm:h-4 text-[#d4af37] drop-shadow-lg" /> <Mail className="w-3.5 h-3.5 sm:w-4 sm:h-4 text-[var(--luxury-gold)] drop-shadow-lg" />
Email <span className="text-[#d4af37] font-semibold">*</span> Email <span className="text-[var(--luxury-gold)] font-semibold">*</span>
</span> </span>
</label> </label>
<input <input
@@ -370,9 +370,9 @@ const ContactPage: React.FC = () => {
onChange={handleChange} onChange={handleChange}
className={`w-full px-4 sm:px-5 py-3 sm:py-4 bg-gradient-to-br from-[#0f0f0f] to-[#0a0a0a] border-2 rounded-lg className={`w-full px-4 sm:px-5 py-3 sm:py-4 bg-gradient-to-br from-[#0f0f0f] to-[#0a0a0a] border-2 rounded-lg
text-white text-sm sm:text-base placeholder-gray-500/60 text-white text-sm sm:text-base placeholder-gray-500/60
focus:outline-none focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37] focus:shadow-lg focus:shadow-[#d4af37]/20 focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)] focus:shadow-lg focus:shadow-[var(--luxury-gold)]/20
transition-all duration-300 hover:border-[#d4af37]/40 transition-all duration-300 hover:border-[var(--luxury-gold)]/40
${errors.email ? 'border-red-500/50 focus:border-red-500 focus:ring-red-500/50' : 'border-[#d4af37]/30'}`} ${errors.email ? 'border-red-500/50 focus:border-red-500 focus:ring-red-500/50' : 'border-[var(--luxury-gold)]/30'}`}
placeholder="your.email@example.com" placeholder="your.email@example.com"
/> />
{errors.email && ( {errors.email && (
@@ -384,7 +384,7 @@ const ContactPage: React.FC = () => {
<div> <div>
<label htmlFor="phone" className="block text-xs sm:text-sm font-medium text-gray-300 mb-2 sm:mb-3 tracking-wide"> <label htmlFor="phone" className="block text-xs sm:text-sm font-medium text-gray-300 mb-2 sm:mb-3 tracking-wide">
<span className="flex items-center gap-1.5 sm:gap-2"> <span className="flex items-center gap-1.5 sm:gap-2">
<Phone className="w-3.5 h-3.5 sm:w-4 sm:h-4 text-[#d4af37] drop-shadow-lg" /> <Phone className="w-3.5 h-3.5 sm:w-4 sm:h-4 text-[var(--luxury-gold)] drop-shadow-lg" />
Phone <span className="text-gray-500 text-xs">(Optional)</span> Phone <span className="text-gray-500 text-xs">(Optional)</span>
</span> </span>
</label> </label>
@@ -394,10 +394,10 @@ const ContactPage: React.FC = () => {
name="phone" name="phone"
value={formData.phone} value={formData.phone}
onChange={handleChange} onChange={handleChange}
className="w-full px-4 sm:px-5 py-3 sm:py-4 bg-gradient-to-br from-[#0f0f0f] to-[#0a0a0a] border-2 border-[#d4af37]/30 rounded-lg className="w-full px-4 sm:px-5 py-3 sm:py-4 bg-gradient-to-br from-[#0f0f0f] to-[#0a0a0a] border-2 border-[var(--luxury-gold)]/30 rounded-lg
text-white text-sm sm:text-base placeholder-gray-500/60 text-white text-sm sm:text-base placeholder-gray-500/60
focus:outline-none focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37] focus:shadow-lg focus:shadow-[#d4af37]/20 focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)] focus:shadow-lg focus:shadow-[var(--luxury-gold)]/20
transition-all duration-300 hover:border-[#d4af37]/40" transition-all duration-300 hover:border-[var(--luxury-gold)]/40"
placeholder="+1 (555) 123-4567" placeholder="+1 (555) 123-4567"
/> />
</div> </div>
@@ -407,8 +407,8 @@ const ContactPage: React.FC = () => {
<div> <div>
<label htmlFor="subject" className="block text-xs sm:text-sm font-medium text-gray-300 mb-2 sm:mb-3 tracking-wide"> <label htmlFor="subject" className="block text-xs sm:text-sm font-medium text-gray-300 mb-2 sm:mb-3 tracking-wide">
<span className="flex items-center gap-1.5 sm:gap-2"> <span className="flex items-center gap-1.5 sm:gap-2">
<MessageSquare className="w-3.5 h-3.5 sm:w-4 sm:h-4 text-[#d4af37] drop-shadow-lg" /> <MessageSquare className="w-3.5 h-3.5 sm:w-4 sm:h-4 text-[var(--luxury-gold)] drop-shadow-lg" />
Subject <span className="text-[#d4af37] font-semibold">*</span> Subject <span className="text-[var(--luxury-gold)] font-semibold">*</span>
</span> </span>
</label> </label>
<input <input
@@ -419,9 +419,9 @@ const ContactPage: React.FC = () => {
onChange={handleChange} onChange={handleChange}
className={`w-full px-4 sm:px-5 py-3 sm:py-4 bg-gradient-to-br from-[#0f0f0f] to-[#0a0a0a] border-2 rounded-lg className={`w-full px-4 sm:px-5 py-3 sm:py-4 bg-gradient-to-br from-[#0f0f0f] to-[#0a0a0a] border-2 rounded-lg
text-white text-sm sm:text-base placeholder-gray-500/60 text-white text-sm sm:text-base placeholder-gray-500/60
focus:outline-none focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37] focus:shadow-lg focus:shadow-[#d4af37]/20 focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)] focus:shadow-lg focus:shadow-[var(--luxury-gold)]/20
transition-all duration-300 hover:border-[#d4af37]/40 transition-all duration-300 hover:border-[var(--luxury-gold)]/40
${errors.subject ? 'border-red-500/50 focus:border-red-500 focus:ring-red-500/50' : 'border-[#d4af37]/30'}`} ${errors.subject ? 'border-red-500/50 focus:border-red-500 focus:ring-red-500/50' : 'border-[var(--luxury-gold)]/30'}`}
placeholder="What is this regarding?" placeholder="What is this regarding?"
/> />
{errors.subject && ( {errors.subject && (
@@ -433,8 +433,8 @@ const ContactPage: React.FC = () => {
<div> <div>
<label htmlFor="message" className="block text-xs sm:text-sm font-medium text-gray-300 mb-2 sm:mb-3 tracking-wide"> <label htmlFor="message" className="block text-xs sm:text-sm font-medium text-gray-300 mb-2 sm:mb-3 tracking-wide">
<span className="flex items-center gap-1.5 sm:gap-2"> <span className="flex items-center gap-1.5 sm:gap-2">
<MessageSquare className="w-3.5 h-3.5 sm:w-4 sm:h-4 text-[#d4af37] drop-shadow-lg" /> <MessageSquare className="w-3.5 h-3.5 sm:w-4 sm:h-4 text-[var(--luxury-gold)] drop-shadow-lg" />
Message <span className="text-[#d4af37] font-semibold">*</span> Message <span className="text-[var(--luxury-gold)] font-semibold">*</span>
</span> </span>
</label> </label>
<textarea <textarea
@@ -445,9 +445,9 @@ const ContactPage: React.FC = () => {
rows={6} rows={6}
className={`w-full px-4 sm:px-5 py-3 sm:py-4 bg-gradient-to-br from-[#0f0f0f] to-[#0a0a0a] border-2 rounded-lg className={`w-full px-4 sm:px-5 py-3 sm:py-4 bg-gradient-to-br from-[#0f0f0f] to-[#0a0a0a] border-2 rounded-lg
text-white text-sm sm:text-base placeholder-gray-500/60 resize-none text-white text-sm sm:text-base placeholder-gray-500/60 resize-none
focus:outline-none focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37] focus:shadow-lg focus:shadow-[#d4af37]/20 focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)] focus:shadow-lg focus:shadow-[var(--luxury-gold)]/20
transition-all duration-300 hover:border-[#d4af37]/40 transition-all duration-300 hover:border-[var(--luxury-gold)]/40
${errors.message ? 'border-red-500/50 focus:border-red-500 focus:ring-red-500/50' : 'border-[#d4af37]/30'}`} ${errors.message ? 'border-red-500/50 focus:border-red-500 focus:ring-red-500/50' : 'border-[var(--luxury-gold)]/30'}`}
placeholder="Tell us more about your inquiry..." placeholder="Tell us more about your inquiry..."
/> />
{errors.message && ( {errors.message && (
@@ -475,14 +475,14 @@ const ContactPage: React.FC = () => {
type="submit" type="submit"
disabled={loading} disabled={loading}
className="group w-full sm:w-auto inline-flex items-center justify-center gap-2 sm:gap-3 className="group w-full sm:w-auto inline-flex items-center justify-center gap-2 sm:gap-3
bg-gradient-to-r from-[#d4af37] via-[#f5d76e] to-[#d4af37] bg-gradient-to-r from-[var(--luxury-gold)] via-[var(--luxury-gold-light)] to-[var(--luxury-gold)]
text-[#0f0f0f] font-semibold text-[#0f0f0f] font-semibold
active:scale-[0.98] active:scale-[0.98]
disabled:opacity-50 disabled:cursor-not-allowed disabled:opacity-50 disabled:cursor-not-allowed
transition-all duration-500 transition-all duration-500
tracking-wide text-sm sm:text-base tracking-wide text-sm sm:text-base
px-6 sm:px-8 md:px-10 py-3 sm:py-3.5 md:py-4 rounded-lg px-6 sm:px-8 md:px-10 py-3 sm:py-3.5 md:py-4 rounded-lg
shadow-2xl shadow-[#d4af37]/40 hover:shadow-[#d4af37]/60 hover:scale-[1.02] shadow-2xl shadow-[var(--luxury-gold)]/40 hover:shadow-[var(--luxury-gold)]/60 hover:scale-[1.02]
relative overflow-hidden relative overflow-hidden
touch-manipulation min-h-[44px] sm:min-h-[48px] md:min-h-[52px]" touch-manipulation min-h-[44px] sm:min-h-[48px] md:min-h-[52px]"
> >

View File

@@ -94,12 +94,12 @@ const FAQPage: React.FC = () => {
}} }}
> >
<div className="text-center"> <div className="text-center">
<HelpCircle className="w-16 h-16 text-[#d4af37]/50 mx-auto mb-4" /> <HelpCircle className="w-16 h-16 text-[var(--luxury-gold)]/50 mx-auto mb-4" />
<h1 className="text-2xl font-elegant font-bold text-white mb-2">Frequently Asked Questions</h1> <h1 className="text-2xl font-elegant font-bold text-white mb-2">Frequently Asked Questions</h1>
<p className="text-gray-400">This page is currently unavailable.</p> <p className="text-gray-400">This page is currently unavailable.</p>
<Link <Link
to="/" to="/"
className="inline-flex items-center gap-2 text-[#d4af37]/80 hover:text-[#d4af37] mt-6 transition-all duration-300" className="inline-flex items-center gap-2 text-[var(--luxury-gold)]/80 hover:text-[var(--luxury-gold)] mt-6 transition-all duration-300"
> >
<ArrowLeft className="w-4 h-4" /> <ArrowLeft className="w-4 h-4" />
<span>Back to Home</span> <span>Back to Home</span>
@@ -123,17 +123,17 @@ const FAQPage: React.FC = () => {
<div className="w-full px-3 sm:px-4 md:px-6 lg:px-8 py-8 sm:py-12 max-w-5xl mx-auto"> <div className="w-full px-3 sm:px-4 md:px-6 lg:px-8 py-8 sm:py-12 max-w-5xl mx-auto">
<Link <Link
to="/" to="/"
className="inline-flex items-center gap-2 text-[#d4af37]/80 hover:text-[#d4af37] mb-6 transition-all duration-300 group font-light tracking-wide text-xs sm:text-sm" className="inline-flex items-center gap-2 text-[var(--luxury-gold)]/80 hover:text-[var(--luxury-gold)] mb-6 transition-all duration-300 group font-light tracking-wide text-xs sm:text-sm"
> >
<ArrowLeft className="w-4 h-4 group-hover:-translate-x-1 transition-transform" /> <ArrowLeft className="w-4 h-4 group-hover:-translate-x-1 transition-transform" />
<span>Back to Home</span> <span>Back to Home</span>
</Link> </Link>
<div className="mb-8 sm:mb-12 text-center"> <div className="mb-8 sm:mb-12 text-center">
<div className="inline-flex items-center justify-center w-16 h-16 sm:w-20 sm:h-20 mb-4 sm:mb-6 bg-gradient-to-br from-[#d4af37]/20 to-[#c9a227]/10 rounded-full border border-[#d4af37]/30"> <div className="inline-flex items-center justify-center w-16 h-16 sm:w-20 sm:h-20 mb-4 sm:mb-6 bg-gradient-to-br from-[var(--luxury-gold)]/20 to-[var(--luxury-gold-dark)]/10 rounded-full border border-[var(--luxury-gold)]/30">
<HelpCircle className="w-8 h-8 sm:w-10 sm:h-10 text-[#d4af37]" /> <HelpCircle className="w-8 h-8 sm:w-10 sm:h-10 text-[var(--luxury-gold)]" />
</div> </div>
<h1 className="text-3xl sm:text-4xl lg:text-5xl font-elegant font-bold text-white mb-3 sm:mb-4 tracking-tight leading-tight bg-gradient-to-r from-white via-[#d4af37] to-white bg-clip-text text-transparent"> <h1 className="text-3xl sm:text-4xl lg:text-5xl font-elegant font-bold text-white mb-3 sm:mb-4 tracking-tight leading-tight bg-gradient-to-r from-white via-[var(--luxury-gold)] to-white bg-clip-text text-transparent">
{pageContent.title || 'Frequently Asked Questions'} {pageContent.title || 'Frequently Asked Questions'}
</h1> </h1>
{pageContent.subtitle && ( {pageContent.subtitle && (
@@ -143,18 +143,18 @@ const FAQPage: React.FC = () => {
)} )}
</div> </div>
<div className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-xl border border-[#d4af37]/20 backdrop-blur-xl shadow-2xl shadow-[#d4af37]/5 p-6 sm:p-8 lg:p-12"> <div className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-xl border border-[var(--luxury-gold)]/20 backdrop-blur-xl shadow-2xl shadow-[var(--luxury-gold)]/5 p-6 sm:p-8 lg:p-12">
<div <div
className="prose prose-invert prose-lg max-w-none text-gray-300 className="prose prose-invert prose-lg max-w-none text-gray-300
prose-headings:text-white prose-headings:font-elegant prose-headings:font-semibold prose-headings:text-white prose-headings:font-elegant prose-headings:font-semibold
prose-h2:text-2xl prose-h2:mt-8 prose-h2:mb-4 prose-h2:border-b prose-h2:border-[#d4af37]/20 prose-h2:pb-2 prose-h2:text-2xl prose-h2:mt-8 prose-h2:mb-4 prose-h2:border-b prose-h2:border-[var(--luxury-gold)]/20 prose-h2:pb-2
prose-p:text-gray-300 prose-p:font-light prose-p:leading-relaxed prose-p:mb-4 prose-p:text-gray-300 prose-p:font-light prose-p:leading-relaxed prose-p:mb-4
prose-ul:text-gray-300 prose-ul:font-light prose-ul:my-4 prose-ul:text-gray-300 prose-ul:font-light prose-ul:my-4
prose-li:text-gray-300 prose-li:mb-2 prose-li:ml-4 prose-li:text-gray-300 prose-li:mb-2 prose-li:ml-4
prose-strong:text-[#d4af37] prose-strong:font-medium prose-strong:text-[var(--luxury-gold)] prose-strong:font-medium
prose-a:text-[#d4af37] prose-a:no-underline hover:prose-a:underline prose-a:text-[var(--luxury-gold)] prose-a:no-underline hover:prose-a:underline
[&_*]:text-gray-300 [&_h1]:text-white [&_h2]:text-white [&_h3]:text-white [&_h4]:text-white [&_h5]:text-white [&_h6]:text-white [&_*]:text-gray-300 [&_h1]:text-white [&_h2]:text-white [&_h3]:text-white [&_h4]:text-white [&_h5]:text-white [&_h6]:text-white
[&_strong]:text-[#d4af37] [&_b]:text-[#d4af37] [&_a]:text-[#d4af37]" [&_strong]:text-[var(--luxury-gold)] [&_b]:text-[var(--luxury-gold)] [&_a]:text-[var(--luxury-gold)]"
style={{ color: '#d1d5db' }} style={{ color: '#d1d5db' }}
dangerouslySetInnerHTML={createSanitizedHtml( dangerouslySetInnerHTML={createSanitizedHtml(
pageContent.content || pageContent.description || '<p style="color: #d1d5db;">No content available.</p>' pageContent.content || pageContent.description || '<p style="color: #d1d5db;">No content available.</p>'
@@ -166,7 +166,7 @@ const FAQPage: React.FC = () => {
<div className="mt-8 text-center"> <div className="mt-8 text-center">
<p className="text-sm text-gray-400 font-light"> <p className="text-sm text-gray-400 font-light">
Still have questions? Contact us at{' '} Still have questions? Contact us at{' '}
<a href={`mailto:${settings.company_email}`} className="text-[#d4af37] hover:underline"> <a href={`mailto:${settings.company_email}`} className="text-[var(--luxury-gold)] hover:underline">
{settings.company_email} {settings.company_email}
</a> </a>
</p> </p>

View File

@@ -708,7 +708,7 @@ const HomePage: React.FC = () => {
<div className="min-h-screen bg-gradient-to-br from-gray-50 via-white to-gray-50/30 relative overflow-hidden"> <div className="min-h-screen bg-gradient-to-br from-gray-50 via-white to-gray-50/30 relative overflow-hidden">
{} {}
<div className="fixed inset-0 opacity-[0.015] bg-[radial-gradient(circle_at_1px_1px,#d4af37_1px,transparent_0)] bg-[length:60px_60px] pointer-events-none"></div> <div className="fixed inset-0 opacity-[0.015] bg-[radial-gradient(circle_at_1px_1px,var(--luxury-gold)_1px,transparent_0)] bg-[length:60px_60px] pointer-events-none"></div>
<div className="relative z-10"> <div className="relative z-10">
{} {}
@@ -717,7 +717,7 @@ const HomePage: React.FC = () => {
{} {}
<div className="text-center animate-fade-in mb-6 md:mb-8"> <div className="text-center animate-fade-in mb-6 md:mb-8">
<div className="inline-block mb-3"> <div className="inline-block mb-3">
<div className="h-0.5 w-16 bg-gradient-to-r from-[#d4af37] to-[#f5d76e] mx-auto rounded-full"></div> <div className="h-0.5 w-16 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] mx-auto rounded-full"></div>
</div> </div>
<h2 className="text-2xl sm:text-3xl md:text-4xl font-serif font-bold text-gray-900 tracking-tight mb-3 md:mb-4"> <h2 className="text-2xl sm:text-3xl md:text-4xl font-serif font-bold text-gray-900 tracking-tight mb-3 md:mb-4">
{pageContent?.rooms_section_title || pageContent?.hero_title || (apiError ? '' : 'Featured & Newest Rooms')} {pageContent?.rooms_section_title || pageContent?.hero_title || (apiError ? '' : 'Featured & Newest Rooms')}
@@ -730,9 +730,9 @@ const HomePage: React.FC = () => {
<div className="mt-6 md:mt-8 flex justify-center"> <div className="mt-6 md:mt-8 flex justify-center">
<Link <Link
to={pageContent?.rooms_section_button_link || '/rooms'} to={pageContent?.rooms_section_button_link || '/rooms'}
className="group relative inline-flex items-center gap-2 px-6 py-2.5 md:px-8 md:py-3 bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-[#0f0f0f] rounded-lg font-semibold tracking-wide text-sm md:text-base shadow-md shadow-[#d4af37]/20 hover:shadow-lg hover:shadow-[#d4af37]/30 hover:-translate-y-0.5 transition-all duration-300 overflow-hidden" className="group relative inline-flex items-center gap-2 px-6 py-2.5 md:px-8 md:py-3 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-[#0f0f0f] rounded-lg font-semibold tracking-wide text-sm md:text-base shadow-md shadow-[var(--luxury-gold)]/20 hover:shadow-lg hover:shadow-[var(--luxury-gold)]/30 hover:-translate-y-0.5 transition-all duration-300 overflow-hidden"
> >
<span className="absolute inset-0 bg-gradient-to-r from-[#f5d76e] to-[#d4af37] opacity-0 group-hover:opacity-100 transition-opacity duration-300"></span> <span className="absolute inset-0 bg-gradient-to-r from-[var(--luxury-gold-light)] to-[var(--luxury-gold)] opacity-0 group-hover:opacity-100 transition-opacity duration-300"></span>
<span className="relative z-10">{pageContent?.rooms_section_button_text || 'View All Rooms'}</span> <span className="relative z-10">{pageContent?.rooms_section_button_text || 'View All Rooms'}</span>
<ArrowRight className="w-4 h-4 md:w-5 md:h-5 relative z-10 group-hover:translate-x-1 transition-transform duration-300" /> <ArrowRight className="w-4 h-4 md:w-5 md:h-5 relative z-10 group-hover:translate-x-1 transition-transform duration-300" />
</Link> </Link>
@@ -810,18 +810,18 @@ const HomePage: React.FC = () => {
// Only show section if we have features from API, or if pageContent was loaded but is empty (not if API failed) // Only show section if we have features from API, or if pageContent was loaded but is empty (not if API failed)
return validFeatures.length > 0 && ( return validFeatures.length > 0 && (
<section className="container mx-auto px-4 sm:px-6 lg:px-8 py-12 md:py-16"> <section className="container mx-auto px-4 sm:px-6 lg:px-8 py-12 md:py-16">
<div className="relative bg-white rounded-xl md:rounded-2xl shadow-xl shadow-[#d4af37]/5 p-6 md:p-8 lg:p-10 animate-fade-in overflow-hidden border border-gray-100/50"> <div className="relative bg-white rounded-xl md:rounded-2xl shadow-xl shadow-[var(--luxury-gold)]/5 p-6 md:p-8 lg:p-10 animate-fade-in overflow-hidden border border-gray-100/50">
{} {}
<div className="absolute top-0 left-0 right-0 h-1 bg-gradient-to-r from-[#d4af37] via-[#f5d76e] to-[#d4af37]"></div> <div className="absolute top-0 left-0 right-0 h-1 bg-gradient-to-r from-[var(--luxury-gold)] via-[var(--luxury-gold-light)] to-[var(--luxury-gold)]"></div>
<div className="absolute bottom-0 left-0 right-0 h-1 bg-gradient-to-r from-[#d4af37] via-[#f5d76e] to-[#d4af37]"></div> <div className="absolute bottom-0 left-0 right-0 h-1 bg-gradient-to-r from-[var(--luxury-gold)] via-[var(--luxury-gold-light)] to-[var(--luxury-gold)]"></div>
{} {}
<div className="absolute inset-0 opacity-[0.015] bg-[radial-gradient(circle_at_1px_1px,#d4af37_1px,transparent_0)] bg-[length:40px_40px]"></div> <div className="absolute inset-0 opacity-[0.015] bg-[radial-gradient(circle_at_1px_1px,var(--luxury-gold)_1px,transparent_0)] bg-[length:40px_40px]"></div>
{(pageContent?.features_section_title || pageContent?.features_section_subtitle) && ( {(pageContent?.features_section_title || pageContent?.features_section_subtitle) && (
<div className="text-center mb-8 md:mb-10 animate-fade-in"> <div className="text-center mb-8 md:mb-10 animate-fade-in">
<div className="inline-block mb-3"> <div className="inline-block mb-3">
<div className="h-0.5 w-16 md:w-20 bg-gradient-to-r from-[#d4af37] to-[#f5d76e] mx-auto rounded-full"></div> <div className="h-0.5 w-16 md:w-20 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] mx-auto rounded-full"></div>
</div> </div>
{pageContent.features_section_title && ( {pageContent.features_section_title && (
<h2 className="text-2xl sm:text-3xl md:text-4xl font-serif font-bold text-gray-900 tracking-tight mb-3 md:mb-4 px-4"> <h2 className="text-2xl sm:text-3xl md:text-4xl font-serif font-bold text-gray-900 tracking-tight mb-3 md:mb-4 px-4">
@@ -841,20 +841,20 @@ const HomePage: React.FC = () => {
validFeatures.map((feature: any, index: number) => ( validFeatures.map((feature: any, index: number) => (
<div key={`feature-${index}-${feature.title || index}`} className="text-center group relative"> <div key={`feature-${index}-${feature.title || index}`} className="text-center group relative">
{feature.image ? ( {feature.image ? (
<div className="w-16 h-16 md:w-20 md:h-20 mx-auto mb-4 md:mb-5 rounded-lg overflow-hidden shadow-lg shadow-[#d4af37]/15 group-hover:scale-110 group-hover:shadow-xl group-hover:shadow-[#d4af37]/25 transition-all duration-300 border border-[#d4af37]/20"> <div className="w-16 h-16 md:w-20 md:h-20 mx-auto mb-4 md:mb-5 rounded-lg overflow-hidden shadow-lg shadow-[var(--luxury-gold)]/15 group-hover:scale-110 group-hover:shadow-xl group-hover:shadow-[var(--luxury-gold)]/25 transition-all duration-300 border border-[var(--luxury-gold)]/20">
<img src={feature.image} alt={feature.title || 'Feature'} className="w-full h-full object-cover" /> <img src={feature.image} alt={feature.title || 'Feature'} className="w-full h-full object-cover" />
</div> </div>
) : ( ) : (
<div <div
className="w-16 h-16 md:w-18 md:h-18 bg-gradient-to-br from-[#d4af37]/15 via-[#f5d76e]/10 to-[#d4af37]/15 className="w-16 h-16 md:w-18 md:h-18 bg-gradient-to-br from-[var(--luxury-gold)]/15 via-[var(--luxury-gold-light)]/10 to-[var(--luxury-gold)]/15
rounded-lg flex items-center justify-center mx-auto mb-4 md:mb-5 rounded-lg flex items-center justify-center mx-auto mb-4 md:mb-5
shadow-lg shadow-[#d4af37]/15 border border-[#d4af37]/25 shadow-lg shadow-[var(--luxury-gold)]/15 border border-[var(--luxury-gold)]/25
group-hover:scale-110 group-hover:shadow-xl group-hover:shadow-[#d4af37]/30 group-hover:border-[#d4af37]/40 group-hover:scale-110 group-hover:shadow-xl group-hover:shadow-[var(--luxury-gold)]/30 group-hover:border-[var(--luxury-gold)]/40
transition-all duration-300 backdrop-blur-sm" transition-all duration-300 backdrop-blur-sm"
> >
{feature.icon && (LucideIcons as any)[feature.icon] ? ( {feature.icon && (LucideIcons as any)[feature.icon] ? (
React.createElement((LucideIcons as any)[feature.icon], { React.createElement((LucideIcons as any)[feature.icon], {
className: 'w-7 h-7 md:w-8 md:h-8 text-[#d4af37] drop-shadow-md' className: 'w-7 h-7 md:w-8 md:h-8 text-[var(--luxury-gold)] drop-shadow-md'
}) })
) : ( ) : (
<span className="text-3xl"></span> <span className="text-3xl"></span>
@@ -864,7 +864,7 @@ const HomePage: React.FC = () => {
{feature.title && ( {feature.title && (
<h3 <h3
className="text-lg md:text-xl font-serif font-semibold mb-2 md:mb-3 className="text-lg md:text-xl font-serif font-semibold mb-2 md:mb-3
text-gray-900 group-hover:text-[#d4af37] transition-colors duration-300 tracking-tight leading-tight" text-gray-900 group-hover:text-[var(--luxury-gold)] transition-colors duration-300 tracking-tight leading-tight"
> >
{feature.title} {feature.title}
</h3> </h3>
@@ -888,7 +888,7 @@ const HomePage: React.FC = () => {
<section className="container mx-auto px-4 sm:px-6 lg:px-8 py-12 md:py-16 bg-gradient-to-b from-white via-gray-50/20 to-white"> <section className="container mx-auto px-4 sm:px-6 lg:px-8 py-12 md:py-16 bg-gradient-to-b from-white via-gray-50/20 to-white">
<div className="text-center mb-8 md:mb-10 animate-fade-in"> <div className="text-center mb-8 md:mb-10 animate-fade-in">
<div className="inline-block mb-3"> <div className="inline-block mb-3">
<div className="h-0.5 w-16 md:w-20 bg-gradient-to-r from-[#d4af37] to-[#f5d76e] mx-auto rounded-full"></div> <div className="h-0.5 w-16 md:w-20 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] mx-auto rounded-full"></div>
</div> </div>
<h2 className="text-2xl sm:text-3xl md:text-4xl font-serif font-bold text-gray-900 tracking-tight mb-3 md:mb-4 px-4"> <h2 className="text-2xl sm:text-3xl md:text-4xl font-serif font-bold text-gray-900 tracking-tight mb-3 md:mb-4 px-4">
{pageContent.luxury_section_title || 'Experience Unparalleled Luxury'} {pageContent.luxury_section_title || 'Experience Unparalleled Luxury'}
@@ -901,7 +901,7 @@ const HomePage: React.FC = () => {
</div> </div>
{pageContent.luxury_section_image && ( {pageContent.luxury_section_image && (
<div className="mb-8 md:mb-10 animate-fade-in px-4"> <div className="mb-8 md:mb-10 animate-fade-in px-4">
<div className="relative rounded-xl md:rounded-2xl overflow-hidden shadow-xl shadow-[#d4af37]/10 group"> <div className="relative rounded-xl md:rounded-2xl overflow-hidden shadow-xl shadow-[var(--luxury-gold)]/10 group">
<img <img
src={pageContent.luxury_section_image} src={pageContent.luxury_section_image}
alt="Luxury Experience" alt="Luxury Experience"
@@ -914,18 +914,18 @@ const HomePage: React.FC = () => {
{pageContent.luxury_features && pageContent.luxury_features.length > 0 && ( {pageContent.luxury_features && pageContent.luxury_features.length > 0 && (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-5 md:gap-6 px-4"> <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-5 md:gap-6 px-4">
{pageContent.luxury_features.map((feature, index) => ( {pageContent.luxury_features.map((feature, index) => (
<div key={index} className="relative bg-white rounded-lg md:rounded-xl p-5 md:p-6 group hover:shadow-xl hover:shadow-[#d4af37]/10 transition-all duration-300 animate-fade-in border border-gray-100/50 hover:border-[#d4af37]/25 hover:-translate-y-1" style={{ animationDelay: `${index * 0.1}s` }}> <div key={index} className="relative bg-white rounded-lg md:rounded-xl p-5 md:p-6 group hover:shadow-xl hover:shadow-[var(--luxury-gold)]/10 transition-all duration-300 animate-fade-in border border-gray-100/50 hover:border-[var(--luxury-gold)]/25 hover:-translate-y-1" style={{ animationDelay: `${index * 0.1}s` }}>
<div className="absolute top-0 left-0 w-full h-0.5 bg-gradient-to-r from-[#d4af37] to-[#f5d76e] opacity-0 group-hover:opacity-100 transition-opacity duration-300 rounded-t-lg md:rounded-t-xl"></div> <div className="absolute top-0 left-0 w-full h-0.5 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] opacity-0 group-hover:opacity-100 transition-opacity duration-300 rounded-t-lg md:rounded-t-xl"></div>
<div className="w-14 h-14 md:w-16 md:h-16 bg-gradient-to-br from-[#d4af37]/15 via-[#f5d76e]/10 to-[#d4af37]/15 rounded-lg flex items-center justify-center mb-4 md:mb-5 mx-auto group-hover:scale-110 group-hover:shadow-lg group-hover:shadow-[#d4af37]/20 transition-all duration-300 border border-[#d4af37]/25 group-hover:border-[#d4af37]/40"> <div className="w-14 h-14 md:w-16 md:h-16 bg-gradient-to-br from-[var(--luxury-gold)]/15 via-[var(--luxury-gold-light)]/10 to-[var(--luxury-gold)]/15 rounded-lg flex items-center justify-center mb-4 md:mb-5 mx-auto group-hover:scale-110 group-hover:shadow-lg group-hover:shadow-[var(--luxury-gold)]/20 transition-all duration-300 border border-[var(--luxury-gold)]/25 group-hover:border-[var(--luxury-gold)]/40">
{feature.icon && (LucideIcons as any)[feature.icon] ? ( {feature.icon && (LucideIcons as any)[feature.icon] ? (
React.createElement((LucideIcons as any)[feature.icon], { React.createElement((LucideIcons as any)[feature.icon], {
className: 'w-7 h-7 md:w-8 md:h-8 text-[#d4af37] drop-shadow-md' className: 'w-7 h-7 md:w-8 md:h-8 text-[var(--luxury-gold)] drop-shadow-md'
}) })
) : ( ) : (
<span className="text-2xl md:text-3xl"></span> <span className="text-2xl md:text-3xl"></span>
)} )}
</div> </div>
<h3 className="text-lg md:text-xl font-serif font-semibold mb-2 md:mb-3 text-gray-900 group-hover:text-[#d4af37] transition-colors duration-300 text-center tracking-tight leading-tight"> <h3 className="text-lg md:text-xl font-serif font-semibold mb-2 md:mb-3 text-gray-900 group-hover:text-[var(--luxury-gold)] transition-colors duration-300 text-center tracking-tight leading-tight">
{feature.title} {feature.title}
</h3> </h3>
<p className="text-sm md:text-base text-gray-600 leading-relaxed font-light text-center tracking-wide"> <p className="text-sm md:text-base text-gray-600 leading-relaxed font-light text-center tracking-wide">
@@ -943,7 +943,7 @@ const HomePage: React.FC = () => {
<section className="container mx-auto px-4 sm:px-6 lg:px-8 py-12 md:py-16"> <section className="container mx-auto px-4 sm:px-6 lg:px-8 py-12 md:py-16">
<div className="text-center mb-8 md:mb-10 animate-fade-in"> <div className="text-center mb-8 md:mb-10 animate-fade-in">
<div className="inline-block mb-3"> <div className="inline-block mb-3">
<div className="h-0.5 w-16 md:w-20 bg-gradient-to-r from-[#d4af37] to-[#f5d76e] mx-auto rounded-full"></div> <div className="h-0.5 w-16 md:w-20 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] mx-auto rounded-full"></div>
</div> </div>
<h2 className="text-2xl sm:text-3xl md:text-4xl font-serif font-bold text-gray-900 tracking-tight mb-3 md:mb-4 px-4"> <h2 className="text-2xl sm:text-3xl md:text-4xl font-serif font-bold text-gray-900 tracking-tight mb-3 md:mb-4 px-4">
{pageContent.luxury_gallery_section_title || 'Luxury Gallery'} {pageContent.luxury_gallery_section_title || 'Luxury Gallery'}
@@ -968,7 +968,7 @@ const HomePage: React.FC = () => {
return ( return (
<div <div
key={`luxury-gallery-${index}-${image}`} key={`luxury-gallery-${index}-${image}`}
className="relative group overflow-hidden rounded-lg md:rounded-xl aspect-square animate-fade-in shadow-md shadow-gray-900/5 hover:shadow-xl hover:shadow-[#d4af37]/15 transition-all duration-300 cursor-pointer" className="relative group overflow-hidden rounded-lg md:rounded-xl aspect-square animate-fade-in shadow-md shadow-gray-900/5 hover:shadow-xl hover:shadow-[var(--luxury-gold)]/15 transition-all duration-300 cursor-pointer"
style={{ animationDelay: `${index * 0.05}s` }} style={{ animationDelay: `${index * 0.05}s` }}
onClick={() => { onClick={() => {
const normalizedImages = (pageContent.luxury_gallery || []) const normalizedImages = (pageContent.luxury_gallery || [])
@@ -998,7 +998,7 @@ const HomePage: React.FC = () => {
<ZoomIn className="w-8 h-8 md:w-10 md:h-10 text-white drop-shadow-2xl" /> <ZoomIn className="w-8 h-8 md:w-10 md:h-10 text-white drop-shadow-2xl" />
</div> </div>
</div> </div>
<div className="absolute inset-0 border-2 border-transparent group-hover:border-[#d4af37]/60 transition-colors duration-300 rounded-lg md:rounded-xl"></div> <div className="absolute inset-0 border-2 border-transparent group-hover:border-[var(--luxury-gold)]/60 transition-colors duration-300 rounded-lg md:rounded-xl"></div>
</div> </div>
); );
})} })}
@@ -1011,7 +1011,7 @@ const HomePage: React.FC = () => {
<section className="container mx-auto px-4 sm:px-6 lg:px-8 py-12 md:py-16 bg-gradient-to-b from-white via-gray-50/20 to-white"> <section className="container mx-auto px-4 sm:px-6 lg:px-8 py-12 md:py-16 bg-gradient-to-b from-white via-gray-50/20 to-white">
<div className="text-center mb-8 md:mb-10 animate-fade-in"> <div className="text-center mb-8 md:mb-10 animate-fade-in">
<div className="inline-block mb-3"> <div className="inline-block mb-3">
<div className="h-0.5 w-16 md:w-20 bg-gradient-to-r from-[#d4af37] to-[#f5d76e] mx-auto rounded-full"></div> <div className="h-0.5 w-16 md:w-20 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] mx-auto rounded-full"></div>
</div> </div>
<h2 className="text-2xl sm:text-3xl md:text-4xl font-serif font-bold text-gray-900 tracking-tight mb-3 md:mb-4 px-4"> <h2 className="text-2xl sm:text-3xl md:text-4xl font-serif font-bold text-gray-900 tracking-tight mb-3 md:mb-4 px-4">
{pageContent.luxury_testimonials_section_title || 'Guest Experiences'} {pageContent.luxury_testimonials_section_title || 'Guest Experiences'}
@@ -1024,16 +1024,16 @@ const HomePage: React.FC = () => {
</div> </div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-5 md:gap-6 px-4"> <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-5 md:gap-6 px-4">
{pageContent.luxury_testimonials.map((testimonial, index) => ( {pageContent.luxury_testimonials.map((testimonial, index) => (
<div key={index} className="relative bg-white rounded-lg md:rounded-xl p-5 md:p-6 shadow-lg shadow-gray-900/5 hover:shadow-xl hover:shadow-[#d4af37]/8 transition-all duration-300 animate-fade-in border border-gray-100/50 hover:border-[#d4af37]/25 hover:-translate-y-1" style={{ animationDelay: `${index * 0.1}s` }}> <div key={index} className="relative bg-white rounded-lg md:rounded-xl p-5 md:p-6 shadow-lg shadow-gray-900/5 hover:shadow-xl hover:shadow-[var(--luxury-gold)]/8 transition-all duration-300 animate-fade-in border border-gray-100/50 hover:border-[var(--luxury-gold)]/25 hover:-translate-y-1" style={{ animationDelay: `${index * 0.1}s` }}>
<div className="absolute top-0 left-0 w-full h-0.5 bg-gradient-to-r from-[#d4af37] to-[#f5d76e] opacity-0 hover:opacity-100 transition-opacity duration-300 rounded-t-lg md:rounded-t-xl"></div> <div className="absolute top-0 left-0 w-full h-0.5 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] opacity-0 hover:opacity-100 transition-opacity duration-300 rounded-t-lg md:rounded-t-xl"></div>
<div className="flex items-center mb-4 md:mb-5"> <div className="flex items-center mb-4 md:mb-5">
{testimonial.image ? ( {testimonial.image ? (
<div className="relative"> <div className="relative">
<img src={testimonial.image} alt={testimonial.name} className="w-12 h-12 md:w-14 md:h-14 rounded-full object-cover mr-3 md:mr-4 border-2 border-[#d4af37]/20 shadow-md" /> <img src={testimonial.image} alt={testimonial.name} className="w-12 h-12 md:w-14 md:h-14 rounded-full object-cover mr-3 md:mr-4 border-2 border-[var(--luxury-gold)]/20 shadow-md" />
<div className="absolute inset-0 rounded-full border border-[#d4af37]/40"></div> <div className="absolute inset-0 rounded-full border border-[var(--luxury-gold)]/40"></div>
</div> </div>
) : ( ) : (
<div className="w-12 h-12 md:w-14 md:h-14 rounded-full bg-gradient-to-br from-[#d4af37] to-[#f5d76e] flex items-center justify-center text-white font-bold text-base md:text-lg mr-3 md:mr-4 shadow-md border-2 border-white"> <div className="w-12 h-12 md:w-14 md:h-14 rounded-full bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] flex items-center justify-center text-white font-bold text-base md:text-lg mr-3 md:mr-4 shadow-md border-2 border-white">
{testimonial.name.charAt(0).toUpperCase()} {testimonial.name.charAt(0).toUpperCase()}
</div> </div>
)} )}
@@ -1045,7 +1045,7 @@ const HomePage: React.FC = () => {
</div> </div>
</div> </div>
<div className="relative"> <div className="relative">
<div className="absolute -top-1 -left-1 text-4xl md:text-5xl text-[#d4af37]/8 font-serif">"</div> <div className="absolute -top-1 -left-1 text-4xl md:text-5xl text-[var(--luxury-gold)]/8 font-serif">"</div>
<p className="text-sm md:text-base text-gray-700 leading-relaxed italic relative z-10 font-light">{testimonial.quote}</p> <p className="text-sm md:text-base text-gray-700 leading-relaxed italic relative z-10 font-light">{testimonial.quote}</p>
</div> </div>
</div> </div>
@@ -1057,15 +1057,15 @@ const HomePage: React.FC = () => {
{} {}
{(pageContent?.sections_enabled?.stats !== false) && pageContent?.stats && Array.isArray(pageContent.stats) && pageContent.stats.length > 0 && ( {(pageContent?.sections_enabled?.stats !== false) && pageContent?.stats && Array.isArray(pageContent.stats) && pageContent.stats.length > 0 && (
<section className="container mx-auto px-4 sm:px-6 lg:px-8 py-12 md:py-16"> <section className="container mx-auto px-4 sm:px-6 lg:px-8 py-12 md:py-16">
<div className="relative bg-gradient-to-br from-slate-900 via-slate-800 to-slate-900 rounded-xl md:rounded-2xl p-6 md:p-8 lg:p-10 shadow-xl shadow-black/30 animate-fade-in overflow-hidden border border-[#d4af37]/15"> <div className="relative bg-gradient-to-br from-slate-900 via-slate-800 to-slate-900 rounded-xl md:rounded-2xl p-6 md:p-8 lg:p-10 shadow-xl shadow-black/30 animate-fade-in overflow-hidden border border-[var(--luxury-gold)]/15">
{} {}
<div className="absolute top-0 left-0 right-0 h-0.5 bg-gradient-to-r from-[#d4af37] via-[#f5d76e] to-[#d4af37]"></div> <div className="absolute top-0 left-0 right-0 h-0.5 bg-gradient-to-r from-[var(--luxury-gold)] via-[var(--luxury-gold-light)] to-[var(--luxury-gold)]"></div>
<div className="absolute inset-0 opacity-8 bg-[radial-gradient(circle_at_1px_1px,#d4af37_1px,transparent_0)] bg-[length:40px_40px]"></div> <div className="absolute inset-0 opacity-8 bg-[radial-gradient(circle_at_1px_1px,var(--luxury-gold)_1px,transparent_0)] bg-[length:40px_40px]"></div>
{(pageContent?.stats_section_title || pageContent?.stats_section_subtitle) && ( {(pageContent?.stats_section_title || pageContent?.stats_section_subtitle) && (
<div className="text-center mb-8 md:mb-10 animate-fade-in relative z-10"> <div className="text-center mb-8 md:mb-10 animate-fade-in relative z-10">
<div className="inline-block mb-3"> <div className="inline-block mb-3">
<div className="h-0.5 w-16 md:w-20 bg-gradient-to-r from-[#d4af37] to-[#f5d76e] mx-auto rounded-full"></div> <div className="h-0.5 w-16 md:w-20 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] mx-auto rounded-full"></div>
</div> </div>
{pageContent.stats_section_title && ( {pageContent.stats_section_title && (
<h2 className="text-2xl sm:text-3xl md:text-4xl font-serif font-bold text-white tracking-tight mb-3 md:mb-4 px-4"> <h2 className="text-2xl sm:text-3xl md:text-4xl font-serif font-bold text-white tracking-tight mb-3 md:mb-4 px-4">
@@ -1087,7 +1087,7 @@ const HomePage: React.FC = () => {
<div className="mb-3 md:mb-4 group-hover:scale-110 transition-transform duration-300 flex items-center justify-center"> <div className="mb-3 md:mb-4 group-hover:scale-110 transition-transform duration-300 flex items-center justify-center">
{stat.icon && (LucideIcons as any)[stat.icon] ? ( {stat.icon && (LucideIcons as any)[stat.icon] ? (
React.createElement((LucideIcons as any)[stat.icon], { React.createElement((LucideIcons as any)[stat.icon], {
className: 'w-8 h-8 md:w-10 md:h-10 text-[#d4af37] drop-shadow-md' className: 'w-8 h-8 md:w-10 md:h-10 text-[var(--luxury-gold)] drop-shadow-md'
}) })
) : ( ) : (
<span className="text-3xl md:text-4xl">{stat.icon}</span> <span className="text-3xl md:text-4xl">{stat.icon}</span>
@@ -1095,7 +1095,7 @@ const HomePage: React.FC = () => {
</div> </div>
)} )}
{stat?.number && ( {stat?.number && (
<div className="text-2xl sm:text-3xl md:text-4xl lg:text-5xl font-bold text-[#d4af37] mb-1 md:mb-2 font-serif tracking-tight"> <div className="text-2xl sm:text-3xl md:text-4xl lg:text-5xl font-bold text-[var(--luxury-gold)] mb-1 md:mb-2 font-serif tracking-tight">
{stat.number} {stat.number}
</div> </div>
)} )}
@@ -1116,7 +1116,7 @@ const HomePage: React.FC = () => {
<section className="container mx-auto px-4 sm:px-6 lg:px-8 py-12 md:py-16"> <section className="container mx-auto px-4 sm:px-6 lg:px-8 py-12 md:py-16">
<div className="text-center mb-8 md:mb-10 animate-fade-in"> <div className="text-center mb-8 md:mb-10 animate-fade-in">
<div className="inline-block mb-3"> <div className="inline-block mb-3">
<div className="h-0.5 w-16 md:w-20 bg-gradient-to-r from-[#d4af37] to-[#f5d76e] mx-auto rounded-full"></div> <div className="h-0.5 w-16 md:w-20 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] mx-auto rounded-full"></div>
</div> </div>
<h2 className="text-2xl sm:text-3xl md:text-4xl font-serif font-bold text-gray-900 tracking-tight mb-3 md:mb-4 px-4"> <h2 className="text-2xl sm:text-3xl md:text-4xl font-serif font-bold text-gray-900 tracking-tight mb-3 md:mb-4 px-4">
{pageContent.amenities_section_title || 'Luxury Amenities'} {pageContent.amenities_section_title || 'Luxury Amenities'}
@@ -1127,24 +1127,24 @@ const HomePage: React.FC = () => {
</div> </div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-5 md:gap-6 px-4"> <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-5 md:gap-6 px-4">
{pageContent.amenities.map((amenity, index) => ( {pageContent.amenities.map((amenity, index) => (
<div key={index} className="relative bg-white rounded-lg md:rounded-xl p-5 md:p-6 group hover:shadow-xl hover:shadow-[#d4af37]/10 transition-all duration-300 animate-fade-in border border-gray-100/50 hover:border-[#d4af37]/25 hover:-translate-y-1" style={{ animationDelay: `${index * 0.1}s` }}> <div key={index} className="relative bg-white rounded-lg md:rounded-xl p-5 md:p-6 group hover:shadow-xl hover:shadow-[var(--luxury-gold)]/10 transition-all duration-300 animate-fade-in border border-gray-100/50 hover:border-[var(--luxury-gold)]/25 hover:-translate-y-1" style={{ animationDelay: `${index * 0.1}s` }}>
<div className="absolute top-0 left-0 w-full h-0.5 bg-gradient-to-r from-[#d4af37] to-[#f5d76e] opacity-0 group-hover:opacity-100 transition-opacity duration-300 rounded-t-lg md:rounded-t-xl"></div> <div className="absolute top-0 left-0 w-full h-0.5 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] opacity-0 group-hover:opacity-100 transition-opacity duration-300 rounded-t-lg md:rounded-t-xl"></div>
{amenity.image ? ( {amenity.image ? (
<div className="w-full h-40 md:h-48 mb-4 md:mb-5 rounded-lg md:rounded-xl overflow-hidden shadow-lg group-hover:scale-105 transition-transform duration-300 border border-gray-100 group-hover:border-[#d4af37]/25"> <div className="w-full h-40 md:h-48 mb-4 md:mb-5 rounded-lg md:rounded-xl overflow-hidden shadow-lg group-hover:scale-105 transition-transform duration-300 border border-gray-100 group-hover:border-[var(--luxury-gold)]/25">
<img src={amenity.image} alt={amenity.title} className="w-full h-full object-cover" /> <img src={amenity.image} alt={amenity.title} className="w-full h-full object-cover" />
</div> </div>
) : ( ) : (
<div className="w-14 h-14 md:w-16 md:h-16 bg-gradient-to-br from-[#d4af37]/15 via-[#f5d76e]/10 to-[#d4af37]/15 rounded-lg flex items-center justify-center mb-4 md:mb-5 mx-auto group-hover:scale-110 group-hover:shadow-lg group-hover:shadow-[#d4af37]/20 transition-all duration-300 border border-[#d4af37]/25 group-hover:border-[#d4af37]/40"> <div className="w-14 h-14 md:w-16 md:h-16 bg-gradient-to-br from-[var(--luxury-gold)]/15 via-[var(--luxury-gold-light)]/10 to-[var(--luxury-gold)]/15 rounded-lg flex items-center justify-center mb-4 md:mb-5 mx-auto group-hover:scale-110 group-hover:shadow-lg group-hover:shadow-[var(--luxury-gold)]/20 transition-all duration-300 border border-[var(--luxury-gold)]/25 group-hover:border-[var(--luxury-gold)]/40">
{amenity.icon && (LucideIcons as any)[amenity.icon] ? ( {amenity.icon && (LucideIcons as any)[amenity.icon] ? (
React.createElement((LucideIcons as any)[amenity.icon], { React.createElement((LucideIcons as any)[amenity.icon], {
className: 'w-7 h-7 md:w-8 md:h-8 text-[#d4af37] drop-shadow-md' className: 'w-7 h-7 md:w-8 md:h-8 text-[var(--luxury-gold)] drop-shadow-md'
}) })
) : ( ) : (
<span className="text-2xl md:text-3xl">✨</span> <span className="text-2xl md:text-3xl">✨</span>
)} )}
</div> </div>
)} )}
<h3 className="text-lg md:text-xl font-serif font-semibold mb-2 md:mb-3 text-gray-900 group-hover:text-[#d4af37] transition-colors duration-300 tracking-tight"> <h3 className="text-lg md:text-xl font-serif font-semibold mb-2 md:mb-3 text-gray-900 group-hover:text-[var(--luxury-gold)] transition-colors duration-300 tracking-tight">
{amenity.title} {amenity.title}
</h3> </h3>
<p className="text-sm md:text-base text-gray-600 leading-relaxed font-light tracking-wide"> <p className="text-sm md:text-base text-gray-600 leading-relaxed font-light tracking-wide">
@@ -1161,10 +1161,10 @@ const HomePage: React.FC = () => {
{} {}
{(pageContent?.sections_enabled?.about_preview !== false) && (pageContent?.about_preview_title || pageContent?.about_preview_content) && ( {(pageContent?.sections_enabled?.about_preview !== false) && (pageContent?.about_preview_title || pageContent?.about_preview_content) && (
<section className="container mx-auto px-4 sm:px-6 lg:px-8 py-12 md:py-16"> <section className="container mx-auto px-4 sm:px-6 lg:px-8 py-12 md:py-16">
<div className="relative bg-white rounded-xl md:rounded-2xl shadow-xl shadow-[#d4af37]/5 overflow-hidden animate-fade-in border border-gray-100/50"> <div className="relative bg-white rounded-xl md:rounded-2xl shadow-xl shadow-[var(--luxury-gold)]/5 overflow-hidden animate-fade-in border border-gray-100/50">
{} {}
<div className="absolute top-0 left-0 right-0 h-1 bg-gradient-to-r from-[#d4af37] via-[#f5d76e] to-[#d4af37]"></div> <div className="absolute top-0 left-0 right-0 h-1 bg-gradient-to-r from-[var(--luxury-gold)] via-[var(--luxury-gold-light)] to-[var(--luxury-gold)]"></div>
<div className="absolute bottom-0 left-0 right-0 h-1 bg-gradient-to-r from-[#d4af37] via-[#f5d76e] to-[#d4af37]"></div> <div className="absolute bottom-0 left-0 right-0 h-1 bg-gradient-to-r from-[var(--luxury-gold)] via-[var(--luxury-gold-light)] to-[var(--luxury-gold)]"></div>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-0"> <div className="grid grid-cols-1 lg:grid-cols-2 gap-0">
{pageContent.about_preview_image && ( {pageContent.about_preview_image && (
@@ -1179,7 +1179,7 @@ const HomePage: React.FC = () => {
)} )}
<div className="p-6 md:p-8 lg:p-10 xl:p-12 flex flex-col justify-center bg-gradient-to-br from-white to-gray-50/20"> <div className="p-6 md:p-8 lg:p-10 xl:p-12 flex flex-col justify-center bg-gradient-to-br from-white to-gray-50/20">
<div className="inline-block mb-3 md:mb-4"> <div className="inline-block mb-3 md:mb-4">
<div className="h-0.5 w-12 md:w-16 bg-gradient-to-r from-[#d4af37] to-[#f5d76e] rounded-full"></div> <div className="h-0.5 w-12 md:w-16 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] rounded-full"></div>
</div> </div>
<h2 className="text-2xl sm:text-3xl md:text-4xl font-serif font-bold text-gray-900 mb-3 md:mb-4 tracking-tight leading-tight"> <h2 className="text-2xl sm:text-3xl md:text-4xl font-serif font-bold text-gray-900 mb-3 md:mb-4 tracking-tight leading-tight">
{pageContent.about_preview_title || 'About Our Hotel'} {pageContent.about_preview_title || 'About Our Hotel'}
@@ -1196,9 +1196,9 @@ const HomePage: React.FC = () => {
)} )}
<Link <Link
to="/about" to="/about"
className="group relative inline-flex items-center gap-2 px-6 py-2.5 md:px-8 md:py-3 bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-[#0f0f0f] rounded-lg font-semibold tracking-wide text-sm md:text-base shadow-md shadow-[#d4af37]/20 hover:shadow-lg hover:shadow-[#d4af37]/30 hover:-translate-y-0.5 transition-all duration-300 overflow-hidden w-fit" className="group relative inline-flex items-center gap-2 px-6 py-2.5 md:px-8 md:py-3 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-[#0f0f0f] rounded-lg font-semibold tracking-wide text-sm md:text-base shadow-md shadow-[var(--luxury-gold)]/20 hover:shadow-lg hover:shadow-[var(--luxury-gold)]/30 hover:-translate-y-0.5 transition-all duration-300 overflow-hidden w-fit"
> >
<span className="absolute inset-0 bg-gradient-to-r from-[#f5d76e] to-[#d4af37] opacity-0 group-hover:opacity-100 transition-opacity duration-300"></span> <span className="absolute inset-0 bg-gradient-to-r from-[var(--luxury-gold-light)] to-[var(--luxury-gold)] opacity-0 group-hover:opacity-100 transition-opacity duration-300"></span>
<span className="relative z-10">Learn More</span> <span className="relative z-10">Learn More</span>
<ArrowRight className="w-4 h-4 md:w-5 md:h-5 relative z-10 group-hover:translate-x-1 transition-transform duration-300" /> <ArrowRight className="w-4 h-4 md:w-5 md:h-5 relative z-10 group-hover:translate-x-1 transition-transform duration-300" />
</Link> </Link>
@@ -1213,7 +1213,7 @@ const HomePage: React.FC = () => {
<section className="container mx-auto px-4 sm:px-6 lg:px-8 py-12 md:py-16"> <section className="container mx-auto px-4 sm:px-6 lg:px-8 py-12 md:py-16">
<div className="text-center mb-8 md:mb-10 animate-fade-in"> <div className="text-center mb-8 md:mb-10 animate-fade-in">
<div className="inline-block mb-3"> <div className="inline-block mb-3">
<div className="h-0.5 w-16 md:w-20 bg-gradient-to-r from-[#d4af37] to-[#f5d76e] mx-auto rounded-full"></div> <div className="h-0.5 w-16 md:w-20 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] mx-auto rounded-full"></div>
</div> </div>
<h2 className="text-2xl sm:text-3xl md:text-4xl font-serif font-bold text-gray-900 tracking-tight mb-3 md:mb-4 px-4"> <h2 className="text-2xl sm:text-3xl md:text-4xl font-serif font-bold text-gray-900 tracking-tight mb-3 md:mb-4 px-4">
{pageContent?.luxury_services_section_title || 'Luxury Services'} {pageContent?.luxury_services_section_title || 'Luxury Services'}
@@ -1231,27 +1231,27 @@ const HomePage: React.FC = () => {
<Link <Link
key={service.id} key={service.id}
to={`/services/${serviceSlug}`} to={`/services/${serviceSlug}`}
className="relative bg-white rounded-lg md:rounded-xl p-5 md:p-6 group hover:shadow-xl hover:shadow-[#d4af37]/10 transition-all duration-300 animate-fade-in border border-gray-100/50 hover:border-[#d4af37]/25 hover:-translate-y-1 block" className="relative bg-white rounded-lg md:rounded-xl p-5 md:p-6 group hover:shadow-xl hover:shadow-[var(--luxury-gold)]/10 transition-all duration-300 animate-fade-in border border-gray-100/50 hover:border-[var(--luxury-gold)]/25 hover:-translate-y-1 block"
style={{ animationDelay: `${index * 0.1}s` }} style={{ animationDelay: `${index * 0.1}s` }}
> >
<div className="absolute top-0 left-0 w-full h-0.5 bg-gradient-to-r from-[#d4af37] to-[#f5d76e] opacity-0 group-hover:opacity-100 transition-opacity duration-300 rounded-t-lg md:rounded-t-xl"></div> <div className="absolute top-0 left-0 w-full h-0.5 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] opacity-0 group-hover:opacity-100 transition-opacity duration-300 rounded-t-lg md:rounded-t-xl"></div>
{service.image ? ( {service.image ? (
<div className="w-full h-40 md:h-48 mb-4 md:mb-5 rounded-lg md:rounded-xl overflow-hidden shadow-lg group-hover:scale-105 transition-transform duration-300 border border-gray-100 group-hover:border-[#d4af37]/25"> <div className="w-full h-40 md:h-48 mb-4 md:mb-5 rounded-lg md:rounded-xl overflow-hidden shadow-lg group-hover:scale-105 transition-transform duration-300 border border-gray-100 group-hover:border-[var(--luxury-gold)]/25">
<img src={service.image} alt={service.name} className="w-full h-full object-cover" /> <img src={service.image} alt={service.name} className="w-full h-full object-cover" />
</div> </div>
) : ( ) : (
<div className="w-14 h-14 md:w-16 md:h-16 bg-gradient-to-br from-[#d4af37]/15 via-[#f5d76e]/10 to-[#d4af37]/15 rounded-lg flex items-center justify-center mb-4 md:mb-5 mx-auto group-hover:scale-110 group-hover:shadow-lg group-hover:shadow-[#d4af37]/20 transition-all duration-300 border border-[#d4af37]/25 group-hover:border-[#d4af37]/40"> <div className="w-14 h-14 md:w-16 md:h-16 bg-gradient-to-br from-[var(--luxury-gold)]/15 via-[var(--luxury-gold-light)]/10 to-[var(--luxury-gold)]/15 rounded-lg flex items-center justify-center mb-4 md:mb-5 mx-auto group-hover:scale-110 group-hover:shadow-lg group-hover:shadow-[var(--luxury-gold)]/20 transition-all duration-300 border border-[var(--luxury-gold)]/25 group-hover:border-[var(--luxury-gold)]/40">
<span className="text-2xl md:text-3xl">✨</span> <span className="text-2xl md:text-3xl">✨</span>
</div> </div>
)} )}
<h3 className="text-lg md:text-xl font-serif font-semibold mb-2 md:mb-3 text-gray-900 group-hover:text-[#d4af37] transition-colors duration-300 tracking-tight"> <h3 className="text-lg md:text-xl font-serif font-semibold mb-2 md:mb-3 text-gray-900 group-hover:text-[var(--luxury-gold)] transition-colors duration-300 tracking-tight">
{service.name} {service.name}
</h3> </h3>
<p className="text-sm md:text-base text-gray-600 leading-relaxed font-light tracking-wide"> <p className="text-sm md:text-base text-gray-600 leading-relaxed font-light tracking-wide">
{service.description || 'Premium service for your comfort'} {service.description || 'Premium service for your comfort'}
</p> </p>
{service.price && ( {service.price && (
<div className="mt-3 text-sm font-semibold text-[#d4af37]"> <div className="mt-3 text-sm font-semibold text-[var(--luxury-gold)]">
Starting from {formatCurrency(service.price)} Starting from {formatCurrency(service.price)}
</div> </div>
)} )}
@@ -1262,7 +1262,7 @@ const HomePage: React.FC = () => {
<div className="text-center mt-8 md:mt-10"> <div className="text-center mt-8 md:mt-10">
<Link <Link
to={pageContent?.services_section_button_link || '/services'} to={pageContent?.services_section_button_link || '/services'}
className="inline-flex items-center gap-2 px-6 py-3 bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-[#0f0f0f] rounded-lg font-medium hover:from-[#f5d76e] hover:to-[#d4af37] transition-all duration-300 shadow-lg shadow-[#d4af37]/30 hover:shadow-xl hover:shadow-[#d4af37]/40 hover:-translate-y-0.5" className="inline-flex items-center gap-2 px-6 py-3 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-[#0f0f0f] rounded-lg font-medium hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] transition-all duration-300 shadow-lg shadow-[var(--luxury-gold)]/30 hover:shadow-xl hover:shadow-[var(--luxury-gold)]/40 hover:-translate-y-0.5"
> >
<span>{pageContent?.services_section_button_text || 'View All Services'}</span> <span>{pageContent?.services_section_button_text || 'View All Services'}</span>
<ArrowRight className="w-5 h-5" /> <ArrowRight className="w-5 h-5" />
@@ -1276,7 +1276,7 @@ const HomePage: React.FC = () => {
<section className="container mx-auto px-4 sm:px-6 lg:px-8 py-12 md:py-16 bg-gradient-to-b from-white via-gray-50/20 to-white"> <section className="container mx-auto px-4 sm:px-6 lg:px-8 py-12 md:py-16 bg-gradient-to-b from-white via-gray-50/20 to-white">
<div className="text-center mb-8 md:mb-10 animate-fade-in"> <div className="text-center mb-8 md:mb-10 animate-fade-in">
<div className="inline-block mb-3"> <div className="inline-block mb-3">
<div className="h-0.5 w-16 md:w-20 bg-gradient-to-r from-[#d4af37] to-[#f5d76e] mx-auto rounded-full"></div> <div className="h-0.5 w-16 md:w-20 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] mx-auto rounded-full"></div>
</div> </div>
<h2 className="text-2xl sm:text-3xl md:text-4xl font-serif font-bold text-gray-900 tracking-tight mb-3 md:mb-4 px-4"> <h2 className="text-2xl sm:text-3xl md:text-4xl font-serif font-bold text-gray-900 tracking-tight mb-3 md:mb-4 px-4">
{pageContent.luxury_experiences_section_title || 'Unique Experiences'} {pageContent.luxury_experiences_section_title || 'Unique Experiences'}
@@ -1289,24 +1289,24 @@ const HomePage: React.FC = () => {
</div> </div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-5 md:gap-6 px-4"> <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-5 md:gap-6 px-4">
{pageContent.luxury_experiences.map((experience: any, index: number) => ( {pageContent.luxury_experiences.map((experience: any, index: number) => (
<div key={index} className="relative bg-white rounded-lg md:rounded-xl p-5 md:p-6 group hover:shadow-xl hover:shadow-[#d4af37]/10 transition-all duration-300 animate-fade-in border border-gray-100/50 hover:border-[#d4af37]/25 hover:-translate-y-1" style={{ animationDelay: `${index * 0.1}s` }}> <div key={index} className="relative bg-white rounded-lg md:rounded-xl p-5 md:p-6 group hover:shadow-xl hover:shadow-[var(--luxury-gold)]/10 transition-all duration-300 animate-fade-in border border-gray-100/50 hover:border-[var(--luxury-gold)]/25 hover:-translate-y-1" style={{ animationDelay: `${index * 0.1}s` }}>
<div className="absolute top-0 left-0 w-full h-0.5 bg-gradient-to-r from-[#d4af37] to-[#f5d76e] opacity-0 group-hover:opacity-100 transition-opacity duration-300 rounded-t-lg md:rounded-t-xl"></div> <div className="absolute top-0 left-0 w-full h-0.5 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] opacity-0 group-hover:opacity-100 transition-opacity duration-300 rounded-t-lg md:rounded-t-xl"></div>
{experience.image ? ( {experience.image ? (
<div className="w-full h-40 md:h-48 mb-4 md:mb-5 rounded-lg md:rounded-xl overflow-hidden shadow-lg group-hover:scale-105 transition-transform duration-300 border border-gray-100 group-hover:border-[#d4af37]/25"> <div className="w-full h-40 md:h-48 mb-4 md:mb-5 rounded-lg md:rounded-xl overflow-hidden shadow-lg group-hover:scale-105 transition-transform duration-300 border border-gray-100 group-hover:border-[var(--luxury-gold)]/25">
<img src={experience.image} alt={experience.title} className="w-full h-full object-cover" /> <img src={experience.image} alt={experience.title} className="w-full h-full object-cover" />
</div> </div>
) : ( ) : (
<div className="w-14 h-14 md:w-16 md:h-16 bg-gradient-to-br from-[#d4af37]/15 via-[#f5d76e]/10 to-[#d4af37]/15 rounded-lg flex items-center justify-center mb-4 md:mb-5 mx-auto group-hover:scale-110 group-hover:shadow-lg group-hover:shadow-[#d4af37]/20 transition-all duration-300 border border-[#d4af37]/25 group-hover:border-[#d4af37]/40"> <div className="w-14 h-14 md:w-16 md:h-16 bg-gradient-to-br from-[var(--luxury-gold)]/15 via-[var(--luxury-gold-light)]/10 to-[var(--luxury-gold)]/15 rounded-lg flex items-center justify-center mb-4 md:mb-5 mx-auto group-hover:scale-110 group-hover:shadow-lg group-hover:shadow-[var(--luxury-gold)]/20 transition-all duration-300 border border-[var(--luxury-gold)]/25 group-hover:border-[var(--luxury-gold)]/40">
{experience.icon && (LucideIcons as any)[experience.icon] ? ( {experience.icon && (LucideIcons as any)[experience.icon] ? (
React.createElement((LucideIcons as any)[experience.icon], { React.createElement((LucideIcons as any)[experience.icon], {
className: 'w-7 h-7 md:w-8 md:h-8 text-[#d4af37] drop-shadow-md' className: 'w-7 h-7 md:w-8 md:h-8 text-[var(--luxury-gold)] drop-shadow-md'
}) })
) : ( ) : (
<span className="text-2xl md:text-3xl">✨</span> <span className="text-2xl md:text-3xl">✨</span>
)} )}
</div> </div>
)} )}
<h3 className="text-lg md:text-xl font-serif font-semibold mb-2 md:mb-3 text-gray-900 group-hover:text-[#d4af37] transition-colors duration-300 tracking-tight"> <h3 className="text-lg md:text-xl font-serif font-semibold mb-2 md:mb-3 text-gray-900 group-hover:text-[var(--luxury-gold)] transition-colors duration-300 tracking-tight">
{experience.title} {experience.title}
</h3> </h3>
<p className="text-sm md:text-base text-gray-600 leading-relaxed font-light tracking-wide"> <p className="text-sm md:text-base text-gray-600 leading-relaxed font-light tracking-wide">
@@ -1323,7 +1323,7 @@ const HomePage: React.FC = () => {
<section className="container mx-auto px-4 sm:px-6 lg:px-8 py-12 md:py-16"> <section className="container mx-auto px-4 sm:px-6 lg:px-8 py-12 md:py-16">
<div className="text-center mb-8 md:mb-10 animate-fade-in"> <div className="text-center mb-8 md:mb-10 animate-fade-in">
<div className="inline-block mb-3"> <div className="inline-block mb-3">
<div className="h-0.5 w-16 md:w-20 bg-gradient-to-r from-[#d4af37] to-[#f5d76e] mx-auto rounded-full"></div> <div className="h-0.5 w-16 md:w-20 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] mx-auto rounded-full"></div>
</div> </div>
<h2 className="text-2xl sm:text-3xl md:text-4xl font-serif font-bold text-gray-900 tracking-tight mb-3 md:mb-4 px-4"> <h2 className="text-2xl sm:text-3xl md:text-4xl font-serif font-bold text-gray-900 tracking-tight mb-3 md:mb-4 px-4">
{pageContent.awards_section_title || 'Awards & Recognition'} {pageContent.awards_section_title || 'Awards & Recognition'}
@@ -1336,17 +1336,17 @@ const HomePage: React.FC = () => {
</div> </div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-5 md:gap-6 px-4"> <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-5 md:gap-6 px-4">
{pageContent.awards.map((award: any, index: number) => ( {pageContent.awards.map((award: any, index: number) => (
<div key={index} className="relative bg-white rounded-lg md:rounded-xl p-5 md:p-6 group hover:shadow-xl hover:shadow-[#d4af37]/10 transition-all duration-300 animate-fade-in border border-gray-100/50 hover:border-[#d4af37]/25 hover:-translate-y-1 text-center" style={{ animationDelay: `${index * 0.1}s` }}> <div key={index} className="relative bg-white rounded-lg md:rounded-xl p-5 md:p-6 group hover:shadow-xl hover:shadow-[var(--luxury-gold)]/10 transition-all duration-300 animate-fade-in border border-gray-100/50 hover:border-[var(--luxury-gold)]/25 hover:-translate-y-1 text-center" style={{ animationDelay: `${index * 0.1}s` }}>
<div className="absolute top-0 left-0 w-full h-0.5 bg-gradient-to-r from-[#d4af37] to-[#f5d76e] opacity-0 group-hover:opacity-100 transition-opacity duration-300 rounded-t-lg md:rounded-t-xl"></div> <div className="absolute top-0 left-0 w-full h-0.5 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] opacity-0 group-hover:opacity-100 transition-opacity duration-300 rounded-t-lg md:rounded-t-xl"></div>
{award.image ? ( {award.image ? (
<div className="w-20 h-20 md:w-24 md:h-24 mx-auto mb-4 md:mb-5 rounded-lg overflow-hidden shadow-lg"> <div className="w-20 h-20 md:w-24 md:h-24 mx-auto mb-4 md:mb-5 rounded-lg overflow-hidden shadow-lg">
<img src={award.image} alt={award.title} className="w-full h-full object-cover" /> <img src={award.image} alt={award.title} className="w-full h-full object-cover" />
</div> </div>
) : ( ) : (
<div className="w-16 h-16 md:w-20 md:h-20 bg-gradient-to-br from-[#d4af37]/15 via-[#f5d76e]/10 to-[#d4af37]/15 rounded-lg flex items-center justify-center mx-auto mb-4 md:mb-5 group-hover:scale-110 group-hover:shadow-lg group-hover:shadow-[#d4af37]/20 transition-all duration-300 border border-[#d4af37]/25 group-hover:border-[#d4af37]/40"> <div className="w-16 h-16 md:w-20 md:h-20 bg-gradient-to-br from-[var(--luxury-gold)]/15 via-[var(--luxury-gold-light)]/10 to-[var(--luxury-gold)]/15 rounded-lg flex items-center justify-center mx-auto mb-4 md:mb-5 group-hover:scale-110 group-hover:shadow-lg group-hover:shadow-[var(--luxury-gold)]/20 transition-all duration-300 border border-[var(--luxury-gold)]/25 group-hover:border-[var(--luxury-gold)]/40">
{award.icon && (LucideIcons as any)[award.icon] ? ( {award.icon && (LucideIcons as any)[award.icon] ? (
React.createElement((LucideIcons as any)[award.icon], { React.createElement((LucideIcons as any)[award.icon], {
className: 'w-8 h-8 md:w-10 md:h-10 text-[#d4af37] drop-shadow-md' className: 'w-8 h-8 md:w-10 md:h-10 text-[var(--luxury-gold)] drop-shadow-md'
}) })
) : ( ) : (
<span className="text-3xl">🏆</span> <span className="text-3xl">🏆</span>
@@ -1354,9 +1354,9 @@ const HomePage: React.FC = () => {
</div> </div>
)} )}
{award.year && ( {award.year && (
<div className="text-xs md:text-sm text-[#d4af37] font-semibold mb-2">{award.year}</div> <div className="text-xs md:text-sm text-[var(--luxury-gold)] font-semibold mb-2">{award.year}</div>
)} )}
<h3 className="text-base md:text-lg font-serif font-semibold mb-2 text-gray-900 group-hover:text-[#d4af37] transition-colors duration-300 tracking-tight"> <h3 className="text-base md:text-lg font-serif font-semibold mb-2 text-gray-900 group-hover:text-[var(--luxury-gold)] transition-colors duration-300 tracking-tight">
{award.title} {award.title}
</h3> </h3>
{award.description && ( {award.description && (
@@ -1373,7 +1373,7 @@ const HomePage: React.FC = () => {
{} {}
{(pageContent?.cta_title || pageContent?.cta_subtitle) && ( {(pageContent?.cta_title || pageContent?.cta_subtitle) && (
<section className="container mx-auto px-4 sm:px-6 lg:px-8 py-12 md:py-16"> <section className="container mx-auto px-4 sm:px-6 lg:px-8 py-12 md:py-16">
<div className="relative bg-gradient-to-br from-slate-900 via-slate-800 to-slate-900 rounded-xl md:rounded-2xl p-8 md:p-12 lg:p-16 shadow-xl shadow-black/30 animate-fade-in overflow-hidden border border-[#d4af37]/15"> <div className="relative bg-gradient-to-br from-slate-900 via-slate-800 to-slate-900 rounded-xl md:rounded-2xl p-8 md:p-12 lg:p-16 shadow-xl shadow-black/30 animate-fade-in overflow-hidden border border-[var(--luxury-gold)]/15">
{pageContent.cta_image && ( {pageContent.cta_image && (
<div className="absolute inset-0 opacity-20"> <div className="absolute inset-0 opacity-20">
<img src={pageContent.cta_image} alt="CTA Background" className="w-full h-full object-cover" /> <img src={pageContent.cta_image} alt="CTA Background" className="w-full h-full object-cover" />
@@ -1382,7 +1382,7 @@ const HomePage: React.FC = () => {
<div className="absolute inset-0 bg-gradient-to-r from-black/60 via-black/40 to-black/60"></div> <div className="absolute inset-0 bg-gradient-to-r from-black/60 via-black/40 to-black/60"></div>
<div className="relative z-10 text-center"> <div className="relative z-10 text-center">
<div className="inline-block mb-4"> <div className="inline-block mb-4">
<div className="h-0.5 w-16 md:w-20 bg-gradient-to-r from-[#d4af37] to-[#f5d76e] mx-auto rounded-full"></div> <div className="h-0.5 w-16 md:w-20 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] mx-auto rounded-full"></div>
</div> </div>
<h2 className="text-2xl sm:text-3xl md:text-4xl lg:text-5xl font-serif font-bold text-white mb-4 md:mb-6 tracking-tight"> <h2 className="text-2xl sm:text-3xl md:text-4xl lg:text-5xl font-serif font-bold text-white mb-4 md:mb-6 tracking-tight">
{pageContent.cta_title} {pageContent.cta_title}
@@ -1395,9 +1395,9 @@ const HomePage: React.FC = () => {
{pageContent.cta_button_text && pageContent.cta_button_link && ( {pageContent.cta_button_text && pageContent.cta_button_link && (
<Link <Link
to={pageContent.cta_button_link} to={pageContent.cta_button_link}
className="group relative inline-flex items-center gap-2 px-8 py-3 md:px-10 md:py-4 bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-[#0f0f0f] rounded-lg font-semibold tracking-wide text-base md:text-lg shadow-lg shadow-[#d4af37]/30 hover:shadow-xl hover:shadow-[#d4af37]/40 hover:-translate-y-1 transition-all duration-300 overflow-hidden" className="group relative inline-flex items-center gap-2 px-8 py-3 md:px-10 md:py-4 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-[#0f0f0f] rounded-lg font-semibold tracking-wide text-base md:text-lg shadow-lg shadow-[var(--luxury-gold)]/30 hover:shadow-xl hover:shadow-[var(--luxury-gold)]/40 hover:-translate-y-1 transition-all duration-300 overflow-hidden"
> >
<span className="absolute inset-0 bg-gradient-to-r from-[#f5d76e] to-[#d4af37] opacity-0 group-hover:opacity-100 transition-opacity duration-300"></span> <span className="absolute inset-0 bg-gradient-to-r from-[var(--luxury-gold-light)] to-[var(--luxury-gold)] opacity-0 group-hover:opacity-100 transition-opacity duration-300"></span>
<span className="relative z-10">{pageContent.cta_button_text}</span> <span className="relative z-10">{pageContent.cta_button_text}</span>
<ArrowRight className="w-5 h-5 md:w-6 md:h-6 relative z-10 group-hover:translate-x-1 transition-transform duration-300" /> <ArrowRight className="w-5 h-5 md:w-6 md:h-6 relative z-10 group-hover:translate-x-1 transition-transform duration-300" />
</Link> </Link>
@@ -1413,7 +1413,7 @@ const HomePage: React.FC = () => {
<div className="container mx-auto px-4 sm:px-6 lg:px-8"> <div className="container mx-auto px-4 sm:px-6 lg:px-8">
<div className="text-center mb-8 md:mb-10 animate-fade-in"> <div className="text-center mb-8 md:mb-10 animate-fade-in">
<div className="inline-block mb-3"> <div className="inline-block mb-3">
<div className="h-0.5 w-16 md:w-20 bg-gradient-to-r from-[#d4af37] to-[#f5d76e] mx-auto rounded-full"></div> <div className="h-0.5 w-16 md:w-20 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] mx-auto rounded-full"></div>
</div> </div>
<h2 className="text-2xl sm:text-3xl md:text-4xl font-serif font-bold text-gray-900 tracking-tight mb-3 md:mb-4 px-4"> <h2 className="text-2xl sm:text-3xl md:text-4xl font-serif font-bold text-gray-900 tracking-tight mb-3 md:mb-4 px-4">
{pageContent.partners_section_title || 'Our Partners'} {pageContent.partners_section_title || 'Our Partners'}
@@ -1439,7 +1439,7 @@ const HomePage: React.FC = () => {
<section className="container mx-auto px-4 sm:px-6 lg:px-8 py-12 md:py-16 bg-gradient-to-b from-white via-gray-50/20 to-white"> <section className="container mx-auto px-4 sm:px-6 lg:px-8 py-12 md:py-16 bg-gradient-to-b from-white via-gray-50/20 to-white">
<div className="text-center mb-8 md:mb-10 animate-fade-in"> <div className="text-center mb-8 md:mb-10 animate-fade-in">
<div className="inline-block mb-3"> <div className="inline-block mb-3">
<div className="h-0.5 w-16 md:w-20 bg-gradient-to-r from-[#d4af37] to-[#f5d76e] mx-auto rounded-full"></div> <div className="h-0.5 w-16 md:w-20 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] mx-auto rounded-full"></div>
</div> </div>
{pageContent.promotions_section_title && ( {pageContent.promotions_section_title && (
<h2 className="text-2xl sm:text-3xl md:text-4xl font-serif font-bold text-gray-900 tracking-tight mb-3 md:mb-4 px-4"> <h2 className="text-2xl sm:text-3xl md:text-4xl font-serif font-bold text-gray-900 tracking-tight mb-3 md:mb-4 px-4">
@@ -1524,7 +1524,7 @@ const HomePage: React.FC = () => {
<div className="p-6"> <div className="p-6">
<div className="flex items-start justify-between mb-2"> <div className="flex items-start justify-between mb-2">
<h3 className={`text-xl font-bold mb-2 transition-colors ${ <h3 className={`text-xl font-bold mb-2 transition-colors ${
isValid ? 'text-gray-900 group-hover:text-[#d4af37]' : 'text-gray-500' isValid ? 'text-gray-900 group-hover:text-[var(--luxury-gold)]' : 'text-gray-500'
}`}> }`}>
{promo.title} {promo.title}
</h3> </h3>
@@ -1561,7 +1561,7 @@ const HomePage: React.FC = () => {
}} }}
className={`inline-flex items-center gap-2 px-6 py-2 rounded-lg font-semibold transition-all duration-300 ${ className={`inline-flex items-center gap-2 px-6 py-2 rounded-lg font-semibold transition-all duration-300 ${
isValid isValid
? 'bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-[#0f0f0f] hover:from-[#f5d76e] hover:to-[#d4af37] cursor-pointer group-hover:shadow-lg' ? 'bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-[#0f0f0f] hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] cursor-pointer group-hover:shadow-lg'
: 'bg-gray-300 text-gray-500 cursor-not-allowed' : 'bg-gray-300 text-gray-500 cursor-not-allowed'
}`} }`}
role="button" role="button"
@@ -1587,7 +1587,7 @@ const HomePage: React.FC = () => {
<section className="container mx-auto px-4 sm:px-6 lg:px-8 py-12 md:py-16 bg-gradient-to-b from-white via-gray-50/20 to-white"> <section className="container mx-auto px-4 sm:px-6 lg:px-8 py-12 md:py-16 bg-gradient-to-b from-white via-gray-50/20 to-white">
<div className="text-center mb-8 md:mb-10 animate-fade-in"> <div className="text-center mb-8 md:mb-10 animate-fade-in">
<div className="inline-block mb-3"> <div className="inline-block mb-3">
<div className="h-0.5 w-16 md:w-20 bg-gradient-to-r from-[#d4af37] to-[#f5d76e] mx-auto rounded-full"></div> <div className="h-0.5 w-16 md:w-20 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] mx-auto rounded-full"></div>
</div> </div>
{pageContent.blog_section_title && ( {pageContent.blog_section_title && (
<h2 className="text-2xl sm:text-3xl md:text-4xl font-serif font-bold text-gray-900 tracking-tight mb-3 md:mb-4 px-4"> <h2 className="text-2xl sm:text-3xl md:text-4xl font-serif font-bold text-gray-900 tracking-tight mb-3 md:mb-4 px-4">
@@ -1636,13 +1636,13 @@ const HomePage: React.FC = () => {
{new Date(post.published_at).toLocaleDateString()} {new Date(post.published_at).toLocaleDateString()}
</p> </p>
)} )}
<h3 className="text-xl font-bold text-gray-900 mb-2 group-hover:text-[#d4af37] transition-colors"> <h3 className="text-xl font-bold text-gray-900 mb-2 group-hover:text-[var(--luxury-gold)] transition-colors">
{post.title} {post.title}
</h3> </h3>
{post.excerpt && ( {post.excerpt && (
<p className="text-gray-600 mb-4 line-clamp-3">{post.excerpt}</p> <p className="text-gray-600 mb-4 line-clamp-3">{post.excerpt}</p>
)} )}
<div className="flex items-center gap-2 text-[#d4af37] font-semibold group-hover:gap-3 transition-all"> <div className="flex items-center gap-2 text-[var(--luxury-gold)] font-semibold group-hover:gap-3 transition-all">
Read More Read More
<ArrowRight className="w-4 h-4" /> <ArrowRight className="w-4 h-4" />
</div> </div>
@@ -1655,7 +1655,7 @@ const HomePage: React.FC = () => {
<div className="text-center mt-8 md:mt-10"> <div className="text-center mt-8 md:mt-10">
<Link <Link
to="/blog" to="/blog"
className="inline-flex items-center gap-2 px-8 py-3 bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-[#0f0f0f] rounded-lg font-semibold hover:from-[#f5d76e] hover:to-[#d4af37] transition-all duration-300 shadow-lg shadow-[#d4af37]/30 hover:shadow-xl hover:shadow-[#d4af37]/40 hover:-translate-y-0.5" className="inline-flex items-center gap-2 px-8 py-3 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-[#0f0f0f] rounded-lg font-semibold hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] transition-all duration-300 shadow-lg shadow-[var(--luxury-gold)]/30 hover:shadow-xl hover:shadow-[var(--luxury-gold)]/40 hover:-translate-y-0.5"
> >
View All Posts View All Posts
<ArrowRight className="w-5 h-5" /> <ArrowRight className="w-5 h-5" />
@@ -1680,7 +1680,7 @@ const HomePage: React.FC = () => {
e.stopPropagation(); e.stopPropagation();
setLightboxOpen(false); setLightboxOpen(false);
}} }}
className="absolute top-4 right-4 md:top-6 md:right-6 z-50 p-3 bg-black/50 hover:bg-black/70 rounded-full text-white hover:text-[#d4af37] transition-all duration-300 backdrop-blur-sm border border-white/10 hover:border-[#d4af37]/50" className="absolute top-4 right-4 md:top-6 md:right-6 z-50 p-3 bg-black/50 hover:bg-black/70 rounded-full text-white hover:text-[var(--luxury-gold)] transition-all duration-300 backdrop-blur-sm border border-white/10 hover:border-[var(--luxury-gold)]/50"
aria-label="Close" aria-label="Close"
> >
<X className="w-6 h-6 md:w-7 md:h-7" /> <X className="w-6 h-6 md:w-7 md:h-7" />
@@ -1693,7 +1693,7 @@ const HomePage: React.FC = () => {
e.stopPropagation(); e.stopPropagation();
setLightboxIndex((prev) => (prev === 0 ? lightboxImages.length - 1 : prev - 1)); setLightboxIndex((prev) => (prev === 0 ? lightboxImages.length - 1 : prev - 1));
}} }}
className="absolute left-4 md:left-6 z-50 p-3 bg-black/50 hover:bg-black/70 rounded-full text-white hover:text-[#d4af37] transition-all duration-300 backdrop-blur-sm border border-white/10 hover:border-[#d4af37]/50" className="absolute left-4 md:left-6 z-50 p-3 bg-black/50 hover:bg-black/70 rounded-full text-white hover:text-[var(--luxury-gold)] transition-all duration-300 backdrop-blur-sm border border-white/10 hover:border-[var(--luxury-gold)]/50"
aria-label="Previous image" aria-label="Previous image"
> >
<ChevronLeft className="w-6 h-6 md:w-7 md:h-7" /> <ChevronLeft className="w-6 h-6 md:w-7 md:h-7" />
@@ -1707,7 +1707,7 @@ const HomePage: React.FC = () => {
e.stopPropagation(); e.stopPropagation();
setLightboxIndex((prev) => (prev === lightboxImages.length - 1 ? 0 : prev + 1)); setLightboxIndex((prev) => (prev === lightboxImages.length - 1 ? 0 : prev + 1));
}} }}
className="absolute right-4 md:right-6 z-50 p-3 bg-black/50 hover:bg-black/70 rounded-full text-white hover:text-[#d4af37] transition-all duration-300 backdrop-blur-sm border border-white/10 hover:border-[#d4af37]/50" className="absolute right-4 md:right-6 z-50 p-3 bg-black/50 hover:bg-black/70 rounded-full text-white hover:text-[var(--luxury-gold)] transition-all duration-300 backdrop-blur-sm border border-white/10 hover:border-[var(--luxury-gold)]/50"
aria-label="Next image" aria-label="Next image"
> >
<ChevronRight className="w-6 h-6 md:w-7 md:h-7" /> <ChevronRight className="w-6 h-6 md:w-7 md:h-7" />
@@ -1748,7 +1748,7 @@ const HomePage: React.FC = () => {
}} }}
className={`flex-shrink-0 w-16 h-16 md:w-20 md:h-20 rounded-lg overflow-hidden border-2 transition-all duration-300 ${ className={`flex-shrink-0 w-16 h-16 md:w-20 md:h-20 rounded-lg overflow-hidden border-2 transition-all duration-300 ${
idx === lightboxIndex idx === lightboxIndex
? 'border-[#d4af37] shadow-lg shadow-[#d4af37]/50 scale-110' ? 'border-[var(--luxury-gold)] shadow-lg shadow-[var(--luxury-gold)]/50 scale-110'
: 'border-white/30 hover:border-white/60 opacity-70 hover:opacity-100' : 'border-white/30 hover:border-white/60 opacity-70 hover:opacity-100'
}`} }`}
> >

View File

@@ -99,12 +99,12 @@ const PrivacyPolicyPage: React.FC = () => {
}} }}
> >
<div className="text-center"> <div className="text-center">
<Shield className="w-16 h-16 text-[#d4af37]/50 mx-auto mb-4" /> <Shield className="w-16 h-16 text-[var(--luxury-gold)]/50 mx-auto mb-4" />
<h1 className="text-2xl font-elegant font-bold text-white mb-2">Privacy Policy</h1> <h1 className="text-2xl font-elegant font-bold text-white mb-2">Privacy Policy</h1>
<p className="text-gray-400">This page is currently unavailable.</p> <p className="text-gray-400">This page is currently unavailable.</p>
<Link <Link
to="/" to="/"
className="inline-flex items-center gap-2 text-[#d4af37]/80 hover:text-[#d4af37] mt-6 transition-all duration-300" className="inline-flex items-center gap-2 text-[var(--luxury-gold)]/80 hover:text-[var(--luxury-gold)] mt-6 transition-all duration-300"
> >
<ArrowLeft className="w-4 h-4" /> <ArrowLeft className="w-4 h-4" />
<span>Back to Home</span> <span>Back to Home</span>
@@ -129,7 +129,7 @@ const PrivacyPolicyPage: React.FC = () => {
{/* Back Link */} {/* Back Link */}
<Link <Link
to="/" to="/"
className="inline-flex items-center gap-2 text-[#d4af37]/80 hover:text-[#d4af37] mb-6 transition-all duration-300 group font-light tracking-wide text-xs sm:text-sm" className="inline-flex items-center gap-2 text-[var(--luxury-gold)]/80 hover:text-[var(--luxury-gold)] mb-6 transition-all duration-300 group font-light tracking-wide text-xs sm:text-sm"
> >
<ArrowLeft className="w-4 h-4 group-hover:-translate-x-1 transition-transform" /> <ArrowLeft className="w-4 h-4 group-hover:-translate-x-1 transition-transform" />
<span>Back to Home</span> <span>Back to Home</span>
@@ -137,10 +137,10 @@ const PrivacyPolicyPage: React.FC = () => {
{/* Header */} {/* Header */}
<div className="mb-8 sm:mb-12 text-center"> <div className="mb-8 sm:mb-12 text-center">
<div className="inline-flex items-center justify-center w-16 h-16 sm:w-20 sm:h-20 mb-4 sm:mb-6 bg-gradient-to-br from-[#d4af37]/20 to-[#c9a227]/10 rounded-full border border-[#d4af37]/30"> <div className="inline-flex items-center justify-center w-16 h-16 sm:w-20 sm:h-20 mb-4 sm:mb-6 bg-gradient-to-br from-[var(--luxury-gold)]/20 to-[var(--luxury-gold-dark)]/10 rounded-full border border-[var(--luxury-gold)]/30">
<Shield className="w-8 h-8 sm:w-10 sm:h-10 text-[#d4af37]" /> <Shield className="w-8 h-8 sm:w-10 sm:h-10 text-[var(--luxury-gold)]" />
</div> </div>
<h1 className="text-3xl sm:text-4xl lg:text-5xl font-elegant font-bold text-white mb-3 sm:mb-4 tracking-tight leading-tight bg-gradient-to-r from-white via-[#d4af37] to-white bg-clip-text text-transparent"> <h1 className="text-3xl sm:text-4xl lg:text-5xl font-elegant font-bold text-white mb-3 sm:mb-4 tracking-tight leading-tight bg-gradient-to-r from-white via-[var(--luxury-gold)] to-white bg-clip-text text-transparent">
{pageContent.title || 'Privacy Policy'} {pageContent.title || 'Privacy Policy'}
</h1> </h1>
{pageContent.subtitle && ( {pageContent.subtitle && (
@@ -151,18 +151,18 @@ const PrivacyPolicyPage: React.FC = () => {
</div> </div>
{/* Content */} {/* Content */}
<div className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-xl border border-[#d4af37]/20 backdrop-blur-xl shadow-2xl shadow-[#d4af37]/5 p-6 sm:p-8 lg:p-12"> <div className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-xl border border-[var(--luxury-gold)]/20 backdrop-blur-xl shadow-2xl shadow-[var(--luxury-gold)]/5 p-6 sm:p-8 lg:p-12">
<div <div
className="prose prose-invert prose-lg max-w-none text-gray-300 className="prose prose-invert prose-lg max-w-none text-gray-300
prose-headings:text-white prose-headings:font-elegant prose-headings:font-semibold prose-headings:text-white prose-headings:font-elegant prose-headings:font-semibold
prose-h2:text-2xl prose-h2:mt-8 prose-h2:mb-4 prose-h2:border-b prose-h2:border-[#d4af37]/20 prose-h2:pb-2 prose-h2:text-2xl prose-h2:mt-8 prose-h2:mb-4 prose-h2:border-b prose-h2:border-[var(--luxury-gold)]/20 prose-h2:pb-2
prose-p:text-gray-300 prose-p:font-light prose-p:leading-relaxed prose-p:mb-4 prose-p:text-gray-300 prose-p:font-light prose-p:leading-relaxed prose-p:mb-4
prose-ul:text-gray-300 prose-ul:font-light prose-ul:my-4 prose-ul:text-gray-300 prose-ul:font-light prose-ul:my-4
prose-li:text-gray-300 prose-li:mb-2 prose-li:ml-4 prose-li:text-gray-300 prose-li:mb-2 prose-li:ml-4
prose-strong:text-[#d4af37] prose-strong:font-medium prose-strong:text-[var(--luxury-gold)] prose-strong:font-medium
prose-a:text-[#d4af37] prose-a:no-underline hover:prose-a:underline prose-a:text-[var(--luxury-gold)] prose-a:no-underline hover:prose-a:underline
[&_*]:text-gray-300 [&_h1]:text-white [&_h2]:text-white [&_h3]:text-white [&_h4]:text-white [&_h5]:text-white [&_h6]:text-white [&_*]:text-gray-300 [&_h1]:text-white [&_h2]:text-white [&_h3]:text-white [&_h4]:text-white [&_h5]:text-white [&_h6]:text-white
[&_strong]:text-[#d4af37] [&_b]:text-[#d4af37] [&_a]:text-[#d4af37]" [&_strong]:text-[var(--luxury-gold)] [&_b]:text-[var(--luxury-gold)] [&_a]:text-[var(--luxury-gold)]"
style={{ color: '#d1d5db' }} style={{ color: '#d1d5db' }}
dangerouslySetInnerHTML={createSanitizedHtml( dangerouslySetInnerHTML={createSanitizedHtml(
pageContent.content || pageContent.description || '<p style="color: #d1d5db;">No content available.</p>' pageContent.content || pageContent.description || '<p style="color: #d1d5db;">No content available.</p>'
@@ -176,7 +176,7 @@ const PrivacyPolicyPage: React.FC = () => {
<div className="text-center"> <div className="text-center">
<p className="text-sm text-gray-400 font-light"> <p className="text-sm text-gray-400 font-light">
For questions about this policy, contact us at{' '} For questions about this policy, contact us at{' '}
<a href={`mailto:${settings.company_email}`} className="text-[#d4af37] hover:underline"> <a href={`mailto:${settings.company_email}`} className="text-[var(--luxury-gold)] hover:underline">
{settings.company_email} {settings.company_email}
</a> </a>
</p> </p>
@@ -185,7 +185,7 @@ const PrivacyPolicyPage: React.FC = () => {
<div className="text-center"> <div className="text-center">
<Link <Link
to="/gdpr" to="/gdpr"
className="inline-flex items-center gap-2 text-sm text-[#d4af37] hover:text-[#f5d76e] transition-colors font-light" className="inline-flex items-center gap-2 text-sm text-[var(--luxury-gold)] hover:text-[var(--luxury-gold-light)] transition-colors font-light"
> >
<Shield className="w-4 h-4" /> <Shield className="w-4 h-4" />
<span>Manage Your Data Privacy (GDPR)</span> <span>Manage Your Data Privacy (GDPR)</span>

View File

@@ -99,12 +99,12 @@ const RefundsPolicyPage: React.FC = () => {
}} }}
> >
<div className="text-center"> <div className="text-center">
<RefreshCw className="w-16 h-16 text-[#d4af37]/50 mx-auto mb-4" /> <RefreshCw className="w-16 h-16 text-[var(--luxury-gold)]/50 mx-auto mb-4" />
<h1 className="text-2xl font-elegant font-bold text-white mb-2">Refunds Policy</h1> <h1 className="text-2xl font-elegant font-bold text-white mb-2">Refunds Policy</h1>
<p className="text-gray-400">This page is currently unavailable.</p> <p className="text-gray-400">This page is currently unavailable.</p>
<Link <Link
to="/" to="/"
className="inline-flex items-center gap-2 text-[#d4af37]/80 hover:text-[#d4af37] mt-6 transition-all duration-300" className="inline-flex items-center gap-2 text-[var(--luxury-gold)]/80 hover:text-[var(--luxury-gold)] mt-6 transition-all duration-300"
> >
<ArrowLeft className="w-4 h-4" /> <ArrowLeft className="w-4 h-4" />
<span>Back to Home</span> <span>Back to Home</span>
@@ -129,7 +129,7 @@ const RefundsPolicyPage: React.FC = () => {
{/* Back Link */} {/* Back Link */}
<Link <Link
to="/" to="/"
className="inline-flex items-center gap-2 text-[#d4af37]/80 hover:text-[#d4af37] mb-6 transition-all duration-300 group font-light tracking-wide text-xs sm:text-sm" className="inline-flex items-center gap-2 text-[var(--luxury-gold)]/80 hover:text-[var(--luxury-gold)] mb-6 transition-all duration-300 group font-light tracking-wide text-xs sm:text-sm"
> >
<ArrowLeft className="w-4 h-4 group-hover:-translate-x-1 transition-transform" /> <ArrowLeft className="w-4 h-4 group-hover:-translate-x-1 transition-transform" />
<span>Back to Home</span> <span>Back to Home</span>
@@ -137,10 +137,10 @@ const RefundsPolicyPage: React.FC = () => {
{/* Header */} {/* Header */}
<div className="mb-8 sm:mb-12 text-center"> <div className="mb-8 sm:mb-12 text-center">
<div className="inline-flex items-center justify-center w-16 h-16 sm:w-20 sm:h-20 mb-4 sm:mb-6 bg-gradient-to-br from-[#d4af37]/20 to-[#c9a227]/10 rounded-full border border-[#d4af37]/30"> <div className="inline-flex items-center justify-center w-16 h-16 sm:w-20 sm:h-20 mb-4 sm:mb-6 bg-gradient-to-br from-[var(--luxury-gold)]/20 to-[var(--luxury-gold-dark)]/10 rounded-full border border-[var(--luxury-gold)]/30">
<RefreshCw className="w-8 h-8 sm:w-10 sm:h-10 text-[#d4af37]" /> <RefreshCw className="w-8 h-8 sm:w-10 sm:h-10 text-[var(--luxury-gold)]" />
</div> </div>
<h1 className="text-3xl sm:text-4xl lg:text-5xl font-elegant font-bold text-white mb-3 sm:mb-4 tracking-tight leading-tight bg-gradient-to-r from-white via-[#d4af37] to-white bg-clip-text text-transparent"> <h1 className="text-3xl sm:text-4xl lg:text-5xl font-elegant font-bold text-white mb-3 sm:mb-4 tracking-tight leading-tight bg-gradient-to-r from-white via-[var(--luxury-gold)] to-white bg-clip-text text-transparent">
{pageContent.title || 'Refunds Policy'} {pageContent.title || 'Refunds Policy'}
</h1> </h1>
{pageContent.subtitle && ( {pageContent.subtitle && (
@@ -151,18 +151,18 @@ const RefundsPolicyPage: React.FC = () => {
</div> </div>
{/* Content */} {/* Content */}
<div className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-xl border border-[#d4af37]/20 backdrop-blur-xl shadow-2xl shadow-[#d4af37]/5 p-6 sm:p-8 lg:p-12"> <div className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-xl border border-[var(--luxury-gold)]/20 backdrop-blur-xl shadow-2xl shadow-[var(--luxury-gold)]/5 p-6 sm:p-8 lg:p-12">
<div <div
className="prose prose-invert prose-lg max-w-none text-gray-300 className="prose prose-invert prose-lg max-w-none text-gray-300
prose-headings:text-white prose-headings:font-elegant prose-headings:font-semibold prose-headings:text-white prose-headings:font-elegant prose-headings:font-semibold
prose-h2:text-2xl prose-h2:mt-8 prose-h2:mb-4 prose-h2:border-b prose-h2:border-[#d4af37]/20 prose-h2:pb-2 prose-h2:text-2xl prose-h2:mt-8 prose-h2:mb-4 prose-h2:border-b prose-h2:border-[var(--luxury-gold)]/20 prose-h2:pb-2
prose-p:text-gray-300 prose-p:font-light prose-p:leading-relaxed prose-p:mb-4 prose-p:text-gray-300 prose-p:font-light prose-p:leading-relaxed prose-p:mb-4
prose-ul:text-gray-300 prose-ul:font-light prose-ul:my-4 prose-ul:text-gray-300 prose-ul:font-light prose-ul:my-4
prose-li:text-gray-300 prose-li:mb-2 prose-li:ml-4 prose-li:text-gray-300 prose-li:mb-2 prose-li:ml-4
prose-strong:text-[#d4af37] prose-strong:font-medium prose-strong:text-[var(--luxury-gold)] prose-strong:font-medium
prose-a:text-[#d4af37] prose-a:no-underline hover:prose-a:underline prose-a:text-[var(--luxury-gold)] prose-a:no-underline hover:prose-a:underline
[&_*]:text-gray-300 [&_h1]:text-white [&_h2]:text-white [&_h3]:text-white [&_h4]:text-white [&_h5]:text-white [&_h6]:text-white [&_*]:text-gray-300 [&_h1]:text-white [&_h2]:text-white [&_h3]:text-white [&_h4]:text-white [&_h5]:text-white [&_h6]:text-white
[&_strong]:text-[#d4af37] [&_b]:text-[#d4af37] [&_a]:text-[#d4af37]" [&_strong]:text-[var(--luxury-gold)] [&_b]:text-[var(--luxury-gold)] [&_a]:text-[var(--luxury-gold)]"
style={{ color: '#d1d5db' }} style={{ color: '#d1d5db' }}
dangerouslySetInnerHTML={createSanitizedHtml( dangerouslySetInnerHTML={createSanitizedHtml(
pageContent.content || pageContent.description || '<p style="color: #d1d5db;">No content available.</p>' pageContent.content || pageContent.description || '<p style="color: #d1d5db;">No content available.</p>'
@@ -175,7 +175,7 @@ const RefundsPolicyPage: React.FC = () => {
<div className="mt-8 text-center"> <div className="mt-8 text-center">
<p className="text-sm text-gray-400 font-light"> <p className="text-sm text-gray-400 font-light">
For refund inquiries, contact us at{' '} For refund inquiries, contact us at{' '}
<a href={`mailto:${settings.company_email}`} className="text-[#d4af37] hover:underline"> <a href={`mailto:${settings.company_email}`} className="text-[var(--luxury-gold)] hover:underline">
{settings.company_email} {settings.company_email}
</a> </a>
</p> </p>

View File

@@ -291,7 +291,7 @@ const ServiceDetailPage: React.FC = () => {
<div className="min-h-screen bg-gradient-to-b from-[#0f0f0f] via-[#1a1a1a] to-black text-white flex items-center justify-center"> <div className="min-h-screen bg-gradient-to-b from-[#0f0f0f] via-[#1a1a1a] to-black text-white flex items-center justify-center">
<div className="text-center"> <div className="text-center">
<h1 className="text-2xl font-bold mb-4">Service not found</h1> <h1 className="text-2xl font-bold mb-4">Service not found</h1>
<Link to="/services" className="text-[#d4af37] hover:underline"> <Link to="/services" className="text-[var(--luxury-gold)] hover:underline">
Back to Services Back to Services
</Link> </Link>
</div> </div>
@@ -316,8 +316,8 @@ const ServiceDetailPage: React.FC = () => {
{/* Luxury Overlay Pattern */} {/* Luxury Overlay Pattern */}
<div className="absolute inset-0 opacity-10"> <div className="absolute inset-0 opacity-10">
<div className="absolute top-0 left-0 w-96 h-96 bg-[#d4af37] rounded-full blur-3xl"></div> <div className="absolute top-0 left-0 w-96 h-96 bg-[var(--luxury-gold)] rounded-full blur-3xl"></div>
<div className="absolute bottom-0 right-0 w-96 h-96 bg-[#c9a227] rounded-full blur-3xl"></div> <div className="absolute bottom-0 right-0 w-96 h-96 bg-[var(--luxury-gold-dark)] rounded-full blur-3xl"></div>
</div> </div>
{/* Hero Content Overlay */} {/* Hero Content Overlay */}
@@ -326,12 +326,12 @@ const ServiceDetailPage: React.FC = () => {
<div className="max-w-5xl mx-auto"> <div className="max-w-5xl mx-auto">
{service.category && ( {service.category && (
<div className="flex flex-wrap gap-3 mb-6"> <div className="flex flex-wrap gap-3 mb-6">
<span className="inline-flex items-center gap-2 px-5 py-2.5 bg-gradient-to-br from-[#d4af37]/20 to-[#c9a227]/10 backdrop-blur-md rounded-xl text-[#d4af37] text-sm font-semibold border border-[#d4af37]/40 shadow-xl"> <span className="inline-flex items-center gap-2 px-5 py-2.5 bg-gradient-to-br from-[var(--luxury-gold)]/20 to-[var(--luxury-gold-dark)]/10 backdrop-blur-md rounded-xl text-[var(--luxury-gold)] text-sm font-semibold border border-[var(--luxury-gold)]/40 shadow-xl">
<Tag className="w-4 h-4" /> <Tag className="w-4 h-4" />
{service.category} {service.category}
</span> </span>
{service.type === 'luxury' && ( {service.type === 'luxury' && (
<span className="inline-flex items-center gap-2 px-5 py-2.5 bg-gradient-to-br from-[#d4af37]/30 to-[#c9a227]/20 backdrop-blur-md rounded-xl text-[#0f0f0f] text-sm font-bold border border-[#d4af37]/50 shadow-xl"> <span className="inline-flex items-center gap-2 px-5 py-2.5 bg-gradient-to-br from-[var(--luxury-gold)]/30 to-[var(--luxury-gold-dark)]/20 backdrop-blur-md rounded-xl text-[#0f0f0f] text-sm font-bold border border-[var(--luxury-gold)]/50 shadow-xl">
<Star className="w-4 h-4 fill-[#0f0f0f]" /> <Star className="w-4 h-4 fill-[#0f0f0f]" />
Premium Premium
</span> </span>
@@ -348,7 +348,7 @@ const ServiceDetailPage: React.FC = () => {
)} )}
{service.price !== undefined && ( {service.price !== undefined && (
<div className="flex items-baseline gap-3 mb-8"> <div className="flex items-baseline gap-3 mb-8">
<span className="text-4xl sm:text-5xl lg:text-6xl font-serif font-bold bg-gradient-to-r from-[#d4af37] via-[#f5d76e] to-[#d4af37] bg-clip-text text-transparent drop-shadow-lg"> <span className="text-4xl sm:text-5xl lg:text-6xl font-serif font-bold bg-gradient-to-r from-[var(--luxury-gold)] via-[var(--luxury-gold-light)] to-[var(--luxury-gold)] bg-clip-text text-transparent drop-shadow-lg">
{formatCurrency(service.price)} {formatCurrency(service.price)}
</span> </span>
{service.unit && ( {service.unit && (
@@ -363,7 +363,7 @@ const ServiceDetailPage: React.FC = () => {
</div> </div>
{/* Decorative Bottom Border */} {/* Decorative Bottom Border */}
<div className="absolute bottom-0 left-0 w-full h-1 bg-gradient-to-r from-transparent via-[#d4af37]/50 to-transparent"></div> <div className="absolute bottom-0 left-0 w-full h-1 bg-gradient-to-r from-transparent via-[var(--luxury-gold)]/50 to-transparent"></div>
</div> </div>
)} )}
@@ -375,7 +375,7 @@ const ServiceDetailPage: React.FC = () => {
{!service.image && ( {!service.image && (
<Link <Link
to="/services" to="/services"
className="inline-flex items-center gap-3 px-6 py-3 bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] border-2 border-[#d4af37]/20 rounded-xl text-gray-300 hover:text-[#d4af37] hover:border-[#d4af37]/50 transition-all duration-300 mb-12 group" className="inline-flex items-center gap-3 px-6 py-3 bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] border-2 border-[var(--luxury-gold)]/20 rounded-xl text-gray-300 hover:text-[var(--luxury-gold)] hover:border-[var(--luxury-gold)]/50 transition-all duration-300 mb-12 group"
> >
<ArrowLeft className="w-5 h-5 group-hover:-translate-x-1 transition-transform" /> <ArrowLeft className="w-5 h-5 group-hover:-translate-x-1 transition-transform" />
<span className="font-medium">Back to Services</span> <span className="font-medium">Back to Services</span>
@@ -389,13 +389,13 @@ const ServiceDetailPage: React.FC = () => {
<div className="flex flex-wrap gap-3 mb-6"> <div className="flex flex-wrap gap-3 mb-6">
<Link <Link
to={`/services?category=${encodeURIComponent(service.category)}`} to={`/services?category=${encodeURIComponent(service.category)}`}
className="inline-flex items-center gap-2 px-5 py-2.5 bg-gradient-to-br from-[#d4af37]/15 to-[#d4af37]/5 text-[#d4af37] rounded-xl text-sm font-semibold border border-[#d4af37]/30 hover:border-[#d4af37]/50 transition-all" className="inline-flex items-center gap-2 px-5 py-2.5 bg-gradient-to-br from-[var(--luxury-gold)]/15 to-[var(--luxury-gold)]/5 text-[var(--luxury-gold)] rounded-xl text-sm font-semibold border border-[var(--luxury-gold)]/30 hover:border-[var(--luxury-gold)]/50 transition-all"
> >
<Tag className="w-4 h-4" /> <Tag className="w-4 h-4" />
{service.category} {service.category}
</Link> </Link>
{service.type === 'luxury' && ( {service.type === 'luxury' && (
<span className="inline-flex items-center gap-2 px-5 py-2.5 bg-gradient-to-br from-[#d4af37]/20 to-[#c9a227]/10 text-[#d4af37] rounded-xl text-sm font-bold border border-[#d4af37]/40"> <span className="inline-flex items-center gap-2 px-5 py-2.5 bg-gradient-to-br from-[var(--luxury-gold)]/20 to-[var(--luxury-gold-dark)]/10 text-[var(--luxury-gold)] rounded-xl text-sm font-bold border border-[var(--luxury-gold)]/40">
<Star className="w-4 h-4" /> <Star className="w-4 h-4" />
Premium Premium
</span> </span>
@@ -406,9 +406,9 @@ const ServiceDetailPage: React.FC = () => {
<div className="flex items-start gap-6 mb-6"> <div className="flex items-start gap-6 mb-6">
{service.icon && (LucideIcons as any)[service.icon] && ( {service.icon && (LucideIcons as any)[service.icon] && (
<div className="relative flex-shrink-0"> <div className="relative flex-shrink-0">
<div className="absolute inset-0 bg-[#d4af37]/20 rounded-full blur-3xl"></div> <div className="absolute inset-0 bg-[var(--luxury-gold)]/20 rounded-full blur-3xl"></div>
{React.createElement((LucideIcons as any)[service.icon], { {React.createElement((LucideIcons as any)[service.icon], {
className: 'w-20 h-20 sm:w-24 sm:h-24 text-[#d4af37] relative z-10 drop-shadow-2xl' className: 'w-20 h-20 sm:w-24 sm:h-24 text-[var(--luxury-gold)] relative z-10 drop-shadow-2xl'
})} })}
</div> </div>
)} )}
@@ -418,7 +418,7 @@ const ServiceDetailPage: React.FC = () => {
</h1> </h1>
{service.price !== undefined && ( {service.price !== undefined && (
<div className="flex items-baseline gap-3 mb-6"> <div className="flex items-baseline gap-3 mb-6">
<span className="text-4xl sm:text-5xl font-serif font-bold bg-gradient-to-r from-[#d4af37] to-[#f5d76e] bg-clip-text text-transparent"> <span className="text-4xl sm:text-5xl font-serif font-bold bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] bg-clip-text text-transparent">
{formatCurrency(service.price)} {formatCurrency(service.price)}
</span> </span>
{service.unit && ( {service.unit && (
@@ -437,10 +437,10 @@ const ServiceDetailPage: React.FC = () => {
</p> </p>
)} )}
<div className="flex flex-wrap items-center gap-6 pt-8 border-t border-[#d4af37]/20"> <div className="flex flex-wrap items-center gap-6 pt-8 border-t border-[var(--luxury-gold)]/20">
<button <button
onClick={handleShare} onClick={handleShare}
className="flex items-center gap-3 px-6 py-3 bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] border-2 border-[#d4af37]/20 rounded-xl text-[#d4af37] hover:border-[#d4af37]/50 hover:bg-[#d4af37]/5 transition-all duration-300 group" className="flex items-center gap-3 px-6 py-3 bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] border-2 border-[var(--luxury-gold)]/20 rounded-xl text-[var(--luxury-gold)] hover:border-[var(--luxury-gold)]/50 hover:bg-[var(--luxury-gold)]/5 transition-all duration-300 group"
> >
<Share2 className="w-5 h-5 group-hover:scale-110 transition-transform" /> <Share2 className="w-5 h-5 group-hover:scale-110 transition-transform" />
<span className="font-medium">Share</span> <span className="font-medium">Share</span>
@@ -454,7 +454,7 @@ const ServiceDetailPage: React.FC = () => {
<div className="flex justify-end mb-12"> <div className="flex justify-end mb-12">
<button <button
onClick={handleShare} onClick={handleShare}
className="flex items-center gap-3 px-6 py-3 bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] border-2 border-[#d4af37]/20 rounded-xl text-[#d4af37] hover:border-[#d4af37]/50 hover:bg-[#d4af37]/5 transition-all duration-300 group" className="flex items-center gap-3 px-6 py-3 bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] border-2 border-[var(--luxury-gold)]/20 rounded-xl text-[var(--luxury-gold)] hover:border-[var(--luxury-gold)]/50 hover:bg-[var(--luxury-gold)]/5 transition-all duration-300 group"
> >
<Share2 className="w-5 h-5 group-hover:scale-110 transition-transform" /> <Share2 className="w-5 h-5 group-hover:scale-110 transition-transform" />
<span className="font-medium">Share</span> <span className="font-medium">Share</span>
@@ -466,23 +466,23 @@ const ServiceDetailPage: React.FC = () => {
{service.content && ( {service.content && (
<article className="prose prose-invert prose-xl max-w-none mb-16 <article className="prose prose-invert prose-xl max-w-none mb-16
prose-headings:text-white prose-headings:font-serif prose-headings:font-bold prose-headings:text-white prose-headings:font-serif prose-headings:font-bold
prose-h2:text-4xl prose-h2:mt-16 prose-h2:mb-8 prose-h2:border-b-2 prose-h2:border-[#d4af37]/30 prose-h2:pb-4 prose-h2:pt-2 prose-h2:text-4xl prose-h2:mt-16 prose-h2:mb-8 prose-h2:border-b-2 prose-h2:border-[var(--luxury-gold)]/30 prose-h2:pb-4 prose-h2:pt-2
prose-h3:text-3xl prose-h3:mt-12 prose-h3:mb-6 prose-h3:text-[#d4af37] prose-h3:text-3xl prose-h3:mt-12 prose-h3:mb-6 prose-h3:text-[var(--luxury-gold)]
prose-h4:text-2xl prose-h4:mt-10 prose-h4:mb-5 prose-h4:text-2xl prose-h4:mt-10 prose-h4:mb-5
prose-p:text-gray-300 prose-p:font-light prose-p:leading-relaxed prose-p:mb-8 prose-p:text-lg prose-p:text-gray-300 prose-p:font-light prose-p:leading-relaxed prose-p:mb-8 prose-p:text-lg
prose-ul:text-gray-300 prose-ul:font-light prose-ul:my-8 prose-ul:text-lg prose-ul:text-gray-300 prose-ul:font-light prose-ul:my-8 prose-ul:text-lg
prose-ol:text-gray-300 prose-ol:font-light prose-ol:my-8 prose-ol:text-lg prose-ol:text-gray-300 prose-ol:font-light prose-ol:my-8 prose-ol:text-lg
prose-li:text-gray-300 prose-li:mb-4 prose-li:leading-relaxed prose-li:text-gray-300 prose-li:mb-4 prose-li:leading-relaxed
prose-strong:text-[#d4af37] prose-strong:font-semibold prose-strong:text-[var(--luxury-gold)] prose-strong:font-semibold
prose-a:text-[#d4af37] prose-a:no-underline hover:prose-a:underline prose-a:font-medium prose-a:text-[var(--luxury-gold)] prose-a:no-underline hover:prose-a:underline prose-a:font-medium
prose-img:rounded-2xl prose-img:shadow-2xl prose-img:border-2 prose-img:border-[#d4af37]/20 prose-img:my-12 prose-img:rounded-2xl prose-img:shadow-2xl prose-img:border-2 prose-img:border-[var(--luxury-gold)]/20 prose-img:my-12
prose-blockquote:border-l-4 prose-blockquote:border-[#d4af37] prose-blockquote:pl-6 prose-blockquote:italic prose-blockquote:text-gray-300 prose-blockquote:border-l-4 prose-blockquote:border-[var(--luxury-gold)] prose-blockquote:pl-6 prose-blockquote:italic prose-blockquote:text-gray-300
[&_*]:text-gray-300 [&_h1]:text-white [&_h2]:text-white [&_h3]:text-[#d4af37] [&_h4]:text-white [&_*]:text-gray-300 [&_h1]:text-white [&_h2]:text-white [&_h3]:text-[var(--luxury-gold)] [&_h4]:text-white
[&_strong]:text-[#d4af37] [&_b]:text-[#d4af37] [&_a]:text-[#d4af37] [&_strong]:text-[var(--luxury-gold)] [&_b]:text-[var(--luxury-gold)] [&_a]:text-[var(--luxury-gold)]
[&_ul]:space-y-3 [&_ol]:space-y-3" [&_ul]:space-y-3 [&_ol]:space-y-3"
> >
<div <div
className="bg-gradient-to-br from-[#1a1a1a]/50 to-[#0f0f0f]/50 rounded-3xl border-2 border-[#d4af37]/10 p-8 md:p-12 lg:p-16 backdrop-blur-sm" className="bg-gradient-to-br from-[#1a1a1a]/50 to-[#0f0f0f]/50 rounded-3xl border-2 border-[var(--luxury-gold)]/10 p-8 md:p-12 lg:p-16 backdrop-blur-sm"
dangerouslySetInnerHTML={createSanitizedHtml( dangerouslySetInnerHTML={createSanitizedHtml(
service.content || '<p>No content available.</p>' service.content || '<p>No content available.</p>'
)} )}
@@ -499,7 +499,7 @@ const ServiceDetailPage: React.FC = () => {
<div key={index}> <div key={index}>
{/* Hero Section - Enhanced */} {/* Hero Section - Enhanced */}
{section.type === 'hero' && ( {section.type === 'hero' && (
<div className="relative rounded-3xl overflow-hidden border-2 border-[#d4af37]/30 shadow-2xl group"> <div className="relative rounded-3xl overflow-hidden border-2 border-[var(--luxury-gold)]/30 shadow-2xl group">
{section.image && ( {section.image && (
<div className="absolute inset-0"> <div className="absolute inset-0">
<img src={section.image} alt={section.title} className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-1000" /> <img src={section.image} alt={section.title} className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-1000" />
@@ -508,8 +508,8 @@ const ServiceDetailPage: React.FC = () => {
</div> </div>
)} )}
<div className="absolute inset-0 opacity-10"> <div className="absolute inset-0 opacity-10">
<div className="absolute top-0 left-0 w-96 h-96 bg-[#d4af37] rounded-full blur-3xl"></div> <div className="absolute top-0 left-0 w-96 h-96 bg-[var(--luxury-gold)] rounded-full blur-3xl"></div>
<div className="absolute bottom-0 right-0 w-96 h-96 bg-[#c9a227] rounded-full blur-3xl"></div> <div className="absolute bottom-0 right-0 w-96 h-96 bg-[var(--luxury-gold-dark)] rounded-full blur-3xl"></div>
</div> </div>
<div className="relative px-8 py-20 md:px-16 md:py-32 text-center"> <div className="relative px-8 py-20 md:px-16 md:py-32 text-center">
{section.title && ( {section.title && (
@@ -523,13 +523,13 @@ const ServiceDetailPage: React.FC = () => {
</p> </p>
)} )}
</div> </div>
<div className="absolute bottom-0 left-0 w-full h-1 bg-gradient-to-r from-transparent via-[#d4af37]/50 to-transparent"></div> <div className="absolute bottom-0 left-0 w-full h-1 bg-gradient-to-r from-transparent via-[var(--luxury-gold)]/50 to-transparent"></div>
</div> </div>
)} )}
{/* Text Section */} {/* Text Section */}
{section.type === 'text' && ( {section.type === 'text' && (
<div className={`bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] rounded-3xl border-2 border-[#d4af37]/20 p-8 md:p-12 shadow-xl ${ <div className={`bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] rounded-3xl border-2 border-[var(--luxury-gold)]/20 p-8 md:p-12 shadow-xl ${
section.alignment === 'center' ? 'text-center' : section.alignment === 'right' ? 'text-right' : 'text-left' section.alignment === 'center' ? 'text-center' : section.alignment === 'right' ? 'text-right' : 'text-left'
}`}> }`}>
{section.title && ( {section.title && (
@@ -548,10 +548,10 @@ const ServiceDetailPage: React.FC = () => {
{/* Image Section */} {/* Image Section */}
{section.type === 'image' && section.image && ( {section.type === 'image' && section.image && (
<div className="rounded-3xl overflow-hidden border-2 border-[#d4af37]/20 shadow-2xl"> <div className="rounded-3xl overflow-hidden border-2 border-[var(--luxury-gold)]/20 shadow-2xl">
<img src={section.image} alt={section.title || 'Service image'} className="w-full h-auto" /> <img src={section.image} alt={section.title || 'Service image'} className="w-full h-auto" />
{section.title && ( {section.title && (
<div className="bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] px-6 py-4 border-t border-[#d4af37]/20"> <div className="bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] px-6 py-4 border-t border-[var(--luxury-gold)]/20">
<p className="text-gray-400 text-sm font-light italic text-center">{section.title}</p> <p className="text-gray-400 text-sm font-light italic text-center">{section.title}</p>
</div> </div>
)} )}
@@ -562,7 +562,7 @@ const ServiceDetailPage: React.FC = () => {
{section.type === 'gallery' && section.images && section.images.length > 0 && ( {section.type === 'gallery' && section.images && section.images.length > 0 && (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{section.images.map((img, imgIndex) => ( {section.images.map((img, imgIndex) => (
<div key={imgIndex} className="rounded-2xl overflow-hidden border-2 border-[#d4af37]/20 shadow-xl group hover:border-[#d4af37]/50 transition-all"> <div key={imgIndex} className="rounded-2xl overflow-hidden border-2 border-[var(--luxury-gold)]/20 shadow-xl group hover:border-[var(--luxury-gold)]/50 transition-all">
<img src={img} alt={`Gallery image ${imgIndex + 1}`} className="w-full h-64 object-cover group-hover:scale-110 transition-transform duration-500" /> <img src={img} alt={`Gallery image ${imgIndex + 1}`} className="w-full h-64 object-cover group-hover:scale-110 transition-transform duration-500" />
</div> </div>
))} ))}
@@ -571,15 +571,15 @@ const ServiceDetailPage: React.FC = () => {
{/* Quote Section */} {/* Quote Section */}
{section.type === 'quote' && ( {section.type === 'quote' && (
<div className="relative bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] rounded-3xl border-2 border-[#d4af37]/30 p-8 md:p-12 shadow-2xl"> <div className="relative bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] rounded-3xl border-2 border-[var(--luxury-gold)]/30 p-8 md:p-12 shadow-2xl">
<div className="absolute top-6 left-6 text-6xl text-[#d4af37]/20 font-serif">"</div> <div className="absolute top-6 left-6 text-6xl text-[var(--luxury-gold)]/20 font-serif">"</div>
{section.quote && ( {section.quote && (
<blockquote className="text-2xl md:text-3xl font-serif font-light text-white italic mb-6 relative z-10 pl-8"> <blockquote className="text-2xl md:text-3xl font-serif font-light text-white italic mb-6 relative z-10 pl-8">
{section.quote} {section.quote}
</blockquote> </blockquote>
)} )}
{section.author && ( {section.author && (
<cite className="text-[#d4af37] text-lg font-medium not-italic block text-right"> <cite className="text-[var(--luxury-gold)] text-lg font-medium not-italic block text-right">
— {section.author} — {section.author}
</cite> </cite>
)} )}
@@ -590,7 +590,7 @@ const ServiceDetailPage: React.FC = () => {
{section.type === 'features' && section.features && ( {section.type === 'features' && section.features && (
<div> <div>
{section.title && ( {section.title && (
<h3 className="text-4xl md:text-5xl font-serif font-bold text-white mb-12 text-center border-b-2 border-[#d4af37]/30 pb-6"> <h3 className="text-4xl md:text-5xl font-serif font-bold text-white mb-12 text-center border-b-2 border-[var(--luxury-gold)]/30 pb-6">
{section.title} {section.title}
</h3> </h3>
)} )}
@@ -600,18 +600,18 @@ const ServiceDetailPage: React.FC = () => {
? (LucideIcons as any)[feature.icon] ? (LucideIcons as any)[feature.icon]
: null; : null;
return ( return (
<div key={featIndex} className="group relative bg-gradient-to-br from-[#1a1a1a] via-[#0f0f0f] to-[#0a0a0a] rounded-3xl border-2 border-[#d4af37]/20 p-8 shadow-2xl hover:border-[#d4af37]/60 hover:shadow-[#d4af37]/20 transition-all duration-500 hover:-translate-y-2"> <div key={featIndex} className="group relative bg-gradient-to-br from-[#1a1a1a] via-[#0f0f0f] to-[#0a0a0a] rounded-3xl border-2 border-[var(--luxury-gold)]/20 p-8 shadow-2xl hover:border-[var(--luxury-gold)]/60 hover:shadow-[var(--luxury-gold)]/20 transition-all duration-500 hover:-translate-y-2">
<div className="absolute inset-0 bg-gradient-to-br from-[#d4af37]/0 to-[#d4af37]/0 group-hover:from-[#d4af37]/5 group-hover:to-transparent rounded-3xl transition-all duration-500"></div> <div className="absolute inset-0 bg-gradient-to-br from-[var(--luxury-gold)]/0 to-[var(--luxury-gold)]/0 group-hover:from-[var(--luxury-gold)]/5 group-hover:to-transparent rounded-3xl transition-all duration-500"></div>
<div className="relative z-10"> <div className="relative z-10">
{IconComponent && ( {IconComponent && (
<div className="mb-6 relative"> <div className="mb-6 relative">
<div className="absolute inset-0 bg-[#d4af37]/20 rounded-full blur-2xl group-hover:blur-3xl transition-all"></div> <div className="absolute inset-0 bg-[var(--luxury-gold)]/20 rounded-full blur-2xl group-hover:blur-3xl transition-all"></div>
{React.createElement(IconComponent, { {React.createElement(IconComponent, {
className: 'w-12 h-12 text-[#d4af37] relative z-10 group-hover:scale-110 transition-transform duration-300' className: 'w-12 h-12 text-[var(--luxury-gold)] relative z-10 group-hover:scale-110 transition-transform duration-300'
})} })}
</div> </div>
)} )}
<h4 className="text-2xl font-bold text-white mb-4 group-hover:text-[#d4af37] transition-colors">{feature.title}</h4> <h4 className="text-2xl font-bold text-white mb-4 group-hover:text-[var(--luxury-gold)] transition-colors">{feature.title}</h4>
<p className="text-gray-300 font-light leading-relaxed text-base">{feature.description}</p> <p className="text-gray-300 font-light leading-relaxed text-base">{feature.description}</p>
</div> </div>
</div> </div>
@@ -623,7 +623,7 @@ const ServiceDetailPage: React.FC = () => {
{/* CTA Section */} {/* CTA Section */}
{section.type === 'cta' && ( {section.type === 'cta' && (
<div className="relative bg-gradient-to-br from-[#d4af37]/10 via-[#c9a227]/5 to-[#d4af37]/10 rounded-3xl border-2 border-[#d4af37]/30 p-8 md:p-12 text-center shadow-2xl"> <div className="relative bg-gradient-to-br from-[var(--luxury-gold)]/10 via-[var(--luxury-gold-dark)]/5 to-[var(--luxury-gold)]/10 rounded-3xl border-2 border-[var(--luxury-gold)]/30 p-8 md:p-12 text-center shadow-2xl">
{section.title && ( {section.title && (
<h3 className="text-3xl md:text-4xl font-serif font-bold text-white mb-4"> <h3 className="text-3xl md:text-4xl font-serif font-bold text-white mb-4">
{section.title} {section.title}
@@ -637,7 +637,7 @@ const ServiceDetailPage: React.FC = () => {
{section.cta_text && section.cta_link && ( {section.cta_text && section.cta_link && (
<a <a
href={section.cta_link} href={section.cta_link}
className="inline-flex items-center gap-3 px-8 py-4 bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-[#0f0f0f] font-semibold rounded-xl hover:from-[#f5d76e] hover:to-[#d4af37] transition-all shadow-lg hover:shadow-xl hover:scale-105" className="inline-flex items-center gap-3 px-8 py-4 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-[#0f0f0f] font-semibold rounded-xl hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] transition-all shadow-lg hover:shadow-xl hover:scale-105"
> >
{section.cta_text} {section.cta_text}
</a> </a>
@@ -647,7 +647,7 @@ const ServiceDetailPage: React.FC = () => {
{/* Video Section */} {/* Video Section */}
{section.type === 'video' && section.video_url && ( {section.type === 'video' && section.video_url && (
<div className="rounded-3xl overflow-hidden border-2 border-[#d4af37]/20 shadow-2xl bg-black"> <div className="rounded-3xl overflow-hidden border-2 border-[var(--luxury-gold)]/20 shadow-2xl bg-black">
<div className="aspect-video"> <div className="aspect-video">
<iframe <iframe
src={section.video_url.replace('watch?v=', 'embed/').replace('vimeo.com/', 'player.vimeo.com/video/')} src={section.video_url.replace('watch?v=', 'embed/').replace('vimeo.com/', 'player.vimeo.com/video/')}
@@ -665,14 +665,14 @@ const ServiceDetailPage: React.FC = () => {
{/* Related Services */} {/* Related Services */}
{relatedServices.length > 0 && ( {relatedServices.length > 0 && (
<div className="mt-16 pt-12 border-t border-[#d4af37]/20"> <div className="mt-16 pt-12 border-t border-[var(--luxury-gold)]/20">
<h2 className="text-2xl sm:text-3xl font-bold text-white mb-8">Related Services</h2> <h2 className="text-2xl sm:text-3xl font-bold text-white mb-8">Related Services</h2>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6"> <div className="grid grid-cols-1 md:grid-cols-3 gap-6">
{relatedServices.map((relatedService) => ( {relatedServices.map((relatedService) => (
<Link <Link
key={relatedService.id} key={relatedService.id}
to={`/services/${relatedService.slug}`} to={`/services/${relatedService.slug}`}
className="group bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] rounded-xl border border-[#d4af37]/20 overflow-hidden hover:border-[#d4af37]/50 transition-all duration-300" className="group bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] rounded-xl border border-[var(--luxury-gold)]/20 overflow-hidden hover:border-[var(--luxury-gold)]/50 transition-all duration-300"
> >
{relatedService.image && ( {relatedService.image && (
<div className="relative h-40 overflow-hidden"> <div className="relative h-40 overflow-hidden">
@@ -684,7 +684,7 @@ const ServiceDetailPage: React.FC = () => {
</div> </div>
)} )}
<div className="p-4"> <div className="p-4">
<h3 className="text-lg font-bold text-white mb-2 group-hover:text-[#d4af37] transition-colors line-clamp-2"> <h3 className="text-lg font-bold text-white mb-2 group-hover:text-[var(--luxury-gold)] transition-colors line-clamp-2">
{relatedService.title} {relatedService.title}
</h3> </h3>
{relatedService.description && ( {relatedService.description && (

View File

@@ -159,41 +159,41 @@ const ServicesPage: React.FC = () => {
return ( return (
<div className="min-h-screen bg-gradient-to-b from-[#0f0f0f] via-[#1a1a1a] to-[#0f0f0f] w-full" style={{ width: '100vw', position: 'relative', left: '50%', right: '50%', marginLeft: '-50vw', marginRight: '-50vw', marginTop: '-1.5rem', marginBottom: '-1.5rem' }}> <div className="min-h-screen bg-gradient-to-b from-[#0f0f0f] via-[#1a1a1a] to-[#0f0f0f] w-full" style={{ width: '100vw', position: 'relative', left: '50%', right: '50%', marginLeft: '-50vw', marginRight: '-50vw', marginTop: '-1.5rem', marginBottom: '-1.5rem' }}>
{/* Hero Section */} {/* Hero Section */}
<div className="w-full bg-gradient-to-br from-[#1a1a1a] via-[#0f0f0f] to-[#1a1a1a] border-b border-[#d4af37]/10 pt-6 sm:pt-7 md:pt-8 overflow-hidden relative"> <div className="w-full bg-gradient-to-br from-[#1a1a1a] via-[#0f0f0f] to-[#1a1a1a] border-b border-[var(--luxury-gold)]/10 pt-6 sm:pt-7 md:pt-8 overflow-hidden relative">
{/* Background Effects */} {/* Background Effects */}
<div className="absolute inset-0 opacity-10"> <div className="absolute inset-0 opacity-10">
<div className="absolute top-10 left-10 w-32 sm:w-48 h-32 sm:h-48 bg-[#d4af37] rounded-full blur-3xl"></div> <div className="absolute top-10 left-10 w-32 sm:w-48 h-32 sm:h-48 bg-[var(--luxury-gold)] rounded-full blur-3xl"></div>
<div className="absolute bottom-10 right-10 w-40 sm:w-64 h-40 sm:h-64 bg-[#c9a227] rounded-full blur-3xl"></div> <div className="absolute bottom-10 right-10 w-40 sm:w-64 h-40 sm:h-64 bg-[var(--luxury-gold-dark)] rounded-full blur-3xl"></div>
</div> </div>
<div className="absolute top-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-[#d4af37]/50 to-transparent"></div> <div className="absolute top-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-[var(--luxury-gold)]/50 to-transparent"></div>
<div className="w-full max-w-[1920px] mx-auto px-3 sm:px-4 md:px-6 lg:px-8 xl:px-12 2xl:px-16 3xl:px-20 py-4 sm:py-5 md:py-6 relative z-10"> <div className="w-full max-w-[1920px] mx-auto px-3 sm:px-4 md:px-6 lg:px-8 xl:px-12 2xl:px-16 3xl:px-20 py-4 sm:py-5 md:py-6 relative z-10">
<div className="max-w-2xl mx-auto text-center px-2"> <div className="max-w-2xl mx-auto text-center px-2">
<div className="flex justify-center mb-2 sm:mb-3 md:mb-4"> <div className="flex justify-center mb-2 sm:mb-3 md:mb-4">
<div className="relative group"> <div className="relative group">
<div className="absolute inset-0 bg-gradient-to-br from-[#d4af37] via-[#f5d76e] to-[#c9a227] rounded-xl blur-lg opacity-40 group-hover:opacity-60 transition-opacity duration-500"></div> <div className="absolute inset-0 bg-gradient-to-br from-[var(--luxury-gold)] via-[var(--luxury-gold-light)] to-[var(--luxury-gold-dark)] rounded-xl blur-lg opacity-40 group-hover:opacity-60 transition-opacity duration-500"></div>
<div className="relative p-2 sm:p-2.5 md:p-3 bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-lg border-2 border-[#d4af37]/40 backdrop-blur-sm shadow-xl shadow-[#d4af37]/20 group-hover:border-[#d4af37]/60 transition-all duration-300"> <div className="relative p-2 sm:p-2.5 md:p-3 bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-lg border-2 border-[var(--luxury-gold)]/40 backdrop-blur-sm shadow-xl shadow-[var(--luxury-gold)]/20 group-hover:border-[var(--luxury-gold)]/60 transition-all duration-300">
<Award className="w-5 h-5 sm:w-6 sm:h-6 md:w-7 md:h-7 text-[#d4af37] drop-shadow-lg" /> <Award className="w-5 h-5 sm:w-6 sm:h-6 md:w-7 md:h-7 text-[var(--luxury-gold)] drop-shadow-lg" />
</div> </div>
</div> </div>
</div> </div>
<h1 className="text-2xl xs:text-3xl sm:text-4xl md:text-5xl font-serif font-semibold mb-2 sm:mb-3 tracking-tight leading-tight px-2"> <h1 className="text-2xl xs:text-3xl sm:text-4xl md:text-5xl font-serif font-semibold mb-2 sm:mb-3 tracking-tight leading-tight px-2">
<span className="bg-gradient-to-r from-white via-[#d4af37] to-white bg-clip-text text-transparent"> <span className="bg-gradient-to-r from-white via-[var(--luxury-gold)] to-white bg-clip-text text-transparent">
{pageContent?.luxury_services_section_title || 'Our Services'} {pageContent?.luxury_services_section_title || 'Our Services'}
</span> </span>
</h1> </h1>
<div className="w-12 sm:w-16 md:w-20 h-0.5 bg-gradient-to-r from-transparent via-[#d4af37] to-transparent mx-auto mb-2 sm:mb-3"></div> <div className="w-12 sm:w-16 md:w-20 h-0.5 bg-gradient-to-r from-transparent via-[var(--luxury-gold)] to-transparent mx-auto mb-2 sm:mb-3"></div>
<p className="text-sm sm:text-base md:text-lg text-gray-300 font-light leading-relaxed max-w-xl mx-auto tracking-wide px-2 sm:px-4"> <p className="text-sm sm:text-base md:text-lg text-gray-300 font-light leading-relaxed max-w-xl mx-auto tracking-wide px-2 sm:px-4">
{pageContent?.luxury_services_section_subtitle || 'Discover our premium services designed to enhance your stay'} {pageContent?.luxury_services_section_subtitle || 'Discover our premium services designed to enhance your stay'}
</p> </p>
<div className="mt-4 flex items-center justify-center gap-2 text-[#d4af37]/60"> <div className="mt-4 flex items-center justify-center gap-2 text-[var(--luxury-gold)]/60">
<Sparkles className="w-4 h-4 animate-pulse" /> <Sparkles className="w-4 h-4 animate-pulse" />
<span className="text-xs sm:text-sm font-light tracking-wider uppercase">Premium Services</span> <span className="text-xs sm:text-sm font-light tracking-wider uppercase">Premium Services</span>
<Sparkles className="w-4 h-4 animate-pulse" style={{ animationDelay: '0.5s' }} /> <Sparkles className="w-4 h-4 animate-pulse" style={{ animationDelay: '0.5s' }} />
</div> </div>
</div> </div>
</div> </div>
<div className="absolute bottom-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-[#d4af37]/30 to-transparent"></div> <div className="absolute bottom-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-[var(--luxury-gold)]/30 to-transparent"></div>
</div> </div>
{/* Main Content - Full Width */} {/* Main Content - Full Width */}
@@ -203,15 +203,15 @@ const ServicesPage: React.FC = () => {
<div className="mb-12 sm:mb-16"> <div className="mb-12 sm:mb-16">
<div className="flex flex-col lg:flex-row gap-6 mb-8"> <div className="flex flex-col lg:flex-row gap-6 mb-8">
<div className="flex-1 relative group"> <div className="flex-1 relative group">
<div className="absolute inset-0 bg-gradient-to-r from-[#d4af37]/10 to-transparent rounded-xl blur-xl opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div> <div className="absolute inset-0 bg-gradient-to-r from-[var(--luxury-gold)]/10 to-transparent rounded-xl blur-xl opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
<div className="relative"> <div className="relative">
<Search className="absolute left-5 top-1/2 transform -translate-y-1/2 text-[#d4af37] w-5 h-5 z-10" /> <Search className="absolute left-5 top-1/2 transform -translate-y-1/2 text-[var(--luxury-gold)] w-5 h-5 z-10" />
<input <input
type="text" type="text"
placeholder="Search services..." placeholder="Search services..."
value={searchTerm} value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)} onChange={(e) => setSearchTerm(e.target.value)}
className="w-full pl-14 pr-5 py-4 bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] border border-[#d4af37]/20 rounded-xl text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37]/50 transition-all duration-300 backdrop-blur-sm font-light" className="w-full pl-14 pr-5 py-4 bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] border border-[var(--luxury-gold)]/20 rounded-xl text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)]/50 transition-all duration-300 backdrop-blur-sm font-light"
/> />
</div> </div>
</div> </div>
@@ -221,13 +221,13 @@ const ServicesPage: React.FC = () => {
{/* Categories Filter - Top Center */} {/* Categories Filter - Top Center */}
{allCategories.length > 0 && ( {allCategories.length > 0 && (
<div className="mb-12 flex justify-center"> <div className="mb-12 flex justify-center">
<div className="inline-flex flex-wrap items-center gap-3 bg-gradient-to-br from-[#1a1a1a] via-[#0f0f0f] to-[#0a0a0a] rounded-2xl border-2 border-[#d4af37]/20 p-4 backdrop-blur-xl shadow-2xl"> <div className="inline-flex flex-wrap items-center gap-3 bg-gradient-to-br from-[#1a1a1a] via-[#0f0f0f] to-[#0a0a0a] rounded-2xl border-2 border-[var(--luxury-gold)]/20 p-4 backdrop-blur-xl shadow-2xl">
<button <button
onClick={() => setSelectedCategory(null)} onClick={() => setSelectedCategory(null)}
className={`group relative px-6 py-3 rounded-xl text-sm font-medium transition-all duration-300 overflow-hidden ${ className={`group relative px-6 py-3 rounded-xl text-sm font-medium transition-all duration-300 overflow-hidden ${
selectedCategory === null selectedCategory === null
? 'bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-[#0f0f0f] shadow-lg shadow-[#d4af37]/40' ? 'bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-[#0f0f0f] shadow-lg shadow-[var(--luxury-gold)]/40'
: 'bg-gradient-to-br from-[#0f0f0f] to-[#0a0a0a] text-gray-300 border-2 border-[#d4af37]/20 hover:border-[#d4af37]/50 hover:text-[#d4af37]' : 'bg-gradient-to-br from-[#0f0f0f] to-[#0a0a0a] text-gray-300 border-2 border-[var(--luxury-gold)]/20 hover:border-[var(--luxury-gold)]/50 hover:text-[var(--luxury-gold)]'
}`} }`}
> >
<span className="relative z-10 flex items-center gap-2"> <span className="relative z-10 flex items-center gap-2">
@@ -241,8 +241,8 @@ const ServicesPage: React.FC = () => {
onClick={() => setSelectedCategory(category)} onClick={() => setSelectedCategory(category)}
className={`group relative px-6 py-3 rounded-xl text-sm font-medium transition-all duration-300 overflow-hidden ${ className={`group relative px-6 py-3 rounded-xl text-sm font-medium transition-all duration-300 overflow-hidden ${
selectedCategory === category selectedCategory === category
? 'bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-[#0f0f0f] shadow-lg shadow-[#d4af37]/40' ? 'bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-[#0f0f0f] shadow-lg shadow-[var(--luxury-gold)]/40'
: 'bg-gradient-to-br from-[#0f0f0f] to-[#0a0a0a] text-gray-300 border-2 border-[#d4af37]/20 hover:border-[#d4af37]/50 hover:text-[#d4af37]' : 'bg-gradient-to-br from-[#0f0f0f] to-[#0a0a0a] text-gray-300 border-2 border-[var(--luxury-gold)]/20 hover:border-[var(--luxury-gold)]/50 hover:text-[var(--luxury-gold)]'
}`} }`}
> >
<span className="relative z-10 flex items-center gap-2"> <span className="relative z-10 flex items-center gap-2">
@@ -267,8 +267,8 @@ const ServicesPage: React.FC = () => {
{/* Services Grid - Luxury Design - Centered */} {/* Services Grid - Luxury Design - Centered */}
{filteredServices.length === 0 ? ( {filteredServices.length === 0 ? (
<div className="text-center py-20"> <div className="text-center py-20">
<div className="inline-flex items-center justify-center w-20 h-20 rounded-full bg-[#d4af37]/10 mb-6"> <div className="inline-flex items-center justify-center w-20 h-20 rounded-full bg-[var(--luxury-gold)]/10 mb-6">
<Award className="w-10 h-10 text-[#d4af37]" /> <Award className="w-10 h-10 text-[var(--luxury-gold)]" />
</div> </div>
<p className="text-gray-400 text-xl font-light">No services found</p> <p className="text-gray-400 text-xl font-light">No services found</p>
<p className="text-gray-500 text-sm mt-2">Try adjusting your search or filters</p> <p className="text-gray-500 text-sm mt-2">Try adjusting your search or filters</p>
@@ -288,12 +288,12 @@ const ServicesPage: React.FC = () => {
<Link <Link
key={service.id} key={service.id}
to={`/services/${serviceSlug}`} to={`/services/${serviceSlug}`}
className="group relative bg-gradient-to-br from-[#1a1a1a] via-[#0f0f0f] to-[#0a0a0a] rounded-3xl border-2 border-[#d4af37]/20 overflow-hidden hover:border-[#d4af37]/60 transition-all duration-700 hover:shadow-2xl hover:shadow-[#d4af37]/30 hover:-translate-y-3 block" className="group relative bg-gradient-to-br from-[#1a1a1a] via-[#0f0f0f] to-[#0a0a0a] rounded-3xl border-2 border-[var(--luxury-gold)]/20 overflow-hidden hover:border-[var(--luxury-gold)]/60 transition-all duration-700 hover:shadow-2xl hover:shadow-[var(--luxury-gold)]/30 hover:-translate-y-3 block"
style={{ animationDelay: `${index * 50}ms` }} style={{ animationDelay: `${index * 50}ms` }}
> >
{/* Premium Glow Effects */} {/* Premium Glow Effects */}
<div className="absolute inset-0 bg-gradient-to-br from-[#d4af37]/0 via-[#d4af37]/0 to-[#d4af37]/0 group-hover:from-[#d4af37]/10 group-hover:via-[#d4af37]/5 group-hover:to-[#d4af37]/10 transition-all duration-700 rounded-3xl blur-2xl opacity-0 group-hover:opacity-100"></div> <div className="absolute inset-0 bg-gradient-to-br from-[var(--luxury-gold)]/0 via-[var(--luxury-gold)]/0 to-[var(--luxury-gold)]/0 group-hover:from-[var(--luxury-gold)]/10 group-hover:via-[var(--luxury-gold)]/5 group-hover:to-[var(--luxury-gold)]/10 transition-all duration-700 rounded-3xl blur-2xl opacity-0 group-hover:opacity-100"></div>
<div className="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-transparent via-[#d4af37]/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div> <div className="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-transparent via-[var(--luxury-gold)]/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
{/* Content */} {/* Content */}
<div className="relative z-10"> <div className="relative z-10">
@@ -308,8 +308,8 @@ const ServicesPage: React.FC = () => {
{/* Premium Badge Overlay */} {/* Premium Badge Overlay */}
{service.type === 'luxury' && ( {service.type === 'luxury' && (
<div className="absolute top-6 left-6 z-20"> <div className="absolute top-6 left-6 z-20">
<div className="bg-gradient-to-br from-[#d4af37]/20 to-[#c9a227]/10 backdrop-blur-md rounded-2xl px-4 py-2 border border-[#d4af37]/40 shadow-xl"> <div className="bg-gradient-to-br from-[var(--luxury-gold)]/20 to-[var(--luxury-gold-dark)]/10 backdrop-blur-md rounded-2xl px-4 py-2 border border-[var(--luxury-gold)]/40 shadow-xl">
<div className="flex items-center gap-2 text-[#d4af37]"> <div className="flex items-center gap-2 text-[var(--luxury-gold)]">
<Star className="w-4 h-4" /> <Star className="w-4 h-4" />
<span className="text-sm font-semibold">Premium</span> <span className="text-sm font-semibold">Premium</span>
</div> </div>
@@ -317,21 +317,21 @@ const ServicesPage: React.FC = () => {
</div> </div>
)} )}
{/* Luxury Corner Accent */} {/* Luxury Corner Accent */}
<div className="absolute top-0 right-0 w-32 h-32 bg-gradient-to-br from-[#d4af37]/20 to-transparent rounded-bl-full opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div> <div className="absolute top-0 right-0 w-32 h-32 bg-gradient-to-br from-[var(--luxury-gold)]/20 to-transparent rounded-bl-full opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
</div> </div>
) : ( ) : (
<div className="h-48 sm:h-56 bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] flex items-center justify-center p-8"> <div className="h-48 sm:h-56 bg-gradient-to-br from-[#1a1a1a] to-[#0f0f0f] flex items-center justify-center p-8">
{service.icon && (LucideIcons as any)[service.icon] ? ( {service.icon && (LucideIcons as any)[service.icon] ? (
<div className="relative"> <div className="relative">
<div className="absolute inset-0 bg-[#d4af37]/20 rounded-full blur-2xl"></div> <div className="absolute inset-0 bg-[var(--luxury-gold)]/20 rounded-full blur-2xl"></div>
{React.createElement((LucideIcons as any)[service.icon], { {React.createElement((LucideIcons as any)[service.icon], {
className: 'w-16 h-16 sm:w-20 sm:h-20 text-[#d4af37] relative z-10 drop-shadow-lg' className: 'w-16 h-16 sm:w-20 sm:h-20 text-[var(--luxury-gold)] relative z-10 drop-shadow-lg'
})} })}
</div> </div>
) : ( ) : (
<div className="relative"> <div className="relative">
<div className="absolute inset-0 bg-[#d4af37]/20 rounded-full blur-2xl"></div> <div className="absolute inset-0 bg-[var(--luxury-gold)]/20 rounded-full blur-2xl"></div>
<Award className="w-16 h-16 sm:w-20 sm:h-20 text-[#d4af37] relative z-10 drop-shadow-lg" /> <Award className="w-16 h-16 sm:w-20 sm:h-20 text-[var(--luxury-gold)] relative z-10 drop-shadow-lg" />
</div> </div>
)} )}
</div> </div>
@@ -339,13 +339,13 @@ const ServicesPage: React.FC = () => {
<div className="p-8"> <div className="p-8">
{service.category && ( {service.category && (
<div className="flex flex-wrap gap-2 mb-5"> <div className="flex flex-wrap gap-2 mb-5">
<span className="inline-flex items-center gap-1.5 px-4 py-1.5 bg-gradient-to-br from-[#d4af37]/15 to-[#d4af37]/5 text-[#d4af37] rounded-full text-xs font-semibold border border-[#d4af37]/30 backdrop-blur-sm shadow-lg"> <span className="inline-flex items-center gap-1.5 px-4 py-1.5 bg-gradient-to-br from-[var(--luxury-gold)]/15 to-[var(--luxury-gold)]/5 text-[var(--luxury-gold)] rounded-full text-xs font-semibold border border-[var(--luxury-gold)]/30 backdrop-blur-sm shadow-lg">
<Tag className="w-3 h-3" /> <Tag className="w-3 h-3" />
{service.category} {service.category}
</span> </span>
</div> </div>
)} )}
<h2 className="text-2xl sm:text-3xl font-serif font-bold text-white mb-4 group-hover:text-[#d4af37] transition-colors duration-500 line-clamp-2 leading-tight tracking-tight"> <h2 className="text-2xl sm:text-3xl font-serif font-bold text-white mb-4 group-hover:text-[var(--luxury-gold)] transition-colors duration-500 line-clamp-2 leading-tight tracking-tight">
{service.title} {service.title}
</h2> </h2>
{service.description && ( {service.description && (
@@ -354,9 +354,9 @@ const ServicesPage: React.FC = () => {
</p> </p>
)} )}
{service.price !== undefined && ( {service.price !== undefined && (
<div className="mb-6 pb-6 border-b border-[#d4af37]/20"> <div className="mb-6 pb-6 border-b border-[var(--luxury-gold)]/20">
<div className="flex items-baseline gap-2"> <div className="flex items-baseline gap-2">
<span className="text-2xl sm:text-3xl font-serif font-semibold bg-gradient-to-r from-[#d4af37] to-[#f5d76e] bg-clip-text text-transparent"> <span className="text-2xl sm:text-3xl font-serif font-semibold bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] bg-clip-text text-transparent">
{formatCurrency(service.price)} {formatCurrency(service.price)}
</span> </span>
{service.unit && ( {service.unit && (
@@ -367,12 +367,12 @@ const ServicesPage: React.FC = () => {
</div> </div>
</div> </div>
)} )}
<div className="flex items-center justify-between pt-4 border-t border-[#d4af37]/10"> <div className="flex items-center justify-between pt-4 border-t border-[var(--luxury-gold)]/10">
<div className="flex items-center gap-3 text-[#d4af37] group-hover:gap-4 transition-all duration-300"> <div className="flex items-center gap-3 text-[var(--luxury-gold)] group-hover:gap-4 transition-all duration-300">
<span className="text-sm font-semibold tracking-wide uppercase">Learn More</span> <span className="text-sm font-semibold tracking-wide uppercase">Learn More</span>
<ArrowRight className="w-5 h-5 group-hover:translate-x-2 transition-transform duration-300" /> <ArrowRight className="w-5 h-5 group-hover:translate-x-2 transition-transform duration-300" />
</div> </div>
<div className="w-12 h-0.5 bg-gradient-to-r from-[#d4af37] to-transparent group-hover:w-20 transition-all duration-500"></div> <div className="w-12 h-0.5 bg-gradient-to-r from-[var(--luxury-gold)] to-transparent group-hover:w-20 transition-all duration-500"></div>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -99,12 +99,12 @@ const TermsPage: React.FC = () => {
}} }}
> >
<div className="text-center"> <div className="text-center">
<Scale className="w-16 h-16 text-[#d4af37]/50 mx-auto mb-4" /> <Scale className="w-16 h-16 text-[var(--luxury-gold)]/50 mx-auto mb-4" />
<h1 className="text-2xl font-elegant font-bold text-white mb-2">Terms & Conditions</h1> <h1 className="text-2xl font-elegant font-bold text-white mb-2">Terms & Conditions</h1>
<p className="text-gray-400">This page is currently unavailable.</p> <p className="text-gray-400">This page is currently unavailable.</p>
<Link <Link
to="/" to="/"
className="inline-flex items-center gap-2 text-[#d4af37]/80 hover:text-[#d4af37] mt-6 transition-all duration-300" className="inline-flex items-center gap-2 text-[var(--luxury-gold)]/80 hover:text-[var(--luxury-gold)] mt-6 transition-all duration-300"
> >
<ArrowLeft className="w-4 h-4" /> <ArrowLeft className="w-4 h-4" />
<span>Back to Home</span> <span>Back to Home</span>
@@ -129,7 +129,7 @@ const TermsPage: React.FC = () => {
{/* Back Link */} {/* Back Link */}
<Link <Link
to="/" to="/"
className="inline-flex items-center gap-2 text-[#d4af37]/80 hover:text-[#d4af37] mb-6 transition-all duration-300 group font-light tracking-wide text-xs sm:text-sm" className="inline-flex items-center gap-2 text-[var(--luxury-gold)]/80 hover:text-[var(--luxury-gold)] mb-6 transition-all duration-300 group font-light tracking-wide text-xs sm:text-sm"
> >
<ArrowLeft className="w-4 h-4 group-hover:-translate-x-1 transition-transform" /> <ArrowLeft className="w-4 h-4 group-hover:-translate-x-1 transition-transform" />
<span>Back to Home</span> <span>Back to Home</span>
@@ -137,10 +137,10 @@ const TermsPage: React.FC = () => {
{/* Header */} {/* Header */}
<div className="mb-8 sm:mb-12 text-center"> <div className="mb-8 sm:mb-12 text-center">
<div className="inline-flex items-center justify-center w-16 h-16 sm:w-20 sm:h-20 mb-4 sm:mb-6 bg-gradient-to-br from-[#d4af37]/20 to-[#c9a227]/10 rounded-full border border-[#d4af37]/30"> <div className="inline-flex items-center justify-center w-16 h-16 sm:w-20 sm:h-20 mb-4 sm:mb-6 bg-gradient-to-br from-[var(--luxury-gold)]/20 to-[var(--luxury-gold-dark)]/10 rounded-full border border-[var(--luxury-gold)]/30">
<Scale className="w-8 h-8 sm:w-10 sm:h-10 text-[#d4af37]" /> <Scale className="w-8 h-8 sm:w-10 sm:h-10 text-[var(--luxury-gold)]" />
</div> </div>
<h1 className="text-3xl sm:text-4xl lg:text-5xl font-elegant font-bold text-white mb-3 sm:mb-4 tracking-tight leading-tight bg-gradient-to-r from-white via-[#d4af37] to-white bg-clip-text text-transparent"> <h1 className="text-3xl sm:text-4xl lg:text-5xl font-elegant font-bold text-white mb-3 sm:mb-4 tracking-tight leading-tight bg-gradient-to-r from-white via-[var(--luxury-gold)] to-white bg-clip-text text-transparent">
{pageContent.title || 'Terms & Conditions'} {pageContent.title || 'Terms & Conditions'}
</h1> </h1>
{pageContent.subtitle && ( {pageContent.subtitle && (
@@ -151,18 +151,18 @@ const TermsPage: React.FC = () => {
</div> </div>
{/* Content */} {/* Content */}
<div className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-xl border border-[#d4af37]/20 backdrop-blur-xl shadow-2xl shadow-[#d4af37]/5 p-6 sm:p-8 lg:p-12"> <div className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-xl border border-[var(--luxury-gold)]/20 backdrop-blur-xl shadow-2xl shadow-[var(--luxury-gold)]/5 p-6 sm:p-8 lg:p-12">
<div <div
className="prose prose-invert prose-lg max-w-none text-gray-300 className="prose prose-invert prose-lg max-w-none text-gray-300
prose-headings:text-white prose-headings:font-elegant prose-headings:font-semibold prose-headings:text-white prose-headings:font-elegant prose-headings:font-semibold
prose-h2:text-2xl prose-h2:mt-8 prose-h2:mb-4 prose-h2:border-b prose-h2:border-[#d4af37]/20 prose-h2:pb-2 prose-h2:text-2xl prose-h2:mt-8 prose-h2:mb-4 prose-h2:border-b prose-h2:border-[var(--luxury-gold)]/20 prose-h2:pb-2
prose-p:text-gray-300 prose-p:font-light prose-p:leading-relaxed prose-p:mb-4 prose-p:text-gray-300 prose-p:font-light prose-p:leading-relaxed prose-p:mb-4
prose-ul:text-gray-300 prose-ul:font-light prose-ul:my-4 prose-ul:text-gray-300 prose-ul:font-light prose-ul:my-4
prose-li:text-gray-300 prose-li:mb-2 prose-li:ml-4 prose-li:text-gray-300 prose-li:mb-2 prose-li:ml-4
prose-strong:text-[#d4af37] prose-strong:font-medium prose-strong:text-[var(--luxury-gold)] prose-strong:font-medium
prose-a:text-[#d4af37] prose-a:no-underline hover:prose-a:underline prose-a:text-[var(--luxury-gold)] prose-a:no-underline hover:prose-a:underline
[&_*]:text-gray-300 [&_h1]:text-white [&_h2]:text-white [&_h3]:text-white [&_h4]:text-white [&_h5]:text-white [&_h6]:text-white [&_*]:text-gray-300 [&_h1]:text-white [&_h2]:text-white [&_h3]:text-white [&_h4]:text-white [&_h5]:text-white [&_h6]:text-white
[&_strong]:text-[#d4af37] [&_b]:text-[#d4af37] [&_a]:text-[#d4af37]" [&_strong]:text-[var(--luxury-gold)] [&_b]:text-[var(--luxury-gold)] [&_a]:text-[var(--luxury-gold)]"
style={{ color: '#d1d5db' }} style={{ color: '#d1d5db' }}
dangerouslySetInnerHTML={createSanitizedHtml( dangerouslySetInnerHTML={createSanitizedHtml(
pageContent.content || pageContent.description || '<p style="color: #d1d5db;">No content available.</p>' pageContent.content || pageContent.description || '<p style="color: #d1d5db;">No content available.</p>'
@@ -175,7 +175,7 @@ const TermsPage: React.FC = () => {
<div className="mt-8 text-center"> <div className="mt-8 text-center">
<p className="text-sm text-gray-400 font-light"> <p className="text-sm text-gray-400 font-light">
For questions about these terms, contact us at{' '} For questions about these terms, contact us at{' '}
<a href={`mailto:${settings.company_email}`} className="text-[#d4af37] hover:underline"> <a href={`mailto:${settings.company_email}`} className="text-[var(--luxury-gold)] hover:underline">
{settings.company_email} {settings.company_email}
</a> </a>
</p> </p>

View File

@@ -368,10 +368,10 @@ const ChatWidget: React.FC<ChatWidgetProps> = ({ onClose }) => {
{!isOpen ? ( {!isOpen ? (
<button <button
onClick={handleOpen} onClick={handleOpen}
className="bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-slate-900 p-5 rounded-full shadow-2xl shadow-[#d4af37]/40 hover:from-[#c9a227] hover:to-[#d4af37] transition-all duration-300 hover:scale-110 flex items-center justify-center group relative" className="bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-slate-900 p-5 rounded-full shadow-2xl shadow-[var(--luxury-gold)]/40 hover:from-[var(--luxury-gold-dark)] hover:to-[var(--luxury-gold)] transition-all duration-300 hover:scale-110 flex items-center justify-center group relative"
aria-label="Open chat" aria-label="Open chat"
> >
<div className="absolute inset-0 bg-gradient-to-r from-[#d4af37] to-[#c9a227] rounded-full blur-xl opacity-50 group-hover:opacity-70 transition-opacity"></div> <div className="absolute inset-0 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] rounded-full blur-xl opacity-50 group-hover:opacity-70 transition-opacity"></div>
<MessageCircle className="w-6 h-6 group-hover:scale-110 transition-transform relative z-10" strokeWidth={2.5} /> <MessageCircle className="w-6 h-6 group-hover:scale-110 transition-transform relative z-10" strokeWidth={2.5} />
{chat && chat.status === 'pending' && ( {chat && chat.status === 'pending' && (
<span className="absolute -top-1 -right-1 w-4 h-4 bg-red-500 rounded-full animate-pulse border-2 border-white shadow-lg z-10"></span> <span className="absolute -top-1 -right-1 w-4 h-4 bg-red-500 rounded-full animate-pulse border-2 border-white shadow-lg z-10"></span>
@@ -379,14 +379,14 @@ const ChatWidget: React.FC<ChatWidgetProps> = ({ onClose }) => {
</button> </button>
) : ( ) : (
<div <div
className={`luxury-glass rounded-2xl shadow-2xl border border-[#d4af37]/30 flex flex-col transition-all duration-300 ${ className={`luxury-glass rounded-2xl shadow-2xl border border-[var(--luxury-gold)]/30 flex flex-col transition-all duration-300 ${
isMinimized ? 'w-80 h-16' : 'w-96 h-[600px]' isMinimized ? 'w-80 h-16' : 'w-96 h-[600px]'
}`} }`}
style={{ transformOrigin: 'bottom right' }} style={{ transformOrigin: 'bottom right' }}
> >
{} {}
<div className="bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-slate-900 p-4 rounded-t-2xl flex items-center justify-between relative overflow-hidden"> <div className="bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-slate-900 p-4 rounded-t-2xl flex items-center justify-between relative overflow-hidden">
<div className="absolute inset-0 bg-gradient-to-r from-[#d4af37]/20 to-[#c9a227]/20"></div> <div className="absolute inset-0 bg-gradient-to-r from-[var(--luxury-gold)]/20 to-[var(--luxury-gold-dark)]/20"></div>
<div className="absolute top-0 left-0 right-0 h-0.5 bg-gradient-to-r from-transparent via-slate-900/20 to-transparent"></div> <div className="absolute top-0 left-0 right-0 h-0.5 bg-gradient-to-r from-transparent via-slate-900/20 to-transparent"></div>
<div className="flex items-center gap-3 relative z-10"> <div className="flex items-center gap-3 relative z-10">
<div className="bg-slate-900/10 p-2 rounded-lg backdrop-blur-sm"> <div className="bg-slate-900/10 p-2 rounded-lg backdrop-blur-sm">
@@ -453,9 +453,9 @@ const ChatWidget: React.FC<ChatWidgetProps> = ({ onClose }) => {
{!isWithinBusinessHours ? ( {!isWithinBusinessHours ? (
<div className="flex-1 overflow-y-auto p-4 bg-gradient-to-b from-slate-50/50 to-white"> <div className="flex-1 overflow-y-auto p-4 bg-gradient-to-b from-slate-50/50 to-white">
<div className="max-w-md mx-auto"> <div className="max-w-md mx-auto">
<div className="mb-6 p-4 bg-gradient-to-r from-[#d4af37]/10 to-[#c9a227]/10 rounded-xl border border-[#d4af37]/20"> <div className="mb-6 p-4 bg-gradient-to-r from-[var(--luxury-gold)]/10 to-[var(--luxury-gold-dark)]/10 rounded-xl border border-[var(--luxury-gold)]/20">
<div className="flex items-start gap-3"> <div className="flex items-start gap-3">
<Clock className="w-5 h-5 text-[#d4af37] mt-0.5 flex-shrink-0" /> <Clock className="w-5 h-5 text-[var(--luxury-gold)] mt-0.5 flex-shrink-0" />
<div> <div>
<p className="text-sm font-semibold text-slate-900 mb-1">Chat Hours</p> <p className="text-sm font-semibold text-slate-900 mb-1">Chat Hours</p>
<p className="text-xs text-slate-600 font-light"> <p className="text-xs text-slate-600 font-light">
@@ -474,7 +474,7 @@ const ChatWidget: React.FC<ChatWidgetProps> = ({ onClose }) => {
type="email" type="email"
value={inquiryEmail} value={inquiryEmail}
onChange={(e) => setInquiryEmail(e.target.value)} onChange={(e) => setInquiryEmail(e.target.value)}
className="w-full px-4 py-2.5 border-2 border-slate-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-[#d4af37]/30 focus:border-[#d4af37] transition-all duration-200 font-light" className="w-full px-4 py-2.5 border-2 border-slate-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)]/30 focus:border-[var(--luxury-gold)] transition-all duration-200 font-light"
placeholder="your.email@example.com" placeholder="your.email@example.com"
/> />
</div> </div>
@@ -486,14 +486,14 @@ const ChatWidget: React.FC<ChatWidgetProps> = ({ onClose }) => {
value={inquiry} value={inquiry}
onChange={(e) => setInquiry(e.target.value)} onChange={(e) => setInquiry(e.target.value)}
rows={6} rows={6}
className="w-full px-4 py-2.5 border-2 border-slate-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-[#d4af37]/30 focus:border-[#d4af37] transition-all duration-200 font-light resize-none" className="w-full px-4 py-2.5 border-2 border-slate-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)]/30 focus:border-[var(--luxury-gold)] transition-all duration-200 font-light resize-none"
placeholder="Please describe your inquiry or question..." placeholder="Please describe your inquiry or question..."
/> />
</div> </div>
<button <button
onClick={handleSubmitInquiry} onClick={handleSubmitInquiry}
disabled={submittingInquiry || !inquiryEmail.trim() || !inquiry.trim()} disabled={submittingInquiry || !inquiryEmail.trim() || !inquiry.trim()}
className="w-full bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-slate-900 px-4 py-3 rounded-xl hover:from-[#c9a227] hover:to-[#d4af37] disabled:bg-gray-300 disabled:text-gray-500 disabled:cursor-not-allowed transition-all duration-300 font-semibold shadow-lg shadow-[#d4af37]/30 hover:shadow-xl disabled:shadow-none" className="w-full bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-slate-900 px-4 py-3 rounded-xl hover:from-[var(--luxury-gold-dark)] hover:to-[var(--luxury-gold)] disabled:bg-gray-300 disabled:text-gray-500 disabled:cursor-not-allowed transition-all duration-300 font-semibold shadow-lg shadow-[var(--luxury-gold)]/30 hover:shadow-xl disabled:shadow-none"
> >
{submittingInquiry ? 'Sending...' : 'Send Inquiry'} {submittingInquiry ? 'Sending...' : 'Send Inquiry'}
</button> </button>
@@ -521,8 +521,8 @@ const ChatWidget: React.FC<ChatWidgetProps> = ({ onClose }) => {
setVisitorInfo({ ...visitorInfo, name: e.target.value }); setVisitorInfo({ ...visitorInfo, name: e.target.value });
if (formErrors.name) setFormErrors({ ...formErrors, name: '' }); if (formErrors.name) setFormErrors({ ...formErrors, name: '' });
}} }}
className={`w-full px-4 py-2.5 border-2 rounded-xl focus:outline-none focus:ring-2 focus:ring-[#d4af37]/30 transition-all duration-200 font-light ${ className={`w-full px-4 py-2.5 border-2 rounded-xl focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)]/30 transition-all duration-200 font-light ${
formErrors.name ? 'border-red-500 focus:border-red-500' : 'border-slate-200 focus:border-[#d4af37]' formErrors.name ? 'border-red-500 focus:border-red-500' : 'border-slate-200 focus:border-[var(--luxury-gold)]'
}`} }`}
placeholder="Your full name" placeholder="Your full name"
/> />
@@ -541,8 +541,8 @@ const ChatWidget: React.FC<ChatWidgetProps> = ({ onClose }) => {
setVisitorInfo({ ...visitorInfo, email: e.target.value }); setVisitorInfo({ ...visitorInfo, email: e.target.value });
if (formErrors.email) setFormErrors({ ...formErrors, email: '' }); if (formErrors.email) setFormErrors({ ...formErrors, email: '' });
}} }}
className={`w-full px-4 py-2.5 border-2 rounded-xl focus:outline-none focus:ring-2 focus:ring-[#d4af37]/30 transition-all duration-200 font-light ${ className={`w-full px-4 py-2.5 border-2 rounded-xl focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)]/30 transition-all duration-200 font-light ${
formErrors.email ? 'border-red-500 focus:border-red-500' : 'border-slate-200 focus:border-[#d4af37]' formErrors.email ? 'border-red-500 focus:border-red-500' : 'border-slate-200 focus:border-[var(--luxury-gold)]'
}`} }`}
placeholder="your.email@example.com" placeholder="your.email@example.com"
/> />
@@ -561,8 +561,8 @@ const ChatWidget: React.FC<ChatWidgetProps> = ({ onClose }) => {
setVisitorInfo({ ...visitorInfo, phone: e.target.value }); setVisitorInfo({ ...visitorInfo, phone: e.target.value });
if (formErrors.phone) setFormErrors({ ...formErrors, phone: '' }); if (formErrors.phone) setFormErrors({ ...formErrors, phone: '' });
}} }}
className={`w-full px-4 py-2.5 border-2 rounded-xl focus:outline-none focus:ring-2 focus:ring-[#d4af37]/30 transition-all duration-200 font-light ${ className={`w-full px-4 py-2.5 border-2 rounded-xl focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)]/30 transition-all duration-200 font-light ${
formErrors.phone ? 'border-red-500 focus:border-red-500' : 'border-slate-200 focus:border-[#d4af37]' formErrors.phone ? 'border-red-500 focus:border-red-500' : 'border-slate-200 focus:border-[var(--luxury-gold)]'
}`} }`}
placeholder="+1 (555) 123-4567" placeholder="+1 (555) 123-4567"
/> />
@@ -573,7 +573,7 @@ const ChatWidget: React.FC<ChatWidgetProps> = ({ onClose }) => {
<button <button
onClick={createChat} onClick={createChat}
disabled={loading} disabled={loading}
className="w-full bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-slate-900 px-4 py-3 rounded-xl hover:from-[#c9a227] hover:to-[#d4af37] disabled:bg-gray-300 disabled:text-gray-500 disabled:cursor-not-allowed transition-all duration-300 font-semibold shadow-lg shadow-[#d4af37]/30 hover:shadow-xl disabled:shadow-none" className="w-full bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-slate-900 px-4 py-3 rounded-xl hover:from-[var(--luxury-gold-dark)] hover:to-[var(--luxury-gold)] disabled:bg-gray-300 disabled:text-gray-500 disabled:cursor-not-allowed transition-all duration-300 font-semibold shadow-lg shadow-[var(--luxury-gold)]/30 hover:shadow-xl disabled:shadow-none"
> >
{loading ? 'Starting chat...' : 'Start Chat'} {loading ? 'Starting chat...' : 'Start Chat'}
</button> </button>
@@ -617,7 +617,7 @@ const ChatWidget: React.FC<ChatWidgetProps> = ({ onClose }) => {
} }
}} }}
disabled={loading} disabled={loading}
className="bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-slate-900 px-8 py-3 rounded-xl hover:from-[#c9a227] hover:to-[#d4af37] transition-all duration-300 font-semibold shadow-lg shadow-[#d4af37]/30 hover:shadow-xl disabled:opacity-50 disabled:cursor-not-allowed" className="bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-slate-900 px-8 py-3 rounded-xl hover:from-[var(--luxury-gold-dark)] hover:to-[var(--luxury-gold)] transition-all duration-300 font-semibold shadow-lg shadow-[var(--luxury-gold)]/30 hover:shadow-xl disabled:opacity-50 disabled:cursor-not-allowed"
> >
{loading ? 'Starting...' : 'Start New Chat'} {loading ? 'Starting...' : 'Start New Chat'}
</button> </button>
@@ -637,12 +637,12 @@ const ChatWidget: React.FC<ChatWidgetProps> = ({ onClose }) => {
<div <div
className={`max-w-[80%] rounded-xl p-4 shadow-lg ${ className={`max-w-[80%] rounded-xl p-4 shadow-lg ${
message.sender_type === 'visitor' message.sender_type === 'visitor'
? 'bg-gradient-to-br from-[#d4af37] to-[#c9a227] text-slate-900 border border-[#d4af37]/30' ? 'bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-slate-900 border border-[var(--luxury-gold)]/30'
: 'bg-white text-slate-800 border border-slate-200/60 shadow-sm' : 'bg-white text-slate-800 border border-slate-200/60 shadow-sm'
}`} }`}
> >
{message.sender_type === 'staff' && ( {message.sender_type === 'staff' && (
<div className="text-xs font-semibold mb-1.5 text-[#d4af37] tracking-wide"> <div className="text-xs font-semibold mb-1.5 text-[var(--luxury-gold)] tracking-wide">
{message.sender_name || 'Staff'} {message.sender_name || 'Staff'}
</div> </div>
)} )}
@@ -671,7 +671,7 @@ const ChatWidget: React.FC<ChatWidgetProps> = ({ onClose }) => {
{} {}
{!showVisitorForm && chat && chat.status !== 'closed' && ( {!showVisitorForm && chat && chat.status !== 'closed' && (
<div className="p-4 border-t border-[#d4af37]/20 bg-white/90 backdrop-blur-sm rounded-b-2xl"> <div className="p-4 border-t border-[var(--luxury-gold)]/20 bg-white/90 backdrop-blur-sm rounded-b-2xl">
<div className="flex gap-3"> <div className="flex gap-3">
<input <input
type="text" type="text"
@@ -679,12 +679,12 @@ const ChatWidget: React.FC<ChatWidgetProps> = ({ onClose }) => {
onChange={(e) => setNewMessage(e.target.value)} onChange={(e) => setNewMessage(e.target.value)}
onKeyPress={handleKeyPress} onKeyPress={handleKeyPress}
placeholder="Type your message..." placeholder="Type your message..."
className="flex-1 px-4 py-3 border-2 border-slate-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-[#d4af37]/30 focus:border-[#d4af37] transition-all duration-200 font-light" className="flex-1 px-4 py-3 border-2 border-slate-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)]/30 focus:border-[var(--luxury-gold)] transition-all duration-200 font-light"
/> />
<button <button
onClick={handleSend} onClick={handleSend}
disabled={!newMessage.trim()} disabled={!newMessage.trim()}
className="bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-slate-900 px-5 py-3 rounded-xl hover:from-[#c9a227] hover:to-[#d4af37] disabled:bg-gray-300 disabled:text-gray-500 disabled:cursor-not-allowed transition-all duration-300 flex items-center gap-2 font-semibold shadow-lg shadow-[#d4af37]/30 hover:shadow-xl disabled:shadow-none" className="bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-slate-900 px-5 py-3 rounded-xl hover:from-[var(--luxury-gold-dark)] hover:to-[var(--luxury-gold)] disabled:bg-gray-300 disabled:text-gray-500 disabled:cursor-not-allowed transition-all duration-300 flex items-center gap-2 font-semibold shadow-lg shadow-[var(--luxury-gold)]/30 hover:shadow-xl disabled:shadow-none"
> >
<Send className="w-4 h-4" /> <Send className="w-4 h-4" />
</button> </button>

View File

@@ -112,16 +112,16 @@ const BoricaPaymentModal: React.FC<BoricaPaymentModalProps> = ({
className="fixed inset-0 bg-black/90 backdrop-blur-sm" className="fixed inset-0 bg-black/90 backdrop-blur-sm"
onClick={onClose} onClick={onClose}
/> />
<div className="relative w-full max-w-md max-h-[95vh] bg-gradient-to-br from-[#0a0a0a] via-[#1a1a1a] to-[#0a0a0a] rounded-xl sm:rounded-2xl border border-[#d4af37]/30 shadow-2xl shadow-[#d4af37]/20 overflow-hidden flex flex-col"> <div className="relative w-full max-w-md max-h-[95vh] bg-gradient-to-br from-[#0a0a0a] via-[#1a1a1a] to-[#0a0a0a] rounded-xl sm:rounded-2xl border border-[var(--luxury-gold)]/30 shadow-2xl shadow-[var(--luxury-gold)]/20 overflow-hidden flex flex-col">
{/* Header */} {/* Header */}
<div className="px-3 sm:px-4 md:px-6 py-3 sm:py-4 border-b border-[#d4af37]/20 bg-gradient-to-r from-[#1a1a1a] to-[#0a0a0a] flex-shrink-0"> <div className="px-3 sm:px-4 md:px-6 py-3 sm:py-4 border-b border-[var(--luxury-gold)]/20 bg-gradient-to-r from-[#1a1a1a] to-[#0a0a0a] flex-shrink-0">
<div className="flex items-center justify-between gap-2"> <div className="flex items-center justify-between gap-2">
<h2 className="text-base sm:text-lg md:text-xl font-serif font-bold text-white tracking-tight truncate flex-1"> <h2 className="text-base sm:text-lg md:text-xl font-serif font-bold text-white tracking-tight truncate flex-1">
Borica Payment Borica Payment
</h2> </h2>
<button <button
onClick={onClose} onClick={onClose}
className="p-1.5 sm:p-2 hover:bg-[#d4af37]/10 rounded-lg transition-colors text-gray-400 hover:text-white flex-shrink-0" className="p-1.5 sm:p-2 hover:bg-[var(--luxury-gold)]/10 rounded-lg transition-colors text-gray-400 hover:text-white flex-shrink-0"
> >
<X className="w-4 h-4 sm:w-5 sm:h-5" /> <X className="w-4 h-4 sm:w-5 sm:h-5" />
</button> </button>
@@ -132,7 +132,7 @@ const BoricaPaymentModal: React.FC<BoricaPaymentModalProps> = ({
<div className="flex-1 overflow-y-auto p-3 sm:p-4 md:p-6"> <div className="flex-1 overflow-y-auto p-3 sm:p-4 md:p-6">
{loading ? ( {loading ? (
<div className="flex flex-col items-center justify-center py-8 sm:py-12"> <div className="flex flex-col items-center justify-center py-8 sm:py-12">
<Loader2 className="w-10 h-10 sm:w-12 sm:h-12 animate-spin text-[#d4af37] mb-3 sm:mb-4" /> <Loader2 className="w-10 h-10 sm:w-12 sm:h-12 animate-spin text-[var(--luxury-gold)] mb-3 sm:mb-4" />
<p className="text-xs sm:text-sm text-gray-400">Initializing Borica payment...</p> <p className="text-xs sm:text-sm text-gray-400">Initializing Borica payment...</p>
</div> </div>
) : error ? ( ) : error ? (
@@ -153,14 +153,14 @@ const BoricaPaymentModal: React.FC<BoricaPaymentModalProps> = ({
<div className="space-y-4 sm:space-y-6"> <div className="space-y-4 sm:space-y-6">
<div className="text-center"> <div className="text-center">
<div className="mb-3 sm:mb-4 flex justify-center"> <div className="mb-3 sm:mb-4 flex justify-center">
<CreditCard className="w-12 h-12 sm:w-16 sm:h-16 text-[#d4af37]" /> <CreditCard className="w-12 h-12 sm:w-16 sm:h-16 text-[var(--luxury-gold)]" />
</div> </div>
<h3 className="text-base sm:text-lg font-serif font-semibold text-white mb-1.5 sm:mb-2"> <h3 className="text-base sm:text-lg font-serif font-semibold text-white mb-1.5 sm:mb-2">
Complete Payment with Borica Complete Payment with Borica
</h3> </h3>
<p className="text-xs sm:text-sm text-gray-400 mb-3 sm:mb-4 leading-relaxed px-2"> <p className="text-xs sm:text-sm text-gray-400 mb-3 sm:mb-4 leading-relaxed px-2">
You will be redirected to Borica payment gateway to securely complete your payment of{' '} You will be redirected to Borica payment gateway to securely complete your payment of{' '}
<span className="font-semibold text-[#d4af37]"> <span className="font-semibold text-[var(--luxury-gold)]">
{new Intl.NumberFormat('en-US', { {new Intl.NumberFormat('en-US', {
style: 'currency', style: 'currency',
currency: currency, currency: currency,
@@ -169,14 +169,14 @@ const BoricaPaymentModal: React.FC<BoricaPaymentModalProps> = ({
</p> </p>
</div> </div>
<div className="bg-[#1a1a1a]/50 border border-[#d4af37]/20 rounded-lg p-3 sm:p-4 space-y-2 sm:space-y-3"> <div className="bg-[#1a1a1a]/50 border border-[var(--luxury-gold)]/20 rounded-lg p-3 sm:p-4 space-y-2 sm:space-y-3">
<div className="flex justify-between items-center text-xs sm:text-sm"> <div className="flex justify-between items-center text-xs sm:text-sm">
<span className="text-gray-400">Order ID:</span> <span className="text-gray-400">Order ID:</span>
<span className="text-white font-mono">{paymentRequest.order_id}</span> <span className="text-white font-mono">{paymentRequest.order_id}</span>
</div> </div>
<div className="flex justify-between items-center text-xs sm:text-sm"> <div className="flex justify-between items-center text-xs sm:text-sm">
<span className="text-gray-400">Amount:</span> <span className="text-gray-400">Amount:</span>
<span className="text-[#d4af37] font-semibold"> <span className="text-[var(--luxury-gold)] font-semibold">
{new Intl.NumberFormat('en-US', { {new Intl.NumberFormat('en-US', {
style: 'currency', style: 'currency',
currency: currency, currency: currency,
@@ -202,7 +202,7 @@ const BoricaPaymentModal: React.FC<BoricaPaymentModalProps> = ({
{/* Footer */} {/* Footer */}
{!loading && !error && paymentRequest && ( {!loading && !error && paymentRequest && (
<div className="px-3 sm:px-4 md:px-6 py-3 sm:py-4 border-t border-[#d4af37]/20 bg-gradient-to-r from-[#1a1a1a] to-[#0a0a0a] flex-shrink-0 flex gap-2 sm:gap-3"> <div className="px-3 sm:px-4 md:px-6 py-3 sm:py-4 border-t border-[var(--luxury-gold)]/20 bg-gradient-to-r from-[#1a1a1a] to-[#0a0a0a] flex-shrink-0 flex gap-2 sm:gap-3">
<button <button
onClick={onClose} onClick={onClose}
className="flex-1 px-3 sm:px-4 py-2 sm:py-2.5 text-xs sm:text-sm font-medium text-gray-300 bg-[#1a1a1a] border border-gray-700 rounded-lg hover:bg-[#2a2a2a] hover:border-gray-600 transition-colors" className="flex-1 px-3 sm:px-4 py-2 sm:py-2.5 text-xs sm:text-sm font-medium text-gray-300 bg-[#1a1a1a] border border-gray-700 rounded-lg hover:bg-[#2a2a2a] hover:border-gray-600 transition-colors"
@@ -211,7 +211,7 @@ const BoricaPaymentModal: React.FC<BoricaPaymentModalProps> = ({
</button> </button>
<button <button
onClick={handleSubmitPayment} onClick={handleSubmitPayment}
className="flex-1 px-3 sm:px-4 py-2 sm:py-2.5 text-xs sm:text-sm font-medium text-white bg-gradient-to-r from-[#d4af37] to-[#b8941f] rounded-lg hover:from-[#e5c048] hover:to-[#c9a428] transition-all shadow-lg shadow-[#d4af37]/20 flex items-center justify-center gap-2" className="flex-1 px-3 sm:px-4 py-2 sm:py-2.5 text-xs sm:text-sm font-medium text-white bg-gradient-to-r from-[var(--luxury-gold)] to-[#b8941f] rounded-lg hover:from-[#e5c048] hover:to-[#c9a428] transition-all shadow-lg shadow-[var(--luxury-gold)]/20 flex items-center justify-center gap-2"
> >
<CreditCard className="w-4 h-4" /> <CreditCard className="w-4 h-4" />
Proceed to Payment Proceed to Payment

View File

@@ -41,16 +41,16 @@ const CashPaymentModal: React.FC<CashPaymentModalProps> = ({
className="fixed inset-0 bg-black/90 backdrop-blur-sm" className="fixed inset-0 bg-black/90 backdrop-blur-sm"
onClick={onClose} onClick={onClose}
/> />
<div className="relative w-full max-w-md max-h-[95vh] bg-gradient-to-br from-[#0a0a0a] via-[#1a1a1a] to-[#0a0a0a] rounded-xl sm:rounded-2xl border border-[#d4af37]/30 shadow-2xl shadow-[#d4af37]/20 overflow-hidden flex flex-col"> <div className="relative w-full max-w-md max-h-[95vh] bg-gradient-to-br from-[#0a0a0a] via-[#1a1a1a] to-[#0a0a0a] rounded-xl sm:rounded-2xl border border-[var(--luxury-gold)]/30 shadow-2xl shadow-[var(--luxury-gold)]/20 overflow-hidden flex flex-col">
{/* Header */} {/* Header */}
<div className="px-3 sm:px-4 md:px-6 py-3 sm:py-4 border-b border-[#d4af37]/20 bg-gradient-to-r from-[#1a1a1a] to-[#0a0a0a] flex-shrink-0"> <div className="px-3 sm:px-4 md:px-6 py-3 sm:py-4 border-b border-[var(--luxury-gold)]/20 bg-gradient-to-r from-[#1a1a1a] to-[#0a0a0a] flex-shrink-0">
<div className="flex items-center justify-between gap-2"> <div className="flex items-center justify-between gap-2">
<h2 className="text-base sm:text-lg md:text-xl font-serif font-bold text-white tracking-tight truncate flex-1"> <h2 className="text-base sm:text-lg md:text-xl font-serif font-bold text-white tracking-tight truncate flex-1">
Booking Created Booking Created
</h2> </h2>
<button <button
onClick={onClose} onClick={onClose}
className="p-1.5 sm:p-2 hover:bg-[#d4af37]/10 rounded-lg transition-colors text-gray-400 hover:text-white flex-shrink-0" className="p-1.5 sm:p-2 hover:bg-[var(--luxury-gold)]/10 rounded-lg transition-colors text-gray-400 hover:text-white flex-shrink-0"
> >
<X className="w-4 h-4 sm:w-5 sm:h-5" /> <X className="w-4 h-4 sm:w-5 sm:h-5" />
</button> </button>
@@ -72,16 +72,16 @@ const CashPaymentModal: React.FC<CashPaymentModalProps> = ({
</p> </p>
</div> </div>
<div className="bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg p-3 sm:p-4 space-y-2 sm:space-y-3"> <div className="bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg p-3 sm:p-4 space-y-2 sm:space-y-3">
<div className="flex items-center justify-between text-xs sm:text-sm"> <div className="flex items-center justify-between text-xs sm:text-sm">
<span className="text-gray-400">Total Amount</span> <span className="text-gray-400">Total Amount</span>
<span className="text-white font-semibold">{formatCurrency(amount)}</span> <span className="text-white font-semibold">{formatCurrency(amount)}</span>
</div> </div>
<div className="flex items-center justify-between text-xs sm:text-sm"> <div className="flex items-center justify-between text-xs sm:text-sm">
<span className="text-gray-400 break-words pr-2">Deposit Required (20%)</span> <span className="text-gray-400 break-words pr-2">Deposit Required (20%)</span>
<span className="text-[#d4af37] font-bold flex-shrink-0">{formatCurrency(depositAmount)}</span> <span className="text-[var(--luxury-gold)] font-bold flex-shrink-0">{formatCurrency(depositAmount)}</span>
</div> </div>
<div className="pt-2 sm:pt-3 border-t border-[#d4af37]/20"> <div className="pt-2 sm:pt-3 border-t border-[var(--luxury-gold)]/20">
<p className="text-xs text-gray-400 leading-relaxed"> <p className="text-xs text-gray-400 leading-relaxed">
Pay the remaining balance on arrival at the hotel. Pay the remaining balance on arrival at the hotel.
</p> </p>
@@ -91,7 +91,7 @@ const CashPaymentModal: React.FC<CashPaymentModalProps> = ({
<div className="flex flex-col gap-2 sm:gap-3 pt-2"> <div className="flex flex-col gap-2 sm:gap-3 pt-2">
<button <button
onClick={handlePayDeposit} onClick={handlePayDeposit}
className="w-full bg-[#d4af37] text-black font-semibold py-2.5 sm:py-3 px-4 sm:px-6 rounded-lg hover:bg-[#c9a227] transition-all flex items-center justify-center gap-2 text-sm sm:text-base min-h-[44px]" className="w-full bg-[var(--luxury-gold)] text-black font-semibold py-2.5 sm:py-3 px-4 sm:px-6 rounded-lg hover:bg-[var(--luxury-gold-dark)] transition-all flex items-center justify-center gap-2 text-sm sm:text-base min-h-[44px]"
> >
<CreditCard className="w-4 h-4 sm:w-5 sm:h-5" /> <CreditCard className="w-4 h-4 sm:w-5 sm:h-5" />
<span>Pay Deposit Now</span> <span>Pay Deposit Now</span>

View File

@@ -177,9 +177,9 @@ const DepositPaymentModal: React.FC<DepositPaymentModalProps> = ({
className="fixed inset-0 bg-black/90 backdrop-blur-sm" className="fixed inset-0 bg-black/90 backdrop-blur-sm"
onClick={onClose} onClick={onClose}
/> />
<div className="relative w-full max-w-3xl max-h-[95vh] bg-gradient-to-br from-[#0a0a0a] via-[#1a1a1a] to-[#0a0a0a] rounded-xl sm:rounded-2xl border border-[#d4af37]/30 shadow-2xl shadow-[#d4af37]/20 overflow-hidden flex flex-col"> <div className="relative w-full max-w-3xl max-h-[95vh] bg-gradient-to-br from-[#0a0a0a] via-[#1a1a1a] to-[#0a0a0a] rounded-xl sm:rounded-2xl border border-[var(--luxury-gold)]/30 shadow-2xl shadow-[var(--luxury-gold)]/20 overflow-hidden flex flex-col">
{/* Header */} {/* Header */}
<div className="px-3 sm:px-4 md:px-6 py-3 sm:py-4 border-b border-[#d4af37]/20 bg-gradient-to-r from-[#1a1a1a] to-[#0a0a0a] flex-shrink-0"> <div className="px-3 sm:px-4 md:px-6 py-3 sm:py-4 border-b border-[var(--luxury-gold)]/20 bg-gradient-to-r from-[#1a1a1a] to-[#0a0a0a] flex-shrink-0">
<div className="flex items-center justify-between gap-2"> <div className="flex items-center justify-between gap-2">
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
<h2 className="text-base sm:text-lg md:text-xl font-serif font-bold text-white tracking-tight truncate"> <h2 className="text-base sm:text-lg md:text-xl font-serif font-bold text-white tracking-tight truncate">
@@ -204,7 +204,7 @@ const DepositPaymentModal: React.FC<DepositPaymentModalProps> = ({
)} )}
<button <button
onClick={onClose} onClick={onClose}
className="p-1.5 sm:p-2 hover:bg-[#d4af37]/10 rounded-lg transition-colors text-gray-400 hover:text-white flex-shrink-0" className="p-1.5 sm:p-2 hover:bg-[var(--luxury-gold)]/10 rounded-lg transition-colors text-gray-400 hover:text-white flex-shrink-0"
> >
<X className="w-4 h-4 sm:w-5 sm:h-5" /> <X className="w-4 h-4 sm:w-5 sm:h-5" />
</button> </button>
@@ -216,7 +216,7 @@ const DepositPaymentModal: React.FC<DepositPaymentModalProps> = ({
<div className="flex-1 overflow-y-auto px-3 sm:px-4 md:px-6 py-4 sm:py-6"> <div className="flex-1 overflow-y-auto px-3 sm:px-4 md:px-6 py-4 sm:py-6">
{loading ? ( {loading ? (
<div className="flex flex-col items-center justify-center py-8 sm:py-12"> <div className="flex flex-col items-center justify-center py-8 sm:py-12">
<Loader2 className="w-10 h-10 sm:w-12 sm:h-12 animate-spin text-[#d4af37] mb-3 sm:mb-4" /> <Loader2 className="w-10 h-10 sm:w-12 sm:h-12 animate-spin text-[var(--luxury-gold)] mb-3 sm:mb-4" />
<p className="text-xs sm:text-sm text-gray-400">Loading payment information...</p> <p className="text-xs sm:text-sm text-gray-400">Loading payment information...</p>
</div> </div>
) : error || !booking || !depositPayment ? ( ) : error || !booking || !depositPayment ? (
@@ -227,7 +227,7 @@ const DepositPaymentModal: React.FC<DepositPaymentModalProps> = ({
</p> </p>
<button <button
onClick={onClose} onClick={onClose}
className="px-4 py-2 sm:py-2.5 bg-[#d4af37] text-black font-semibold rounded-lg hover:bg-[#c9a227] transition-all text-sm sm:text-base min-h-[44px]" className="px-4 py-2 sm:py-2.5 bg-[var(--luxury-gold)] text-black font-semibold rounded-lg hover:bg-[var(--luxury-gold-dark)] transition-all text-sm sm:text-base min-h-[44px]"
> >
Close Close
</button> </button>
@@ -260,17 +260,17 @@ const DepositPaymentModal: React.FC<DepositPaymentModalProps> = ({
{/* Payment Required Message */} {/* Payment Required Message */}
{!isDepositPaid && ( {!isDepositPaid && (
<div className="bg-[#d4af37]/10 border border-[#d4af37]/30 rounded-lg p-3 sm:p-4"> <div className="bg-[var(--luxury-gold)]/10 border border-[var(--luxury-gold)]/30 rounded-lg p-3 sm:p-4">
<div className="flex items-start gap-2 sm:gap-3"> <div className="flex items-start gap-2 sm:gap-3">
<div className="w-10 h-10 sm:w-12 sm:h-12 bg-[#d4af37]/20 rounded-full flex items-center justify-center border border-[#d4af37]/30 flex-shrink-0"> <div className="w-10 h-10 sm:w-12 sm:h-12 bg-[var(--luxury-gold)]/20 rounded-full flex items-center justify-center border border-[var(--luxury-gold)]/30 flex-shrink-0">
<CreditCard className="w-5 h-5 sm:w-6 sm:h-6 md:w-7 md:h-7 text-[#d4af37]" /> <CreditCard className="w-5 h-5 sm:w-6 sm:h-6 md:w-7 md:h-7 text-[var(--luxury-gold)]" />
</div> </div>
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
<h3 className="text-base sm:text-lg font-serif font-semibold text-[#d4af37] mb-1"> <h3 className="text-base sm:text-lg font-serif font-semibold text-[var(--luxury-gold)] mb-1">
Deposit Payment Required Deposit Payment Required
</h3> </h3>
<p className="text-xs sm:text-sm text-gray-300 leading-relaxed"> <p className="text-xs sm:text-sm text-gray-300 leading-relaxed">
Please pay <strong className="text-[#d4af37]">20% deposit</strong> to confirm your booking. Pay the remaining balance on arrival at the hotel. Please pay <strong className="text-[var(--luxury-gold)]">20% deposit</strong> to confirm your booking. Pay the remaining balance on arrival at the hotel.
</p> </p>
</div> </div>
</div> </div>
@@ -278,14 +278,14 @@ const DepositPaymentModal: React.FC<DepositPaymentModalProps> = ({
)} )}
{/* Payment Information */} {/* Payment Information */}
<div className="bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg p-3 sm:p-4"> <div className="bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg p-3 sm:p-4">
<h3 className="text-xs sm:text-sm font-semibold text-[#d4af37] mb-2 sm:mb-3">Payment Information</h3> <h3 className="text-xs sm:text-sm font-semibold text-[var(--luxury-gold)] mb-2 sm:mb-3">Payment Information</h3>
<div className="space-y-1.5 sm:space-y-2 text-xs sm:text-sm"> <div className="space-y-1.5 sm:space-y-2 text-xs sm:text-sm">
<div className="flex justify-between text-gray-300"> <div className="flex justify-between text-gray-300">
<span>Total Room Price</span> <span>Total Room Price</span>
<span>{formatCurrency(booking.total_price)}</span> <span>{formatCurrency(booking.total_price)}</span>
</div> </div>
<div className="flex justify-between text-base sm:text-lg font-bold text-[#d4af37] pt-2 border-t border-[#d4af37]/20"> <div className="flex justify-between text-base sm:text-lg font-bold text-[var(--luxury-gold)] pt-2 border-t border-[var(--luxury-gold)]/20">
<span className="break-words pr-2">Deposit Amount (20%)</span> <span className="break-words pr-2">Deposit Amount (20%)</span>
<span className="flex-shrink-0">{formatCurrency(depositAmount)}</span> <span className="flex-shrink-0">{formatCurrency(depositAmount)}</span>
</div> </div>
@@ -298,18 +298,18 @@ const DepositPaymentModal: React.FC<DepositPaymentModalProps> = ({
{/* Payment Method Selection */} {/* Payment Method Selection */}
{!isDepositPaid && !selectedPaymentMethod && ( {!isDepositPaid && !selectedPaymentMethod && (
<div className="bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg p-3 sm:p-4"> <div className="bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg p-3 sm:p-4">
<h3 className="text-xs sm:text-sm font-semibold text-[#d4af37] mb-2 sm:mb-3">Choose Payment Method</h3> <h3 className="text-xs sm:text-sm font-semibold text-[var(--luxury-gold)] mb-2 sm:mb-3">Choose Payment Method</h3>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-2 sm:gap-3"> <div className="grid grid-cols-1 sm:grid-cols-2 gap-2 sm:gap-3">
<button <button
onClick={() => handlePaymentMethodSelect('stripe')} onClick={() => handlePaymentMethodSelect('stripe')}
className="p-3 sm:p-4 bg-[#1a1a1a] border-2 border-gray-600/30 rounded-lg hover:border-[#d4af37]/50 transition-all text-left group min-h-[80px] sm:min-h-[100px]" className="p-3 sm:p-4 bg-[#1a1a1a] border-2 border-gray-600/30 rounded-lg hover:border-[var(--luxury-gold)]/50 transition-all text-left group min-h-[80px] sm:min-h-[100px]"
> >
<div className="flex items-center justify-between mb-1.5 sm:mb-2"> <div className="flex items-center justify-between mb-1.5 sm:mb-2">
<div className="w-8 h-8 sm:w-10 sm:h-10 bg-indigo-500/20 rounded-lg flex items-center justify-center border border-indigo-500/30 flex-shrink-0"> <div className="w-8 h-8 sm:w-10 sm:h-10 bg-indigo-500/20 rounded-lg flex items-center justify-center border border-indigo-500/30 flex-shrink-0">
<CreditCard className="w-4 h-4 sm:w-5 sm:h-5 text-indigo-400 group-hover:text-[#d4af37] transition-colors" /> <CreditCard className="w-4 h-4 sm:w-5 sm:h-5 text-indigo-400 group-hover:text-[var(--luxury-gold)] transition-colors" />
</div> </div>
<span className="text-xs font-semibold text-indigo-400 group-hover:text-[#d4af37] transition-colors"> <span className="text-xs font-semibold text-indigo-400 group-hover:text-[var(--luxury-gold)] transition-colors">
Card Payment Card Payment
</span> </span>
</div> </div>
@@ -320,19 +320,19 @@ const DepositPaymentModal: React.FC<DepositPaymentModalProps> = ({
<button <button
onClick={() => handlePaymentMethodSelect('paypal')} onClick={() => handlePaymentMethodSelect('paypal')}
className="p-3 sm:p-4 bg-[#1a1a1a] border-2 border-gray-600/30 rounded-lg hover:border-[#d4af37]/50 transition-all text-left group min-h-[80px] sm:min-h-[100px]" className="p-3 sm:p-4 bg-[#1a1a1a] border-2 border-gray-600/30 rounded-lg hover:border-[var(--luxury-gold)]/50 transition-all text-left group min-h-[80px] sm:min-h-[100px]"
> >
<div className="flex items-center justify-between mb-1.5 sm:mb-2"> <div className="flex items-center justify-between mb-1.5 sm:mb-2">
<div className="w-8 h-8 sm:w-10 sm:h-10 bg-blue-500/20 rounded-lg flex items-center justify-center border border-blue-500/30 flex-shrink-0"> <div className="w-8 h-8 sm:w-10 sm:h-10 bg-blue-500/20 rounded-lg flex items-center justify-center border border-blue-500/30 flex-shrink-0">
<svg <svg
className="w-4 h-4 sm:w-5 sm:h-5 text-blue-400 group-hover:text-[#d4af37] transition-colors" className="w-4 h-4 sm:w-5 sm:h-5 text-blue-400 group-hover:text-[var(--luxury-gold)] transition-colors"
viewBox="0 0 24 24" viewBox="0 0 24 24"
fill="currentColor" fill="currentColor"
> >
<path d="M7.076 21.337H2.47a.641.641 0 0 1-.633-.74L4.944.901C5.026.382 5.474 0 5.998 0h7.46c2.57 0 4.578.543 5.69 1.81 1.01 1.15 1.304 2.42 1.012 4.287-.023.143-.047.288-.077.437-.983 5.05-4.349 6.797-8.647 6.797h-2.19c-.524 0-.968.382-1.05.9l-1.12 7.203zm14.146-14.42a.477.477 0 0 0-.414-.24h-3.84c-.48 0-.856.355-.932.826-.075.47-.232 1.21-.232 1.21s-.156-.74-.232-1.21a.957.957 0 0 0-.932-.826H5.342a.957.957 0 0 0-.932.826c-.076.47-.232 1.21-.232 1.21s-.156-.74-.232-1.21a.957.957 0 0 0-.932-.826H.477a.477.477 0 0 0-.414.24c-.11.19-.14.426-.08.643.06.217.2.4.388.51l.04.02c.19.11.426.14.643.08.217-.06.4-.2.51-.388l.01-.02c.11-.19.14-.426.08-.643a.955.955 0 0 0-.388-.51l-.01-.01a.955.955 0 0 0-.51-.388.955.955 0 0 0-.643.08l-.01.01a.955.955 0 0 0-.388.51c-.06.217-.03.453.08.643l.01.02c.11.188.293.328.51.388.217.06.453.03.643-.08l.01-.02c.188-.11.328-.293.388-.51.06-.217.03-.453-.08-.643l-.01-.01z"/> <path d="M7.076 21.337H2.47a.641.641 0 0 1-.633-.74L4.944.901C5.026.382 5.474 0 5.998 0h7.46c2.57 0 4.578.543 5.69 1.81 1.01 1.15 1.304 2.42 1.012 4.287-.023.143-.047.288-.077.437-.983 5.05-4.349 6.797-8.647 6.797h-2.19c-.524 0-.968.382-1.05.9l-1.12 7.203zm14.146-14.42a.477.477 0 0 0-.414-.24h-3.84c-.48 0-.856.355-.932.826-.075.47-.232 1.21-.232 1.21s-.156-.74-.232-1.21a.957.957 0 0 0-.932-.826H5.342a.957.957 0 0 0-.932.826c-.076.47-.232 1.21-.232 1.21s-.156-.74-.232-1.21a.957.957 0 0 0-.932-.826H.477a.477.477 0 0 0-.414.24c-.11.19-.14.426-.08.643.06.217.2.4.388.51l.04.02c.19.11.426.14.643.08.217-.06.4-.2.51-.388l.01-.02c.11-.19.14-.426.08-.643a.955.955 0 0 0-.388-.51l-.01-.01a.955.955 0 0 0-.51-.388.955.955 0 0 0-.643.08l-.01.01a.955.955 0 0 0-.388.51c-.06.217-.03.453.08.643l.01.02c.11.188.293.328.51.388.217.06.453.03.643-.08l.01-.02c.188-.11.328-.293.388-.51.06-.217.03-.453-.08-.643l-.01-.01z"/>
</svg> </svg>
</div> </div>
<span className="text-xs font-semibold text-blue-400 group-hover:text-[#d4af37] transition-colors"> <span className="text-xs font-semibold text-blue-400 group-hover:text-[var(--luxury-gold)] transition-colors">
PayPal PayPal
</span> </span>
</div> </div>
@@ -346,10 +346,10 @@ const DepositPaymentModal: React.FC<DepositPaymentModalProps> = ({
{/* Change Payment Method */} {/* Change Payment Method */}
{!isDepositPaid && selectedPaymentMethod && ( {!isDepositPaid && selectedPaymentMethod && (
<div className="bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg p-3 sm:p-4"> <div className="bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg p-3 sm:p-4">
<div className="flex items-center justify-between gap-2 mb-2 sm:mb-3"> <div className="flex items-center justify-between gap-2 mb-2 sm:mb-3">
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
<h3 className="text-xs sm:text-sm font-semibold text-[#d4af37]"> <h3 className="text-xs sm:text-sm font-semibold text-[var(--luxury-gold)]">
{selectedPaymentMethod === 'stripe' ? 'Card Payment' : 'PayPal Payment'} {selectedPaymentMethod === 'stripe' ? 'Card Payment' : 'PayPal Payment'}
</h3> </h3>
<p className="text-xs text-gray-400 mt-0.5 sm:mt-1"> <p className="text-xs text-gray-400 mt-0.5 sm:mt-1">
@@ -361,7 +361,7 @@ const DepositPaymentModal: React.FC<DepositPaymentModalProps> = ({
setSelectedPaymentMethod(null); setSelectedPaymentMethod(null);
setShowPaymentModal(false); setShowPaymentModal(false);
}} }}
className="text-xs text-gray-400 hover:text-[#d4af37] underline transition-colors flex-shrink-0 whitespace-nowrap" className="text-xs text-gray-400 hover:text-[var(--luxury-gold)] underline transition-colors flex-shrink-0 whitespace-nowrap"
> >
Change method Change method
</button> </button>

View File

@@ -89,16 +89,16 @@ const PayPalPaymentModal: React.FC<PayPalPaymentModalProps> = ({
className="fixed inset-0 bg-black/90 backdrop-blur-sm" className="fixed inset-0 bg-black/90 backdrop-blur-sm"
onClick={onClose} onClick={onClose}
/> />
<div className="relative w-full max-w-md max-h-[95vh] bg-gradient-to-br from-[#0a0a0a] via-[#1a1a1a] to-[#0a0a0a] rounded-xl sm:rounded-2xl border border-[#d4af37]/30 shadow-2xl shadow-[#d4af37]/20 overflow-hidden flex flex-col"> <div className="relative w-full max-w-md max-h-[95vh] bg-gradient-to-br from-[#0a0a0a] via-[#1a1a1a] to-[#0a0a0a] rounded-xl sm:rounded-2xl border border-[var(--luxury-gold)]/30 shadow-2xl shadow-[var(--luxury-gold)]/20 overflow-hidden flex flex-col">
{/* Header */} {/* Header */}
<div className="px-3 sm:px-4 md:px-6 py-3 sm:py-4 border-b border-[#d4af37]/20 bg-gradient-to-r from-[#1a1a1a] to-[#0a0a0a] flex-shrink-0"> <div className="px-3 sm:px-4 md:px-6 py-3 sm:py-4 border-b border-[var(--luxury-gold)]/20 bg-gradient-to-r from-[#1a1a1a] to-[#0a0a0a] flex-shrink-0">
<div className="flex items-center justify-between gap-2"> <div className="flex items-center justify-between gap-2">
<h2 className="text-base sm:text-lg md:text-xl font-serif font-bold text-white tracking-tight truncate flex-1"> <h2 className="text-base sm:text-lg md:text-xl font-serif font-bold text-white tracking-tight truncate flex-1">
PayPal Payment PayPal Payment
</h2> </h2>
<button <button
onClick={onClose} onClick={onClose}
className="p-1.5 sm:p-2 hover:bg-[#d4af37]/10 rounded-lg transition-colors text-gray-400 hover:text-white flex-shrink-0" className="p-1.5 sm:p-2 hover:bg-[var(--luxury-gold)]/10 rounded-lg transition-colors text-gray-400 hover:text-white flex-shrink-0"
> >
<X className="w-4 h-4 sm:w-5 sm:h-5" /> <X className="w-4 h-4 sm:w-5 sm:h-5" />
</button> </button>
@@ -109,7 +109,7 @@ const PayPalPaymentModal: React.FC<PayPalPaymentModalProps> = ({
<div className="flex-1 overflow-y-auto p-3 sm:p-4 md:p-6"> <div className="flex-1 overflow-y-auto p-3 sm:p-4 md:p-6">
{loading ? ( {loading ? (
<div className="flex flex-col items-center justify-center py-8 sm:py-12"> <div className="flex flex-col items-center justify-center py-8 sm:py-12">
<Loader2 className="w-10 h-10 sm:w-12 sm:h-12 animate-spin text-[#d4af37] mb-3 sm:mb-4" /> <Loader2 className="w-10 h-10 sm:w-12 sm:h-12 animate-spin text-[var(--luxury-gold)] mb-3 sm:mb-4" />
<p className="text-xs sm:text-sm text-gray-400">Initializing PayPal payment...</p> <p className="text-xs sm:text-sm text-gray-400">Initializing PayPal payment...</p>
</div> </div>
) : error ? ( ) : error ? (
@@ -147,7 +147,7 @@ const PayPalPaymentModal: React.FC<PayPalPaymentModalProps> = ({
</h3> </h3>
<p className="text-xs sm:text-sm text-gray-400 mb-3 sm:mb-4 leading-relaxed px-2"> <p className="text-xs sm:text-sm text-gray-400 mb-3 sm:mb-4 leading-relaxed px-2">
You will be redirected to PayPal to securely complete your payment of{' '} You will be redirected to PayPal to securely complete your payment of{' '}
<span className="font-semibold text-[#d4af37]"> <span className="font-semibold text-[var(--luxury-gold)]">
{new Intl.NumberFormat('en-US', { {new Intl.NumberFormat('en-US', {
style: 'currency', style: 'currency',
currency: currency, currency: currency,
@@ -178,7 +178,7 @@ const PayPalPaymentModal: React.FC<PayPalPaymentModalProps> = ({
</div> </div>
) : ( ) : (
<div className="flex flex-col items-center justify-center py-8 sm:py-12"> <div className="flex flex-col items-center justify-center py-8 sm:py-12">
<Loader2 className="w-10 h-10 sm:w-12 sm:h-12 animate-spin text-[#d4af37] mb-3 sm:mb-4" /> <Loader2 className="w-10 h-10 sm:w-12 sm:h-12 animate-spin text-[var(--luxury-gold)] mb-3 sm:mb-4" />
<p className="text-xs sm:text-sm text-gray-400">Loading PayPal...</p> <p className="text-xs sm:text-sm text-gray-400">Loading PayPal...</p>
</div> </div>
)} )}

View File

@@ -83,10 +83,10 @@ const PayPalPaymentWrapper: React.FC<PayPalPaymentWrapperProps> = ({
if (loading) { if (loading) {
return ( return (
<div className="flex items-center justify-center p-8"> <div className="flex items-center justify-center p-8">
<div className="w-16 h-16 bg-gradient-to-br from-[#d4af37]/20 to-[#f5d76e]/20 <div className="w-16 h-16 bg-gradient-to-br from-[var(--luxury-gold)]/20 to-[var(--luxury-gold-light)]/20
rounded-full flex items-center justify-center rounded-full flex items-center justify-center
border border-[#d4af37]/30 shadow-lg shadow-[#d4af37]/20"> border border-[var(--luxury-gold)]/30 shadow-lg shadow-[var(--luxury-gold)]/20">
<Loader2 className="w-8 h-8 animate-spin text-[#d4af37]" /> <Loader2 className="w-8 h-8 animate-spin text-[var(--luxury-gold)]" />
</div> </div>
<span className="ml-4 text-gray-300 font-light tracking-wide"> <span className="ml-4 text-gray-300 font-light tracking-wide">
Initializing PayPal payment... Initializing PayPal payment...
@@ -117,10 +117,10 @@ const PayPalPaymentWrapper: React.FC<PayPalPaymentWrapperProps> = ({
if (!approvalUrl) { if (!approvalUrl) {
return ( return (
<div className="flex items-center justify-center p-8"> <div className="flex items-center justify-center p-8">
<div className="w-16 h-16 bg-gradient-to-br from-[#d4af37]/20 to-[#f5d76e]/20 <div className="w-16 h-16 bg-gradient-to-br from-[var(--luxury-gold)]/20 to-[var(--luxury-gold-light)]/20
rounded-full flex items-center justify-center rounded-full flex items-center justify-center
border border-[#d4af37]/30 shadow-lg shadow-[#d4af37]/20"> border border-[var(--luxury-gold)]/30 shadow-lg shadow-[var(--luxury-gold)]/20">
<Loader2 className="w-8 h-8 animate-spin text-[#d4af37]" /> <Loader2 className="w-8 h-8 animate-spin text-[var(--luxury-gold)]" />
</div> </div>
<span className="ml-4 text-gray-300 font-light tracking-wide"> <span className="ml-4 text-gray-300 font-light tracking-wide">
Loading PayPal... Loading PayPal...
@@ -144,12 +144,12 @@ const PayPalPaymentWrapper: React.FC<PayPalPaymentWrapperProps> = ({
/> />
</svg> </svg>
</div> </div>
<h3 className="text-xl font-serif font-semibold text-[#d4af37] mb-3 tracking-wide"> <h3 className="text-xl font-serif font-semibold text-[var(--luxury-gold)] mb-3 tracking-wide">
Complete Payment with PayPal Complete Payment with PayPal
</h3> </h3>
<p className="text-gray-300/80 font-light text-lg mb-8 tracking-wide"> <p className="text-gray-300/80 font-light text-lg mb-8 tracking-wide">
You will be redirected to PayPal to securely complete your payment of{' '} You will be redirected to PayPal to securely complete your payment of{' '}
<span className="font-semibold text-[#d4af37]"> <span className="font-semibold text-[var(--luxury-gold)]">
{new Intl.NumberFormat('en-US', { {new Intl.NumberFormat('en-US', {
style: 'currency', style: 'currency',
currency: currency, currency: currency,

View File

@@ -75,7 +75,7 @@ const StripePaymentForm: React.FC<StripePaymentFormProps> = ({
if (!stripe || !elements) { if (!stripe || !elements) {
return ( return (
<div className="flex items-center justify-center p-8"> <div className="flex items-center justify-center p-8">
<Loader2 className="w-8 h-8 animate-spin text-[#d4af37]" /> <Loader2 className="w-8 h-8 animate-spin text-[var(--luxury-gold)]" />
<span className="ml-2 text-gray-300">Loading payment form...</span> <span className="ml-2 text-gray-300">Loading payment form...</span>
</div> </div>
); );
@@ -88,12 +88,12 @@ const StripePaymentForm: React.FC<StripePaymentFormProps> = ({
autoComplete="off" autoComplete="off"
// SECURITY: Prevent form caching and autocomplete for payment forms // SECURITY: Prevent form caching and autocomplete for payment forms
> >
<div className="mb-4 p-4 bg-[#d4af37]/10 border border-[#d4af37]/20 rounded-lg"> <div className="mb-4 p-4 bg-[var(--luxury-gold)]/10 border border-[var(--luxury-gold)]/20 rounded-lg">
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<span className="text-sm font-medium text-gray-300"> <span className="text-sm font-medium text-gray-300">
Amount to Pay Amount to Pay
</span> </span>
<span className="text-xl font-bold text-[#d4af37]"> <span className="text-xl font-bold text-[var(--luxury-gold)]">
${amount.toFixed(2)} ${amount.toFixed(2)}
</span> </span>
</div> </div>
@@ -141,8 +141,8 @@ const StripePaymentForm: React.FC<StripePaymentFormProps> = ({
<button <button
type="submit" type="submit"
disabled={isProcessing || !stripe || !elements} disabled={isProcessing || !stripe || !elements}
className="w-full bg-[#d4af37] text-black py-3 px-4 rounded-lg className="w-full bg-[var(--luxury-gold)] text-black py-3 px-4 rounded-lg
hover:bg-[#c9a227] transition-colors font-semibold hover:bg-[var(--luxury-gold-dark)] transition-colors font-semibold
disabled:bg-gray-600 disabled:cursor-not-allowed disabled:text-gray-400 disabled:bg-gray-600 disabled:cursor-not-allowed disabled:text-gray-400
flex items-center justify-center gap-2" flex items-center justify-center gap-2"
> >

View File

@@ -123,16 +123,16 @@ const StripePaymentModal: React.FC<StripePaymentModalProps> = ({
className="fixed inset-0 bg-black/90 backdrop-blur-sm" className="fixed inset-0 bg-black/90 backdrop-blur-sm"
onClick={onClose} onClick={onClose}
/> />
<div className="relative w-full max-w-md max-h-[95vh] bg-gradient-to-br from-[#0a0a0a] via-[#1a1a1a] to-[#0a0a0a] rounded-xl sm:rounded-2xl border border-[#d4af37]/30 shadow-2xl shadow-[#d4af37]/20 overflow-hidden flex flex-col"> <div className="relative w-full max-w-md max-h-[95vh] bg-gradient-to-br from-[#0a0a0a] via-[#1a1a1a] to-[#0a0a0a] rounded-xl sm:rounded-2xl border border-[var(--luxury-gold)]/30 shadow-2xl shadow-[var(--luxury-gold)]/20 overflow-hidden flex flex-col">
{/* Header */} {/* Header */}
<div className="px-3 sm:px-4 md:px-6 py-3 sm:py-4 border-b border-[#d4af37]/20 bg-gradient-to-r from-[#1a1a1a] to-[#0a0a0a] flex-shrink-0"> <div className="px-3 sm:px-4 md:px-6 py-3 sm:py-4 border-b border-[var(--luxury-gold)]/20 bg-gradient-to-r from-[#1a1a1a] to-[#0a0a0a] flex-shrink-0">
<div className="flex items-center justify-between gap-2"> <div className="flex items-center justify-between gap-2">
<h2 className="text-base sm:text-lg md:text-xl font-serif font-bold text-white tracking-tight truncate flex-1"> <h2 className="text-base sm:text-lg md:text-xl font-serif font-bold text-white tracking-tight truncate flex-1">
Complete Payment Complete Payment
</h2> </h2>
<button <button
onClick={onClose} onClick={onClose}
className="p-1.5 sm:p-2 hover:bg-[#d4af37]/10 rounded-lg transition-colors text-gray-400 hover:text-white flex-shrink-0" className="p-1.5 sm:p-2 hover:bg-[var(--luxury-gold)]/10 rounded-lg transition-colors text-gray-400 hover:text-white flex-shrink-0"
> >
<X className="w-4 h-4 sm:w-5 sm:h-5" /> <X className="w-4 h-4 sm:w-5 sm:h-5" />
</button> </button>
@@ -143,7 +143,7 @@ const StripePaymentModal: React.FC<StripePaymentModalProps> = ({
<div className="flex-1 overflow-y-auto p-3 sm:p-4 md:p-6"> <div className="flex-1 overflow-y-auto p-3 sm:p-4 md:p-6">
{loading ? ( {loading ? (
<div className="flex flex-col items-center justify-center py-8 sm:py-12"> <div className="flex flex-col items-center justify-center py-8 sm:py-12">
<Loader2 className="w-10 h-10 sm:w-12 sm:h-12 animate-spin text-[#d4af37] mb-3 sm:mb-4" /> <Loader2 className="w-10 h-10 sm:w-12 sm:h-12 animate-spin text-[var(--luxury-gold)] mb-3 sm:mb-4" />
<p className="text-xs sm:text-sm text-gray-400">Initializing payment...</p> <p className="text-xs sm:text-sm text-gray-400">Initializing payment...</p>
</div> </div>
) : error ? ( ) : error ? (
@@ -171,7 +171,7 @@ const StripePaymentModal: React.FC<StripePaymentModalProps> = ({
</Elements> </Elements>
) : ( ) : (
<div className="flex flex-col items-center justify-center py-8 sm:py-12"> <div className="flex flex-col items-center justify-center py-8 sm:py-12">
<Loader2 className="w-10 h-10 sm:w-12 sm:h-12 animate-spin text-[#d4af37] mb-3 sm:mb-4" /> <Loader2 className="w-10 h-10 sm:w-12 sm:h-12 animate-spin text-[var(--luxury-gold)] mb-3 sm:mb-4" />
<p className="text-xs sm:text-sm text-gray-400">Loading payment form...</p> <p className="text-xs sm:text-sm text-gray-400">Loading payment form...</p>
</div> </div>
)} )}

View File

@@ -143,7 +143,7 @@ const BannerCarousel: React.FC<BannerCarouselProps> = ({
<div className="relative w-full flex flex-col items-center"> <div className="relative w-full flex flex-col items-center">
{} {}
<div <div
className="w-0 h-0.5 bg-gradient-to-r from-transparent via-[#d4af37] to-transparent mb-4 sm:mb-6 opacity-90 className="w-0 h-0.5 bg-gradient-to-r from-transparent via-[var(--luxury-gold)] to-transparent mb-4 sm:mb-6 opacity-90
animate-lineExpand" animate-lineExpand"
style={{ style={{
animation: 'lineExpand 1.2s cubic-bezier(0.4, 0, 0.2, 1) 0.3s forwards', animation: 'lineExpand 1.2s cubic-bezier(0.4, 0, 0.2, 1) 0.3s forwards',
@@ -168,7 +168,7 @@ const BannerCarousel: React.FC<BannerCarouselProps> = ({
}} }}
> >
<span <span
className="bg-gradient-to-b from-white via-white via-[#f5d76e] to-[#d4af37] bg-clip-text text-transparent className="bg-gradient-to-b from-white via-white via-[var(--luxury-gold-light)] to-[var(--luxury-gold)] bg-clip-text text-transparent
animate-gradientShift" animate-gradientShift"
style={{ style={{
backgroundSize: '200% 200%', backgroundSize: '200% 200%',
@@ -201,7 +201,7 @@ const BannerCarousel: React.FC<BannerCarouselProps> = ({
{} {}
<div <div
className="w-0 h-0.5 bg-gradient-to-r from-transparent via-[#d4af37] to-transparent mt-3 sm:mt-4 opacity-90 className="w-0 h-0.5 bg-gradient-to-r from-transparent via-[var(--luxury-gold)] to-transparent mt-3 sm:mt-4 opacity-90
animate-lineExpand" animate-lineExpand"
style={{ style={{
animation: 'lineExpand 1.2s cubic-bezier(0.4, 0, 0.2, 1) 0.9s forwards', animation: 'lineExpand 1.2s cubic-bezier(0.4, 0, 0.2, 1) 0.9s forwards',
@@ -229,7 +229,7 @@ const BannerCarousel: React.FC<BannerCarouselProps> = ({
{[...Array(3)].map((_, i) => ( {[...Array(3)].map((_, i) => (
<div <div
key={i} key={i}
className="absolute w-1 h-1 bg-[#d4af37] rounded-full opacity-40" className="absolute w-1 h-1 bg-[var(--luxury-gold)] rounded-full opacity-40"
style={{ style={{
left: `${20 + i * 30}%`, left: `${20 + i * 30}%`,
top: `${30 + i * 20}%`, top: `${30 + i * 20}%`,
@@ -314,7 +314,7 @@ const BannerCarousel: React.FC<BannerCarouselProps> = ({
transition-all duration-300 cursor-pointer transition-all duration-300 cursor-pointer
${ ${
index === currentIndex index === currentIndex
? 'bg-gradient-to-r from-[#d4af37] to-[#f5d76e] w-8 sm:w-10 shadow-lg shadow-[#d4af37]/50' ? 'bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] w-8 sm:w-10 shadow-lg shadow-[var(--luxury-gold)]/50'
: 'bg-white/40 hover:bg-white/70 w-2 sm:h-2.5 hover:scale-125' : 'bg-white/40 hover:bg-white/70 w-2 sm:h-2.5 hover:scale-125'
}`} }`}
aria-label={`Go to banner ${index + 1}`} aria-label={`Go to banner ${index + 1}`}

View File

@@ -77,9 +77,9 @@ const Pagination: React.FC<PaginationProps> = ({
<button <button
onClick={() => handlePageChange(currentPage - 1)} onClick={() => handlePageChange(currentPage - 1)}
disabled={currentPage === 1} disabled={currentPage === 1}
className="px-4 py-2 border border-[#d4af37]/30 className="px-4 py-2 border border-[var(--luxury-gold)]/30
rounded-lg bg-[#0a0a0a] text-gray-300 rounded-lg bg-[#0a0a0a] text-gray-300
hover:bg-[#1a1a1a] hover:border-[#d4af37] hover:text-[#d4af37] hover:bg-[#1a1a1a] hover:border-[var(--luxury-gold)] hover:text-[var(--luxury-gold)]
disabled:opacity-50 disabled:cursor-not-allowed disabled:opacity-50 disabled:cursor-not-allowed
transition-all duration-300 font-medium tracking-wide" transition-all duration-300 font-medium tracking-wide"
aria-label="Previous page" aria-label="Previous page"
@@ -110,8 +110,8 @@ const Pagination: React.FC<PaginationProps> = ({
className={`px-5 py-2 rounded-lg transition-all duration-300 className={`px-5 py-2 rounded-lg transition-all duration-300
font-medium tracking-wide ${ font-medium tracking-wide ${
isActive isActive
? 'bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-[#0f0f0f] shadow-lg shadow-[#d4af37]/30' ? 'bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-[#0f0f0f] shadow-lg shadow-[var(--luxury-gold)]/30'
: 'border border-[#d4af37]/30 bg-[#0a0a0a] text-gray-300 hover:bg-[#1a1a1a] hover:border-[#d4af37] hover:text-[#d4af37]' : 'border border-[var(--luxury-gold)]/30 bg-[#0a0a0a] text-gray-300 hover:bg-[#1a1a1a] hover:border-[var(--luxury-gold)] hover:text-[var(--luxury-gold)]'
}`} }`}
aria-label={`Page ${pageNum}`} aria-label={`Page ${pageNum}`}
aria-current={isActive ? 'page' : undefined} aria-current={isActive ? 'page' : undefined}
@@ -125,9 +125,9 @@ const Pagination: React.FC<PaginationProps> = ({
<button <button
onClick={() => handlePageChange(currentPage + 1)} onClick={() => handlePageChange(currentPage + 1)}
disabled={currentPage === totalPages} disabled={currentPage === totalPages}
className="px-4 py-2 border border-[#d4af37]/30 className="px-4 py-2 border border-[var(--luxury-gold)]/30
rounded-lg bg-[#0a0a0a] text-gray-300 rounded-lg bg-[#0a0a0a] text-gray-300
hover:bg-[#1a1a1a] hover:border-[#d4af37] hover:text-[#d4af37] hover:bg-[#1a1a1a] hover:border-[var(--luxury-gold)] hover:text-[var(--luxury-gold)]
disabled:opacity-50 disabled:cursor-not-allowed disabled:opacity-50 disabled:cursor-not-allowed
transition-all duration-300 font-medium tracking-wide" transition-all duration-300 font-medium tracking-wide"
aria-label="Next page" aria-label="Next page"

View File

@@ -71,7 +71,7 @@ const RatingStars: React.FC<RatingStarsProps> = ({
<Star <Star
className={`${sizeClasses[size]} ${ className={`${sizeClasses[size]} ${
isFilled isFilled
? 'text-[#d4af37] fill-[#d4af37]' ? 'text-[var(--luxury-gold)] fill-[var(--luxury-gold)]'
: 'text-gray-500' : 'text-gray-500'
}`} }`}
/> />

View File

@@ -184,13 +184,13 @@ const ReviewSection: React.FC<ReviewSectionProps> = ({
return ( return (
<div className="space-y-4"> <div className="space-y-4">
{} {}
<div className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-lg border border-[#d4af37]/20 p-3 sm:p-4 backdrop-blur-xl shadow-lg shadow-[#d4af37]/5"> <div className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-lg border border-[var(--luxury-gold)]/20 p-3 sm:p-4 backdrop-blur-xl shadow-lg shadow-[var(--luxury-gold)]/5">
<h3 className="text-sm sm:text-base font-serif font-semibold text-white mb-3 tracking-wide"> <h3 className="text-sm sm:text-base font-serif font-semibold text-white mb-3 tracking-wide">
Customer Reviews Customer Reviews
</h3> </h3>
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<div className="text-center"> <div className="text-center">
<div className="text-2xl sm:text-3xl font-serif font-bold bg-gradient-to-r from-[#d4af37] to-[#f5d76e] bg-clip-text text-transparent"> <div className="text-2xl sm:text-3xl font-serif font-bold bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] bg-clip-text text-transparent">
{totalReviews > 0 && averageRating > 0 {totalReviews > 0 && averageRating > 0
? averageRating.toFixed(1) ? averageRating.toFixed(1)
: totalReviews === 0 : totalReviews === 0
@@ -214,7 +214,7 @@ const ReviewSection: React.FC<ReviewSectionProps> = ({
{} {}
{isAuthenticated ? ( {isAuthenticated ? (
<div className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-lg border border-[#d4af37]/20 p-3 sm:p-4 backdrop-blur-xl shadow-lg shadow-[#d4af37]/5"> <div className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-lg border border-[var(--luxury-gold)]/20 p-3 sm:p-4 backdrop-blur-xl shadow-lg shadow-[var(--luxury-gold)]/5">
<h4 className="text-xs sm:text-sm font-serif font-semibold text-white mb-3 tracking-wide"> <h4 className="text-xs sm:text-sm font-serif font-semibold text-white mb-3 tracking-wide">
Write Your Review Write Your Review
</h4> </h4>
@@ -263,9 +263,9 @@ const ReviewSection: React.FC<ReviewSectionProps> = ({
id="comment" id="comment"
rows={3} rows={3}
className="w-full px-2.5 py-1.5 bg-[#0a0a0a] border className="w-full px-2.5 py-1.5 bg-[#0a0a0a] border
border-[#d4af37]/20 rounded-lg text-white placeholder-gray-500 text-xs sm:text-sm border-[var(--luxury-gold)]/20 rounded-lg text-white placeholder-gray-500 text-xs sm:text-sm
focus:ring-2 focus:ring-[#d4af37]/50 focus:ring-2 focus:ring-[var(--luxury-gold)]/50
focus:border-[#d4af37] transition-all duration-300 focus:border-[var(--luxury-gold)] transition-all duration-300
font-light tracking-wide resize-none" font-light tracking-wide resize-none"
placeholder="Share your experience..." placeholder="Share your experience..."
/> />
@@ -292,27 +292,27 @@ const ReviewSection: React.FC<ReviewSectionProps> = ({
<button <button
type="submit" type="submit"
disabled={submitting} disabled={submitting}
className="px-4 py-2 bg-gradient-to-r from-[#d4af37] to-[#c9a227] className="px-4 py-2 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]
text-[#0f0f0f] rounded-sm hover:from-[#f5d76e] hover:to-[#d4af37] text-[#0f0f0f] rounded-sm hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)]
disabled:bg-gray-800 disabled:text-gray-500 disabled:bg-gray-800 disabled:text-gray-500
disabled:cursor-not-allowed disabled:cursor-not-allowed
transition-all duration-300 font-medium text-xs sm:text-sm transition-all duration-300 font-medium text-xs sm:text-sm
shadow-sm shadow-[#d4af37]/30 tracking-wide" shadow-sm shadow-[var(--luxury-gold)]/30 tracking-wide"
> >
{submitting ? 'Submitting...' : 'Submit Review'} {submitting ? 'Submitting...' : 'Submit Review'}
</button> </button>
</form> </form>
</div> </div>
) : ( ) : (
<div className="bg-gradient-to-br from-[#d4af37]/10 to-[#c9a227]/5 border border-[#d4af37]/30 <div className="bg-gradient-to-br from-[var(--luxury-gold)]/10 to-[var(--luxury-gold-dark)]/5 border border-[var(--luxury-gold)]/30
rounded-lg p-3 sm:p-4 text-center backdrop-blur-sm" rounded-lg p-3 sm:p-4 text-center backdrop-blur-sm"
> >
<p className="text-[#d4af37] text-xs sm:text-sm font-light"> <p className="text-[var(--luxury-gold)] text-xs sm:text-sm font-light">
Please{' '} Please{' '}
<button <button
onClick={() => openModal('login')} onClick={() => openModal('login')}
className="font-semibold underline className="font-semibold underline
hover:text-[#f5d76e] transition-colors" hover:text-[var(--luxury-gold-light)] transition-colors"
> >
login login
</button>{' '} </button>{' '}
@@ -332,7 +332,7 @@ const ReviewSection: React.FC<ReviewSectionProps> = ({
{Array.from({ length: 3 }).map((_, index) => ( {Array.from({ length: 3 }).map((_, index) => (
<div <div
key={index} key={index}
className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-lg border border-[#d4af37]/20 p-3 className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-lg border border-[var(--luxury-gold)]/20 p-3
animate-pulse" animate-pulse"
> >
<div className="h-3 bg-gray-700 <div className="h-3 bg-gray-700
@@ -345,7 +345,7 @@ const ReviewSection: React.FC<ReviewSectionProps> = ({
))} ))}
</div> </div>
) : reviews.length === 0 ? ( ) : reviews.length === 0 ? (
<div className="text-center py-6 sm:py-8 bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-lg border border-[#d4af37]/20 p-4" <div className="text-center py-6 sm:py-8 bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-lg border border-[var(--luxury-gold)]/20 p-4"
> >
<p className="text-gray-300 text-sm sm:text-base font-light"> <p className="text-gray-300 text-sm sm:text-base font-light">
No reviews yet No reviews yet
@@ -359,8 +359,8 @@ const ReviewSection: React.FC<ReviewSectionProps> = ({
{reviews.map((review) => ( {reviews.map((review) => (
<div <div
key={review.id} key={review.id}
className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-lg border border-[#d4af37]/20 className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-lg border border-[var(--luxury-gold)]/20
p-3 sm:p-4 backdrop-blur-xl shadow-sm shadow-[#d4af37]/5" p-3 sm:p-4 backdrop-blur-xl shadow-sm shadow-[var(--luxury-gold)]/5"
> >
<div className="flex items-start <div className="flex items-start
justify-between mb-2" justify-between mb-2"

View File

@@ -75,8 +75,8 @@ const RoomCard: React.FC<RoomCardProps> = ({ room, compact = false }) => {
className={`luxury-card overflow-hidden group h-full flex flex-col className={`luxury-card overflow-hidden group h-full flex flex-col
border-t-2 transition-all duration-300 border-t-2 transition-all duration-300
${room.featured ${room.featured
? 'border-[#d4af37] shadow-lg shadow-[#d4af37]/20 hover:border-[#d4af37] hover:shadow-luxury-gold' ? 'border-[var(--luxury-gold)] shadow-lg shadow-[var(--luxury-gold)]/20 hover:border-[var(--luxury-gold)] hover:shadow-luxury-gold'
: 'border-transparent hover:border-[#d4af37] hover:shadow-luxury-gold' : 'border-transparent hover:border-[var(--luxury-gold)] hover:shadow-luxury-gold'
}`} }`}
> >
{} {}
@@ -112,10 +112,10 @@ const RoomCard: React.FC<RoomCardProps> = ({ room, compact = false }) => {
{room.featured && ( {room.featured && (
<div <div
className="absolute top-3 left-3 z-20 className="absolute top-3 left-3 z-20
bg-gradient-to-r from-[#d4af37] to-[#c9a227] bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]
text-[#0f0f0f] px-3 py-1.5 text-[#0f0f0f] px-3 py-1.5
rounded-sm text-xs font-medium tracking-wide rounded-sm text-xs font-medium tracking-wide
shadow-lg shadow-[#d4af37]/30 backdrop-blur-sm shadow-lg shadow-[var(--luxury-gold)]/30 backdrop-blur-sm
flex items-center gap-1.5" flex items-center gap-1.5"
> >
<Crown className="w-4 h-4 fill-[#0f0f0f] text-[#0f0f0f]" /> <Crown className="w-4 h-4 fill-[#0f0f0f] text-[#0f0f0f]" />
@@ -153,7 +153,7 @@ const RoomCard: React.FC<RoomCardProps> = ({ room, compact = false }) => {
{room.featured && ( {room.featured && (
<Crown <Crown
className={`${compact ? 'w-4 h-4' : 'w-5 h-5'} className={`${compact ? 'w-4 h-4' : 'w-5 h-5'}
text-[#d4af37] fill-[#d4af37] text-[var(--luxury-gold)] fill-[var(--luxury-gold)]
drop-shadow-lg animate-pulse`} drop-shadow-lg animate-pulse`}
/> />
)} )}
@@ -165,7 +165,7 @@ const RoomCard: React.FC<RoomCardProps> = ({ room, compact = false }) => {
className={`flex items-center text-gray-600 font-light tracking-wide className={`flex items-center text-gray-600 font-light tracking-wide
${compact ? 'text-xs mb-1.5' : 'text-xs sm:text-sm mb-2'}`} ${compact ? 'text-xs mb-1.5' : 'text-xs sm:text-sm mb-2'}`}
> >
<MapPin className={`${compact ? 'w-3 h-3' : 'w-4 h-4'} mr-1.5 text-[#d4af37]`} /> <MapPin className={`${compact ? 'w-3 h-3' : 'w-4 h-4'} mr-1.5 text-[var(--luxury-gold)]`} />
<span> <span>
Room {room.room_number} - Floor {room.floor} Room {room.room_number} - Floor {room.floor}
</span> </span>
@@ -182,7 +182,7 @@ const RoomCard: React.FC<RoomCardProps> = ({ room, compact = false }) => {
{} {}
<div className={`flex items-center justify-between ${compact ? 'mb-1.5' : 'mb-3'}`}> <div className={`flex items-center justify-between ${compact ? 'mb-1.5' : 'mb-3'}`}>
<div className="flex items-center text-gray-700"> <div className="flex items-center text-gray-700">
<Users className={`${compact ? 'w-3 h-3' : 'w-4 h-4'} mr-1.5 text-[#d4af37]`} /> <Users className={`${compact ? 'w-3 h-3' : 'w-4 h-4'} mr-1.5 text-[var(--luxury-gold)]`} />
<span className={`font-light tracking-wide ${compact ? 'text-xs' : 'text-sm'}`}> <span className={`font-light tracking-wide ${compact ? 'text-xs' : 'text-sm'}`}>
{room.capacity || roomType.capacity} guests {room.capacity || roomType.capacity} guests
</span> </span>
@@ -191,7 +191,7 @@ const RoomCard: React.FC<RoomCardProps> = ({ room, compact = false }) => {
{room.average_rating != null && ( {room.average_rating != null && (
<div className="flex items-center"> <div className="flex items-center">
<Star <Star
className={`${compact ? 'w-3 h-3' : 'w-4 h-4'} text-[#d4af37] mr-1`} className={`${compact ? 'w-3 h-3' : 'w-4 h-4'} text-[var(--luxury-gold)] mr-1`}
fill="#d4af37" fill="#d4af37"
/> />
<span className={`font-semibold text-gray-900 ${compact ? 'text-xs' : 'text-sm'}`}> <span className={`font-semibold text-gray-900 ${compact ? 'text-xs' : 'text-sm'}`}>
@@ -213,13 +213,13 @@ const RoomCard: React.FC<RoomCardProps> = ({ room, compact = false }) => {
<div <div
key={index} key={index}
className="flex items-center gap-1 className="flex items-center gap-1
text-gray-700 text-xs bg-[#d4af37]/10 text-gray-700 text-xs bg-[var(--luxury-gold)]/10
border border-[#d4af37]/20 border border-[var(--luxury-gold)]/20
px-2 sm:px-2.5 py-1 sm:py-1.5 rounded-sm px-2 sm:px-2.5 py-1 sm:py-1.5 rounded-sm
font-light tracking-wide" font-light tracking-wide"
title={amenity} title={amenity}
> >
<span className="text-[#d4af37]"> <span className="text-[var(--luxury-gold)]">
{amenityIcons[amenity.toLowerCase()] || {amenityIcons[amenity.toLowerCase()] ||
<span></span>} <span></span>}
</span> </span>

View File

@@ -4,8 +4,8 @@ const RoomCardSkeleton: React.FC = () => {
return ( return (
<div <div
className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a]
rounded-xl border border-[#d4af37]/20 rounded-xl border border-[var(--luxury-gold)]/20
overflow-hidden animate-pulse shadow-lg shadow-[#d4af37]/5" overflow-hidden animate-pulse shadow-lg shadow-[var(--luxury-gold)]/5"
> >
{} {}
<div className="h-40 sm:h-44 md:h-48 lg:h-52 bg-gradient-to-br from-gray-800 to-gray-900" /> <div className="h-40 sm:h-44 md:h-48 lg:h-52 bg-gradient-to-br from-gray-800 to-gray-900" />
@@ -40,7 +40,7 @@ const RoomCardSkeleton: React.FC = () => {
{} {}
<div <div
className="flex items-center justify-between className="flex items-center justify-between
pt-3 border-t border-[#d4af37]/20" pt-3 border-t border-[var(--luxury-gold)]/20"
> >
<div> <div>
<div className="h-3 bg-gray-800 rounded w-12 mb-1" /> <div className="h-3 bg-gray-800 rounded w-12 mb-1" />

View File

@@ -150,11 +150,11 @@ const RoomCarousel: React.FC<RoomCarouselProps> = ({
disabled={isAnimating || currentIndex === 0} disabled={isAnimating || currentIndex === 0}
className="absolute left-0 top-1/2 -translate-y-1/2 -translate-x-2 sm:-translate-x-4 className="absolute left-0 top-1/2 -translate-y-1/2 -translate-x-2 sm:-translate-x-4
z-10 w-8 h-8 sm:w-9 sm:h-9 z-10 w-8 h-8 sm:w-9 sm:h-9
bg-gradient-to-r from-[#d4af37] to-[#c9a227] bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]
text-white rounded-full text-white rounded-full
flex items-center justify-center flex items-center justify-center
shadow-lg shadow-[#d4af37]/40 shadow-lg shadow-[var(--luxury-gold)]/40
hover:shadow-xl hover:shadow-[#d4af37]/50 hover:shadow-xl hover:shadow-[var(--luxury-gold)]/50
hover:scale-110 hover:scale-110
active:scale-95 active:scale-95
transition-all duration-300 transition-all duration-300
@@ -170,11 +170,11 @@ const RoomCarousel: React.FC<RoomCarouselProps> = ({
disabled={isAnimating || currentIndex >= rooms.length - 1} disabled={isAnimating || currentIndex >= rooms.length - 1}
className="absolute right-0 top-1/2 -translate-y-1/2 translate-x-2 sm:translate-x-4 className="absolute right-0 top-1/2 -translate-y-1/2 translate-x-2 sm:translate-x-4
z-10 w-8 h-8 sm:w-9 sm:h-9 z-10 w-8 h-8 sm:w-9 sm:h-9
bg-gradient-to-r from-[#d4af37] to-[#c9a227] bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]
text-white rounded-full text-white rounded-full
flex items-center justify-center flex items-center justify-center
shadow-lg shadow-[#d4af37]/40 shadow-lg shadow-[var(--luxury-gold)]/40
hover:shadow-xl hover:shadow-[#d4af37]/50 hover:shadow-xl hover:shadow-[var(--luxury-gold)]/50
hover:scale-110 hover:scale-110
active:scale-95 active:scale-95
transition-all duration-300 transition-all duration-300
@@ -198,8 +198,8 @@ const RoomCarousel: React.FC<RoomCarouselProps> = ({
className={`transition-all duration-300 rounded-full className={`transition-all duration-300 rounded-full
${ ${
index === currentIndex index === currentIndex
? 'w-6 h-1.5 sm:w-7 sm:h-2 bg-gradient-to-r from-[#d4af37] to-[#c9a227] shadow-lg shadow-[#d4af37]/40' ? 'w-6 h-1.5 sm:w-7 sm:h-2 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] shadow-lg shadow-[var(--luxury-gold)]/40'
: 'w-1.5 h-1.5 sm:w-2 sm:h-2 bg-gray-300 hover:bg-[#d4af37]/50' : 'w-1.5 h-1.5 sm:w-2 sm:h-2 bg-gray-300 hover:bg-[var(--luxury-gold)]/50'
} }
disabled:cursor-not-allowed disabled:cursor-not-allowed
`} `}

View File

@@ -250,14 +250,14 @@ const RoomFilter: React.FC<RoomFilterProps> = ({ onFilterChange }) => {
return ( return (
<div className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] <div className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a]
rounded-xl border border-[#d4af37]/30 rounded-xl border border-[var(--luxury-gold)]/30
backdrop-blur-xl shadow-2xl shadow-[#d4af37]/10 backdrop-blur-xl shadow-2xl shadow-[var(--luxury-gold)]/10
p-4 sm:p-5 md:p-6" p-4 sm:p-5 md:p-6"
> >
<div className="flex items-center gap-2 sm:gap-3 mb-4 sm:mb-5 md:mb-6"> <div className="flex items-center gap-2 sm:gap-3 mb-4 sm:mb-5 md:mb-6">
<div className="p-1.5 sm:p-2 bg-[#d4af37]/10 rounded-lg <div className="p-1.5 sm:p-2 bg-[var(--luxury-gold)]/10 rounded-lg
border border-[#d4af37]/30"> border border-[var(--luxury-gold)]/30">
<svg className="w-4 h-4 sm:w-5 sm:h-5 text-[#d4af37]" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <svg className="w-4 h-4 sm:w-5 sm:h-5 text-[var(--luxury-gold)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z" /> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z" />
</svg> </svg>
</div> </div>
@@ -282,12 +282,12 @@ const RoomFilter: React.FC<RoomFilterProps> = ({ onFilterChange }) => {
value={filters.type || ''} value={filters.type || ''}
onChange={handleInputChange} onChange={handleInputChange}
className="w-full px-4 py-3.5 bg-[#1a1a1a] border-2 className="w-full px-4 py-3.5 bg-[#1a1a1a] border-2
border-[#d4af37]/30 rounded-lg text-white text-base border-[var(--luxury-gold)]/30 rounded-lg text-white text-base
placeholder-gray-400 focus:ring-2 placeholder-gray-400 focus:ring-2
focus:ring-[#d4af37]/60 focus:border-[#d4af37] focus:ring-[var(--luxury-gold)]/60 focus:border-[var(--luxury-gold)]
transition-all duration-300 font-normal tracking-wide transition-all duration-300 font-normal tracking-wide
appearance-none cursor-pointer appearance-none cursor-pointer
hover:border-[#d4af37]/50" hover:border-[var(--luxury-gold)]/50"
> >
<option value="" className="bg-[#1a1a1a] text-white">All Room Types</option> <option value="" className="bg-[#1a1a1a] text-white">All Room Types</option>
<option value="Standard Room" className="bg-[#1a1a1a] text-white">Standard Room</option> <option value="Standard Room" className="bg-[#1a1a1a] text-white">Standard Room</option>
@@ -297,7 +297,7 @@ const RoomFilter: React.FC<RoomFilterProps> = ({ onFilterChange }) => {
<option value="Twin Room" className="bg-[#1a1a1a] text-white">Twin Room</option> <option value="Twin Room" className="bg-[#1a1a1a] text-white">Twin Room</option>
</select> </select>
<div className="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none"> <div className="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none">
<svg className="w-5 h-5 text-[#d4af37]" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <svg className="w-5 h-5 text-[var(--luxury-gold)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" /> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
</svg> </svg>
</div> </div>
@@ -311,7 +311,7 @@ const RoomFilter: React.FC<RoomFilterProps> = ({ onFilterChange }) => {
htmlFor="from" htmlFor="from"
className="block text-sm font-medium text-gray-200 mb-2 tracking-wide flex items-center gap-2" className="block text-sm font-medium text-gray-200 mb-2 tracking-wide flex items-center gap-2"
> >
<Calendar className="w-4 h-4 text-[#d4af37]" /> <Calendar className="w-4 h-4 text-[var(--luxury-gold)]" />
Check-in Date Check-in Date
</label> </label>
<div className="relative"> <div className="relative">
@@ -331,11 +331,11 @@ const RoomFilter: React.FC<RoomFilterProps> = ({ onFilterChange }) => {
dateFormat="dd/MM/yyyy" dateFormat="dd/MM/yyyy"
placeholderText="Select check-in" placeholderText="Select check-in"
className="w-full px-4 py-3.5 pl-11 bg-[#1a1a1a] border-2 className="w-full px-4 py-3.5 pl-11 bg-[#1a1a1a] border-2
border-[#d4af37]/30 rounded-lg text-white text-base border-[var(--luxury-gold)]/30 rounded-lg text-white text-base
placeholder-gray-400 focus:ring-2 placeholder-gray-400 focus:ring-2
focus:ring-[#d4af37]/60 focus:border-[#d4af37] focus:ring-[var(--luxury-gold)]/60 focus:border-[var(--luxury-gold)]
transition-all duration-300 font-normal tracking-wide transition-all duration-300 font-normal tracking-wide
hover:border-[#d4af37]/50" hover:border-[var(--luxury-gold)]/50"
wrapperClassName="w-full" wrapperClassName="w-full"
/> />
{checkInDate && ( {checkInDate && (
@@ -349,13 +349,13 @@ const RoomFilter: React.FC<RoomFilterProps> = ({ onFilterChange }) => {
} }
}} }}
className="absolute right-3 top-1/2 -translate-y-1/2 className="absolute right-3 top-1/2 -translate-y-1/2
text-gray-400 hover:text-[#d4af37] transition-colors" text-gray-400 hover:text-[var(--luxury-gold)] transition-colors"
> >
<X className="w-4 h-4" /> <X className="w-4 h-4" />
</button> </button>
)} )}
<Calendar className="absolute left-3 top-1/2 -translate-y-1/2 <Calendar className="absolute left-3 top-1/2 -translate-y-1/2
w-5 h-5 text-[#d4af37] pointer-events-none" /> w-5 h-5 text-[var(--luxury-gold)] pointer-events-none" />
</div> </div>
</div> </div>
@@ -364,7 +364,7 @@ const RoomFilter: React.FC<RoomFilterProps> = ({ onFilterChange }) => {
htmlFor="to" htmlFor="to"
className="block text-sm font-medium text-gray-200 mb-2 tracking-wide flex items-center gap-2" className="block text-sm font-medium text-gray-200 mb-2 tracking-wide flex items-center gap-2"
> >
<Calendar className="w-4 h-4 text-[#d4af37]" /> <Calendar className="w-4 h-4 text-[var(--luxury-gold)]" />
Check-out Date Check-out Date
</label> </label>
<div className="relative"> <div className="relative">
@@ -383,11 +383,11 @@ const RoomFilter: React.FC<RoomFilterProps> = ({ onFilterChange }) => {
dateFormat="dd/MM/yyyy" dateFormat="dd/MM/yyyy"
placeholderText={checkInDate ? "Select check-out" : "Select check-in first"} placeholderText={checkInDate ? "Select check-out" : "Select check-in first"}
className="w-full px-4 py-3.5 pl-11 bg-[#1a1a1a] border-2 className="w-full px-4 py-3.5 pl-11 bg-[#1a1a1a] border-2
border-[#d4af37]/30 rounded-lg text-white text-base border-[var(--luxury-gold)]/30 rounded-lg text-white text-base
placeholder-gray-400 focus:ring-2 placeholder-gray-400 focus:ring-2
focus:ring-[#d4af37]/60 focus:border-[#d4af37] focus:ring-[var(--luxury-gold)]/60 focus:border-[var(--luxury-gold)]
transition-all duration-300 font-normal tracking-wide transition-all duration-300 font-normal tracking-wide
hover:border-[#d4af37]/50 hover:border-[var(--luxury-gold)]/50
disabled:opacity-50 disabled:cursor-not-allowed" disabled:opacity-50 disabled:cursor-not-allowed"
wrapperClassName="w-full" wrapperClassName="w-full"
/> />
@@ -399,13 +399,13 @@ const RoomFilter: React.FC<RoomFilterProps> = ({ onFilterChange }) => {
setCheckOutDate(null); setCheckOutDate(null);
}} }}
className="absolute right-3 top-1/2 -translate-y-1/2 className="absolute right-3 top-1/2 -translate-y-1/2
text-gray-400 hover:text-[#d4af37] transition-colors" text-gray-400 hover:text-[var(--luxury-gold)] transition-colors"
> >
<X className="w-4 h-4" /> <X className="w-4 h-4" />
</button> </button>
)} )}
<Calendar className="absolute left-3 top-1/2 -translate-y-1/2 <Calendar className="absolute left-3 top-1/2 -translate-y-1/2
w-5 h-5 text-[#d4af37] pointer-events-none" /> w-5 h-5 text-[var(--luxury-gold)] pointer-events-none" />
</div> </div>
{checkInDate && !checkOutDate && ( {checkInDate && !checkOutDate && (
<p className="mt-1.5 text-xs text-gray-400 font-light"> <p className="mt-1.5 text-xs text-gray-400 font-light">
@@ -418,7 +418,7 @@ const RoomFilter: React.FC<RoomFilterProps> = ({ onFilterChange }) => {
{} {}
<div> <div>
<label className="block text-sm font-medium text-gray-200 mb-3 tracking-wide flex items-center gap-2"> <label className="block text-sm font-medium text-gray-200 mb-3 tracking-wide flex items-center gap-2">
<DollarSign className="w-4 h-4 text-[#d4af37]" /> <DollarSign className="w-4 h-4 text-[var(--luxury-gold)]" />
Price Range Price Range
</label> </label>
<div className="grid grid-cols-2 gap-4"> <div className="grid grid-cols-2 gap-4">
@@ -432,7 +432,7 @@ const RoomFilter: React.FC<RoomFilterProps> = ({ onFilterChange }) => {
</label> </label>
<div className="relative"> <div className="relative">
<DollarSign className="absolute left-3 top-1/2 -translate-y-1/2 <DollarSign className="absolute left-3 top-1/2 -translate-y-1/2
w-4 h-4 text-[#d4af37] pointer-events-none" /> w-4 h-4 text-[var(--luxury-gold)] pointer-events-none" />
<input <input
type="text" type="text"
id="minPrice" id="minPrice"
@@ -447,11 +447,11 @@ const RoomFilter: React.FC<RoomFilterProps> = ({ onFilterChange }) => {
inputMode="numeric" inputMode="numeric"
pattern="[0-9.]*" pattern="[0-9.]*"
className="w-full px-4 py-3.5 pl-10 bg-[#1a1a1a] border-2 className="w-full px-4 py-3.5 pl-10 bg-[#1a1a1a] border-2
border-[#d4af37]/30 rounded-lg text-white text-base border-[var(--luxury-gold)]/30 rounded-lg text-white text-base
placeholder-gray-400 focus:ring-2 placeholder-gray-400 focus:ring-2
focus:ring-[#d4af37]/60 focus:border-[#d4af37] focus:ring-[var(--luxury-gold)]/60 focus:border-[var(--luxury-gold)]
transition-all duration-300 font-normal tracking-wide transition-all duration-300 font-normal tracking-wide
hover:border-[#d4af37]/50" hover:border-[var(--luxury-gold)]/50"
/> />
</div> </div>
</div> </div>
@@ -465,7 +465,7 @@ const RoomFilter: React.FC<RoomFilterProps> = ({ onFilterChange }) => {
</label> </label>
<div className="relative"> <div className="relative">
<DollarSign className="absolute left-3 top-1/2 -translate-y-1/2 <DollarSign className="absolute left-3 top-1/2 -translate-y-1/2
w-4 h-4 text-[#d4af37] pointer-events-none" /> w-4 h-4 text-[var(--luxury-gold)] pointer-events-none" />
<input <input
type="text" type="text"
id="maxPrice" id="maxPrice"
@@ -480,11 +480,11 @@ const RoomFilter: React.FC<RoomFilterProps> = ({ onFilterChange }) => {
inputMode="numeric" inputMode="numeric"
pattern="[0-9.]*" pattern="[0-9.]*"
className="w-full px-4 py-3.5 pl-10 bg-[#1a1a1a] border-2 className="w-full px-4 py-3.5 pl-10 bg-[#1a1a1a] border-2
border-[#d4af37]/30 rounded-lg text-white text-base border-[var(--luxury-gold)]/30 rounded-lg text-white text-base
placeholder-gray-400 focus:ring-2 placeholder-gray-400 focus:ring-2
focus:ring-[#d4af37]/60 focus:border-[#d4af37] focus:ring-[var(--luxury-gold)]/60 focus:border-[var(--luxury-gold)]
transition-all duration-300 font-normal tracking-wide transition-all duration-300 font-normal tracking-wide
hover:border-[#d4af37]/50" hover:border-[var(--luxury-gold)]/50"
/> />
</div> </div>
</div> </div>
@@ -498,12 +498,12 @@ const RoomFilter: React.FC<RoomFilterProps> = ({ onFilterChange }) => {
className="block text-sm font-medium className="block text-sm font-medium
text-gray-200 mb-2 tracking-wide flex items-center gap-2" text-gray-200 mb-2 tracking-wide flex items-center gap-2"
> >
<Users className="w-4 h-4 text-[#d4af37]" /> <Users className="w-4 h-4 text-[var(--luxury-gold)]" />
Number of Guests Number of Guests
</label> </label>
<div className="relative"> <div className="relative">
<Users className="absolute left-3 top-1/2 -translate-y-1/2 <Users className="absolute left-3 top-1/2 -translate-y-1/2
w-5 h-5 text-[#d4af37] pointer-events-none" /> w-5 h-5 text-[var(--luxury-gold)] pointer-events-none" />
<input <input
type="number" type="number"
id="capacity" id="capacity"
@@ -514,11 +514,11 @@ const RoomFilter: React.FC<RoomFilterProps> = ({ onFilterChange }) => {
min="1" min="1"
max="10" max="10"
className="w-full px-4 py-3.5 pl-11 bg-[#1a1a1a] border-2 className="w-full px-4 py-3.5 pl-11 bg-[#1a1a1a] border-2
border-[#d4af37]/30 rounded-lg text-white text-base border-[var(--luxury-gold)]/30 rounded-lg text-white text-base
placeholder-gray-400 focus:ring-2 placeholder-gray-400 focus:ring-2
focus:ring-[#d4af37]/60 focus:border-[#d4af37] focus:ring-[var(--luxury-gold)]/60 focus:border-[var(--luxury-gold)]
transition-all duration-300 font-normal tracking-wide transition-all duration-300 font-normal tracking-wide
hover:border-[#d4af37]/50 hover:border-[var(--luxury-gold)]/50
[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none
[&::-webkit-inner-spin-button]:appearance-none" [&::-webkit-inner-spin-button]:appearance-none"
/> />
@@ -532,29 +532,29 @@ const RoomFilter: React.FC<RoomFilterProps> = ({ onFilterChange }) => {
</label> </label>
{availableAmenities.length === 0 ? ( {availableAmenities.length === 0 ? (
<div className="text-sm text-gray-400 font-light bg-[#1a1a1a]/50 <div className="text-sm text-gray-400 font-light bg-[#1a1a1a]/50
border border-[#d4af37]/20 rounded-lg px-4 py-3"> border border-[var(--luxury-gold)]/20 rounded-lg px-4 py-3">
Loading amenities... Loading amenities...
</div> </div>
) : ( ) : (
<div className="bg-[#1a1a1a]/50 border border-[#d4af37]/20 rounded-lg p-3 <div className="bg-[#1a1a1a]/50 border border-[var(--luxury-gold)]/20 rounded-lg p-3
max-h-48 overflow-y-auto custom-scrollbar space-y-2"> max-h-48 overflow-y-auto custom-scrollbar space-y-2">
{availableAmenities.map((amenity) => ( {availableAmenities.map((amenity) => (
<label <label
key={amenity} key={amenity}
className="flex items-center gap-3 text-sm w-full font-normal tracking-wide className="flex items-center gap-3 text-sm w-full font-normal tracking-wide
hover:text-[#d4af37] transition-colors cursor-pointer hover:text-[var(--luxury-gold)] transition-colors cursor-pointer
text-gray-200 group" text-gray-200 group"
> >
<input <input
type="checkbox" type="checkbox"
checked={selectedAmenities.includes(amenity)} checked={selectedAmenities.includes(amenity)}
onChange={() => toggleAmenity(amenity)} onChange={() => toggleAmenity(amenity)}
className="h-5 w-5 accent-[#d4af37] cursor-pointer className="h-5 w-5 accent-[var(--luxury-gold)] cursor-pointer
border-2 border-[#d4af37]/30 rounded border-2 border-[var(--luxury-gold)]/30 rounded
checked:bg-[#d4af37] checked:border-[#d4af37] checked:bg-[var(--luxury-gold)] checked:border-[var(--luxury-gold)]
group-hover:border-[#d4af37] transition-all" group-hover:border-[var(--luxury-gold)] transition-all"
/> />
<span className="flex-1 group-hover:text-[#d4af37] transition-colors"> <span className="flex-1 group-hover:text-[var(--luxury-gold)] transition-colors">
{amenity} {amenity}
</span> </span>
</label> </label>
@@ -562,7 +562,7 @@ const RoomFilter: React.FC<RoomFilterProps> = ({ onFilterChange }) => {
</div> </div>
)} )}
{selectedAmenities.length > 0 && ( {selectedAmenities.length > 0 && (
<p className="mt-2 text-xs text-[#d4af37] font-light"> <p className="mt-2 text-xs text-[var(--luxury-gold)] font-light">
{selectedAmenities.length} amenit{selectedAmenities.length === 1 ? 'y' : 'ies'} selected {selectedAmenities.length} amenit{selectedAmenities.length === 1 ? 'y' : 'ies'} selected
</p> </p>
)} )}
@@ -572,10 +572,10 @@ const RoomFilter: React.FC<RoomFilterProps> = ({ onFilterChange }) => {
<div className="flex flex-col sm:flex-row gap-2 sm:gap-3 pt-2"> <div className="flex flex-col sm:flex-row gap-2 sm:gap-3 pt-2">
<button <button
type="submit" type="submit"
className="flex-1 bg-gradient-to-r from-[#d4af37] to-[#c9a227] className="flex-1 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]
text-[#0f0f0f] py-2.5 sm:py-3 px-4 rounded-sm font-medium tracking-wide text-sm sm:text-base text-[#0f0f0f] py-2.5 sm:py-3 px-4 rounded-sm font-medium tracking-wide text-sm sm:text-base
hover:from-[#f5d76e] hover:to-[#d4af37] active:scale-95 hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] active:scale-95
transition-all duration-300 shadow-lg shadow-[#d4af37]/30 transition-all duration-300 shadow-lg shadow-[var(--luxury-gold)]/30
relative overflow-hidden group touch-manipulation min-h-[44px]" relative overflow-hidden group touch-manipulation min-h-[44px]"
> >
<span className="relative z-10">Apply</span> <span className="relative z-10">Apply</span>
@@ -585,8 +585,8 @@ const RoomFilter: React.FC<RoomFilterProps> = ({ onFilterChange }) => {
type="button" type="button"
onClick={handleReset} onClick={handleReset}
className="flex-1 bg-[#0a0a0a] backdrop-blur-sm text-gray-300 className="flex-1 bg-[#0a0a0a] backdrop-blur-sm text-gray-300
py-2.5 sm:py-3 px-4 rounded-sm border border-[#d4af37]/30 py-2.5 sm:py-3 px-4 rounded-sm border border-[var(--luxury-gold)]/30
hover:bg-[#1a1a1a] hover:border-[#d4af37] hover:text-[#d4af37] active:scale-95 hover:bg-[#1a1a1a] hover:border-[var(--luxury-gold)] hover:text-[var(--luxury-gold)] active:scale-95
transition-all font-medium tracking-wide text-sm sm:text-base transition-all font-medium tracking-wide text-sm sm:text-base
touch-manipulation min-h-[44px]" touch-manipulation min-h-[44px]"
> >

View File

@@ -103,15 +103,15 @@ const SearchRoomForm: React.FC<SearchRoomFormProps> = ({
const isOverlay = className.includes('overlay'); const isOverlay = className.includes('overlay');
return ( return (
<div className={`w-full ${isOverlay ? 'bg-transparent shadow-none border-none p-0' : 'luxury-glass rounded-sm shadow-2xl p-6 border border-[#d4af37]/20'} ${className}`}> <div className={`w-full ${isOverlay ? 'bg-transparent shadow-none border-none p-0' : 'luxury-glass rounded-sm shadow-2xl p-6 border border-[var(--luxury-gold)]/20'} ${className}`}>
{} {}
{(!isOverlay || !isMobile) && ( {(!isOverlay || !isMobile) && (
<div className={`flex items-center justify-center gap-1.5 sm:gap-2 md:gap-3 ${isOverlay ? 'mb-1 sm:mb-2 md:mb-3 lg:mb-4 xl:mb-6' : 'mb-6'}`}> <div className={`flex items-center justify-center gap-1.5 sm:gap-2 md:gap-3 ${isOverlay ? 'mb-1 sm:mb-2 md:mb-3 lg:mb-4 xl:mb-6' : 'mb-6'}`}>
<div className={`${isOverlay ? 'w-0.5 sm:w-0.5 md:w-1' : 'w-1'} ${isOverlay ? 'h-3 sm:h-4 md:h-6 lg:h-8' : 'h-8'} bg-gradient-to-b from-[#d4af37] to-[#c9a227]`}></div> <div className={`${isOverlay ? 'w-0.5 sm:w-0.5 md:w-1' : 'w-1'} ${isOverlay ? 'h-3 sm:h-4 md:h-6 lg:h-8' : 'h-8'} bg-gradient-to-b from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]`}></div>
<h3 className={`${isOverlay ? 'text-xs sm:text-sm md:text-base lg:text-lg xl:text-xl' : 'text-2xl'} font-serif font-semibold text-gray-900 tracking-tight`}> <h3 className={`${isOverlay ? 'text-xs sm:text-sm md:text-base lg:text-lg xl:text-xl' : 'text-2xl'} font-serif font-semibold text-gray-900 tracking-tight`}>
{isOverlay && isMobile ? 'Find Rooms' : 'Find Available Rooms'} {isOverlay && isMobile ? 'Find Rooms' : 'Find Available Rooms'}
</h3> </h3>
<div className={`${isOverlay ? 'w-0.5 sm:w-0.5 md:w-1' : 'w-1'} ${isOverlay ? 'h-3 sm:h-4 md:h-6 lg:h-8' : 'h-8'} bg-gradient-to-b from-[#d4af37] to-[#c9a227]`}></div> <div className={`${isOverlay ? 'w-0.5 sm:w-0.5 md:w-1' : 'w-1'} ${isOverlay ? 'h-3 sm:h-4 md:h-6 lg:h-8' : 'h-8'} bg-gradient-to-b from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]`}></div>
</div> </div>
)} )}

View File

@@ -212,6 +212,26 @@ export interface UpdateRecaptchaSettingsRequest {
recaptcha_enabled?: boolean; recaptcha_enabled?: boolean;
} }
export interface ThemeSettingsResponse {
status: string;
data: {
theme_primary_color: string;
theme_primary_light: string;
theme_primary_dark: string;
theme_primary_accent: string;
updated_at?: string | null;
updated_by?: string | null;
};
message?: string;
}
export interface UpdateThemeSettingsRequest {
theme_primary_color?: string;
theme_primary_light?: string;
theme_primary_dark?: string;
theme_primary_accent?: string;
}
export interface VerifyRecaptchaRequest { export interface VerifyRecaptchaRequest {
token: string; token: string;
} }
@@ -438,6 +458,25 @@ const recaptchaService = {
}, },
}; };
export default systemSettingsService; const themeService = {
export { recaptchaService }; getThemeSettings: async (): Promise<ThemeSettingsResponse> => {
const response = await apiClient.get<ThemeSettingsResponse>(
'/api/admin/system-settings/theme'
);
return response.data;
},
updateThemeSettings: async (
settings: UpdateThemeSettingsRequest
): Promise<ThemeSettingsResponse> => {
const response = await apiClient.put<ThemeSettingsResponse>(
'/api/admin/system-settings/theme',
settings
);
return response.data;
},
};
export default systemSettingsService;
export { recaptchaService, themeService };

View File

@@ -42,14 +42,14 @@ const HousekeepingLayout: React.FC = () => {
return ( return (
<div className="min-h-screen bg-gradient-to-br from-gray-50 via-white to-gray-50 overflow-x-hidden"> <div className="min-h-screen bg-gradient-to-br from-gray-50 via-white to-gray-50 overflow-x-hidden">
{/* Luxury Top Navigation Bar */} {/* Luxury Top Navigation Bar */}
<header className="sticky top-0 z-50 bg-white/95 backdrop-blur-xl border-b border-[#d4af37]/20 shadow-sm"> <header className="sticky top-0 z-50 bg-white/95 backdrop-blur-xl border-b border-[var(--luxury-gold)]/20 shadow-sm">
<div className="w-full max-w-7xl mx-auto px-3 sm:px-4 md:px-6 lg:px-8"> <div className="w-full max-w-7xl mx-auto px-3 sm:px-4 md:px-6 lg:px-8">
<div className="flex items-center justify-between h-14 sm:h-16"> <div className="flex items-center justify-between h-14 sm:h-16">
{/* Logo/Brand */} {/* Logo/Brand */}
<div className="flex items-center space-x-2 sm:space-x-3 min-w-0 flex-shrink-0"> <div className="flex items-center space-x-2 sm:space-x-3 min-w-0 flex-shrink-0">
<div className="relative flex-shrink-0"> <div className="relative flex-shrink-0">
<div className="absolute inset-0 bg-gradient-to-r from-[#d4af37] to-[#c9a227] rounded-lg blur-sm opacity-50"></div> <div className="absolute inset-0 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] rounded-lg blur-sm opacity-50"></div>
<div className="relative bg-gradient-to-r from-[#d4af37] to-[#c9a227] p-1.5 sm:p-2 rounded-lg"> <div className="relative bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] p-1.5 sm:p-2 rounded-lg">
<Sparkles className="w-4 h-4 sm:w-5 sm:h-5 md:w-6 md:h-6 text-white" /> <Sparkles className="w-4 h-4 sm:w-5 sm:h-5 md:w-6 md:h-6 text-white" />
</div> </div>
</div> </div>
@@ -70,7 +70,7 @@ const HousekeepingLayout: React.FC = () => {
to={item.path} to={item.path}
className={`flex items-center space-x-1 sm:space-x-2 px-2 sm:px-3 py-1.5 sm:py-2 rounded-lg text-xs sm:text-sm font-medium transition-all duration-200 ${ className={`flex items-center space-x-1 sm:space-x-2 px-2 sm:px-3 py-1.5 sm:py-2 rounded-lg text-xs sm:text-sm font-medium transition-all duration-200 ${
isActive(item.path) isActive(item.path)
? 'bg-gradient-to-r from-[#d4af37]/10 to-[#c9a227]/10 text-[#d4af37] border border-[#d4af37]/30' ? 'bg-gradient-to-r from-[var(--luxury-gold)]/10 to-[var(--luxury-gold-dark)]/10 text-[var(--luxury-gold)] border border-[var(--luxury-gold)]/30'
: 'text-gray-600 hover:text-gray-900 hover:bg-gray-100' : 'text-gray-600 hover:text-gray-900 hover:bg-gray-100'
}`} }`}
> >
@@ -87,7 +87,7 @@ const HousekeepingLayout: React.FC = () => {
<InAppNotificationBell /> <InAppNotificationBell />
<div className="hidden lg:flex items-center space-x-2 px-3 py-1.5 rounded-lg bg-gradient-to-r from-gray-50 to-gray-100/50 border border-gray-200/50"> <div className="hidden lg:flex items-center space-x-2 px-3 py-1.5 rounded-lg bg-gradient-to-r from-gray-50 to-gray-100/50 border border-gray-200/50">
<div className="w-7 h-7 rounded-full bg-gradient-to-br from-[#d4af37] to-[#c9a227] flex items-center justify-center flex-shrink-0"> <div className="w-7 h-7 rounded-full bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] flex items-center justify-center flex-shrink-0">
<User className="w-3.5 h-3.5 text-white" /> <User className="w-3.5 h-3.5 text-white" />
</div> </div>
<div className="text-left min-w-0"> <div className="text-left min-w-0">

View File

@@ -417,7 +417,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div className="mb-6 sm:mb-8 animate-fade-in"> <div className="mb-6 sm:mb-8 animate-fade-in">
<div className="flex items-center gap-2 sm:gap-3 mb-2 sm:mb-3"> <div className="flex items-center gap-2 sm:gap-3 mb-2 sm:mb-3">
<div className="h-1 w-12 sm:w-16 md:w-20 bg-gradient-to-r from-[#d4af37] via-amber-400 to-[#d4af37] rounded-full"></div> <div className="h-1 w-12 sm:w-16 md:w-20 bg-gradient-to-r from-[var(--luxury-gold)] via-amber-400 to-[var(--luxury-gold)] rounded-full"></div>
<h1 className="text-2xl sm:text-3xl lg:text-4xl font-serif font-bold bg-gradient-to-r from-gray-900 via-amber-900/90 to-gray-900 bg-clip-text text-transparent tracking-tight"> <h1 className="text-2xl sm:text-3xl lg:text-4xl font-serif font-bold bg-gradient-to-r from-gray-900 via-amber-900/90 to-gray-900 bg-clip-text text-transparent tracking-tight">
Accountant Profile & Settings Accountant Profile & Settings
</h1> </h1>
@@ -428,61 +428,61 @@ const ProfilePage: React.FC = () => {
</div> </div>
{} {}
<div className="mb-4 sm:mb-6 border-b border-[#d4af37]/20 overflow-x-auto bg-white/50 backdrop-blur-sm rounded-t-lg sm:rounded-t-xl px-4 sm:px-6"> <div className="mb-4 sm:mb-6 border-b border-[var(--luxury-gold)]/20 overflow-x-auto bg-white/50 backdrop-blur-sm rounded-t-lg sm:rounded-t-xl px-4 sm:px-6">
<div className="flex space-x-4 sm:space-x-8 min-w-max"> <div className="flex space-x-4 sm:space-x-8 min-w-max">
<button <button
onClick={() => setActiveTab('profile')} onClick={() => setActiveTab('profile')}
className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${ className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${
activeTab === 'profile' activeTab === 'profile'
? 'border-[#d4af37] text-[#d4af37] shadow-sm' ? 'border-[var(--luxury-gold)] text-[var(--luxury-gold)] shadow-sm'
: 'border-transparent text-gray-500 hover:text-[#d4af37] hover:border-[#d4af37]/30' : 'border-transparent text-gray-500 hover:text-[var(--luxury-gold)] hover:border-[var(--luxury-gold)]/30'
}`} }`}
> >
<User className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'profile' ? 'text-[#d4af37]' : ''}`} /> <User className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'profile' ? 'text-[var(--luxury-gold)]' : ''}`} />
Profile Information Profile Information
</button> </button>
<button <button
onClick={() => setActiveTab('password')} onClick={() => setActiveTab('password')}
className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${ className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${
activeTab === 'password' activeTab === 'password'
? 'border-[#d4af37] text-[#d4af37] shadow-sm' ? 'border-[var(--luxury-gold)] text-[var(--luxury-gold)] shadow-sm'
: 'border-transparent text-gray-500 hover:text-[#d4af37] hover:border-[#d4af37]/30' : 'border-transparent text-gray-500 hover:text-[var(--luxury-gold)] hover:border-[var(--luxury-gold)]/30'
}`} }`}
> >
<KeyRound className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'password' ? 'text-[#d4af37]' : ''}`} /> <KeyRound className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'password' ? 'text-[var(--luxury-gold)]' : ''}`} />
Change Password Change Password
</button> </button>
<button <button
onClick={() => setActiveTab('mfa')} onClick={() => setActiveTab('mfa')}
className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${ className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${
activeTab === 'mfa' activeTab === 'mfa'
? 'border-[#d4af37] text-[#d4af37] shadow-sm' ? 'border-[var(--luxury-gold)] text-[var(--luxury-gold)] shadow-sm'
: 'border-transparent text-gray-500 hover:text-[#d4af37] hover:border-[#d4af37]/30' : 'border-transparent text-gray-500 hover:text-[var(--luxury-gold)] hover:border-[var(--luxury-gold)]/30'
}`} }`}
> >
<Shield className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'mfa' ? 'text-[#d4af37]' : ''}`} /> <Shield className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'mfa' ? 'text-[var(--luxury-gold)]' : ''}`} />
Two-Factor Authentication Two-Factor Authentication
</button> </button>
<button <button
onClick={() => setActiveTab('sessions')} onClick={() => setActiveTab('sessions')}
className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${ className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${
activeTab === 'sessions' activeTab === 'sessions'
? 'border-[#d4af37] text-[#d4af37] shadow-sm' ? 'border-[var(--luxury-gold)] text-[var(--luxury-gold)] shadow-sm'
: 'border-transparent text-gray-500 hover:text-[#d4af37] hover:border-[#d4af37]/30' : 'border-transparent text-gray-500 hover:text-[var(--luxury-gold)] hover:border-[var(--luxury-gold)]/30'
}`} }`}
> >
<Monitor className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'sessions' ? 'text-[#d4af37]' : ''}`} /> <Monitor className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'sessions' ? 'text-[var(--luxury-gold)]' : ''}`} />
Active Sessions Active Sessions
</button> </button>
<button <button
onClick={() => setActiveTab('gdpr')} onClick={() => setActiveTab('gdpr')}
className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${ className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${
activeTab === 'gdpr' activeTab === 'gdpr'
? 'border-[#d4af37] text-[#d4af37] shadow-sm' ? 'border-[var(--luxury-gold)] text-[var(--luxury-gold)] shadow-sm'
: 'border-transparent text-gray-500 hover:text-[#d4af37] hover:border-[#d4af37]/30' : 'border-transparent text-gray-500 hover:text-[var(--luxury-gold)] hover:border-[var(--luxury-gold)]/30'
}`} }`}
> >
<Database className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'gdpr' ? 'text-[#d4af37]' : ''}`} /> <Database className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'gdpr' ? 'text-[var(--luxury-gold)]' : ''}`} />
Data Privacy Data Privacy
</button> </button>
</div> </div>
@@ -490,7 +490,7 @@ const ProfilePage: React.FC = () => {
{} {}
{activeTab === 'profile' && ( {activeTab === 'profile' && (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl animate-slide-up"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl animate-slide-up">
<form onSubmit={handleSubmitProfile(onSubmitProfile)} className="space-y-5 sm:space-y-6"> <form onSubmit={handleSubmitProfile(onSubmitProfile)} className="space-y-5 sm:space-y-6">
{} {}
<div className="flex flex-col sm:flex-row items-center sm:items-start gap-4 sm:gap-6 pb-5 sm:pb-6 border-b border-gray-200"> <div className="flex flex-col sm:flex-row items-center sm:items-start gap-4 sm:gap-6 pb-5 sm:pb-6 border-b border-gray-200">
@@ -499,20 +499,20 @@ const ProfilePage: React.FC = () => {
<img <img
src={avatarPreview || normalizeImageUrl(userInfo?.avatar)} src={avatarPreview || normalizeImageUrl(userInfo?.avatar)}
alt="Profile" alt="Profile"
className="w-20 h-20 sm:w-24 sm:h-24 rounded-full object-cover ring-4 ring-[#d4af37]/20 shadow-lg" className="w-20 h-20 sm:w-24 sm:h-24 rounded-full object-cover ring-4 ring-[var(--luxury-gold)]/20 shadow-lg"
onError={() => { onError={() => {
// If image fails to load, show default avatar // If image fails to load, show default avatar
setAvatarError(true); setAvatarError(true);
}} }}
/> />
) : ( ) : (
<div className="w-20 h-20 sm:w-24 sm:h-24 rounded-full bg-gradient-to-br from-[#d4af37] to-[#c9a227] flex items-center justify-center ring-4 ring-[#d4af37]/20 shadow-lg"> <div className="w-20 h-20 sm:w-24 sm:h-24 rounded-full bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] flex items-center justify-center ring-4 ring-[var(--luxury-gold)]/20 shadow-lg">
<User className="w-10 h-10 sm:w-12 sm:h-12 text-white" /> <User className="w-10 h-10 sm:w-12 sm:h-12 text-white" />
</div> </div>
)} )}
<label <label
htmlFor="avatar-upload" htmlFor="avatar-upload"
className="absolute bottom-0 right-0 p-2 bg-gradient-to-br from-[#d4af37] to-[#c9a227] rounded-full cursor-pointer hover:from-[#f5d76e] hover:to-[#d4af37] transition-all duration-300 shadow-lg hover:shadow-xl hover:shadow-[#d4af37]/40 hover:-translate-y-0.5 active:translate-y-0" className="absolute bottom-0 right-0 p-2 bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] rounded-full cursor-pointer hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] transition-all duration-300 shadow-lg hover:shadow-xl hover:shadow-[var(--luxury-gold)]/40 hover:-translate-y-0.5 active:translate-y-0"
> >
<Camera className="w-3.5 h-3.5 sm:w-4 sm:h-4 text-white" /> <Camera className="w-3.5 h-3.5 sm:w-4 sm:h-4 text-white" />
<input <input
@@ -528,7 +528,7 @@ const ProfilePage: React.FC = () => {
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<User className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <User className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
Full Name Full Name
<span className="text-red-500 ml-1">*</span> <span className="text-red-500 ml-1">*</span>
</label> </label>
@@ -551,7 +551,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<Mail className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <Mail className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
Email Address Email Address
<span className="text-red-500 ml-1">*</span> <span className="text-red-500 ml-1">*</span>
</label> </label>
@@ -574,7 +574,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<Phone className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <Phone className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
Phone Number Phone Number
<span className="text-red-500 ml-1">*</span> <span className="text-red-500 ml-1">*</span>
</label> </label>
@@ -611,7 +611,7 @@ const ProfilePage: React.FC = () => {
{} {}
{activeTab === 'password' && ( {activeTab === 'password' && (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl animate-slide-up"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl animate-slide-up">
<form onSubmit={handleSubmitPassword(onSubmitPassword)} className="space-y-5 sm:space-y-6"> <form onSubmit={handleSubmitPassword(onSubmitPassword)} className="space-y-5 sm:space-y-6">
{} {}
<div className="bg-gradient-to-r from-blue-50 to-indigo-50 border border-blue-200/60 rounded-sm p-4 sm:p-5"> <div className="bg-gradient-to-r from-blue-50 to-indigo-50 border border-blue-200/60 rounded-sm p-4 sm:p-5">
@@ -640,7 +640,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
Current Password Current Password
<span className="text-red-500 ml-1">*</span> <span className="text-red-500 ml-1">*</span>
</label> </label>
@@ -656,7 +656,7 @@ const ProfilePage: React.FC = () => {
<button <button
type="button" type="button"
onClick={() => setShowPassword({ ...showPassword, current: !showPassword.current })} onClick={() => setShowPassword({ ...showPassword, current: !showPassword.current })}
className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[#d4af37] transition-colors" className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[var(--luxury-gold)] transition-colors"
> >
{showPassword.current ? ( {showPassword.current ? (
<EyeOff className="w-4 h-4 sm:w-5 sm:h-5" /> <EyeOff className="w-4 h-4 sm:w-5 sm:h-5" />
@@ -676,7 +676,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
New Password New Password
<span className="text-red-500 ml-1">*</span> <span className="text-red-500 ml-1">*</span>
</label> </label>
@@ -692,7 +692,7 @@ const ProfilePage: React.FC = () => {
<button <button
type="button" type="button"
onClick={() => setShowPassword({ ...showPassword, new: !showPassword.new })} onClick={() => setShowPassword({ ...showPassword, new: !showPassword.new })}
className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[#d4af37] transition-colors" className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[var(--luxury-gold)] transition-colors"
> >
{showPassword.new ? ( {showPassword.new ? (
<EyeOff className="w-4 h-4 sm:w-5 sm:h-5" /> <EyeOff className="w-4 h-4 sm:w-5 sm:h-5" />
@@ -712,7 +712,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
Confirm New Password Confirm New Password
<span className="text-red-500 ml-1">*</span> <span className="text-red-500 ml-1">*</span>
</label> </label>
@@ -728,7 +728,7 @@ const ProfilePage: React.FC = () => {
<button <button
type="button" type="button"
onClick={() => setShowPassword({ ...showPassword, confirm: !showPassword.confirm })} onClick={() => setShowPassword({ ...showPassword, confirm: !showPassword.confirm })}
className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[#d4af37] transition-colors" className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[var(--luxury-gold)] transition-colors"
> >
{showPassword.confirm ? ( {showPassword.confirm ? (
<EyeOff className="w-4 h-4 sm:w-5 sm:h-5" /> <EyeOff className="w-4 h-4 sm:w-5 sm:h-5" />
@@ -762,11 +762,11 @@ const ProfilePage: React.FC = () => {
{} {}
{activeTab === 'mfa' && ( {activeTab === 'mfa' && (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl animate-slide-up space-y-5 sm:space-y-6"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl animate-slide-up space-y-5 sm:space-y-6">
{} {}
<div> <div>
<h2 className="text-xl sm:text-2xl font-serif font-semibold text-gray-900 mb-2 flex items-center gap-2"> <h2 className="text-xl sm:text-2xl font-serif font-semibold text-gray-900 mb-2 flex items-center gap-2">
<Shield className="w-5 h-5 sm:w-6 sm:h-6 text-[#d4af37]" /> <Shield className="w-5 h-5 sm:w-6 sm:h-6 text-[var(--luxury-gold)]" />
Two-Factor Authentication Two-Factor Authentication
</h2> </h2>
<p className="text-xs sm:text-sm text-gray-600 font-light leading-relaxed"> <p className="text-xs sm:text-sm text-gray-600 font-light leading-relaxed">
@@ -838,7 +838,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div className="bg-white border border-gray-200 rounded-sm p-4 sm:p-5"> <div className="bg-white border border-gray-200 rounded-sm p-4 sm:p-5">
<h3 className="text-sm sm:text-base font-semibold text-gray-900 mb-2 flex items-center gap-2"> <h3 className="text-sm sm:text-base font-semibold text-gray-900 mb-2 flex items-center gap-2">
<RefreshCw className="w-4 h-4 sm:w-5 sm:h-5 text-[#d4af37]" /> <RefreshCw className="w-4 h-4 sm:w-5 sm:h-5 text-[var(--luxury-gold)]" />
Backup Codes Backup Codes
</h3> </h3>
<p className="text-xs sm:text-sm text-gray-600 font-light mb-4 leading-relaxed"> <p className="text-xs sm:text-sm text-gray-600 font-light mb-4 leading-relaxed">
@@ -984,7 +984,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div className="bg-white border border-gray-200 rounded-sm p-4 sm:p-5"> <div className="bg-white border border-gray-200 rounded-sm p-4 sm:p-5">
<h3 className="font-semibold text-gray-900 mb-2 text-sm sm:text-base flex items-center gap-2"> <h3 className="font-semibold text-gray-900 mb-2 text-sm sm:text-base flex items-center gap-2">
<KeyRound className="w-4 h-4 sm:w-5 sm:h-5 text-[#d4af37]" /> <KeyRound className="w-4 h-4 sm:w-5 sm:h-5 text-[var(--luxury-gold)]" />
Step 2: Verify Setup Step 2: Verify Setup
</h3> </h3>
<p className="text-xs sm:text-sm text-gray-600 font-light mb-4 leading-relaxed"> <p className="text-xs sm:text-sm text-gray-600 font-light mb-4 leading-relaxed">
@@ -1110,10 +1110,10 @@ const SessionsTab: React.FC = () => {
}; };
const getDeviceIcon = (userAgent?: string) => { const getDeviceIcon = (userAgent?: string) => {
if (!userAgent) return <Monitor className="w-5 h-5 text-[#d4af37]" />; if (!userAgent) return <Monitor className="w-5 h-5 text-[var(--luxury-gold)]" />;
if (userAgent.includes('Mobile')) return <Smartphone className="w-5 h-5 text-blue-500" />; if (userAgent.includes('Mobile')) return <Smartphone className="w-5 h-5 text-blue-500" />;
if (userAgent.includes('Tablet')) return <Tablet className="w-5 h-5 text-purple-500" />; if (userAgent.includes('Tablet')) return <Tablet className="w-5 h-5 text-purple-500" />;
return <Monitor className="w-5 h-5 text-[#d4af37]" />; return <Monitor className="w-5 h-5 text-[var(--luxury-gold)]" />;
}; };
const getDeviceName = (userAgent?: string) => { const getDeviceName = (userAgent?: string) => {
@@ -1181,17 +1181,17 @@ const SessionsTab: React.FC = () => {
if (loading) { if (loading) {
return ( return (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl">
<Loading text="Loading sessions..." /> <Loading text="Loading sessions..." />
</div> </div>
); );
} }
return ( return (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl animate-slide-up space-y-5 sm:space-y-6"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl animate-slide-up space-y-5 sm:space-y-6">
<div> <div>
<h2 className="text-xl sm:text-2xl font-serif font-semibold text-gray-900 mb-2 flex items-center gap-2"> <h2 className="text-xl sm:text-2xl font-serif font-semibold text-gray-900 mb-2 flex items-center gap-2">
<Monitor className="w-5 h-5 sm:w-6 sm:h-6 text-[#d4af37]" /> <Monitor className="w-5 h-5 sm:w-6 sm:h-6 text-[var(--luxury-gold)]" />
Active Sessions Active Sessions
</h2> </h2>
<p className="text-xs sm:text-sm text-gray-600 font-light"> <p className="text-xs sm:text-sm text-gray-600 font-light">
@@ -1220,11 +1220,11 @@ const SessionsTab: React.FC = () => {
{sessions.map((session) => ( {sessions.map((session) => (
<div <div
key={session.id} key={session.id}
className="bg-gradient-to-r from-slate-50 to-white border border-[#d4af37]/20 rounded-sm p-4 sm:p-5 hover:shadow-lg hover:border-[#d4af37]/40 transition-all duration-300" className="bg-gradient-to-r from-slate-50 to-white border border-[var(--luxury-gold)]/20 rounded-sm p-4 sm:p-5 hover:shadow-lg hover:border-[var(--luxury-gold)]/40 transition-all duration-300"
> >
<div className="flex items-start justify-between gap-4"> <div className="flex items-start justify-between gap-4">
<div className="flex items-start gap-4 flex-1"> <div className="flex items-start gap-4 flex-1">
<div className="p-2 sm:p-3 bg-gradient-to-br from-[#d4af37]/10 to-[#c9a227]/10 rounded-sm flex-shrink-0"> <div className="p-2 sm:p-3 bg-gradient-to-br from-[var(--luxury-gold)]/10 to-[var(--luxury-gold-dark)]/10 rounded-sm flex-shrink-0">
{getDeviceIcon(session.user_agent)} {getDeviceIcon(session.user_agent)}
</div> </div>
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
@@ -1354,17 +1354,17 @@ const GDPRTab: React.FC = () => {
if (loading) { if (loading) {
return ( return (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl">
<Loading text="Loading privacy data..." /> <Loading text="Loading privacy data..." />
</div> </div>
); );
} }
return ( return (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl animate-slide-up space-y-5 sm:space-y-6"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl animate-slide-up space-y-5 sm:space-y-6">
<div> <div>
<h2 className="text-xl sm:text-2xl font-serif font-semibold text-gray-900 mb-2 flex items-center gap-2"> <h2 className="text-xl sm:text-2xl font-serif font-semibold text-gray-900 mb-2 flex items-center gap-2">
<Database className="w-5 h-5 sm:w-6 sm:h-6 text-[#d4af37]" /> <Database className="w-5 h-5 sm:w-6 sm:h-6 text-[var(--luxury-gold)]" />
Data Privacy & GDPR Rights Data Privacy & GDPR Rights
</h2> </h2>
<p className="text-xs sm:text-sm text-gray-600 font-light"> <p className="text-xs sm:text-sm text-gray-600 font-light">
@@ -1431,14 +1431,14 @@ const GDPRTab: React.FC = () => {
{requests.length > 0 && ( {requests.length > 0 && (
<div className="border-t border-gray-200 pt-5 sm:pt-6"> <div className="border-t border-gray-200 pt-5 sm:pt-6">
<h3 className="text-base sm:text-lg font-semibold text-gray-900 mb-4 flex items-center gap-2"> <h3 className="text-base sm:text-lg font-semibold text-gray-900 mb-4 flex items-center gap-2">
<FileText className="w-5 h-5 text-[#d4af37]" /> <FileText className="w-5 h-5 text-[var(--luxury-gold)]" />
Request History Request History
</h3> </h3>
<div className="space-y-3 sm:space-y-4"> <div className="space-y-3 sm:space-y-4">
{requests.map((request) => ( {requests.map((request) => (
<div <div
key={request.id} key={request.id}
className="bg-gradient-to-r from-slate-50 to-white border border-[#d4af37]/20 rounded-sm p-4 sm:p-5 hover:shadow-md hover:border-[#d4af37]/40 transition-all duration-300" className="bg-gradient-to-r from-slate-50 to-white border border-[var(--luxury-gold)]/20 rounded-sm p-4 sm:p-5 hover:shadow-md hover:border-[var(--luxury-gold)]/40 transition-all duration-300"
> >
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3 sm:gap-4"> <div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3 sm:gap-4">
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">

View File

@@ -1334,10 +1334,10 @@ const AdvancedRoomManagementPage: React.FC = () => {
{/* Room Modal */} {/* Room Modal */}
{showRoomModal && ( {showRoomModal && (
<div className="fixed inset-0 bg-black/80 backdrop-blur-sm flex items-center justify-center z-[100] p-4"> <div className="fixed inset-0 bg-black/80 backdrop-blur-sm flex items-center justify-center z-[100] p-4">
<div className="bg-gradient-to-br from-[#1a1a1a] via-[#0f0f0f] to-[#1a1a1a] rounded-xl border border-[#d4af37]/30 backdrop-blur-xl shadow-2xl shadow-[#d4af37]/20 p-8 w-full max-w-4xl max-h-[90vh] overflow-y-auto"> <div className="bg-gradient-to-br from-[#1a1a1a] via-[#0f0f0f] to-[#1a1a1a] rounded-xl border border-[var(--luxury-gold)]/30 backdrop-blur-xl shadow-2xl shadow-[var(--luxury-gold)]/20 p-8 w-full max-w-4xl max-h-[90vh] overflow-y-auto">
<div className="flex justify-between items-center mb-6 pb-6 border-b border-[#d4af37]/20"> <div className="flex justify-between items-center mb-6 pb-6 border-b border-[var(--luxury-gold)]/20">
<div> <div>
<h2 className="text-xl sm:text-2xl md:text-2xl font-serif font-semibold bg-gradient-to-r from-white via-[#d4af37] to-white bg-clip-text text-transparent tracking-wide"> <h2 className="text-xl sm:text-2xl md:text-2xl font-serif font-semibold bg-gradient-to-r from-white via-[var(--luxury-gold)] to-white bg-clip-text text-transparent tracking-wide">
{editingRoom ? 'Update Room' : 'Add New Room'} {editingRoom ? 'Update Room' : 'Add New Room'}
</h2> </h2>
<p className="text-gray-400 text-sm mt-1 font-light"> <p className="text-gray-400 text-sm mt-1 font-light">
@@ -1346,16 +1346,16 @@ const AdvancedRoomManagementPage: React.FC = () => {
</div> </div>
<button <button
onClick={() => setShowRoomModal(false)} onClick={() => setShowRoomModal(false)}
className="p-2 hover:bg-[#d4af37]/10 rounded-lg transition-colors border border-[#d4af37]/20 hover:border-[#d4af37]/40" className="p-2 hover:bg-[var(--luxury-gold)]/10 rounded-lg transition-colors border border-[var(--luxury-gold)]/20 hover:border-[var(--luxury-gold)]/40"
> >
<X className="w-6 h-6 text-[#d4af37] hover:text-white transition-colors" /> <X className="w-6 h-6 text-[var(--luxury-gold)] hover:text-white transition-colors" />
</button> </button>
</div> </div>
<form onSubmit={handleRoomSubmit} className="space-y-6"> <form onSubmit={handleRoomSubmit} className="space-y-6">
<div className="space-y-4"> <div className="space-y-4">
<h3 className="text-lg font-serif font-semibold text-[#d4af37] mb-4 flex items-center gap-2"> <h3 className="text-lg font-serif font-semibold text-[var(--luxury-gold)] mb-4 flex items-center gap-2">
<div className="w-1 h-6 bg-gradient-to-b from-[#d4af37] to-[#c9a227]" /> <div className="w-1 h-6 bg-gradient-to-b from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]" />
Basic Information Basic Information
</h3> </h3>
@@ -1368,7 +1368,7 @@ const AdvancedRoomManagementPage: React.FC = () => {
type="text" type="text"
value={roomFormData.room_number} value={roomFormData.room_number}
onChange={(e) => setRoomFormData({ ...roomFormData, room_number: e.target.value })} onChange={(e) => setRoomFormData({ ...roomFormData, room_number: e.target.value })}
className="w-full px-4 py-3 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white placeholder-gray-500 focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37] transition-all duration-300" className="w-full px-4 py-3 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white placeholder-gray-500 focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)] transition-all duration-300"
placeholder="e.g., 1001" placeholder="e.g., 1001"
required required
/> />
@@ -1381,7 +1381,7 @@ const AdvancedRoomManagementPage: React.FC = () => {
type="number" type="number"
value={roomFormData.floor} value={roomFormData.floor}
onChange={(e) => setRoomFormData({ ...roomFormData, floor: parseInt(e.target.value) })} onChange={(e) => setRoomFormData({ ...roomFormData, floor: parseInt(e.target.value) })}
className="w-full px-4 py-3 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white placeholder-gray-500 focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37] transition-all duration-300" className="w-full px-4 py-3 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white placeholder-gray-500 focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)] transition-all duration-300"
required required
min="1" min="1"
/> />
@@ -1405,7 +1405,7 @@ const AdvancedRoomManagementPage: React.FC = () => {
amenities: inheritedAmenities // Inherit amenities from room type amenities: inheritedAmenities // Inherit amenities from room type
}); });
}} }}
className="w-full px-4 py-3 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37] transition-all duration-300" className="w-full px-4 py-3 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)] transition-all duration-300"
required required
> >
{roomTypes.length > 0 ? ( {roomTypes.length > 0 ? (
@@ -1430,7 +1430,7 @@ const AdvancedRoomManagementPage: React.FC = () => {
<select <select
value={roomFormData.status} value={roomFormData.status}
onChange={(e) => setRoomFormData({ ...roomFormData, status: e.target.value as 'available' | 'occupied' | 'maintenance' })} onChange={(e) => setRoomFormData({ ...roomFormData, status: e.target.value as 'available' | 'occupied' | 'maintenance' })}
className="w-full px-4 py-3 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37] transition-all duration-300" className="w-full px-4 py-3 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)] transition-all duration-300"
required required
> >
<option value="available" className="bg-[#1a1a1a]">Available</option> <option value="available" className="bg-[#1a1a1a]">Available</option>
@@ -1439,13 +1439,13 @@ const AdvancedRoomManagementPage: React.FC = () => {
</select> </select>
</div> </div>
<div className="flex items-center gap-3 p-4 bg-[#0a0a0a] rounded-lg border border-[#d4af37]/20"> <div className="flex items-center gap-3 p-4 bg-[#0a0a0a] rounded-lg border border-[var(--luxury-gold)]/20">
<input <input
type="checkbox" type="checkbox"
id="featured" id="featured"
checked={roomFormData.featured} checked={roomFormData.featured}
onChange={(e) => setRoomFormData({ ...roomFormData, featured: e.target.checked })} onChange={(e) => setRoomFormData({ ...roomFormData, featured: e.target.checked })}
className="w-5 h-5 text-[#d4af37] bg-[#1a1a1a] border-[#d4af37]/30 rounded focus:ring-[#d4af37]/50 focus:ring-2 cursor-pointer transition-all" className="w-5 h-5 text-[var(--luxury-gold)] bg-[#1a1a1a] border-[var(--luxury-gold)]/30 rounded focus:ring-[var(--luxury-gold)]/50 focus:ring-2 cursor-pointer transition-all"
/> />
<label htmlFor="featured" className="text-sm text-gray-300 cursor-pointer font-medium"> <label htmlFor="featured" className="text-sm text-gray-300 cursor-pointer font-medium">
Featured Room Featured Room
@@ -1462,7 +1462,7 @@ const AdvancedRoomManagementPage: React.FC = () => {
min="0" min="0"
value={roomFormData.price} value={roomFormData.price}
onChange={(e) => setRoomFormData({ ...roomFormData, price: e.target.value })} onChange={(e) => setRoomFormData({ ...roomFormData, price: e.target.value })}
className="w-full px-4 py-3 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white placeholder-gray-500 focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37] transition-all duration-300" className="w-full px-4 py-3 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white placeholder-gray-500 focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)] transition-all duration-300"
placeholder="e.g., 150.00" placeholder="e.g., 150.00"
/> />
</div> </div>
@@ -1475,7 +1475,7 @@ const AdvancedRoomManagementPage: React.FC = () => {
value={roomFormData.description} value={roomFormData.description}
onChange={(e) => setRoomFormData({ ...roomFormData, description: e.target.value })} onChange={(e) => setRoomFormData({ ...roomFormData, description: e.target.value })}
rows={4} rows={4}
className="w-full px-4 py-3 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white placeholder-gray-500 focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37] transition-all duration-300 resize-none" className="w-full px-4 py-3 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white placeholder-gray-500 focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)] transition-all duration-300 resize-none"
placeholder="Enter the actual description for this specific room..." placeholder="Enter the actual description for this specific room..."
/> />
</div> </div>
@@ -1490,7 +1490,7 @@ const AdvancedRoomManagementPage: React.FC = () => {
min="1" min="1"
value={roomFormData.capacity} value={roomFormData.capacity}
onChange={(e) => setRoomFormData({ ...roomFormData, capacity: e.target.value })} onChange={(e) => setRoomFormData({ ...roomFormData, capacity: e.target.value })}
className="w-full px-4 py-3 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white placeholder-gray-500 focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37] transition-all duration-300" className="w-full px-4 py-3 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white placeholder-gray-500 focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)] transition-all duration-300"
placeholder="e.g., 4" placeholder="e.g., 4"
/> />
</div> </div>
@@ -1503,7 +1503,7 @@ const AdvancedRoomManagementPage: React.FC = () => {
type="text" type="text"
value={roomFormData.room_size} value={roomFormData.room_size}
onChange={(e) => setRoomFormData({ ...roomFormData, room_size: e.target.value })} onChange={(e) => setRoomFormData({ ...roomFormData, room_size: e.target.value })}
className="w-full px-4 py-3 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white placeholder-gray-500 focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37] transition-all duration-300" className="w-full px-4 py-3 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white placeholder-gray-500 focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)] transition-all duration-300"
placeholder="e.g., 1 Room, 50 sqm" placeholder="e.g., 1 Room, 50 sqm"
/> />
</div> </div>
@@ -1517,19 +1517,19 @@ const AdvancedRoomManagementPage: React.FC = () => {
type="text" type="text"
value={roomFormData.view} value={roomFormData.view}
onChange={(e) => setRoomFormData({ ...roomFormData, view: e.target.value })} onChange={(e) => setRoomFormData({ ...roomFormData, view: e.target.value })}
className="w-full px-4 py-3 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white placeholder-gray-500 focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37] transition-all duration-300" className="w-full px-4 py-3 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white placeholder-gray-500 focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)] transition-all duration-300"
placeholder="e.g., City View, Ocean View, Mountain View" placeholder="e.g., City View, Ocean View, Mountain View"
/> />
</div> </div>
</div> </div>
<div className="space-y-4"> <div className="space-y-4">
<h3 className="text-lg font-serif font-semibold text-[#d4af37] mb-4 flex items-center gap-2"> <h3 className="text-lg font-serif font-semibold text-[var(--luxury-gold)] mb-4 flex items-center gap-2">
<div className="w-1 h-6 bg-gradient-to-b from-[#d4af37] to-[#c9a227]" /> <div className="w-1 h-6 bg-gradient-to-b from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]" />
Amenities & Features Amenities & Features
</h3> </h3>
<div className="border border-[#d4af37]/20 rounded-lg p-4 bg-[#0a0a0a]/50 backdrop-blur-sm"> <div className="border border-[var(--luxury-gold)]/20 rounded-lg p-4 bg-[#0a0a0a]/50 backdrop-blur-sm">
{(() => { {(() => {
const selectedRoomType = roomTypesList.find(rt => rt.id === roomFormData.room_type_id); const selectedRoomType = roomTypesList.find(rt => rt.id === roomFormData.room_type_id);
const inheritedAmenities = selectedRoomType ? getAmenitiesArray(selectedRoomType.amenities) : []; const inheritedAmenities = selectedRoomType ? getAmenitiesArray(selectedRoomType.amenities) : [];
@@ -1549,15 +1549,15 @@ const AdvancedRoomManagementPage: React.FC = () => {
<> <>
<div className="mb-3"> <div className="mb-3">
<p className="text-xs text-gray-400 italic flex items-center gap-2"> <p className="text-xs text-gray-400 italic flex items-center gap-2">
<Check className="w-3 h-3 text-[#d4af37]" /> <Check className="w-3 h-3 text-[var(--luxury-gold)]" />
Inherited from room type: <strong className="text-[#d4af37]">{selectedRoomType?.name}</strong> Inherited from room type: <strong className="text-[var(--luxury-gold)]">{selectedRoomType?.name}</strong>
</p> </p>
</div> </div>
<div className="flex flex-wrap gap-2"> <div className="flex flex-wrap gap-2">
{inheritedAmenities.map((amenity) => ( {inheritedAmenities.map((amenity) => (
<span <span
key={amenity} key={amenity}
className="px-3 py-1.5 bg-gradient-to-r from-[#d4af37]/20 to-[#c9a227]/20 border border-[#d4af37]/30 rounded-lg text-sm text-[#d4af37] font-medium" className="px-3 py-1.5 bg-gradient-to-r from-[var(--luxury-gold)]/20 to-[var(--luxury-gold-dark)]/20 border border-[var(--luxury-gold)]/30 rounded-lg text-sm text-[var(--luxury-gold)] font-medium"
> >
{amenity} {amenity}
</span> </span>
@@ -1572,17 +1572,17 @@ const AdvancedRoomManagementPage: React.FC = () => {
</div> </div>
</div> </div>
<div className="flex gap-4 pt-4 border-t border-[#d4af37]/20"> <div className="flex gap-4 pt-4 border-t border-[var(--luxury-gold)]/20">
<button <button
type="button" type="button"
onClick={() => setShowRoomModal(false)} onClick={() => setShowRoomModal(false)}
className="flex-1 px-6 py-3 border border-[#d4af37]/30 text-gray-300 rounded-lg hover:bg-[#d4af37]/10 hover:border-[#d4af37] transition-all duration-300 font-medium" className="flex-1 px-6 py-3 border border-[var(--luxury-gold)]/30 text-gray-300 rounded-lg hover:bg-[var(--luxury-gold)]/10 hover:border-[var(--luxury-gold)] transition-all duration-300 font-medium"
> >
Cancel Cancel
</button> </button>
<button <button
type="submit" type="submit"
className="flex-1 px-6 py-3 bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-[#0f0f0f] rounded-lg hover:from-[#f5d76e] hover:to-[#d4af37] transition-all duration-300 font-semibold shadow-lg shadow-[#d4af37]/30 hover:shadow-xl hover:shadow-[#d4af37]/40" className="flex-1 px-6 py-3 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-[#0f0f0f] rounded-lg hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] transition-all duration-300 font-semibold shadow-lg shadow-[var(--luxury-gold)]/30 hover:shadow-xl hover:shadow-[var(--luxury-gold)]/40"
> >
{editingRoom ? 'Update Room' : 'Add Room'} {editingRoom ? 'Update Room' : 'Add Room'}
</button> </button>
@@ -1590,9 +1590,9 @@ const AdvancedRoomManagementPage: React.FC = () => {
</form> </form>
{editingRoom && ( {editingRoom && (
<div className="mt-8 pt-8 border-t border-[#d4af37]/20"> <div className="mt-8 pt-8 border-t border-[var(--luxury-gold)]/20">
<h3 className="text-lg font-serif font-semibold text-[#d4af37] mb-6 flex items-center gap-2"> <h3 className="text-lg font-serif font-semibold text-[var(--luxury-gold)] mb-6 flex items-center gap-2">
<div className="w-1 h-6 bg-gradient-to-b from-[#d4af37] to-[#c9a227]" /> <div className="w-1 h-6 bg-gradient-to-b from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]" />
<ImageIcon className="w-5 h-5" /> <ImageIcon className="w-5 h-5" />
Room Images Room Images
</h3> </h3>
@@ -1655,8 +1655,8 @@ const AdvancedRoomManagementPage: React.FC = () => {
return ( return (
<div key={index} className="relative group"> <div key={index} className="relative group">
<div className="overflow-hidden rounded-lg border border-[#d4af37]/20 <div className="overflow-hidden rounded-lg border border-[var(--luxury-gold)]/20
hover:border-[#d4af37] transition-all duration-300"> hover:border-[var(--luxury-gold)] transition-all duration-300">
<img <img
src={imageUrl} src={imageUrl}
alt={`Room Image ${index + 1}`} alt={`Room Image ${index + 1}`}
@@ -1669,7 +1669,7 @@ const AdvancedRoomManagementPage: React.FC = () => {
</div> </div>
{isRoomImage && ( {isRoomImage && (
<> <>
<div className="absolute top-2 left-2 bg-[#d4af37]/90 backdrop-blur-sm <div className="absolute top-2 left-2 bg-[var(--luxury-gold)]/90 backdrop-blur-sm
text-[#0f0f0f] px-2 py-1 rounded text-xs font-semibold text-[#0f0f0f] px-2 py-1 rounded text-xs font-semibold
opacity-0 group-hover:opacity-100 transition-opacity duration-300"> opacity-0 group-hover:opacity-100 transition-opacity duration-300">
Room Image Room Image
@@ -1692,7 +1692,7 @@ const AdvancedRoomManagementPage: React.FC = () => {
</div> </div>
</div> </div>
) : ( ) : (
<div className="mb-6 p-8 bg-[#0a0a0a]/50 rounded-lg border border-[#d4af37]/10 text-center"> <div className="mb-6 p-8 bg-[#0a0a0a]/50 rounded-lg border border-[var(--luxury-gold)]/10 text-center">
<ImageIcon className="w-12 h-12 text-gray-600 mx-auto mb-3" /> <ImageIcon className="w-12 h-12 text-gray-600 mx-auto mb-3" />
<p className="text-sm text-gray-400 font-light"> <p className="text-sm text-gray-400 font-light">
No images uploaded yet. Upload images below to display them here. No images uploaded yet. Upload images below to display them here.
@@ -1717,10 +1717,10 @@ const AdvancedRoomManagementPage: React.FC = () => {
className="w-full text-sm text-gray-400 className="w-full text-sm text-gray-400
file:mr-4 file:py-3 file:px-6 file:rounded-lg file:border-0 file:mr-4 file:py-3 file:px-6 file:rounded-lg file:border-0
file:text-sm file:font-semibold file:text-sm file:font-semibold
file:bg-gradient-to-r file:from-[#d4af37]/20 file:to-[#c9a227]/20 file:bg-gradient-to-r file:from-[var(--luxury-gold)]/20 file:to-[var(--luxury-gold-dark)]/20
file:text-[#d4af37] file:border file:border-[#d4af37]/30 file:text-[var(--luxury-gold)] file:border file:border-[var(--luxury-gold)]/30
hover:file:from-[#d4af37]/30 hover:file:to-[#c9a227]/30 hover:file:from-[var(--luxury-gold)]/30 hover:file:to-[var(--luxury-gold-dark)]/30
hover:file:border-[#d4af37] file:cursor-pointer hover:file:border-[var(--luxury-gold)] file:cursor-pointer
transition-all duration-300 bg-[#0a0a0a] rounded-lg" transition-all duration-300 bg-[#0a0a0a] rounded-lg"
/> />
<p className="text-xs text-gray-500 mt-1 italic"> <p className="text-xs text-gray-500 mt-1 italic">
@@ -1742,7 +1742,7 @@ const AdvancedRoomManagementPage: React.FC = () => {
type="button" type="button"
onClick={handleUploadImages} onClick={handleUploadImages}
disabled={uploadingImages || selectedFiles.length === 0} disabled={uploadingImages || selectedFiles.length === 0}
className="px-6 py-2 bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-[#0f0f0f] rounded-lg hover:from-[#f5d76e] hover:to-[#d4af37] transition-all duration-300 font-semibold shadow-lg shadow-[#d4af37]/30 hover:shadow-xl hover:shadow-[#d4af37]/40 disabled:opacity-50 disabled:cursor-not-allowed" className="px-6 py-2 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-[#0f0f0f] rounded-lg hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] transition-all duration-300 font-semibold shadow-lg shadow-[var(--luxury-gold)]/30 hover:shadow-xl hover:shadow-[var(--luxury-gold)]/40 disabled:opacity-50 disabled:cursor-not-allowed"
> >
{uploadingImages ? 'Uploading...' : 'Upload Images'} {uploadingImages ? 'Uploading...' : 'Upload Images'}
</button> </button>
@@ -1752,7 +1752,7 @@ const AdvancedRoomManagementPage: React.FC = () => {
</div> </div>
)} )}
<div className="mt-8 pt-6 border-t border-[#d4af37]/20 flex justify-end"> <div className="mt-8 pt-6 border-t border-[var(--luxury-gold)]/20 flex justify-end">
<button <button
type="button" type="button"
onClick={() => { onClick={() => {

View File

@@ -1,4 +1,5 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { import {
BarChart3, BarChart3,
FileText, FileText,
@@ -26,7 +27,8 @@ import {
CreditCard, CreditCard,
Building2, Building2,
Target, Target,
Award Award,
ChevronRight
} from 'lucide-react'; } from 'lucide-react';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import Loading from '../../shared/components/Loading'; import Loading from '../../shared/components/Loading';
@@ -36,7 +38,6 @@ import Pagination from '../../shared/components/Pagination';
import CurrencyIcon from '../../shared/components/CurrencyIcon'; import CurrencyIcon from '../../shared/components/CurrencyIcon';
import { useAsync } from '../../shared/hooks/useAsync'; import { useAsync } from '../../shared/hooks/useAsync';
import reportService, { ReportData } from '../../features/analytics/services/reportService'; import reportService, { ReportData } from '../../features/analytics/services/reportService';
import reviewService, { Review } from '../../features/reviews/services/reviewService';
import { auditService, AuditLog, AuditLogFilters } from '../../features/analytics/services/auditService'; import { auditService, AuditLog, AuditLogFilters } from '../../features/analytics/services/auditService';
import { formatDate } from '../../shared/utils/format'; import { formatDate } from '../../shared/utils/format';
import { useFormatCurrency } from '../../features/payments/hooks/useFormatCurrency'; import { useFormatCurrency } from '../../features/payments/hooks/useFormatCurrency';
@@ -62,10 +63,11 @@ import { SimpleBarChart, SimpleLineChart, SimplePieChart, KPICard } from '../../
import { exportData } from '../../shared/utils/exportUtils'; import { exportData } from '../../shared/utils/exportUtils';
import CustomReportBuilder from '../../features/analytics/components/CustomReportBuilder'; import CustomReportBuilder from '../../features/analytics/components/CustomReportBuilder';
type AnalyticsTab = 'overview' | 'reports' | 'revenue' | 'operational' | 'guest' | 'financial' | 'audit-logs' | 'reviews'; type AnalyticsTab = 'overview' | 'reports' | 'revenue' | 'operational' | 'guest' | 'financial' | 'audit-logs';
const AnalyticsDashboardPage: React.FC = () => { const AnalyticsDashboardPage: React.FC = () => {
const { formatCurrency } = useFormatCurrency(); const { formatCurrency } = useFormatCurrency();
const navigate = useNavigate();
const [activeTab, setActiveTab] = useState<AnalyticsTab>('overview'); const [activeTab, setActiveTab] = useState<AnalyticsTab>('overview');
const [showReportBuilder, setShowReportBuilder] = useState(false); const [showReportBuilder, setShowReportBuilder] = useState(false);
const [analyticsDateRange, setAnalyticsDateRange] = useState({ const [analyticsDateRange, setAnalyticsDateRange] = useState({
@@ -96,16 +98,6 @@ const AnalyticsDashboardPage: React.FC = () => {
}); });
const [reviews, setReviews] = useState<Review[]>([]);
const [reviewsLoading, setReviewsLoading] = useState(true);
const [reviewsFilters, setReviewsFilters] = useState({
status: '',
});
const [reviewsCurrentPage, setReviewsCurrentPage] = useState(1);
const [reviewsTotalPages, setReviewsTotalPages] = useState(1);
const [reviewsTotalItems, setReviewsTotalItems] = useState(0);
const reviewsPerPage = 5;
// Advanced Analytics Data // Advanced Analytics Data
const { data: comprehensiveData, loading: comprehensiveLoading, execute: fetchComprehensive } = useAsync<ComprehensiveAnalyticsData>( const { data: comprehensiveData, loading: comprehensiveLoading, execute: fetchComprehensive } = useAsync<ComprehensiveAnalyticsData>(
() => analyticsService.getComprehensiveAnalytics({ () => analyticsService.getComprehensiveAnalytics({
@@ -214,8 +206,6 @@ const AnalyticsDashboardPage: React.FC = () => {
useEffect(() => { useEffect(() => {
if (activeTab === 'audit-logs') { if (activeTab === 'audit-logs') {
fetchLogs(); fetchLogs();
} else if (activeTab === 'reviews') {
fetchReviews();
} else if (activeTab === 'overview') { } else if (activeTab === 'overview') {
fetchComprehensive(); fetchComprehensive();
} else if (activeTab === 'revenue') { } else if (activeTab === 'revenue') {
@@ -227,17 +217,12 @@ const AnalyticsDashboardPage: React.FC = () => {
} else if (activeTab === 'financial') { } else if (activeTab === 'financial') {
Promise.all([fetchProfitLoss(), fetchPaymentMethods(), fetchRefunds()]); Promise.all([fetchProfitLoss(), fetchPaymentMethods(), fetchRefunds()]);
} }
}, [activeTab, auditFilters, currentPage, reviewsFilters, reviewsCurrentPage, analyticsDateRange]); }, [activeTab, auditFilters, currentPage, analyticsDateRange]);
useEffect(() => { useEffect(() => {
setAuditFilters(prev => ({ ...prev, page: currentPage })); setAuditFilters(prev => ({ ...prev, page: currentPage }));
}, [currentPage]); }, [currentPage]);
useEffect(() => {
if (activeTab === 'reviews') {
setReviewsCurrentPage(1);
}
}, [reviewsFilters, activeTab]);
const fetchLogs = async () => { const fetchLogs = async () => {
try { try {
@@ -400,76 +385,6 @@ const AnalyticsDashboardPage: React.FC = () => {
} }
}; };
const fetchReviews = async () => {
try {
setReviewsLoading(true);
const response = await reviewService.getReviews({
...reviewsFilters,
page: reviewsCurrentPage,
limit: reviewsPerPage,
});
setReviews(response.data.reviews);
if (response.data.pagination) {
setReviewsTotalPages(response.data.pagination.totalPages);
setReviewsTotalItems(response.data.pagination.total);
}
} catch (error: any) {
toast.error(error.response?.data?.message || 'Unable to load reviews list');
} finally {
setReviewsLoading(false);
}
};
const handleApproveReview = async (id: number) => {
try {
await reviewService.approveReview(id);
toast.success('Review approved successfully');
fetchReviews();
} catch (error: any) {
toast.error(error.response?.data?.message || 'Unable to approve review');
}
};
const handleRejectReview = async (id: number) => {
if (!window.confirm('Are you sure you want to reject this review?')) return;
try {
await reviewService.rejectReview(id);
toast.success('Review rejected successfully');
fetchReviews();
} catch (error: any) {
toast.error(error.response?.data?.message || 'Unable to reject review');
}
};
const getReviewStatusBadge = (status: string) => {
const badges: Record<string, { bg: string; text: string; label: string; border: string }> = {
pending: { bg: 'bg-gradient-to-r from-amber-50 to-yellow-50', text: 'text-amber-800', label: 'Pending', border: 'border-amber-200' },
approved: { bg: 'bg-gradient-to-r from-emerald-50 to-green-50', text: 'text-emerald-800', label: 'Approved', border: 'border-emerald-200' },
rejected: { bg: 'bg-gradient-to-r from-rose-50 to-red-50', text: 'text-rose-800', label: 'Rejected', border: 'border-rose-200' },
};
const badge = badges[status] || badges.pending;
return (
<span className={`px-3 py-1.5 rounded-full text-xs font-semibold border shadow-sm ${badge.bg} ${badge.text} ${badge.border}`}>
{badge.label}
</span>
);
};
const renderStars = (rating: number) => {
return (
<div className="flex items-center gap-0.5">
{[1, 2, 3, 4, 5].map((star) => (
<Star
key={star}
className={`w-4 h-4 ${star <= rating ? 'text-amber-400 fill-amber-400' : 'text-gray-300'}`}
/>
))}
</div>
);
};
const tabs = [ const tabs = [
{ id: 'overview' as AnalyticsTab, label: 'Overview', icon: BarChart3 }, { id: 'overview' as AnalyticsTab, label: 'Overview', icon: BarChart3 },
{ id: 'revenue' as AnalyticsTab, label: 'Revenue', icon: DollarSign }, { id: 'revenue' as AnalyticsTab, label: 'Revenue', icon: DollarSign },
@@ -478,7 +393,6 @@ const AnalyticsDashboardPage: React.FC = () => {
{ id: 'financial' as AnalyticsTab, label: 'Financial', icon: CreditCard }, { id: 'financial' as AnalyticsTab, label: 'Financial', icon: CreditCard },
{ id: 'reports' as AnalyticsTab, label: 'Reports', icon: FileText }, { id: 'reports' as AnalyticsTab, label: 'Reports', icon: FileText },
{ id: 'audit-logs' as AnalyticsTab, label: 'Audit Logs', icon: ClipboardList }, { id: 'audit-logs' as AnalyticsTab, label: 'Audit Logs', icon: ClipboardList },
{ id: 'reviews' as AnalyticsTab, label: 'Reviews', icon: Star },
]; ];
return ( return (
@@ -668,7 +582,7 @@ const AnalyticsDashboardPage: React.FC = () => {
</div> </div>
{/* Quick Access Cards */} {/* Quick Access Cards */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 lg:gap-8"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 lg:gap-8">
<div <div
onClick={() => setActiveTab('revenue')} onClick={() => setActiveTab('revenue')}
className="group relative bg-white/90 backdrop-blur-xl rounded-2xl shadow-xl border border-green-100/50 p-8 cursor-pointer transition-all duration-300 hover:shadow-2xl hover:scale-105 hover:border-green-300/60 overflow-hidden" className="group relative bg-white/90 backdrop-blur-xl rounded-2xl shadow-xl border border-green-100/50 p-8 cursor-pointer transition-all duration-300 hover:shadow-2xl hover:scale-105 hover:border-green-300/60 overflow-hidden"
@@ -731,6 +645,34 @@ const AnalyticsDashboardPage: React.FC = () => {
</p> </p>
</div> </div>
</div> </div>
<div
onClick={() => navigate('/admin/reviews')}
className="group relative bg-white/90 backdrop-blur-xl rounded-2xl shadow-xl border border-amber-100/50 p-8 cursor-pointer transition-all duration-300 hover:shadow-2xl hover:scale-105 hover:border-amber-300/60 overflow-hidden"
>
<div className="absolute top-0 right-0 w-32 h-32 bg-gradient-to-br from-amber-400/10 to-transparent rounded-bl-full"></div>
<div className="relative space-y-5">
<div className="flex items-center gap-4">
<div className="p-3.5 rounded-xl bg-gradient-to-br from-amber-500 to-amber-600 shadow-lg">
<Star className="w-6 h-6 text-white" />
</div>
<div>
<h3 className="font-bold text-gray-900 text-xl mb-1">Review Management</h3>
<div className="h-1 w-12 bg-gradient-to-r from-amber-500 to-amber-600 rounded-full"></div>
</div>
</div>
<p className="text-gray-600 text-sm leading-relaxed">
Approve and manage customer reviews and ratings
</p>
<div className="pt-5 border-t border-gray-100">
<div className="flex items-center justify-between text-sm">
<span className="text-gray-500 font-medium">Manage Reviews</span>
<ChevronRight className="w-5 h-5 text-amber-600 group-hover:translate-x-1 transition-transform" />
</div>
</div>
</div>
<div className="absolute inset-0 bg-gradient-to-r from-transparent via-amber-50/30 to-transparent opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none"></div>
</div>
</div> </div>
</> </>
) : ( ) : (
@@ -1275,169 +1217,6 @@ const AnalyticsDashboardPage: React.FC = () => {
</div> </div>
)} )}
{}
{activeTab === 'reviews' && (
<div className="space-y-8">
{}
<div className="bg-white/90 backdrop-blur-xl rounded-2xl shadow-xl border border-gray-200/50 p-8">
<div className="space-y-3">
<div className="flex items-center gap-3">
<div className="p-2.5 rounded-xl bg-gradient-to-br from-amber-500/10 to-yellow-500/10 border border-amber-200/40">
<Star className="w-6 h-6 text-amber-600 fill-amber-600" />
</div>
<h2 className="text-3xl font-extrabold text-gray-900">Review Management</h2>
</div>
<p className="text-gray-600 text-base max-w-2xl leading-relaxed">
Approve and manage customer reviews and ratings
</p>
</div>
</div>
{}
<div className="relative bg-white/90 backdrop-blur-xl rounded-2xl shadow-xl border border-gray-200/50 p-8">
<div className="flex items-center gap-3 mb-6">
<div className="p-2 rounded-xl bg-gradient-to-br from-amber-500/10 to-amber-600/10 border border-amber-200/40">
<Filter className="w-5 h-5 text-amber-600" />
</div>
<h3 className="text-xl font-bold text-gray-900">Filters</h3>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="space-y-2">
<label className="block text-sm font-semibold text-gray-900">Status</label>
<select
value={reviewsFilters.status}
onChange={(e) => setReviewsFilters({ ...reviewsFilters, status: e.target.value })}
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-amber-400 focus:ring-4 focus:ring-amber-100 transition-all duration-200 text-gray-700 font-medium shadow-sm hover:shadow-md cursor-pointer"
>
<option value="">All statuses</option>
<option value="pending">Pending</option>
<option value="approved">Approved</option>
<option value="rejected">Rejected</option>
</select>
</div>
<div className="flex items-end">
<div className="w-full px-4 py-3 bg-gradient-to-r from-gray-50 to-white border-2 border-gray-200 rounded-xl">
<span className="text-sm font-semibold text-gray-700">
{reviewsTotalItems} review{reviewsTotalItems !== 1 ? 's' : ''}
</span>
</div>
</div>
</div>
</div>
{}
{reviewsLoading && reviews.length === 0 ? (
<Loading fullScreen text="Loading reviews..." />
) : reviews.length === 0 ? (
<div className="relative bg-white/90 backdrop-blur-xl rounded-2xl shadow-xl border border-gray-200/50 p-8">
<EmptyState
title="No Reviews Found"
description="No reviews match your current filters."
/>
</div>
) : (
<>
<div className="relative bg-white/90 backdrop-blur-xl rounded-2xl shadow-xl border border-gray-200/50 overflow-hidden">
<div className="overflow-x-auto">
<table className="min-w-full divide-y divide-gray-200">
<thead className="bg-gradient-to-r from-gray-50 to-gray-100">
<tr>
<th className="px-8 py-5 text-left text-xs font-bold text-gray-700 uppercase tracking-wider border-b border-gray-200">User</th>
<th className="px-8 py-5 text-left text-xs font-bold text-gray-700 uppercase tracking-wider border-b border-gray-200">Room</th>
<th className="px-8 py-5 text-left text-xs font-bold text-gray-700 uppercase tracking-wider border-b border-gray-200">Rating</th>
<th className="px-8 py-5 text-left text-xs font-bold text-gray-700 uppercase tracking-wider border-b border-gray-200">Comment</th>
<th className="px-8 py-5 text-left text-xs font-bold text-gray-700 uppercase tracking-wider border-b border-gray-200">Created Date</th>
<th className="px-8 py-5 text-left text-xs font-bold text-gray-700 uppercase tracking-wider border-b border-gray-200">Status</th>
<th className="px-8 py-5 text-right text-xs font-bold text-gray-700 uppercase tracking-wider border-b border-gray-200">Actions</th>
</tr>
</thead>
<tbody className="bg-white divide-y divide-gray-200">
{reviews.map((review) => (
<tr key={review.id} className="hover:bg-gray-50 transition-colors">
<td className="px-8 py-5 whitespace-nowrap">
<div className="text-sm font-semibold text-gray-900">{review.user?.name}</div>
{review.user?.email && (
<div className="text-xs text-gray-500">{review.user.email}</div>
)}
</td>
<td className="px-8 py-5 whitespace-nowrap">
<div className="text-sm font-medium text-gray-900">
Room {review.room?.room_number}
</div>
{review.room?.room_type?.name && (
<div className="text-xs text-gray-500">{review.room.room_type.name}</div>
)}
</td>
<td className="px-8 py-5 whitespace-nowrap">
<div className="flex items-center gap-2">
{renderStars(review.rating)}
<span className="text-sm font-semibold text-gray-700">({review.rating})</span>
</div>
</td>
<td className="px-8 py-5">
<div className="text-sm text-gray-900 max-w-xs">{review.comment}</div>
</td>
<td className="px-8 py-5 whitespace-nowrap">
<div className="text-sm text-gray-600">
{new Date(review.created_at).toLocaleDateString('en-US', {
year: 'numeric',
month: 'short',
day: 'numeric'
})}
</div>
</td>
<td className="px-8 py-5 whitespace-nowrap">
{getReviewStatusBadge(review.status)}
</td>
<td className="px-8 py-5 whitespace-nowrap text-right text-sm font-medium">
{review.status === 'pending' && (
<div className="flex items-center justify-end gap-3">
<button
onClick={() => handleApproveReview(review.id)}
className="px-4 py-2 bg-gradient-to-r from-emerald-500 to-emerald-600 text-white rounded-lg hover:from-emerald-600 hover:to-emerald-700 transition-all duration-200 shadow-lg hover:shadow-xl font-semibold flex items-center gap-2"
title="Approve"
>
<CheckCircle className="w-4 h-4" />
Approve
</button>
<button
onClick={() => handleRejectReview(review.id)}
className="px-4 py-2 bg-gradient-to-r from-rose-500 to-rose-600 text-white rounded-lg hover:from-rose-600 hover:to-rose-700 transition-all duration-200 shadow-lg hover:shadow-xl font-semibold flex items-center gap-2"
title="Reject"
>
<XCircle className="w-4 h-4" />
Reject
</button>
</div>
)}
{review.status !== 'pending' && (
<span className="text-gray-400 text-xs">No actions available</span>
)}
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
{}
{reviewsTotalPages > 1 && (
<div className="flex justify-center">
<Pagination
currentPage={reviewsCurrentPage}
totalPages={reviewsTotalPages}
onPageChange={setReviewsCurrentPage}
totalItems={reviewsTotalItems}
itemsPerPage={reviewsPerPage}
/>
</div>
)}
</>
)}
</div>
)}
{} {}
{showDetails && selectedLog && ( {showDetails && selectedLog && (
<div className="fixed inset-0 bg-black/60 backdrop-blur-sm flex items-center justify-center z-50 p-4"> <div className="fixed inset-0 bg-black/60 backdrop-blur-sm flex items-center justify-center z-50 p-4">

View File

@@ -1,472 +0,0 @@
import React, { useState, useEffect, useRef } from 'react';
import {
FileText,
Search,
Filter,
Eye,
Activity,
AlertCircle,
CheckCircle,
XCircle,
Info
} from 'lucide-react';
import { toast } from 'react-toastify';
import Loading from '../../shared/components/Loading';
import EmptyState from '../../shared/components/EmptyState';
import Pagination from '../../shared/components/Pagination';
import { auditService, AuditLog, AuditLogFilters } from '../../features/analytics/services/auditService';
import { formatDate } from '../../shared/utils/format';
import { logger } from '../../shared/utils/logger';
const AuditLogsPage: React.FC = () => {
const [logs, setLogs] = useState<AuditLog[]>([]);
const [loading, setLoading] = useState(true);
const [currentPage, setCurrentPage] = useState(1);
const [totalPages, setTotalPages] = useState(1);
const [totalItems, setTotalItems] = useState(0);
const [selectedLog, setSelectedLog] = useState<AuditLog | null>(null);
const [showDetails, setShowDetails] = useState(false);
const itemsPerPage = 20;
const abortControllerRef = useRef<AbortController | null>(null);
const [filters, setFilters] = useState<AuditLogFilters>({
page: 1,
limit: itemsPerPage,
});
useEffect(() => {
// Cancel previous request if exists
if (abortControllerRef.current) {
abortControllerRef.current.abort();
}
// Create new abort controller
abortControllerRef.current = new AbortController();
fetchLogs();
// Cleanup: abort request on unmount
return () => {
if (abortControllerRef.current) {
abortControllerRef.current.abort();
}
};
}, [filters, currentPage]);
useEffect(() => {
setFilters(prev => ({ ...prev, page: currentPage }));
}, [currentPage]);
const fetchLogs = async () => {
try {
setLoading(true);
const response = await auditService.getAuditLogs({
...filters,
page: currentPage,
limit: itemsPerPage,
});
setLogs(response.data.logs);
if (response.data.pagination) {
setTotalPages(response.data.pagination.totalPages);
setTotalItems(response.data.pagination.total);
}
} catch (error: any) {
// Handle AbortError silently
if (error.name === 'AbortError') {
return;
}
// Clear data when API connection fails
setLogs([]);
setTotalPages(1);
setTotalItems(0);
logger.error('Error fetching audit logs', error);
toast.error(error.response?.data?.message || 'Unable to load audit logs');
} finally {
setLoading(false);
}
};
const handleFilterChange = (key: keyof AuditLogFilters, value: any) => {
setFilters(prev => ({ ...prev, [key]: value }));
setCurrentPage(1);
};
const handleSearch = (searchTerm: string) => {
handleFilterChange('search', searchTerm || undefined);
};
const handleViewDetails = (log: AuditLog) => {
setSelectedLog(log);
setShowDetails(true);
};
const getStatusIcon = (status: string) => {
switch (status) {
case 'success':
return <CheckCircle className="w-5 h-5 text-green-500" />;
case 'failed':
return <XCircle className="w-5 h-5 text-red-500" />;
case 'error':
return <AlertCircle className="w-5 h-5 text-orange-500" />;
default:
return <Info className="w-5 h-5 text-gray-500" />;
}
};
const getStatusBadge = (status: string) => {
const baseClasses = "px-2 py-1 rounded-full text-xs font-medium";
switch (status) {
case 'success':
return `${baseClasses} bg-green-100 text-green-800`;
case 'failed':
return `${baseClasses} bg-red-100 text-red-800`;
case 'error':
return `${baseClasses} bg-orange-100 text-orange-800`;
default:
return `${baseClasses} bg-gray-100 text-gray-800`;
}
};
if (loading && logs.length === 0) {
return <Loading fullScreen text="Loading audit logs..." />;
}
return (
<div className="container mx-auto px-4 py-8">
<div className="mb-8">
<h1 className="text-3xl font-bold text-gray-900 mb-2">Audit Logs</h1>
<p className="text-gray-600">View all system activity and actions</p>
</div>
{}
<div className="mb-6 bg-white p-4 rounded-lg shadow-md">
<div className="flex items-center space-x-2 mb-4">
<Filter className="w-5 h-5 text-gray-500" />
<h3 className="text-lg font-semibold text-gray-900">Filters</h3>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Search
</label>
<div className="relative">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
<input
type="text"
placeholder="Search actions, types..."
value={filters.search || ''}
onChange={(e) => handleSearch(e.target.value)}
className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-[#d4af37]"
/>
</div>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Action
</label>
<input
type="text"
placeholder="Filter by action"
value={filters.action || ''}
onChange={(e) => handleFilterChange('action', e.target.value || undefined)}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-[#d4af37]"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Resource Type
</label>
<input
type="text"
placeholder="Filter by type"
value={filters.resource_type || ''}
onChange={(e) => handleFilterChange('resource_type', e.target.value || undefined)}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-[#d4af37]"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Status
</label>
<select
value={filters.status || ''}
onChange={(e) => handleFilterChange('status', e.target.value || undefined)}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-[#d4af37]"
>
<option value="">All</option>
<option value="success">Success</option>
<option value="failed">Failed</option>
<option value="error">Error</option>
</select>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Start Date
</label>
<input
type="date"
value={filters.start_date || ''}
onChange={(e) => handleFilterChange('start_date', e.target.value || undefined)}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-[#d4af37]"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
End Date
</label>
<input
type="date"
value={filters.end_date || ''}
onChange={(e) => handleFilterChange('end_date', e.target.value || undefined)}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-[#d4af37]"
/>
</div>
</div>
</div>
{}
<div className="grid grid-cols-1 md:grid-cols-4 gap-4 mb-6">
<div className="bg-white p-4 rounded-lg shadow-md">
<div className="flex items-center justify-between">
<div>
<p className="text-sm text-gray-600">Total Logs</p>
<p className="text-2xl font-bold text-gray-900">{totalItems}</p>
</div>
<FileText className="w-8 h-8 text-[#d4af37]" />
</div>
</div>
<div className="bg-white p-4 rounded-lg shadow-md">
<div className="flex items-center justify-between">
<div>
<p className="text-sm text-gray-600">Current Page</p>
<p className="text-2xl font-bold text-gray-900">{currentPage}</p>
</div>
<Activity className="w-8 h-8 text-blue-500" />
</div>
</div>
</div>
{}
{logs.length === 0 ? (
<EmptyState
title="No Audit Logs Found"
description="No audit logs match your current filters."
/>
) : (
<div className="bg-white rounded-lg shadow-md overflow-hidden">
<div className="overflow-x-auto">
<table className="min-w-full divide-y divide-gray-200">
<thead className="bg-gray-50">
<tr>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
ID
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Action
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Resource
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
User
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Status
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
IP Address
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Date
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Actions
</th>
</tr>
</thead>
<tbody className="bg-white divide-y divide-gray-200">
{logs.map((log) => (
<tr key={log.id} className="hover:bg-gray-50">
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
#{log.id}
</td>
<td className="px-6 py-4 whitespace-nowrap">
<div className="text-sm font-medium text-gray-900">{log.action}</div>
</td>
<td className="px-6 py-4 whitespace-nowrap">
<div className="text-sm text-gray-900">{log.resource_type}</div>
{log.resource_id && (
<div className="text-xs text-gray-500">ID: {log.resource_id}</div>
)}
</td>
<td className="px-6 py-4 whitespace-nowrap">
{log.user ? (
<div>
<div className="text-sm font-medium text-gray-900">{log.user.full_name}</div>
<div className="text-xs text-gray-500">{log.user.email}</div>
</div>
) : (
<span className="text-sm text-gray-400">System</span>
)}
</td>
<td className="px-6 py-4 whitespace-nowrap">
<div className="flex items-center space-x-2">
{getStatusIcon(log.status)}
<span className={getStatusBadge(log.status)}>
{log.status}
</span>
</div>
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{log.ip_address || '-'}
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{formatDate(log.created_at)}
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium">
<button
onClick={() => handleViewDetails(log)}
className="text-[#d4af37] hover:text-[#c9a227] flex items-center space-x-1"
>
<Eye className="w-4 h-4" />
<span>View</span>
</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
)}
{}
{totalPages > 1 && (
<div className="mt-6">
<Pagination
currentPage={currentPage}
totalPages={totalPages}
onPageChange={setCurrentPage}
/>
</div>
)}
{}
{showDetails && selectedLog && (
<div className="fixed inset-0 bg-black bg-opacity-50 z-50 overflow-y-auto p-4">
<div className="min-h-full flex items-start justify-center py-8">
<div className="bg-white rounded-lg max-w-3xl w-full my-8 max-h-[calc(100vh-4rem)] overflow-y-auto">
<div className="p-6">
<div className="flex justify-between items-center mb-4">
<h2 className="text-2xl font-bold text-gray-900">Audit Log Details</h2>
<button
onClick={() => setShowDetails(false)}
className="text-gray-400 hover:text-gray-600"
>
<XCircle className="w-6 h-6" />
</button>
</div>
<div className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-gray-700">ID</label>
<p className="mt-1 text-sm text-gray-900">#{selectedLog.id}</p>
</div>
<div>
<label className="block text-sm font-medium text-gray-700">Status</label>
<div className="mt-1 flex items-center space-x-2">
{getStatusIcon(selectedLog.status)}
<span className={getStatusBadge(selectedLog.status)}>
{selectedLog.status}
</span>
</div>
</div>
<div>
<label className="block text-sm font-medium text-gray-700">Action</label>
<p className="mt-1 text-sm text-gray-900">{selectedLog.action}</p>
</div>
<div>
<label className="block text-sm font-medium text-gray-700">Resource Type</label>
<p className="mt-1 text-sm text-gray-900">{selectedLog.resource_type}</p>
</div>
{selectedLog.resource_id && (
<div>
<label className="block text-sm font-medium text-gray-700">Resource ID</label>
<p className="mt-1 text-sm text-gray-900">{selectedLog.resource_id}</p>
</div>
)}
<div>
<label className="block text-sm font-medium text-gray-700">Date</label>
<p className="mt-1 text-sm text-gray-900">{formatDate(selectedLog.created_at)}</p>
</div>
{selectedLog.user && (
<>
<div>
<label className="block text-sm font-medium text-gray-700">User</label>
<p className="mt-1 text-sm text-gray-900">{selectedLog.user.full_name}</p>
<p className="text-xs text-gray-500">{selectedLog.user.email}</p>
</div>
<div>
<label className="block text-sm font-medium text-gray-700">User ID</label>
<p className="mt-1 text-sm text-gray-900">{selectedLog.user_id}</p>
</div>
</>
)}
{selectedLog.ip_address && (
<div>
<label className="block text-sm font-medium text-gray-700">IP Address</label>
<p className="mt-1 text-sm text-gray-900">{selectedLog.ip_address}</p>
</div>
)}
{selectedLog.request_id && (
<div>
<label className="block text-sm font-medium text-gray-700">Request ID</label>
<p className="mt-1 text-sm text-gray-900 font-mono text-xs">{selectedLog.request_id}</p>
</div>
)}
</div>
{selectedLog.user_agent && (
<div>
<label className="block text-sm font-medium text-gray-700">User Agent</label>
<p className="mt-1 text-sm text-gray-900 break-all">{selectedLog.user_agent}</p>
</div>
)}
{selectedLog.error_message && (
<div>
<label className="block text-sm font-medium text-red-700">Error Message</label>
<p className="mt-1 text-sm text-red-900 bg-red-50 p-3 rounded">{selectedLog.error_message}</p>
</div>
)}
{selectedLog.details && (
<div>
<label className="block text-sm font-medium text-gray-700">Details</label>
<pre className="mt-1 text-sm text-gray-900 bg-gray-50 p-3 rounded overflow-x-auto">
{JSON.stringify(selectedLog.details, null, 2)}
</pre>
</div>
)}
</div>
<div className="mt-6 flex justify-end">
<button
onClick={() => setShowDetails(false)}
className="px-4 py-2 bg-gray-200 text-gray-800 rounded-lg hover:bg-gray-300 transition-colors"
>
Close
</button>
</div>
</div>
</div>
</div>
</div>
)}
</div>
);
};
export default AuditLogsPage;

View File

@@ -255,7 +255,7 @@ const BannerManagementPage: React.FC = () => {
resetForm(); resetForm();
setShowModal(true); setShowModal(true);
}} }}
className="flex items-center space-x-2 px-4 py-2 bg-[#d4af37] text-white rounded-lg hover:bg-[#c9a227] transition-colors" className="flex items-center space-x-2 px-4 py-2 bg-[var(--luxury-gold)] text-white rounded-lg hover:bg-[var(--luxury-gold-dark)] transition-colors"
> >
<Plus className="w-5 h-5" /> <Plus className="w-5 h-5" />
<span>Add Banner</span> <span>Add Banner</span>
@@ -276,7 +276,7 @@ const BannerManagementPage: React.FC = () => {
placeholder="Search by title..." placeholder="Search by title..."
value={filters.search} value={filters.search}
onChange={(e) => setFilters({ ...filters, search: e.target.value })} onChange={(e) => setFilters({ ...filters, search: e.target.value })}
className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-[#d4af37]" className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-[var(--luxury-gold)]"
/> />
</div> </div>
</div> </div>
@@ -287,7 +287,7 @@ const BannerManagementPage: React.FC = () => {
<select <select
value={filters.position} value={filters.position}
onChange={(e) => setFilters({ ...filters, position: e.target.value })} onChange={(e) => setFilters({ ...filters, position: e.target.value })}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-[#d4af37]" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-[var(--luxury-gold)]"
> >
<option value="">All Positions</option> <option value="">All Positions</option>
<option value="home">Home</option> <option value="home">Home</option>
@@ -384,7 +384,7 @@ const BannerManagementPage: React.FC = () => {
<div className="flex space-x-2"> <div className="flex space-x-2">
<button <button
onClick={() => handleEdit(banner)} onClick={() => handleEdit(banner)}
className="text-[#d4af37] hover:text-[#c9a227]" className="text-[var(--luxury-gold)] hover:text-[var(--luxury-gold-dark)]"
> >
<Edit className="w-5 h-5" /> <Edit className="w-5 h-5" />
</button> </button>

View File

@@ -426,7 +426,7 @@ const BlogManagementPage: React.FC = () => {
type="button" type="button"
onClick={() => fileInputRef.current?.click()} onClick={() => fileInputRef.current?.click()}
disabled={isUploading} disabled={isUploading}
className="w-full flex items-center justify-center gap-2 px-4 py-2 bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-white rounded-lg hover:from-[#f5d76e] hover:to-[#d4af37] transition-all disabled:opacity-50 disabled:cursor-not-allowed" className="w-full flex items-center justify-center gap-2 px-4 py-2 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-white rounded-lg hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] transition-all disabled:opacity-50 disabled:cursor-not-allowed"
> >
{isUploading ? ( {isUploading ? (
<> <>
@@ -468,7 +468,7 @@ const BlogManagementPage: React.FC = () => {
</button> </button>
<button <button
onClick={() => handleOpenModal()} onClick={() => handleOpenModal()}
className="flex items-center gap-2 px-4 py-2 bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-white rounded-lg hover:from-[#f5d76e] hover:to-[#d4af37] transition-all shadow-lg" className="flex items-center gap-2 px-4 py-2 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-white rounded-lg hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] transition-all shadow-lg"
> >
<Plus className="w-5 h-5" /> <Plus className="w-5 h-5" />
<span>New Post</span> <span>New Post</span>
@@ -488,7 +488,7 @@ const BlogManagementPage: React.FC = () => {
placeholder="Search posts..." placeholder="Search posts..."
value={filters.search} value={filters.search}
onChange={(e) => setFilters({ ...filters, search: e.target.value })} onChange={(e) => setFilters({ ...filters, search: e.target.value })}
className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-transparent" className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-transparent"
/> />
</div> </div>
</div> </div>
@@ -501,7 +501,7 @@ const BlogManagementPage: React.FC = () => {
published: value === 'all' ? undefined : value === 'published', published: value === 'all' ? undefined : value === 'published',
}); });
}} }}
className="px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-transparent" className="px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-transparent"
> >
<option value="all">All Posts</option> <option value="all">All Posts</option>
<option value="published">Published</option> <option value="published">Published</option>
@@ -561,7 +561,7 @@ const BlogManagementPage: React.FC = () => {
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<button <button
onClick={() => handleOpenModal(post)} onClick={() => handleOpenModal(post)}
className="text-[#d4af37] hover:text-[#c9a227]" className="text-[var(--luxury-gold)] hover:text-[var(--luxury-gold-dark)]"
> >
<Edit className="w-4 h-4" /> <Edit className="w-4 h-4" />
</button> </button>
@@ -646,7 +646,7 @@ const BlogManagementPage: React.FC = () => {
value={formData.slug} value={formData.slug}
onChange={(e) => setFormData({ ...formData, slug: e.target.value })} onChange={(e) => setFormData({ ...formData, slug: e.target.value })}
placeholder="Auto-generated from title" placeholder="Auto-generated from title"
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-transparent bg-gray-50" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-transparent bg-gray-50"
/> />
<p className="mt-1 text-xs text-gray-500">Leave empty to auto-generate, or customize the URL slug</p> <p className="mt-1 text-xs text-gray-500">Leave empty to auto-generate, or customize the URL slug</p>
</div> </div>
@@ -657,7 +657,7 @@ const BlogManagementPage: React.FC = () => {
value={formData.excerpt} value={formData.excerpt}
onChange={(e) => setFormData({ ...formData, excerpt: e.target.value })} onChange={(e) => setFormData({ ...formData, excerpt: e.target.value })}
rows={3} rows={3}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-transparent" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-transparent"
/> />
</div> </div>
@@ -668,7 +668,7 @@ const BlogManagementPage: React.FC = () => {
value={formData.content} value={formData.content}
onChange={(e) => setFormData({ ...formData, content: e.target.value })} onChange={(e) => setFormData({ ...formData, content: e.target.value })}
rows={10} rows={10}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-transparent" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-transparent"
/> />
</div> </div>
@@ -682,7 +682,7 @@ const BlogManagementPage: React.FC = () => {
<button <button
type="button" type="button"
onClick={() => setShowSectionBuilder(!showSectionBuilder)} onClick={() => setShowSectionBuilder(!showSectionBuilder)}
className="flex items-center gap-2 px-4 py-2 bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-white rounded-lg hover:from-[#f5d76e] hover:to-[#d4af37] transition-all shadow-lg" className="flex items-center gap-2 px-4 py-2 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-white rounded-lg hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] transition-all shadow-lg"
> >
<Sparkles className="w-4 h-4" /> <Sparkles className="w-4 h-4" />
<span>{showSectionBuilder ? 'Hide' : 'Show'} Section Builder</span> <span>{showSectionBuilder ? 'Hide' : 'Show'} Section Builder</span>
@@ -707,9 +707,9 @@ const BlogManagementPage: React.FC = () => {
key={type} key={type}
type="button" type="button"
onClick={() => addSection(type)} onClick={() => addSection(type)}
className="flex flex-col items-center gap-2 p-4 bg-gradient-to-br from-gray-50 to-white border-2 border-gray-200 rounded-xl hover:border-[#d4af37] hover:shadow-lg transition-all group" className="flex flex-col items-center gap-2 p-4 bg-gradient-to-br from-gray-50 to-white border-2 border-gray-200 rounded-xl hover:border-[var(--luxury-gold)] hover:shadow-lg transition-all group"
> >
<Icon className="w-6 h-6 text-gray-600 group-hover:text-[#d4af37] transition-colors" /> <Icon className="w-6 h-6 text-gray-600 group-hover:text-[var(--luxury-gold)] transition-colors" />
<span className="text-sm font-medium text-gray-700">{label}</span> <span className="text-sm font-medium text-gray-700">{label}</span>
</button> </button>
))} ))}
@@ -726,7 +726,7 @@ const BlogManagementPage: React.FC = () => {
<div className="flex items-center justify-between mb-4"> <div className="flex items-center justify-between mb-4">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<GripVertical className="w-5 h-5 text-gray-400" /> <GripVertical className="w-5 h-5 text-gray-400" />
<span className="px-3 py-1 bg-[#d4af37]/10 text-[#d4af37] rounded-full text-sm font-semibold uppercase"> <span className="px-3 py-1 bg-[var(--luxury-gold)]/10 text-[var(--luxury-gold)] rounded-full text-sm font-semibold uppercase">
{section.type} {section.type}
</span> </span>
</div> </div>
@@ -735,7 +735,7 @@ const BlogManagementPage: React.FC = () => {
type="button" type="button"
onClick={() => moveSection(index, 'up')} onClick={() => moveSection(index, 'up')}
disabled={index === 0} disabled={index === 0}
className="p-2 text-gray-400 hover:text-[#d4af37] disabled:opacity-30 disabled:cursor-not-allowed" className="p-2 text-gray-400 hover:text-[var(--luxury-gold)] disabled:opacity-30 disabled:cursor-not-allowed"
> >
<MoveUp className="w-4 h-4" /> <MoveUp className="w-4 h-4" />
</button> </button>
@@ -743,7 +743,7 @@ const BlogManagementPage: React.FC = () => {
type="button" type="button"
onClick={() => moveSection(index, 'down')} onClick={() => moveSection(index, 'down')}
disabled={index === (formData.sections?.length || 0) - 1} disabled={index === (formData.sections?.length || 0) - 1}
className="p-2 text-gray-400 hover:text-[#d4af37] disabled:opacity-30 disabled:cursor-not-allowed" className="p-2 text-gray-400 hover:text-[var(--luxury-gold)] disabled:opacity-30 disabled:cursor-not-allowed"
> >
<MoveDown className="w-4 h-4" /> <MoveDown className="w-4 h-4" />
</button> </button>
@@ -767,7 +767,7 @@ const BlogManagementPage: React.FC = () => {
type="text" type="text"
value={section.title || ''} value={section.title || ''}
onChange={(e) => updateSection(index, { title: e.target.value })} onChange={(e) => updateSection(index, { title: e.target.value })}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37]" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)]"
placeholder="Hero Title" placeholder="Hero Title"
/> />
</div> </div>
@@ -777,7 +777,7 @@ const BlogManagementPage: React.FC = () => {
value={section.content || ''} value={section.content || ''}
onChange={(e) => updateSection(index, { content: e.target.value })} onChange={(e) => updateSection(index, { content: e.target.value })}
rows={3} rows={3}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37]" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)]"
placeholder="Hero content" placeholder="Hero content"
/> />
</div> </div>
@@ -795,7 +795,7 @@ const BlogManagementPage: React.FC = () => {
type="url" type="url"
value={section.image || ''} value={section.image || ''}
onChange={(e) => updateSection(index, { image: e.target.value })} onChange={(e) => updateSection(index, { image: e.target.value })}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] text-sm" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] text-sm"
placeholder="https://..." placeholder="https://..."
/> />
</div> </div>
@@ -811,7 +811,7 @@ const BlogManagementPage: React.FC = () => {
type="text" type="text"
value={section.title || ''} value={section.title || ''}
onChange={(e) => updateSection(index, { title: e.target.value })} onChange={(e) => updateSection(index, { title: e.target.value })}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37]" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)]"
/> />
</div> </div>
<div> <div>
@@ -820,7 +820,7 @@ const BlogManagementPage: React.FC = () => {
value={section.content || ''} value={section.content || ''}
onChange={(e) => updateSection(index, { content: e.target.value })} onChange={(e) => updateSection(index, { content: e.target.value })}
rows={6} rows={6}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37]" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)]"
placeholder="Enter your text content (HTML supported). You can use &lt;img src='URL' /&gt; to add images." placeholder="Enter your text content (HTML supported). You can use &lt;img src='URL' /&gt; to add images."
/> />
<div className="mt-2"> <div className="mt-2">
@@ -847,7 +847,7 @@ const BlogManagementPage: React.FC = () => {
<select <select
value={section.alignment || 'left'} value={section.alignment || 'left'}
onChange={(e) => updateSection(index, { alignment: e.target.value as 'left' | 'center' | 'right' })} onChange={(e) => updateSection(index, { alignment: e.target.value as 'left' | 'center' | 'right' })}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37]" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)]"
> >
<option value="left">Left</option> <option value="left">Left</option>
<option value="center">Center</option> <option value="center">Center</option>
@@ -873,7 +873,7 @@ const BlogManagementPage: React.FC = () => {
type="url" type="url"
value={section.image || ''} value={section.image || ''}
onChange={(e) => updateSection(index, { image: e.target.value })} onChange={(e) => updateSection(index, { image: e.target.value })}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] text-sm" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] text-sm"
placeholder="https://..." placeholder="https://..."
/> />
</div> </div>
@@ -884,7 +884,7 @@ const BlogManagementPage: React.FC = () => {
type="text" type="text"
value={section.title || ''} value={section.title || ''}
onChange={(e) => updateSection(index, { title: e.target.value })} onChange={(e) => updateSection(index, { title: e.target.value })}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37]" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)]"
/> />
</div> </div>
</> </>
@@ -915,7 +915,7 @@ const BlogManagementPage: React.FC = () => {
updatedImages[imgIndex] = e.target.value; updatedImages[imgIndex] = e.target.value;
updateSection(index, { images: updatedImages }); updateSection(index, { images: updatedImages });
}} }}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] text-sm mb-2" className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] text-sm mb-2"
placeholder="Image URL" placeholder="Image URL"
/> />
<div className="flex gap-2"> <div className="flex gap-2">
@@ -950,7 +950,7 @@ const BlogManagementPage: React.FC = () => {
value={(section.images || []).join('\n')} value={(section.images || []).join('\n')}
onChange={(e) => updateSection(index, { images: e.target.value.split('\n').filter(url => url.trim()) })} onChange={(e) => updateSection(index, { images: e.target.value.split('\n').filter(url => url.trim()) })}
rows={4} rows={4}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] text-sm" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] text-sm"
placeholder="https://image1.com/...&#10;https://image2.com/..." placeholder="https://image1.com/...&#10;https://image2.com/..."
/> />
</div> </div>
@@ -965,7 +965,7 @@ const BlogManagementPage: React.FC = () => {
value={section.quote || ''} value={section.quote || ''}
onChange={(e) => updateSection(index, { quote: e.target.value })} onChange={(e) => updateSection(index, { quote: e.target.value })}
rows={4} rows={4}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37]" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)]"
placeholder="Enter the quote" placeholder="Enter the quote"
/> />
</div> </div>
@@ -975,7 +975,7 @@ const BlogManagementPage: React.FC = () => {
type="text" type="text"
value={section.author || ''} value={section.author || ''}
onChange={(e) => updateSection(index, { author: e.target.value })} onChange={(e) => updateSection(index, { author: e.target.value })}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37]" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)]"
/> />
</div> </div>
</> </>
@@ -1012,7 +1012,7 @@ const BlogManagementPage: React.FC = () => {
updateSection(index, { features: updatedFeatures }); updateSection(index, { features: updatedFeatures });
}} }}
placeholder="Feature title" placeholder="Feature title"
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] text-sm" className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] text-sm"
/> />
<textarea <textarea
value={feature.description || ''} value={feature.description || ''}
@@ -1023,7 +1023,7 @@ const BlogManagementPage: React.FC = () => {
}} }}
placeholder="Feature description" placeholder="Feature description"
rows={2} rows={2}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] text-sm" className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] text-sm"
/> />
<input <input
type="text" type="text"
@@ -1034,7 +1034,7 @@ const BlogManagementPage: React.FC = () => {
updateSection(index, { features: updatedFeatures }); updateSection(index, { features: updatedFeatures });
}} }}
placeholder="Icon URL (optional)" placeholder="Icon URL (optional)"
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] text-sm" className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] text-sm"
/> />
</div> </div>
</div> </div>
@@ -1062,7 +1062,7 @@ const BlogManagementPage: React.FC = () => {
type="text" type="text"
value={section.title || ''} value={section.title || ''}
onChange={(e) => updateSection(index, { title: e.target.value })} onChange={(e) => updateSection(index, { title: e.target.value })}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37]" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)]"
/> />
</div> </div>
<div> <div>
@@ -1071,7 +1071,7 @@ const BlogManagementPage: React.FC = () => {
value={section.content || ''} value={section.content || ''}
onChange={(e) => updateSection(index, { content: e.target.value })} onChange={(e) => updateSection(index, { content: e.target.value })}
rows={3} rows={3}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37]" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)]"
/> />
</div> </div>
<div className="grid grid-cols-2 gap-4"> <div className="grid grid-cols-2 gap-4">
@@ -1081,7 +1081,7 @@ const BlogManagementPage: React.FC = () => {
type="text" type="text"
value={section.cta_text || ''} value={section.cta_text || ''}
onChange={(e) => updateSection(index, { cta_text: e.target.value })} onChange={(e) => updateSection(index, { cta_text: e.target.value })}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37]" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)]"
/> />
</div> </div>
<div> <div>
@@ -1090,7 +1090,7 @@ const BlogManagementPage: React.FC = () => {
type="url" type="url"
value={section.cta_link || ''} value={section.cta_link || ''}
onChange={(e) => updateSection(index, { cta_link: e.target.value })} onChange={(e) => updateSection(index, { cta_link: e.target.value })}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37]" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)]"
/> />
</div> </div>
</div> </div>
@@ -1104,7 +1104,7 @@ const BlogManagementPage: React.FC = () => {
type="url" type="url"
value={section.video_url || ''} value={section.video_url || ''}
onChange={(e) => updateSection(index, { video_url: e.target.value })} onChange={(e) => updateSection(index, { video_url: e.target.value })}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37]" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)]"
placeholder="https://youtube.com/watch?v=..." placeholder="https://youtube.com/watch?v=..."
/> />
</div> </div>
@@ -1125,7 +1125,7 @@ const BlogManagementPage: React.FC = () => {
value={formData.featured_image} value={formData.featured_image}
onChange={(e) => setFormData({ ...formData, featured_image: e.target.value })} onChange={(e) => setFormData({ ...formData, featured_image: e.target.value })}
placeholder="https://images.unsplash.com/..." placeholder="https://images.unsplash.com/..."
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-transparent" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-transparent"
/> />
</div> </div>
@@ -1143,7 +1143,7 @@ const BlogManagementPage: React.FC = () => {
} }
}} }}
placeholder="Add a tag and press Enter" placeholder="Add a tag and press Enter"
className="flex-1 px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-transparent" className="flex-1 px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-transparent"
/> />
<button <button
type="button" type="button"
@@ -1157,13 +1157,13 @@ const BlogManagementPage: React.FC = () => {
{formData.tags?.map((tag) => ( {formData.tags?.map((tag) => (
<span <span
key={tag} key={tag}
className="inline-flex items-center gap-1 px-3 py-1 bg-[#d4af37]/10 text-[#d4af37] rounded-full text-sm" className="inline-flex items-center gap-1 px-3 py-1 bg-[var(--luxury-gold)]/10 text-[var(--luxury-gold)] rounded-full text-sm"
> >
{tag} {tag}
<button <button
type="button" type="button"
onClick={() => handleRemoveTag(tag)} onClick={() => handleRemoveTag(tag)}
className="hover:text-[#c9a227]" className="hover:text-[var(--luxury-gold-dark)]"
> >
<X className="w-3 h-3" /> <X className="w-3 h-3" />
</button> </button>
@@ -1179,7 +1179,7 @@ const BlogManagementPage: React.FC = () => {
type="text" type="text"
value={formData.meta_title} value={formData.meta_title}
onChange={(e) => setFormData({ ...formData, meta_title: e.target.value })} onChange={(e) => setFormData({ ...formData, meta_title: e.target.value })}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-transparent" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-transparent"
/> />
</div> </div>
<div> <div>
@@ -1188,7 +1188,7 @@ const BlogManagementPage: React.FC = () => {
type="text" type="text"
value={formData.meta_keywords} value={formData.meta_keywords}
onChange={(e) => setFormData({ ...formData, meta_keywords: e.target.value })} onChange={(e) => setFormData({ ...formData, meta_keywords: e.target.value })}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-transparent" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-transparent"
/> />
</div> </div>
</div> </div>
@@ -1199,7 +1199,7 @@ const BlogManagementPage: React.FC = () => {
value={formData.meta_description} value={formData.meta_description}
onChange={(e) => setFormData({ ...formData, meta_description: e.target.value })} onChange={(e) => setFormData({ ...formData, meta_description: e.target.value })}
rows={3} rows={3}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-transparent" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-transparent"
/> />
</div> </div>
@@ -1209,7 +1209,7 @@ const BlogManagementPage: React.FC = () => {
type="checkbox" type="checkbox"
checked={formData.is_published} checked={formData.is_published}
onChange={(e) => setFormData({ ...formData, is_published: e.target.checked })} onChange={(e) => setFormData({ ...formData, is_published: e.target.checked })}
className="w-4 h-4 text-[#d4af37] border-gray-300 rounded focus:ring-[#d4af37]" className="w-4 h-4 text-[var(--luxury-gold)] border-gray-300 rounded focus:ring-[var(--luxury-gold)]"
/> />
<span className="text-sm font-medium text-gray-700">Publish</span> <span className="text-sm font-medium text-gray-700">Publish</span>
</label> </label>
@@ -1220,7 +1220,7 @@ const BlogManagementPage: React.FC = () => {
type="datetime-local" type="datetime-local"
value={formData.published_at ? new Date(formData.published_at).toISOString().slice(0, 16) : ''} value={formData.published_at ? new Date(formData.published_at).toISOString().slice(0, 16) : ''}
onChange={(e) => setFormData({ ...formData, published_at: e.target.value ? new Date(e.target.value).toISOString() : undefined })} onChange={(e) => setFormData({ ...formData, published_at: e.target.value ? new Date(e.target.value).toISOString() : undefined })}
className="px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-transparent" className="px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-transparent"
/> />
</div> </div>
)} )}

File diff suppressed because it is too large Load Diff

View File

@@ -162,7 +162,7 @@ const ComplaintManagementPage: React.FC = () => {
<select <select
value={filters.status || ''} value={filters.status || ''}
onChange={(e) => setFilters({ ...filters, status: e.target.value || undefined, page: 1 })} onChange={(e) => setFilters({ ...filters, status: e.target.value || undefined, page: 1 })}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-transparent" className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-transparent"
> >
<option value="">All Statuses</option> <option value="">All Statuses</option>
<option value="open">Open</option> <option value="open">Open</option>
@@ -177,7 +177,7 @@ const ComplaintManagementPage: React.FC = () => {
<select <select
value={filters.priority || ''} value={filters.priority || ''}
onChange={(e) => setFilters({ ...filters, priority: e.target.value || undefined, page: 1 })} onChange={(e) => setFilters({ ...filters, priority: e.target.value || undefined, page: 1 })}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-transparent" className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-transparent"
> >
<option value="">All Priorities</option> <option value="">All Priorities</option>
<option value="low">Low</option> <option value="low">Low</option>
@@ -191,7 +191,7 @@ const ComplaintManagementPage: React.FC = () => {
<select <select
value={filters.category || ''} value={filters.category || ''}
onChange={(e) => setFilters({ ...filters, category: e.target.value || undefined, page: 1 })} onChange={(e) => setFilters({ ...filters, category: e.target.value || undefined, page: 1 })}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-transparent" className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-transparent"
> >
<option value="">All Categories</option> <option value="">All Categories</option>
<option value="room_quality">Room Quality</option> <option value="room_quality">Room Quality</option>
@@ -261,7 +261,7 @@ const ComplaintManagementPage: React.FC = () => {
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium"> <td className="px-6 py-4 whitespace-nowrap text-sm font-medium">
<button <button
onClick={() => handleViewDetails(complaint.id)} onClick={() => handleViewDetails(complaint.id)}
className="text-[#d4af37] hover:text-[#c9a227] mr-3" className="text-[var(--luxury-gold)] hover:text-[var(--luxury-gold-dark)] mr-3"
> >
<Eye className="w-5 h-5" /> <Eye className="w-5 h-5" />
</button> </button>
@@ -415,7 +415,7 @@ const ResolveComplaintModal: React.FC<{
value={resolution} value={resolution}
onChange={(e) => setResolution(e.target.value)} onChange={(e) => setResolution(e.target.value)}
rows={4} rows={4}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-transparent" className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-transparent"
placeholder="Describe how the complaint was resolved..." placeholder="Describe how the complaint was resolved..."
/> />
</div> </div>
@@ -426,7 +426,7 @@ const ResolveComplaintModal: React.FC<{
<select <select
value={rating || ''} value={rating || ''}
onChange={(e) => setRating(e.target.value ? parseInt(e.target.value) : undefined)} onChange={(e) => setRating(e.target.value ? parseInt(e.target.value) : undefined)}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-transparent" className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-transparent"
> >
<option value="">Not rated</option> <option value="">Not rated</option>
<option value="1">1 - Very Dissatisfied</option> <option value="1">1 - Very Dissatisfied</option>
@@ -444,7 +444,7 @@ const ResolveComplaintModal: React.FC<{
value={feedback} value={feedback}
onChange={(e) => setFeedback(e.target.value)} onChange={(e) => setFeedback(e.target.value)}
rows={3} rows={3}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-transparent" className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-transparent"
placeholder="Guest feedback on resolution..." placeholder="Guest feedback on resolution..."
/> />
</div> </div>

View File

@@ -98,7 +98,7 @@ const ComplianceReportingPage: React.FC = () => {
<button <button
onClick={handleExport} onClick={handleExport}
disabled={generating} disabled={generating}
className="flex items-center space-x-2 px-4 py-2 bg-[#d4af37] text-white rounded-lg hover:bg-[#c9a227] transition-colors disabled:opacity-50 disabled:cursor-not-allowed" className="flex items-center space-x-2 px-4 py-2 bg-[var(--luxury-gold)] text-white rounded-lg hover:bg-[var(--luxury-gold-dark)] transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
> >
<Download className="w-5 h-5" /> <Download className="w-5 h-5" />
<span>{generating ? 'Generating...' : 'Export CSV'}</span> <span>{generating ? 'Generating...' : 'Export CSV'}</span>
@@ -114,7 +114,7 @@ const ComplianceReportingPage: React.FC = () => {
type="date" type="date"
value={dateRange.start_date} value={dateRange.start_date}
onChange={(e) => setDateRange({ ...dateRange, start_date: e.target.value })} onChange={(e) => setDateRange({ ...dateRange, start_date: e.target.value })}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-transparent" className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-transparent"
/> />
</div> </div>
<div> <div>
@@ -123,13 +123,13 @@ const ComplianceReportingPage: React.FC = () => {
type="date" type="date"
value={dateRange.end_date} value={dateRange.end_date}
onChange={(e) => setDateRange({ ...dateRange, end_date: e.target.value })} onChange={(e) => setDateRange({ ...dateRange, end_date: e.target.value })}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-transparent" className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-transparent"
/> />
</div> </div>
<div className="flex items-end"> <div className="flex items-end">
<button <button
onClick={fetchComplianceData} onClick={fetchComplianceData}
className="w-full px-4 py-2 bg-[#d4af37] text-white rounded-lg hover:bg-[#c9a227] transition-colors" className="w-full px-4 py-2 bg-[var(--luxury-gold)] text-white rounded-lg hover:bg-[var(--luxury-gold-dark)] transition-colors"
> >
Refresh Report Refresh Report
</button> </button>

View File

@@ -117,8 +117,8 @@ const CookieSettingsPage: React.FC = () => {
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-6 pb-6 border-b border-gray-200/60"> <div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-6 pb-6 border-b border-gray-200/60">
<div className="space-y-3"> <div className="space-y-3">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<div className="p-2.5 rounded-lg bg-gradient-to-br from-[#d4af37]/10 to-[#d4af37]/5 border border-[#d4af37]/20 shadow-sm"> <div className="p-2.5 rounded-lg bg-gradient-to-br from-[var(--luxury-gold)]/10 to-[var(--luxury-gold)]/5 border border-[var(--luxury-gold)]/20 shadow-sm">
<Shield className="w-6 h-6 text-[#d4af37]" /> <Shield className="w-6 h-6 text-[var(--luxury-gold)]" />
</div> </div>
<h1 className="enterprise-section-title">Cookie & Privacy Controls</h1> <h1 className="enterprise-section-title">Cookie & Privacy Controls</h1>
</div> </div>

View File

@@ -78,8 +78,8 @@ const CurrencySettingsPage: React.FC = () => {
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-6 pb-6 border-b border-gray-200/60"> <div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-6 pb-6 border-b border-gray-200/60">
<div className="space-y-3"> <div className="space-y-3">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<div className="p-2.5 rounded-lg bg-gradient-to-br from-[#d4af37]/10 to-[#d4af37]/5 border border-[#d4af37]/20 shadow-sm"> <div className="p-2.5 rounded-lg bg-gradient-to-br from-[var(--luxury-gold)]/10 to-[var(--luxury-gold)]/5 border border-[var(--luxury-gold)]/20 shadow-sm">
<DollarSign className="w-6 h-6 text-[#d4af37]" /> <DollarSign className="w-6 h-6 text-[var(--luxury-gold)]" />
</div> </div>
<h1 className="enterprise-section-title">Platform Currency Settings</h1> <h1 className="enterprise-section-title">Platform Currency Settings</h1>
</div> </div>

View File

@@ -124,7 +124,7 @@ const FinancialAuditTrailPage: React.FC = () => {
</div> </div>
<button <button
onClick={handleExport} onClick={handleExport}
className="flex items-center space-x-2 px-4 py-2 bg-[#d4af37] text-white rounded-lg hover:bg-[#c9a227] transition-colors" className="flex items-center space-x-2 px-4 py-2 bg-[var(--luxury-gold)] text-white rounded-lg hover:bg-[var(--luxury-gold-dark)] transition-colors"
> >
<Download className="w-5 h-5" /> <Download className="w-5 h-5" />
<span>Export CSV</span> <span>Export CSV</span>
@@ -139,7 +139,7 @@ const FinancialAuditTrailPage: React.FC = () => {
<select <select
value={filters.action_type || ''} value={filters.action_type || ''}
onChange={(e) => setFilters({ ...filters, action_type: e.target.value || undefined, page: 1 })} onChange={(e) => setFilters({ ...filters, action_type: e.target.value || undefined, page: 1 })}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-transparent" className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-transparent"
> >
<option value="">All Actions</option> <option value="">All Actions</option>
<option value="payment_created">Payment Created</option> <option value="payment_created">Payment Created</option>
@@ -159,7 +159,7 @@ const FinancialAuditTrailPage: React.FC = () => {
type="number" type="number"
value={filters.payment_id || ''} value={filters.payment_id || ''}
onChange={(e) => setFilters({ ...filters, payment_id: e.target.value ? parseInt(e.target.value) : undefined, page: 1 })} onChange={(e) => setFilters({ ...filters, payment_id: e.target.value ? parseInt(e.target.value) : undefined, page: 1 })}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-transparent" className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-transparent"
placeholder="Filter by payment ID" placeholder="Filter by payment ID"
/> />
</div> </div>
@@ -169,7 +169,7 @@ const FinancialAuditTrailPage: React.FC = () => {
type="number" type="number"
value={filters.booking_id || ''} value={filters.booking_id || ''}
onChange={(e) => setFilters({ ...filters, booking_id: e.target.value ? parseInt(e.target.value) : undefined, page: 1 })} onChange={(e) => setFilters({ ...filters, booking_id: e.target.value ? parseInt(e.target.value) : undefined, page: 1 })}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-transparent" className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-transparent"
placeholder="Filter by booking ID" placeholder="Filter by booking ID"
/> />
</div> </div>
@@ -230,7 +230,7 @@ const FinancialAuditTrailPage: React.FC = () => {
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium"> <td className="px-6 py-4 whitespace-nowrap text-sm font-medium">
<button <button
onClick={() => handleViewDetails(record.id)} onClick={() => handleViewDetails(record.id)}
className="text-[#d4af37] hover:text-[#c9a227]" className="text-[var(--luxury-gold)] hover:text-[var(--luxury-gold-dark)]"
> >
<Eye className="w-5 h-5" /> <Eye className="w-5 h-5" />
</button> </button>

View File

@@ -359,4 +359,3 @@ const InvoiceManagementPage: React.FC = () => {
}; };
export default InvoiceManagementPage; export default InvoiceManagementPage;

View File

@@ -417,7 +417,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div className="mb-6 sm:mb-8 animate-fade-in"> <div className="mb-6 sm:mb-8 animate-fade-in">
<div className="flex items-center gap-2 sm:gap-3 mb-2 sm:mb-3"> <div className="flex items-center gap-2 sm:gap-3 mb-2 sm:mb-3">
<div className="h-1 w-12 sm:w-16 md:w-20 bg-gradient-to-r from-[#d4af37] via-amber-400 to-[#d4af37] rounded-full"></div> <div className="h-1 w-12 sm:w-16 md:w-20 bg-gradient-to-r from-[var(--luxury-gold)] via-amber-400 to-[var(--luxury-gold)] rounded-full"></div>
<h1 className="text-2xl sm:text-3xl lg:text-4xl font-serif font-bold bg-gradient-to-r from-gray-900 via-amber-900/90 to-gray-900 bg-clip-text text-transparent tracking-tight"> <h1 className="text-2xl sm:text-3xl lg:text-4xl font-serif font-bold bg-gradient-to-r from-gray-900 via-amber-900/90 to-gray-900 bg-clip-text text-transparent tracking-tight">
Admin Profile & Settings Admin Profile & Settings
</h1> </h1>
@@ -428,61 +428,61 @@ const ProfilePage: React.FC = () => {
</div> </div>
{} {}
<div className="mb-4 sm:mb-6 border-b border-[#d4af37]/20 overflow-x-auto bg-white/50 backdrop-blur-sm rounded-t-lg sm:rounded-t-xl px-4 sm:px-6"> <div className="mb-4 sm:mb-6 border-b border-[var(--luxury-gold)]/20 overflow-x-auto bg-white/50 backdrop-blur-sm rounded-t-lg sm:rounded-t-xl px-4 sm:px-6">
<div className="flex space-x-4 sm:space-x-8 min-w-max"> <div className="flex space-x-4 sm:space-x-8 min-w-max">
<button <button
onClick={() => setActiveTab('profile')} onClick={() => setActiveTab('profile')}
className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${ className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${
activeTab === 'profile' activeTab === 'profile'
? 'border-[#d4af37] text-[#d4af37] shadow-sm' ? 'border-[var(--luxury-gold)] text-[var(--luxury-gold)] shadow-sm'
: 'border-transparent text-gray-500 hover:text-[#d4af37] hover:border-[#d4af37]/30' : 'border-transparent text-gray-500 hover:text-[var(--luxury-gold)] hover:border-[var(--luxury-gold)]/30'
}`} }`}
> >
<User className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'profile' ? 'text-[#d4af37]' : ''}`} /> <User className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'profile' ? 'text-[var(--luxury-gold)]' : ''}`} />
Profile Information Profile Information
</button> </button>
<button <button
onClick={() => setActiveTab('password')} onClick={() => setActiveTab('password')}
className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${ className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${
activeTab === 'password' activeTab === 'password'
? 'border-[#d4af37] text-[#d4af37] shadow-sm' ? 'border-[var(--luxury-gold)] text-[var(--luxury-gold)] shadow-sm'
: 'border-transparent text-gray-500 hover:text-[#d4af37] hover:border-[#d4af37]/30' : 'border-transparent text-gray-500 hover:text-[var(--luxury-gold)] hover:border-[var(--luxury-gold)]/30'
}`} }`}
> >
<KeyRound className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'password' ? 'text-[#d4af37]' : ''}`} /> <KeyRound className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'password' ? 'text-[var(--luxury-gold)]' : ''}`} />
Change Password Change Password
</button> </button>
<button <button
onClick={() => setActiveTab('mfa')} onClick={() => setActiveTab('mfa')}
className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${ className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${
activeTab === 'mfa' activeTab === 'mfa'
? 'border-[#d4af37] text-[#d4af37] shadow-sm' ? 'border-[var(--luxury-gold)] text-[var(--luxury-gold)] shadow-sm'
: 'border-transparent text-gray-500 hover:text-[#d4af37] hover:border-[#d4af37]/30' : 'border-transparent text-gray-500 hover:text-[var(--luxury-gold)] hover:border-[var(--luxury-gold)]/30'
}`} }`}
> >
<Shield className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'mfa' ? 'text-[#d4af37]' : ''}`} /> <Shield className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'mfa' ? 'text-[var(--luxury-gold)]' : ''}`} />
Two-Factor Authentication Two-Factor Authentication
</button> </button>
<button <button
onClick={() => setActiveTab('sessions')} onClick={() => setActiveTab('sessions')}
className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${ className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${
activeTab === 'sessions' activeTab === 'sessions'
? 'border-[#d4af37] text-[#d4af37] shadow-sm' ? 'border-[var(--luxury-gold)] text-[var(--luxury-gold)] shadow-sm'
: 'border-transparent text-gray-500 hover:text-[#d4af37] hover:border-[#d4af37]/30' : 'border-transparent text-gray-500 hover:text-[var(--luxury-gold)] hover:border-[var(--luxury-gold)]/30'
}`} }`}
> >
<Monitor className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'sessions' ? 'text-[#d4af37]' : ''}`} /> <Monitor className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'sessions' ? 'text-[var(--luxury-gold)]' : ''}`} />
Active Sessions Active Sessions
</button> </button>
<button <button
onClick={() => setActiveTab('gdpr')} onClick={() => setActiveTab('gdpr')}
className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${ className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${
activeTab === 'gdpr' activeTab === 'gdpr'
? 'border-[#d4af37] text-[#d4af37] shadow-sm' ? 'border-[var(--luxury-gold)] text-[var(--luxury-gold)] shadow-sm'
: 'border-transparent text-gray-500 hover:text-[#d4af37] hover:border-[#d4af37]/30' : 'border-transparent text-gray-500 hover:text-[var(--luxury-gold)] hover:border-[var(--luxury-gold)]/30'
}`} }`}
> >
<Database className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'gdpr' ? 'text-[#d4af37]' : ''}`} /> <Database className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'gdpr' ? 'text-[var(--luxury-gold)]' : ''}`} />
Data Privacy Data Privacy
</button> </button>
</div> </div>
@@ -490,7 +490,7 @@ const ProfilePage: React.FC = () => {
{} {}
{activeTab === 'profile' && ( {activeTab === 'profile' && (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl animate-slide-up"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl animate-slide-up">
<form onSubmit={handleSubmitProfile(onSubmitProfile)} className="space-y-5 sm:space-y-6"> <form onSubmit={handleSubmitProfile(onSubmitProfile)} className="space-y-5 sm:space-y-6">
{} {}
<div className="flex flex-col sm:flex-row items-center sm:items-start gap-4 sm:gap-6 pb-5 sm:pb-6 border-b border-gray-200"> <div className="flex flex-col sm:flex-row items-center sm:items-start gap-4 sm:gap-6 pb-5 sm:pb-6 border-b border-gray-200">
@@ -499,20 +499,20 @@ const ProfilePage: React.FC = () => {
<img <img
src={avatarPreview || normalizeImageUrl(userInfo?.avatar)} src={avatarPreview || normalizeImageUrl(userInfo?.avatar)}
alt="Profile" alt="Profile"
className="w-20 h-20 sm:w-24 sm:h-24 rounded-full object-cover ring-4 ring-[#d4af37]/20 shadow-lg" className="w-20 h-20 sm:w-24 sm:h-24 rounded-full object-cover ring-4 ring-[var(--luxury-gold)]/20 shadow-lg"
onError={() => { onError={() => {
// If image fails to load, show default avatar // If image fails to load, show default avatar
setAvatarError(true); setAvatarError(true);
}} }}
/> />
) : ( ) : (
<div className="w-20 h-20 sm:w-24 sm:h-24 rounded-full bg-gradient-to-br from-[#d4af37] to-[#c9a227] flex items-center justify-center ring-4 ring-[#d4af37]/20 shadow-lg"> <div className="w-20 h-20 sm:w-24 sm:h-24 rounded-full bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] flex items-center justify-center ring-4 ring-[var(--luxury-gold)]/20 shadow-lg">
<User className="w-10 h-10 sm:w-12 sm:h-12 text-white" /> <User className="w-10 h-10 sm:w-12 sm:h-12 text-white" />
</div> </div>
)} )}
<label <label
htmlFor="avatar-upload" htmlFor="avatar-upload"
className="absolute bottom-0 right-0 p-2 bg-gradient-to-br from-[#d4af37] to-[#c9a227] rounded-full cursor-pointer hover:from-[#f5d76e] hover:to-[#d4af37] transition-all duration-300 shadow-lg hover:shadow-xl hover:shadow-[#d4af37]/40 hover:-translate-y-0.5 active:translate-y-0" className="absolute bottom-0 right-0 p-2 bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] rounded-full cursor-pointer hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] transition-all duration-300 shadow-lg hover:shadow-xl hover:shadow-[var(--luxury-gold)]/40 hover:-translate-y-0.5 active:translate-y-0"
> >
<Camera className="w-3.5 h-3.5 sm:w-4 sm:h-4 text-white" /> <Camera className="w-3.5 h-3.5 sm:w-4 sm:h-4 text-white" />
<input <input
@@ -528,7 +528,7 @@ const ProfilePage: React.FC = () => {
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<User className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <User className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
Full Name Full Name
<span className="text-red-500 ml-1">*</span> <span className="text-red-500 ml-1">*</span>
</label> </label>
@@ -551,7 +551,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<Mail className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <Mail className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
Email Address Email Address
<span className="text-red-500 ml-1">*</span> <span className="text-red-500 ml-1">*</span>
</label> </label>
@@ -574,7 +574,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<Phone className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <Phone className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
Phone Number Phone Number
<span className="text-red-500 ml-1">*</span> <span className="text-red-500 ml-1">*</span>
</label> </label>
@@ -611,7 +611,7 @@ const ProfilePage: React.FC = () => {
{} {}
{activeTab === 'password' && ( {activeTab === 'password' && (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl animate-slide-up"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl animate-slide-up">
<form onSubmit={handleSubmitPassword(onSubmitPassword)} className="space-y-5 sm:space-y-6"> <form onSubmit={handleSubmitPassword(onSubmitPassword)} className="space-y-5 sm:space-y-6">
{} {}
<div className="bg-gradient-to-r from-blue-50 to-indigo-50 border border-blue-200/60 rounded-sm p-4 sm:p-5"> <div className="bg-gradient-to-r from-blue-50 to-indigo-50 border border-blue-200/60 rounded-sm p-4 sm:p-5">
@@ -640,7 +640,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
Current Password Current Password
<span className="text-red-500 ml-1">*</span> <span className="text-red-500 ml-1">*</span>
</label> </label>
@@ -656,7 +656,7 @@ const ProfilePage: React.FC = () => {
<button <button
type="button" type="button"
onClick={() => setShowPassword({ ...showPassword, current: !showPassword.current })} onClick={() => setShowPassword({ ...showPassword, current: !showPassword.current })}
className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[#d4af37] transition-colors" className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[var(--luxury-gold)] transition-colors"
> >
{showPassword.current ? ( {showPassword.current ? (
<EyeOff className="w-4 h-4 sm:w-5 sm:h-5" /> <EyeOff className="w-4 h-4 sm:w-5 sm:h-5" />
@@ -676,7 +676,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
New Password New Password
<span className="text-red-500 ml-1">*</span> <span className="text-red-500 ml-1">*</span>
</label> </label>
@@ -692,7 +692,7 @@ const ProfilePage: React.FC = () => {
<button <button
type="button" type="button"
onClick={() => setShowPassword({ ...showPassword, new: !showPassword.new })} onClick={() => setShowPassword({ ...showPassword, new: !showPassword.new })}
className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[#d4af37] transition-colors" className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[var(--luxury-gold)] transition-colors"
> >
{showPassword.new ? ( {showPassword.new ? (
<EyeOff className="w-4 h-4 sm:w-5 sm:h-5" /> <EyeOff className="w-4 h-4 sm:w-5 sm:h-5" />
@@ -712,7 +712,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
Confirm New Password Confirm New Password
<span className="text-red-500 ml-1">*</span> <span className="text-red-500 ml-1">*</span>
</label> </label>
@@ -728,7 +728,7 @@ const ProfilePage: React.FC = () => {
<button <button
type="button" type="button"
onClick={() => setShowPassword({ ...showPassword, confirm: !showPassword.confirm })} onClick={() => setShowPassword({ ...showPassword, confirm: !showPassword.confirm })}
className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[#d4af37] transition-colors" className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[var(--luxury-gold)] transition-colors"
> >
{showPassword.confirm ? ( {showPassword.confirm ? (
<EyeOff className="w-4 h-4 sm:w-5 sm:h-5" /> <EyeOff className="w-4 h-4 sm:w-5 sm:h-5" />
@@ -762,11 +762,11 @@ const ProfilePage: React.FC = () => {
{} {}
{activeTab === 'mfa' && ( {activeTab === 'mfa' && (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl animate-slide-up space-y-5 sm:space-y-6"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl animate-slide-up space-y-5 sm:space-y-6">
{} {}
<div> <div>
<h2 className="text-xl sm:text-2xl font-serif font-semibold text-gray-900 mb-2 flex items-center gap-2"> <h2 className="text-xl sm:text-2xl font-serif font-semibold text-gray-900 mb-2 flex items-center gap-2">
<Shield className="w-5 h-5 sm:w-6 sm:h-6 text-[#d4af37]" /> <Shield className="w-5 h-5 sm:w-6 sm:h-6 text-[var(--luxury-gold)]" />
Two-Factor Authentication Two-Factor Authentication
</h2> </h2>
<p className="text-xs sm:text-sm text-gray-600 font-light leading-relaxed"> <p className="text-xs sm:text-sm text-gray-600 font-light leading-relaxed">
@@ -838,7 +838,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div className="bg-white border border-gray-200 rounded-sm p-4 sm:p-5"> <div className="bg-white border border-gray-200 rounded-sm p-4 sm:p-5">
<h3 className="text-sm sm:text-base font-semibold text-gray-900 mb-2 flex items-center gap-2"> <h3 className="text-sm sm:text-base font-semibold text-gray-900 mb-2 flex items-center gap-2">
<RefreshCw className="w-4 h-4 sm:w-5 sm:h-5 text-[#d4af37]" /> <RefreshCw className="w-4 h-4 sm:w-5 sm:h-5 text-[var(--luxury-gold)]" />
Backup Codes Backup Codes
</h3> </h3>
<p className="text-xs sm:text-sm text-gray-600 font-light mb-4 leading-relaxed"> <p className="text-xs sm:text-sm text-gray-600 font-light mb-4 leading-relaxed">
@@ -984,7 +984,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div className="bg-white border border-gray-200 rounded-sm p-4 sm:p-5"> <div className="bg-white border border-gray-200 rounded-sm p-4 sm:p-5">
<h3 className="font-semibold text-gray-900 mb-2 text-sm sm:text-base flex items-center gap-2"> <h3 className="font-semibold text-gray-900 mb-2 text-sm sm:text-base flex items-center gap-2">
<KeyRound className="w-4 h-4 sm:w-5 sm:h-5 text-[#d4af37]" /> <KeyRound className="w-4 h-4 sm:w-5 sm:h-5 text-[var(--luxury-gold)]" />
Step 2: Verify Setup Step 2: Verify Setup
</h3> </h3>
<p className="text-xs sm:text-sm text-gray-600 font-light mb-4 leading-relaxed"> <p className="text-xs sm:text-sm text-gray-600 font-light mb-4 leading-relaxed">
@@ -1110,10 +1110,10 @@ const SessionsTab: React.FC = () => {
}; };
const getDeviceIcon = (userAgent?: string) => { const getDeviceIcon = (userAgent?: string) => {
if (!userAgent) return <Monitor className="w-5 h-5 text-[#d4af37]" />; if (!userAgent) return <Monitor className="w-5 h-5 text-[var(--luxury-gold)]" />;
if (userAgent.includes('Mobile')) return <Smartphone className="w-5 h-5 text-blue-500" />; if (userAgent.includes('Mobile')) return <Smartphone className="w-5 h-5 text-blue-500" />;
if (userAgent.includes('Tablet')) return <Tablet className="w-5 h-5 text-purple-500" />; if (userAgent.includes('Tablet')) return <Tablet className="w-5 h-5 text-purple-500" />;
return <Monitor className="w-5 h-5 text-[#d4af37]" />; return <Monitor className="w-5 h-5 text-[var(--luxury-gold)]" />;
}; };
const getDeviceName = (userAgent?: string) => { const getDeviceName = (userAgent?: string) => {
@@ -1181,17 +1181,17 @@ const SessionsTab: React.FC = () => {
if (loading) { if (loading) {
return ( return (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl">
<Loading text="Loading sessions..." /> <Loading text="Loading sessions..." />
</div> </div>
); );
} }
return ( return (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl animate-slide-up space-y-5 sm:space-y-6"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl animate-slide-up space-y-5 sm:space-y-6">
<div> <div>
<h2 className="text-xl sm:text-2xl font-serif font-semibold text-gray-900 mb-2 flex items-center gap-2"> <h2 className="text-xl sm:text-2xl font-serif font-semibold text-gray-900 mb-2 flex items-center gap-2">
<Monitor className="w-5 h-5 sm:w-6 sm:h-6 text-[#d4af37]" /> <Monitor className="w-5 h-5 sm:w-6 sm:h-6 text-[var(--luxury-gold)]" />
Active Sessions Active Sessions
</h2> </h2>
<p className="text-xs sm:text-sm text-gray-600 font-light"> <p className="text-xs sm:text-sm text-gray-600 font-light">
@@ -1220,11 +1220,11 @@ const SessionsTab: React.FC = () => {
{sessions.map((session) => ( {sessions.map((session) => (
<div <div
key={session.id} key={session.id}
className="bg-gradient-to-r from-slate-50 to-white border border-[#d4af37]/20 rounded-sm p-4 sm:p-5 hover:shadow-lg hover:border-[#d4af37]/40 transition-all duration-300" className="bg-gradient-to-r from-slate-50 to-white border border-[var(--luxury-gold)]/20 rounded-sm p-4 sm:p-5 hover:shadow-lg hover:border-[var(--luxury-gold)]/40 transition-all duration-300"
> >
<div className="flex items-start justify-between gap-4"> <div className="flex items-start justify-between gap-4">
<div className="flex items-start gap-4 flex-1"> <div className="flex items-start gap-4 flex-1">
<div className="p-2 sm:p-3 bg-gradient-to-br from-[#d4af37]/10 to-[#c9a227]/10 rounded-sm flex-shrink-0"> <div className="p-2 sm:p-3 bg-gradient-to-br from-[var(--luxury-gold)]/10 to-[var(--luxury-gold-dark)]/10 rounded-sm flex-shrink-0">
{getDeviceIcon(session.user_agent)} {getDeviceIcon(session.user_agent)}
</div> </div>
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
@@ -1354,17 +1354,17 @@ const GDPRTab: React.FC = () => {
if (loading) { if (loading) {
return ( return (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl">
<Loading text="Loading privacy data..." /> <Loading text="Loading privacy data..." />
</div> </div>
); );
} }
return ( return (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl animate-slide-up space-y-5 sm:space-y-6"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl animate-slide-up space-y-5 sm:space-y-6">
<div> <div>
<h2 className="text-xl sm:text-2xl font-serif font-semibold text-gray-900 mb-2 flex items-center gap-2"> <h2 className="text-xl sm:text-2xl font-serif font-semibold text-gray-900 mb-2 flex items-center gap-2">
<Database className="w-5 h-5 sm:w-6 sm:h-6 text-[#d4af37]" /> <Database className="w-5 h-5 sm:w-6 sm:h-6 text-[var(--luxury-gold)]" />
Data Privacy & GDPR Rights Data Privacy & GDPR Rights
</h2> </h2>
<p className="text-xs sm:text-sm text-gray-600 font-light"> <p className="text-xs sm:text-sm text-gray-600 font-light">
@@ -1431,14 +1431,14 @@ const GDPRTab: React.FC = () => {
{requests.length > 0 && ( {requests.length > 0 && (
<div className="border-t border-gray-200 pt-5 sm:pt-6"> <div className="border-t border-gray-200 pt-5 sm:pt-6">
<h3 className="text-base sm:text-lg font-semibold text-gray-900 mb-4 flex items-center gap-2"> <h3 className="text-base sm:text-lg font-semibold text-gray-900 mb-4 flex items-center gap-2">
<FileText className="w-5 h-5 text-[#d4af37]" /> <FileText className="w-5 h-5 text-[var(--luxury-gold)]" />
Request History Request History
</h3> </h3>
<div className="space-y-3 sm:space-y-4"> <div className="space-y-3 sm:space-y-4">
{requests.map((request) => ( {requests.map((request) => (
<div <div
key={request.id} key={request.id}
className="bg-gradient-to-r from-slate-50 to-white border border-[#d4af37]/20 rounded-sm p-4 sm:p-5 hover:shadow-md hover:border-[#d4af37]/40 transition-all duration-300" className="bg-gradient-to-r from-slate-50 to-white border border-[var(--luxury-gold)]/20 rounded-sm p-4 sm:p-5 hover:shadow-md hover:border-[var(--luxury-gold)]/40 transition-all duration-300"
> >
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3 sm:gap-4"> <div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3 sm:gap-4">
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">

View File

@@ -0,0 +1,859 @@
import React, { useEffect, useState } from 'react';
import {
Tag,
Search,
Plus,
Edit,
Trash2,
Filter,
X,
} from 'lucide-react';
import { toast } from 'react-toastify';
import Loading from '../../shared/components/Loading';
import Pagination from '../../shared/components/Pagination';
import { useFormatCurrency } from '../../features/payments/hooks/useFormatCurrency';
import { useCurrency } from '../../features/payments/contexts/CurrencyContext';
import promotionService, { Promotion } from '../../features/loyalty/services/promotionService';
import { getRoomTypes } from '../../features/rooms/services/roomService';
interface RoomType {
id: number;
name: string;
}
const PromotionsManagementPage: React.FC = () => {
const { formatCurrency } = useFormatCurrency();
const { currency } = useCurrency();
const [promotions, setPromotions] = useState<Promotion[]>([]);
const [promotionsLoading, setPromotionsLoading] = useState(true);
const [showPromotionModal, setShowPromotionModal] = useState(false);
const [editingPromotion, setEditingPromotion] = useState<Promotion | null>(null);
const [promotionFilters, setPromotionFilters] = useState({
search: '',
status: '',
type: '',
});
const [promotionsCurrentPage, setPromotionsCurrentPage] = useState(1);
const [promotionsTotalPages, setPromotionsTotalPages] = useState(1);
const [promotionsTotalItems, setPromotionsTotalItems] = useState(0);
const promotionsPerPage = 5;
const [promotionFormData, setPromotionFormData] = useState({
code: '',
name: '',
description: '',
discount_type: 'percentage' as 'percentage' | 'fixed',
discount_value: 0,
min_booking_amount: 0,
max_discount_amount: 0,
min_stay_days: 0,
max_stay_days: 0,
advance_booking_days: 0,
max_advance_booking_days: 0,
allowed_check_in_days: [] as number[],
allowed_check_out_days: [] as number[],
allowed_room_type_ids: [] as number[],
excluded_room_type_ids: [] as number[],
min_guests: 0,
max_guests: 0,
first_time_customer_only: false,
repeat_customer_only: false,
blackout_dates: [] as string[],
start_date: '',
end_date: '',
usage_limit: 0,
status: 'active' as 'active' | 'inactive' | 'expired',
});
const [roomTypes, setRoomTypes] = useState<RoomType[]>([]);
useEffect(() => {
fetchPromotions();
}, [promotionFilters, promotionsCurrentPage]);
useEffect(() => {
fetchRoomTypes();
}, []);
useEffect(() => {
setPromotionsCurrentPage(1);
}, [promotionFilters]);
const fetchRoomTypes = async () => {
try {
const response = await getRoomTypes();
if (response.success && response.data.room_types) {
setRoomTypes(response.data.room_types);
}
} catch (error: any) {
console.error('Failed to fetch room types:', error);
}
};
const fetchPromotions = async () => {
try {
setPromotionsLoading(true);
const response = await promotionService.getPromotions({
...promotionFilters,
page: promotionsCurrentPage,
limit: promotionsPerPage,
});
setPromotions(response.data.promotions);
if (response.data.pagination) {
setPromotionsTotalPages(response.data.pagination.totalPages);
setPromotionsTotalItems(response.data.pagination.total);
}
} catch (error: any) {
toast.error(error.response?.data?.message || 'Unable to load promotions list');
} finally {
setPromotionsLoading(false);
}
};
const handlePromotionSubmit = async (e: React.FormEvent) => {
e.preventDefault();
try {
const submitData: any = {
...promotionFormData,
min_stay_days: promotionFormData.min_stay_days || undefined,
max_stay_days: promotionFormData.max_stay_days || undefined,
advance_booking_days: promotionFormData.advance_booking_days || undefined,
max_advance_booking_days: promotionFormData.max_advance_booking_days || undefined,
min_guests: promotionFormData.min_guests || undefined,
max_guests: promotionFormData.max_guests || undefined,
allowed_check_in_days: promotionFormData.allowed_check_in_days?.length ? promotionFormData.allowed_check_in_days : undefined,
allowed_check_out_days: promotionFormData.allowed_check_out_days?.length ? promotionFormData.allowed_check_out_days : undefined,
allowed_room_type_ids: promotionFormData.allowed_room_type_ids?.length ? promotionFormData.allowed_room_type_ids : undefined,
excluded_room_type_ids: promotionFormData.excluded_room_type_ids?.length ? promotionFormData.excluded_room_type_ids : undefined,
blackout_dates: promotionFormData.blackout_dates?.length ? promotionFormData.blackout_dates : undefined,
min_booking_amount: promotionFormData.min_booking_amount || undefined,
max_discount_amount: promotionFormData.max_discount_amount || undefined,
usage_limit: promotionFormData.usage_limit || undefined,
};
if (editingPromotion) {
await promotionService.updatePromotion(editingPromotion.id, submitData);
toast.success('Promotion updated successfully');
} else {
await promotionService.createPromotion(submitData);
toast.success('Promotion added successfully');
}
setShowPromotionModal(false);
resetPromotionForm();
fetchPromotions();
} catch (error: any) {
toast.error(error.response?.data?.message || 'An error occurred');
}
};
const handleEditPromotion = (promotion: Promotion) => {
setEditingPromotion(promotion);
setPromotionFormData({
code: promotion.code,
name: promotion.name,
description: promotion.description || '',
discount_type: promotion.discount_type,
discount_value: promotion.discount_value,
min_booking_amount: promotion.min_booking_amount || 0,
max_discount_amount: promotion.max_discount_amount || 0,
min_stay_days: promotion.min_stay_days || 0,
max_stay_days: promotion.max_stay_days || 0,
advance_booking_days: promotion.advance_booking_days || 0,
max_advance_booking_days: promotion.max_advance_booking_days || 0,
allowed_check_in_days: promotion.allowed_check_in_days || [],
allowed_check_out_days: promotion.allowed_check_out_days || [],
allowed_room_type_ids: promotion.allowed_room_type_ids || [],
excluded_room_type_ids: promotion.excluded_room_type_ids || [],
min_guests: promotion.min_guests || 0,
max_guests: promotion.max_guests || 0,
first_time_customer_only: promotion.first_time_customer_only || false,
repeat_customer_only: promotion.repeat_customer_only || false,
blackout_dates: promotion.blackout_dates || [],
start_date: promotion.start_date?.split('T')[0] || '',
end_date: promotion.end_date?.split('T')[0] || '',
usage_limit: promotion.usage_limit || 0,
status: promotion.status,
});
setShowPromotionModal(true);
};
const handleDeletePromotion = async (id: number) => {
if (!window.confirm('Are you sure you want to delete this promotion?')) return;
try {
await promotionService.deletePromotion(id);
toast.success('Promotion deleted successfully');
fetchPromotions();
} catch (error: any) {
toast.error(error.response?.data?.message || 'Unable to delete promotion');
}
};
const resetPromotionForm = () => {
setEditingPromotion(null);
setPromotionFormData({
code: '',
name: '',
description: '',
discount_type: 'percentage',
discount_value: 0,
min_booking_amount: 0,
max_discount_amount: 0,
min_stay_days: 0,
max_stay_days: 0,
advance_booking_days: 0,
max_advance_booking_days: 0,
allowed_check_in_days: [],
allowed_check_out_days: [],
allowed_room_type_ids: [],
excluded_room_type_ids: [],
min_guests: 0,
max_guests: 0,
first_time_customer_only: false,
repeat_customer_only: false,
blackout_dates: [],
start_date: '',
end_date: '',
usage_limit: 0,
status: 'active',
});
};
const getPromotionStatusBadge = (status: string) => {
const badges: Record<string, { bg: string; text: string; label: string; border: string }> = {
active: { bg: 'bg-gradient-to-r from-emerald-50 to-green-50', text: 'text-emerald-800', label: 'Active', border: 'border-emerald-200' },
inactive: { bg: 'bg-gradient-to-r from-slate-50 to-gray-50', text: 'text-slate-700', label: 'Inactive', border: 'border-slate-200' },
expired: { bg: 'bg-gradient-to-r from-rose-50 to-red-50', text: 'text-rose-800', label: 'Expired', border: 'border-rose-200' },
};
const badge = badges[status] || badges.active;
return (
<span className={`px-4 py-1.5 rounded-full text-xs font-semibold border shadow-sm ${badge.bg} ${badge.text} ${badge.border}`}>
{badge.label}
</span>
);
};
return (
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-white to-slate-50 -m-6 p-8">
<div className="space-y-8">
{}
<div className="bg-white/90 backdrop-blur-xl rounded-2xl shadow-xl border border-gray-200/50 p-8">
<div className="flex flex-col md:flex-row md:items-center md:justify-between gap-6">
<div className="space-y-3">
<div className="flex items-center gap-3">
<div className="p-2.5 rounded-xl bg-gradient-to-br from-purple-500/10 to-pink-500/10 border border-purple-200/40">
<Tag className="w-6 h-6 text-purple-600" />
</div>
<h2 className="text-3xl font-extrabold text-gray-900">Promotion Management</h2>
</div>
<p className="text-gray-600 text-base max-w-2xl leading-relaxed">
Manage discount codes and promotional campaigns
</p>
</div>
<button
onClick={() => {
resetPromotionForm();
setShowPromotionModal(true);
}}
className="group relative px-8 py-4 bg-gradient-to-r from-purple-500 via-purple-500 to-pink-600 text-white font-semibold rounded-xl shadow-xl shadow-purple-500/30 hover:shadow-2xl hover:shadow-purple-500/40 transition-all duration-300 hover:scale-105 overflow-hidden"
>
<div className="absolute inset-0 bg-gradient-to-r from-transparent via-white/20 to-transparent translate-x-[-100%] group-hover:translate-x-[100%] transition-transform duration-1000"></div>
<div className="relative flex items-center gap-3">
<Plus className="w-5 h-5" />
Add Promotion
</div>
</button>
</div>
</div>
{}
<div className="relative bg-white/90 backdrop-blur-xl rounded-2xl shadow-xl border border-gray-200/50 p-8">
<div className="flex items-center gap-3 mb-6">
<div className="p-2 rounded-xl bg-gradient-to-br from-amber-500/10 to-amber-600/10 border border-amber-200/40">
<Filter className="w-5 h-5 text-amber-600" />
</div>
<h3 className="text-xl font-bold text-gray-900">Filters</h3>
</div>
<div className="grid grid-cols-1 md:grid-cols-4 gap-6">
<div className="relative group">
<Search className="absolute left-4 top-1/2 transform -translate-y-1/2 text-gray-400 w-5 h-5 group-focus-within:text-purple-500 transition-colors" />
<input
type="text"
placeholder="Search by code or name..."
value={promotionFilters.search}
onChange={(e) => setPromotionFilters({ ...promotionFilters, search: e.target.value })}
className="w-full pl-12 pr-4 py-3.5 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 text-gray-700 placeholder-gray-400 font-medium shadow-sm hover:shadow-md"
/>
</div>
<select
value={promotionFilters.type}
onChange={(e) => setPromotionFilters({ ...promotionFilters, type: e.target.value })}
className="px-4 py-3.5 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 text-gray-700 font-medium shadow-sm hover:shadow-md cursor-pointer"
>
<option value="">All Types</option>
<option value="percentage">Percentage</option>
<option value="fixed">Fixed Amount</option>
</select>
<select
value={promotionFilters.status}
onChange={(e) => setPromotionFilters({ ...promotionFilters, status: e.target.value })}
className="px-4 py-3.5 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 text-gray-700 font-medium shadow-sm hover:shadow-md cursor-pointer"
>
<option value="">All Statuses</option>
<option value="active">Active</option>
<option value="inactive">Inactive</option>
</select>
</div>
</div>
{}
{promotionsLoading && promotions.length === 0 ? (
<Loading fullScreen text="Loading promotions..." />
) : (
<div className="relative bg-white/90 backdrop-blur-xl rounded-2xl shadow-xl border border-gray-200/50 overflow-hidden">
<div className="overflow-x-auto">
<table className="w-full">
<thead className="bg-gradient-to-r from-gray-50 to-gray-100">
<tr>
<th className="px-8 py-5 text-left text-xs font-bold text-gray-700 uppercase tracking-wider border-b border-gray-200">Code</th>
<th className="px-8 py-5 text-left text-xs font-bold text-gray-700 uppercase tracking-wider border-b border-gray-200">Program Name</th>
<th className="px-8 py-5 text-left text-xs font-bold text-gray-700 uppercase tracking-wider border-b border-gray-200">Value</th>
<th className="px-8 py-5 text-left text-xs font-bold text-gray-700 uppercase tracking-wider border-b border-gray-200">Period</th>
<th className="px-8 py-5 text-left text-xs font-bold text-gray-700 uppercase tracking-wider border-b border-gray-200">Used</th>
<th className="px-8 py-5 text-left text-xs font-bold text-gray-700 uppercase tracking-wider border-b border-gray-200">Status</th>
<th className="px-8 py-5 text-right text-xs font-bold text-gray-700 uppercase tracking-wider border-b border-gray-200">Actions</th>
</tr>
</thead>
<tbody className="bg-white divide-y divide-gray-100">
{promotions.map((promotion) => (
<tr key={promotion.id} className="hover:bg-gray-50 transition-colors">
<td className="px-8 py-5 whitespace-nowrap">
<div className="flex items-center gap-3">
<div className="p-2 bg-gradient-to-br from-purple-100 to-purple-200 rounded-lg">
<Tag className="w-4 h-4 text-purple-600" />
</div>
<span className="text-sm font-mono font-bold bg-gradient-to-r from-purple-600 to-purple-700 bg-clip-text text-transparent">{promotion.code}</span>
</div>
</td>
<td className="px-8 py-5">
<div className="text-sm font-semibold text-gray-900">{promotion.name}</div>
<div className="text-xs text-gray-500 mt-0.5">{promotion.description}</div>
</td>
<td className="px-8 py-5 whitespace-nowrap">
<div className="text-sm font-bold bg-gradient-to-r from-emerald-600 to-emerald-700 bg-clip-text text-transparent">
{promotion.discount_type === 'percentage'
? `${promotion.discount_value}%`
: formatCurrency(promotion.discount_value)}
</div>
</td>
<td className="px-8 py-5 whitespace-nowrap">
<div className="text-xs text-gray-600">
{promotion.start_date ? new Date(promotion.start_date).toLocaleDateString('en-US', { month: 'short', day: 'numeric' }) : 'N/A'}
<span className="text-gray-400 mx-1"></span>
{promotion.end_date ? new Date(promotion.end_date).toLocaleDateString('en-US', { month: 'short', day: 'numeric' }) : 'N/A'}
</div>
</td>
<td className="px-8 py-5 whitespace-nowrap">
<div className="text-sm font-medium text-gray-700">
<span className="text-purple-600 font-semibold">{promotion.used_count || 0}</span>
<span className="text-gray-400 mx-1">/</span>
<span className="text-gray-600">{promotion.usage_limit || '∞'}</span>
</div>
</td>
<td className="px-8 py-5 whitespace-nowrap">
{getPromotionStatusBadge(promotion.status)}
</td>
<td className="px-8 py-5 whitespace-nowrap text-right">
<div className="flex items-center justify-end gap-2">
<button
onClick={() => handleEditPromotion(promotion)}
className="p-2 rounded-lg text-blue-600 hover:text-blue-700 hover:bg-blue-50 transition-all duration-200 shadow-sm hover:shadow-md border border-blue-200 hover:border-blue-300"
title="Edit"
>
<Edit className="w-5 h-5" />
</button>
<button
onClick={() => handleDeletePromotion(promotion.id)}
className="p-2 rounded-lg text-rose-600 hover:text-rose-700 hover:bg-rose-50 transition-all duration-200 shadow-sm hover:shadow-md border border-rose-200 hover:border-rose-300"
title="Delete"
>
<Trash2 className="w-5 h-5" />
</button>
</div>
</td>
</tr>
))}
</tbody>
</table>
</div>
<Pagination
currentPage={promotionsCurrentPage}
totalPages={promotionsTotalPages}
onPageChange={setPromotionsCurrentPage}
totalItems={promotionsTotalItems}
itemsPerPage={promotionsPerPage}
/>
</div>
)}
</div>
{}
{showPromotionModal && (
<div className="fixed inset-0 bg-black/70 backdrop-blur-md z-50 overflow-y-auto p-3 sm:p-4">
<div className="min-h-full flex items-center justify-center py-4">
<div className="bg-white rounded-2xl sm:rounded-3xl shadow-2xl max-w-5xl w-full my-4 flex flex-col border border-gray-200" style={{ maxHeight: 'calc(100vh - 2rem)' }}>
<div className="bg-gradient-to-r from-slate-900 via-slate-800 to-slate-900 px-4 sm:px-6 md:px-8 py-4 sm:py-5 md:py-6 border-b border-slate-700 flex-shrink-0">
<div className="flex justify-between items-center">
<div>
<h2 className="text-xl sm:text-2xl md:text-3xl font-bold text-purple-100 mb-1">
{editingPromotion ? 'Update Promotion' : 'Add New Promotion'}
</h2>
<p className="text-purple-200/80 text-xs sm:text-sm font-light">
{editingPromotion ? 'Modify promotion details' : 'Create a new promotion program'}
</p>
</div>
<button
onClick={() => setShowPromotionModal(false)}
className="w-9 h-9 sm:w-10 sm:h-10 flex items-center justify-center rounded-xl text-purple-100 hover:text-white hover:bg-slate-700/50 transition-all duration-200 border border-slate-600 hover:border-purple-400"
>
<X className="w-5 h-5 sm:w-6 sm:h-6" />
</button>
</div>
</div>
<div className="flex-1 overflow-y-auto min-h-0">
<form onSubmit={handlePromotionSubmit} className="p-4 sm:p-6 md:p-8 space-y-4 sm:space-y-5 md:space-y-6">
<div className="grid grid-cols-2 gap-6">
<div>
<label className="block text-xs font-semibold text-gray-600 uppercase tracking-wider mb-2">
Code <span className="text-red-500">*</span>
</label>
<input
type="text"
value={promotionFormData.code}
onChange={(e) => setPromotionFormData({ ...promotionFormData, code: e.target.value.toUpperCase() })}
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 text-gray-700 font-medium shadow-sm font-mono"
placeholder="e.g: SUMMER2024"
required
/>
</div>
<div>
<label className="block text-xs font-semibold text-gray-600 uppercase tracking-wider mb-2">
Program Name <span className="text-red-500">*</span>
</label>
<input
type="text"
value={promotionFormData.name}
onChange={(e) => setPromotionFormData({ ...promotionFormData, name: e.target.value })}
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 text-gray-700 font-medium shadow-sm"
placeholder="e.g: Summer Sale"
required
/>
</div>
</div>
<div>
<label className="block text-xs font-semibold text-gray-600 uppercase tracking-wider mb-2">
Description
</label>
<textarea
value={promotionFormData.description}
onChange={(e) => setPromotionFormData({ ...promotionFormData, description: e.target.value })}
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 text-gray-700 font-medium shadow-sm"
rows={3}
placeholder="Detailed description of the program..."
/>
</div>
<div className="grid grid-cols-2 gap-6">
<div>
<label className="block text-xs font-semibold text-gray-600 uppercase tracking-wider mb-2">
Discount Type <span className="text-red-500">*</span>
</label>
<select
value={promotionFormData.discount_type}
onChange={(e) => setPromotionFormData({ ...promotionFormData, discount_type: e.target.value as 'percentage' | 'fixed' })}
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 text-gray-700 font-medium shadow-sm cursor-pointer"
>
<option value="percentage">Percentage (%)</option>
<option value="fixed">Fixed Amount ({currency})</option>
</select>
</div>
<div>
<label className="block text-xs font-semibold text-gray-600 uppercase tracking-wider mb-2">
Discount Value <span className="text-red-500">*</span>
</label>
<input
type="number"
value={promotionFormData.discount_value}
onChange={(e) => setPromotionFormData({ ...promotionFormData, discount_value: parseFloat(e.target.value) })}
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 text-gray-700 font-medium shadow-sm"
min="0"
max={promotionFormData.discount_type === 'percentage' ? 100 : undefined}
required
/>
</div>
</div>
<div className="grid grid-cols-2 gap-6">
<div>
<label className="block text-xs font-semibold text-gray-600 uppercase tracking-wider mb-2">
Minimum Order Value ({currency})
</label>
<input
type="number"
value={promotionFormData.min_booking_amount}
onChange={(e) => setPromotionFormData({ ...promotionFormData, min_booking_amount: parseFloat(e.target.value) })}
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 text-gray-700 font-medium shadow-sm"
min="0"
/>
</div>
<div>
<label className="block text-xs font-semibold text-gray-600 uppercase tracking-wider mb-2">
Maximum Discount ({currency})
</label>
<input
type="number"
value={promotionFormData.max_discount_amount}
onChange={(e) => setPromotionFormData({ ...promotionFormData, max_discount_amount: parseFloat(e.target.value) })}
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 text-gray-700 font-medium shadow-sm"
min="0"
/>
</div>
</div>
{/* Enterprise Booking Conditions Section */}
<div className="border-t-2 border-purple-200 pt-6 mt-6">
<h3 className="text-lg font-bold text-gray-900 mb-4 flex items-center gap-2">
<div className="h-1 w-8 bg-gradient-to-r from-purple-400 to-purple-600 rounded-full"></div>
Enterprise Booking Conditions
</h3>
<p className="text-sm text-gray-600 mb-6">Configure advanced conditions for when this promotion applies</p>
</div>
<div className="grid grid-cols-2 gap-6">
<div>
<label className="block text-xs font-semibold text-gray-600 uppercase tracking-wider mb-2">
Minimum Stay (nights)
</label>
<input
type="number"
value={promotionFormData.min_stay_days || ''}
onChange={(e) => setPromotionFormData({ ...promotionFormData, min_stay_days: parseInt(e.target.value) || 0 })}
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 text-gray-700 font-medium shadow-sm"
min="0"
placeholder="0 = no minimum"
/>
<p className="text-xs text-gray-500 mt-1">Minimum number of nights required for booking</p>
</div>
<div>
<label className="block text-xs font-semibold text-gray-600 uppercase tracking-wider mb-2">
Advance Booking (days)
</label>
<input
type="number"
value={promotionFormData.advance_booking_days || ''}
onChange={(e) => setPromotionFormData({ ...promotionFormData, advance_booking_days: parseInt(e.target.value) || 0 })}
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 text-gray-700 font-medium shadow-sm"
min="0"
placeholder="0 = no requirement"
/>
<p className="text-xs text-gray-500 mt-1">Minimum days in advance the booking must be made</p>
</div>
</div>
<div className="grid grid-cols-2 gap-6">
<div>
<label className="block text-xs font-semibold text-gray-600 uppercase tracking-wider mb-2">
Maximum Stay (nights)
</label>
<input
type="number"
value={promotionFormData.max_stay_days || ''}
onChange={(e) => setPromotionFormData({ ...promotionFormData, max_stay_days: parseInt(e.target.value) || 0 })}
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 text-gray-700 font-medium shadow-sm"
min="0"
placeholder="0 = no maximum"
/>
<p className="text-xs text-gray-500 mt-1">Maximum number of nights allowed for booking</p>
</div>
<div>
<label className="block text-xs font-semibold text-gray-600 uppercase tracking-wider mb-2">
Max Advance Booking (days)
</label>
<input
type="number"
value={promotionFormData.max_advance_booking_days || ''}
onChange={(e) => setPromotionFormData({ ...promotionFormData, max_advance_booking_days: parseInt(e.target.value) || 0 })}
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 text-gray-700 font-medium shadow-sm"
min="0"
placeholder="0 = no maximum"
/>
<p className="text-xs text-gray-500 mt-1">Maximum days in advance the booking can be made</p>
</div>
</div>
<div className="grid grid-cols-2 gap-6">
<div>
<label className="block text-xs font-semibold text-gray-600 uppercase tracking-wider mb-2">
Allowed Check-in Days
</label>
<div className="grid grid-cols-7 gap-2">
{['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'].map((day, index) => (
<label key={day} className="flex items-center gap-2 cursor-pointer">
<input
type="checkbox"
checked={promotionFormData.allowed_check_in_days?.includes(index) || false}
onChange={(e) => {
const current = promotionFormData.allowed_check_in_days || [];
if (e.target.checked) {
setPromotionFormData({ ...promotionFormData, allowed_check_in_days: [...current, index] });
} else {
setPromotionFormData({ ...promotionFormData, allowed_check_in_days: current.filter(d => d !== index) });
}
}}
className="w-4 h-4 text-purple-600 border-gray-300 rounded focus:ring-purple-500"
/>
<span className="text-xs text-gray-700">{day}</span>
</label>
))}
</div>
<p className="text-xs text-gray-500 mt-1">Leave empty to allow all days</p>
</div>
<div>
<label className="block text-xs font-semibold text-gray-600 uppercase tracking-wider mb-2">
Allowed Check-out Days
</label>
<div className="grid grid-cols-7 gap-2">
{['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'].map((day, index) => (
<label key={day} className="flex items-center gap-2 cursor-pointer">
<input
type="checkbox"
checked={promotionFormData.allowed_check_out_days?.includes(index) || false}
onChange={(e) => {
const current = promotionFormData.allowed_check_out_days || [];
if (e.target.checked) {
setPromotionFormData({ ...promotionFormData, allowed_check_out_days: [...current, index] });
} else {
setPromotionFormData({ ...promotionFormData, allowed_check_out_days: current.filter(d => d !== index) });
}
}}
className="w-4 h-4 text-purple-600 border-gray-300 rounded focus:ring-purple-500"
/>
<span className="text-xs text-gray-700">{day}</span>
</label>
))}
</div>
<p className="text-xs text-gray-500 mt-1">Leave empty to allow all days</p>
</div>
</div>
<div className="grid grid-cols-2 gap-6">
<div>
<label className="block text-xs font-semibold text-gray-600 uppercase tracking-wider mb-2">
Allowed Room Types
</label>
<select
multiple
value={promotionFormData.allowed_room_type_ids?.map(String) || []}
onChange={(e) => {
const selected = Array.from(e.target.selectedOptions, option => parseInt(option.value));
setPromotionFormData({ ...promotionFormData, allowed_room_type_ids: selected });
}}
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 text-gray-700 font-medium shadow-sm"
size={4}
>
{roomTypes.map(rt => (
<option key={rt.id} value={rt.id}>{rt.name}</option>
))}
</select>
<p className="text-xs text-gray-500 mt-1">Hold Ctrl/Cmd to select multiple. Leave empty to allow all room types.</p>
</div>
<div>
<label className="block text-xs font-semibold text-gray-600 uppercase tracking-wider mb-2">
Excluded Room Types
</label>
<select
multiple
value={promotionFormData.excluded_room_type_ids?.map(String) || []}
onChange={(e) => {
const selected = Array.from(e.target.selectedOptions, option => parseInt(option.value));
setPromotionFormData({ ...promotionFormData, excluded_room_type_ids: selected });
}}
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 text-gray-700 font-medium shadow-sm"
size={4}
>
{roomTypes.map(rt => (
<option key={rt.id} value={rt.id}>{rt.name}</option>
))}
</select>
<p className="text-xs text-gray-500 mt-1">Hold Ctrl/Cmd to select multiple. These room types cannot use this promotion.</p>
</div>
</div>
<div className="grid grid-cols-2 gap-6">
<div>
<label className="block text-xs font-semibold text-gray-600 uppercase tracking-wider mb-2">
Minimum Guests
</label>
<input
type="number"
value={promotionFormData.min_guests || ''}
onChange={(e) => setPromotionFormData({ ...promotionFormData, min_guests: parseInt(e.target.value) || 0 })}
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 text-gray-700 font-medium shadow-sm"
min="1"
placeholder="0 = no minimum"
/>
<p className="text-xs text-gray-500 mt-1">Minimum number of guests required</p>
</div>
<div>
<label className="block text-xs font-semibold text-gray-600 uppercase tracking-wider mb-2">
Maximum Guests
</label>
<input
type="number"
value={promotionFormData.max_guests || ''}
onChange={(e) => setPromotionFormData({ ...promotionFormData, max_guests: parseInt(e.target.value) || 0 })}
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 text-gray-700 font-medium shadow-sm"
min="1"
placeholder="0 = no maximum"
/>
<p className="text-xs text-gray-500 mt-1">Maximum number of guests allowed</p>
</div>
</div>
<div className="grid grid-cols-2 gap-6">
<div>
<label className="flex items-center gap-3 cursor-pointer">
<input
type="checkbox"
checked={promotionFormData.first_time_customer_only || false}
onChange={(e) => setPromotionFormData({ ...promotionFormData, first_time_customer_only: e.target.checked, repeat_customer_only: e.target.checked ? false : promotionFormData.repeat_customer_only })}
className="w-5 h-5 text-purple-600 border-gray-300 rounded focus:ring-purple-500"
/>
<span className="text-sm font-semibold text-gray-700">First-Time Customer Only</span>
</label>
<p className="text-xs text-gray-500 mt-1 ml-8">Only available to first-time customers</p>
</div>
<div>
<label className="flex items-center gap-3 cursor-pointer">
<input
type="checkbox"
checked={promotionFormData.repeat_customer_only || false}
onChange={(e) => setPromotionFormData({ ...promotionFormData, repeat_customer_only: e.target.checked, first_time_customer_only: e.target.checked ? false : promotionFormData.first_time_customer_only })}
className="w-5 h-5 text-purple-600 border-gray-300 rounded focus:ring-purple-500"
/>
<span className="text-sm font-semibold text-gray-700">Repeat Customer Only</span>
</label>
<p className="text-xs text-gray-500 mt-1 ml-8">Only available to returning customers</p>
</div>
</div>
<div>
<label className="block text-xs font-semibold text-gray-600 uppercase tracking-wider mb-2">
Blackout Dates
</label>
<textarea
value={promotionFormData.blackout_dates?.join('\n') || ''}
onChange={(e) => {
const dates = e.target.value.split('\n').filter(d => d.trim()).map(d => d.trim());
setPromotionFormData({ ...promotionFormData, blackout_dates: dates });
}}
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 text-gray-700 font-medium shadow-sm"
rows={3}
placeholder="Enter dates (one per line) in YYYY-MM-DD format&#10;Example:&#10;2024-12-25&#10;2024-12-31&#10;2025-01-01"
/>
<p className="text-xs text-gray-500 mt-1">Dates when promotion doesn't apply. One date per line (YYYY-MM-DD format).</p>
</div>
{/* Dates & Status Section */}
<div className="border-t-2 border-purple-200 pt-6 mt-6">
<h3 className="text-lg font-bold text-gray-900 mb-4 flex items-center gap-2">
<div className="h-1 w-8 bg-gradient-to-r from-purple-400 to-purple-600 rounded-full"></div>
Promotion Period & Status
</h3>
</div>
<div className="grid grid-cols-2 gap-6">
<div>
<label className="block text-xs font-semibold text-gray-600 uppercase tracking-wider mb-2">
Start Date <span className="text-red-500">*</span>
</label>
<input
type="date"
value={promotionFormData.start_date}
onChange={(e) => setPromotionFormData({ ...promotionFormData, start_date: e.target.value })}
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 text-gray-700 font-medium shadow-sm"
required
/>
</div>
<div>
<label className="block text-xs font-semibold text-gray-600 uppercase tracking-wider mb-2">
End Date <span className="text-red-500">*</span>
</label>
<input
type="date"
value={promotionFormData.end_date}
onChange={(e) => setPromotionFormData({ ...promotionFormData, end_date: e.target.value })}
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 text-gray-700 font-medium shadow-sm"
required
/>
</div>
</div>
<div className="grid grid-cols-2 gap-6">
<div>
<label className="block text-xs font-semibold text-gray-600 uppercase tracking-wider mb-2">
Usage Limit (0 = unlimited)
</label>
<input
type="number"
value={promotionFormData.usage_limit}
onChange={(e) => setPromotionFormData({ ...promotionFormData, usage_limit: parseInt(e.target.value) })}
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 text-gray-700 font-medium shadow-sm"
min="0"
/>
</div>
<div>
<label className="block text-xs font-semibold text-gray-600 uppercase tracking-wider mb-2">
Status
</label>
<select
value={promotionFormData.status}
onChange={(e) => setPromotionFormData({ ...promotionFormData, status: e.target.value as 'active' | 'inactive' })}
className="w-full px-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:border-purple-400 focus:ring-4 focus:ring-purple-100 transition-all duration-200 text-gray-700 font-medium shadow-sm cursor-pointer"
>
<option value="active">Active</option>
<option value="inactive">Inactive</option>
</select>
</div>
</div>
<div className="sticky bottom-0 bg-white border-t border-gray-200 mt-8 -mx-4 sm:-mx-6 md:-mx-8 px-4 sm:px-6 md:px-8 py-4 flex justify-end gap-3">
<button
type="button"
onClick={() => setShowPromotionModal(false)}
className="px-8 py-3 border-2 border-gray-300 rounded-xl text-gray-700 font-semibold hover:bg-gray-50 transition-all duration-200 shadow-sm hover:shadow-md"
>
Cancel
</button>
<button
type="submit"
className="px-8 py-3 bg-gradient-to-r from-purple-500 to-purple-600 text-white rounded-xl font-semibold hover:from-purple-600 hover:to-purple-700 transition-all duration-200 shadow-lg hover:shadow-xl"
>
{editingPromotion ? 'Update' : 'Create'}
</button>
</div>
</form>
</div>
</div>
</div>
</div>
)}
</div>
);
};
export default PromotionsManagementPage;

View File

@@ -1,4 +1,5 @@
import React, { useState, useEffect, useCallback } from 'react'; import React, { useState, useEffect, useCallback } from 'react';
import { useNavigate } from 'react-router-dom';
import { import {
LogIn, LogIn,
LogOut, LogOut,
@@ -1293,19 +1294,28 @@ const ReceptionDashboardPage: React.FC = () => {
<div className="p-2.5 rounded-xl bg-gradient-to-br from-blue-500/10 to-indigo-500/10 border border-blue-200/40"> <div className="p-2.5 rounded-xl bg-gradient-to-br from-blue-500/10 to-indigo-500/10 border border-blue-200/40">
<Calendar className="w-6 h-6 text-blue-600" /> <Calendar className="w-6 h-6 text-blue-600" />
</div> </div>
<h2 className="text-xl sm:text-2xl md:text-2xl font-extrabold text-gray-900">Bookings Management</h2> <h2 className="text-xl sm:text-2xl md:text-2xl font-extrabold text-gray-900">Reception Bookings</h2>
</div> </div>
<p className="text-gray-600 text-base max-w-2xl leading-relaxed"> <p className="text-gray-600 text-base max-w-2xl leading-relaxed">
Manage and track all hotel bookings with precision Quick view of bookings relevant to reception operations (confirmed, checked-in, checked-out)
</p> </p>
</div> </div>
<button <div className="flex gap-3">
onClick={() => setShowCreateBookingModal(true)} <button
className="flex items-center justify-center gap-2 px-6 py-3 bg-gradient-to-r from-amber-500 to-amber-600 text-white rounded-xl font-semibold hover:from-amber-600 hover:to-amber-700 transition-all duration-200 shadow-lg hover:shadow-xl whitespace-nowrap w-full sm:w-auto" onClick={() => navigate('/admin/bookings')}
> className="flex items-center justify-center gap-2 px-6 py-3 bg-gradient-to-r from-blue-500 to-blue-600 text-white rounded-xl font-semibold hover:from-blue-600 hover:to-blue-700 transition-all duration-200 shadow-lg hover:shadow-xl whitespace-nowrap w-full sm:w-auto"
<Plus className="w-5 h-5" /> >
Create Booking <Eye className="w-5 h-5" />
</button> View All Bookings
</button>
<button
onClick={() => setShowCreateBookingModal(true)}
className="flex items-center justify-center gap-2 px-6 py-3 bg-gradient-to-r from-amber-500 to-amber-600 text-white rounded-xl font-semibold hover:from-amber-600 hover:to-amber-700 transition-all duration-200 shadow-lg hover:shadow-xl whitespace-nowrap w-full sm:w-auto"
>
<Plus className="w-5 h-5" />
Create Booking
</button>
</div>
</div> </div>
</div> </div>

View File

@@ -1,379 +0,0 @@
import React, { useState } from 'react';
import {
Calendar,
Users,
Hotel,
TrendingUp,
Download,
Filter,
BarChart3,
PieChart
} from 'lucide-react';
import { toast } from 'react-toastify';
import Loading from '../../shared/components/Loading';
import EmptyState from '../../shared/components/EmptyState';
import CurrencyIcon from '../../shared/components/CurrencyIcon';
import { useAsync } from '../../shared/hooks/useAsync';
import reportService, { ReportData } from '../../features/analytics/services/reportService';
import { formatDate } from '../../shared/utils/format';
import { useFormatCurrency } from '../../features/payments/hooks/useFormatCurrency';
const ReportsPage: React.FC = () => {
const { formatCurrency } = useFormatCurrency();
const [dateRange, setDateRange] = useState({
from: '',
to: '',
});
const [reportType, setReportType] = useState<'daily' | 'weekly' | 'monthly' | 'yearly' | ''>('');
const fetchReports = async (): Promise<ReportData> => {
const params: any = {};
if (dateRange.from) params.from = dateRange.from;
if (dateRange.to) params.to = dateRange.to;
if (reportType) params.type = reportType;
const response = await reportService.getReports(params);
return response.data;
};
const {
data: reportData,
loading,
error,
execute: refetchReports
} = useAsync<ReportData>(fetchReports, {
immediate: true,
onError: (error: any) => {
toast.error(error.message || 'Unable to load reports');
}
});
const handleExport = async () => {
try {
const params: any = {};
if (dateRange.from) params.from = dateRange.from;
if (dateRange.to) params.to = dateRange.to;
if (reportType) params.type = reportType;
const blob = await reportService.exportReport(params);
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `report-${new Date().toISOString().split('T')[0]}.csv`;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
toast.success('Report exported successfully');
} catch (error: any) {
toast.error(error.message || 'Failed to export report');
}
};
const handleFilter = () => {
refetchReports();
};
if (loading && !reportData) {
return <Loading fullScreen text="Loading reports..." />;
}
if (error && !reportData) {
return (
<div className="container mx-auto px-4 py-8">
<EmptyState
title="Unable to Load Reports"
description={error.message || 'Something went wrong. Please try again.'}
action={{
label: 'Retry',
onClick: refetchReports
}}
/>
</div>
);
}
return (
<div className="container mx-auto px-4 py-8">
<div className="mb-8 flex justify-between items-center">
<div>
<h1 className="text-3xl font-bold text-gray-900 mb-2">Reports & Analytics</h1>
<p className="text-gray-600">View comprehensive reports and statistics</p>
</div>
<button
onClick={handleExport}
className="flex items-center space-x-2 px-4 py-2 bg-[#d4af37] text-white rounded-lg hover:bg-[#c9a227] transition-colors"
>
<Download className="w-5 h-5" />
<span>Export CSV</span>
</button>
</div>
{}
<div className="mb-6 bg-white p-4 rounded-lg shadow-md">
<div className="flex items-center space-x-2 mb-4">
<Filter className="w-5 h-5 text-gray-500" />
<h3 className="text-lg font-semibold text-gray-900">Filters</h3>
</div>
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
From Date
</label>
<input
type="date"
value={dateRange.from}
onChange={(e) => setDateRange({ ...dateRange, from: e.target.value })}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-[#d4af37]"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
To Date
</label>
<input
type="date"
value={dateRange.to}
onChange={(e) => setDateRange({ ...dateRange, to: e.target.value })}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-[#d4af37]"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Report Type
</label>
<select
value={reportType}
onChange={(e) => setReportType(e.target.value as any)}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-[#d4af37]"
>
<option value="">All</option>
<option value="daily">Daily</option>
<option value="weekly">Weekly</option>
<option value="monthly">Monthly</option>
<option value="yearly">Yearly</option>
</select>
</div>
<div className="flex items-end">
<button
onClick={handleFilter}
className="w-full px-4 py-2 bg-[#d4af37] text-white rounded-lg hover:bg-[#c9a227] transition-colors"
>
Apply Filters
</button>
</div>
</div>
</div>
{reportData && (
<>
{}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
<div className="bg-white p-6 rounded-lg shadow-md border-l-4 border-blue-500">
<div className="flex items-center justify-between mb-4">
<div className="p-3 bg-blue-100 rounded-lg">
<Calendar className="w-6 h-6 text-blue-600" />
</div>
<TrendingUp className="w-5 h-5 text-green-500" />
</div>
<h3 className="text-gray-500 text-sm font-medium mb-1">
Total Bookings
</h3>
<p className="text-3xl font-bold text-gray-800">
{reportData.total_bookings || 0}
</p>
</div>
<div className="bg-white p-6 rounded-lg shadow-md border-l-4 border-green-500">
<div className="flex items-center justify-between mb-4">
<div className="p-3 bg-green-100 rounded-lg">
<CurrencyIcon className="text-green-600" size={24} />
</div>
<TrendingUp className="w-5 h-5 text-green-500" />
</div>
<h3 className="text-gray-500 text-sm font-medium mb-1">
Total Revenue
</h3>
<p className="text-3xl font-bold text-gray-800">
{formatCurrency(reportData.total_revenue || 0)}
</p>
</div>
<div className="bg-white p-6 rounded-lg shadow-md border-l-4 border-purple-500">
<div className="flex items-center justify-between mb-4">
<div className="p-3 bg-purple-100 rounded-lg">
<Users className="w-6 h-6 text-purple-600" />
</div>
<TrendingUp className="w-5 h-5 text-green-500" />
</div>
<h3 className="text-gray-500 text-sm font-medium mb-1">
Total Customers
</h3>
<p className="text-3xl font-bold text-gray-800">
{reportData.total_customers || 0}
</p>
</div>
<div className="bg-white p-6 rounded-lg shadow-md border-l-4 border-orange-500">
<div className="flex items-center justify-between mb-4">
<div className="p-3 bg-orange-100 rounded-lg">
<Hotel className="w-6 h-6 text-orange-600" />
</div>
</div>
<h3 className="text-gray-500 text-sm font-medium mb-1">
Available Rooms
</h3>
<p className="text-3xl font-bold text-gray-800">
{reportData.available_rooms || 0}
</p>
<p className="text-sm text-gray-500 mt-1">
{reportData.occupied_rooms || 0} occupied
</p>
</div>
</div>
{}
{reportData.bookings_by_status && (
<div className="bg-white p-6 rounded-lg shadow-md mb-8">
<div className="flex items-center space-x-2 mb-6">
<PieChart className="w-5 h-5 text-gray-500" />
<h2 className="text-xl font-bold text-gray-900">Bookings by Status</h2>
</div>
<div className="grid grid-cols-2 md:grid-cols-5 gap-4">
{Object.entries(reportData.bookings_by_status).map(([status, count]) => (
<div key={status} className="text-center p-4 bg-gray-50 rounded-lg">
<p className="text-2xl font-bold text-gray-800">{count}</p>
<p className="text-sm text-gray-600 capitalize mt-1">{status.replace('_', ' ')}</p>
</div>
))}
</div>
</div>
)}
{}
{reportData.revenue_by_date && reportData.revenue_by_date.length > 0 && (
<div className="bg-white p-6 rounded-lg shadow-md mb-8">
<div className="flex items-center space-x-2 mb-6">
<BarChart3 className="w-5 h-5 text-gray-500" />
<h2 className="text-xl font-bold text-gray-900">Revenue by Date</h2>
</div>
<div className="overflow-x-auto">
<table className="w-full">
<thead className="bg-gray-50">
<tr>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">
Date
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">
Bookings
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">
Revenue
</th>
</tr>
</thead>
<tbody className="bg-white divide-y divide-gray-200">
{reportData.revenue_by_date.map((item, index) => (
<tr key={index} className="hover:bg-gray-50">
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
{formatDate(new Date(item.date), 'short')}
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{item.bookings}
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
{formatCurrency(item.revenue)}
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
)}
{}
{reportData.top_rooms && reportData.top_rooms.length > 0 && (
<div className="bg-white p-6 rounded-lg shadow-md mb-8">
<h2 className="text-xl font-bold text-gray-900 mb-6">Top Performing Rooms</h2>
<div className="overflow-x-auto">
<table className="w-full">
<thead className="bg-gray-50">
<tr>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">
Room Number
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">
Bookings
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">
Revenue
</th>
</tr>
</thead>
<tbody className="bg-white divide-y divide-gray-200">
{reportData.top_rooms.map((room) => (
<tr key={room.room_id} className="hover:bg-gray-50">
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
{room.room_number}
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{room.bookings}
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
{formatCurrency(room.revenue)}
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
)}
{}
{reportData.service_usage && reportData.service_usage.length > 0 && (
<div className="bg-white p-6 rounded-lg shadow-md">
<h2 className="text-xl font-bold text-gray-900 mb-6">Service Usage</h2>
<div className="overflow-x-auto">
<table className="w-full">
<thead className="bg-gray-50">
<tr>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">
Service Name
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">
Usage Count
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">
Total Revenue
</th>
</tr>
</thead>
<tbody className="bg-white divide-y divide-gray-200">
{reportData.service_usage.map((service) => (
<tr key={service.service_id} className="hover:bg-gray-50">
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
{service.service_name}
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{service.usage_count}
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
{formatCurrency(service.total_revenue)}
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
)}
</>
)}
</div>
);
};
export default ReportsPage;

View File

@@ -22,7 +22,8 @@ import {
MessageCircle, MessageCircle,
Clock, Clock,
X, X,
CheckCircle2 CheckCircle2,
Palette
} from 'lucide-react'; } from 'lucide-react';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import adminPrivacyService, { import adminPrivacyService, {
@@ -42,12 +43,13 @@ import systemSettingsService, {
CompanySettingsResponse, CompanySettingsResponse,
UpdateCompanySettingsRequest, UpdateCompanySettingsRequest,
} from '../../features/system/services/systemSettingsService'; } from '../../features/system/services/systemSettingsService';
import { themeService, ThemeSettingsResponse, UpdateThemeSettingsRequest } from '../../features/system/services/systemSettingsService';
import { recaptchaService, RecaptchaSettingsAdminResponse, UpdateRecaptchaSettingsRequest } from '../../features/system/services/systemSettingsService'; import { recaptchaService, RecaptchaSettingsAdminResponse, UpdateRecaptchaSettingsRequest } from '../../features/system/services/systemSettingsService';
import { useCurrency } from '../../features/payments/contexts/CurrencyContext'; import { useCurrency } from '../../features/payments/contexts/CurrencyContext';
import Loading from '../../shared/components/Loading'; import Loading from '../../shared/components/Loading';
import { getCurrencySymbol } from '../../shared/utils/format'; import { getCurrencySymbol } from '../../shared/utils/format';
type SettingsTab = 'general' | 'cookie' | 'currency' | 'payment' | 'smtp' | 'company' | 'recaptcha'; type SettingsTab = 'general' | 'cookie' | 'currency' | 'payment' | 'smtp' | 'company' | 'recaptcha' | 'theme';
const SettingsPage: React.FC = () => { const SettingsPage: React.FC = () => {
const { currency, supportedCurrencies, refreshCurrency } = useCurrency(); const { currency, supportedCurrencies, refreshCurrency } = useCurrency();
@@ -147,6 +149,15 @@ const SettingsPage: React.FC = () => {
}); });
const [showRecaptchaSecret, setShowRecaptchaSecret] = useState(false); const [showRecaptchaSecret, setShowRecaptchaSecret] = useState(false);
// Theme settings state
const [themeSettings, setThemeSettings] = useState<ThemeSettingsResponse['data'] | null>(null);
const [themeFormData, setThemeFormData] = useState<UpdateThemeSettingsRequest>({
theme_primary_color: '#d4af37',
theme_primary_light: '#f5d76e',
theme_primary_dark: '#c9a227',
theme_primary_accent: '#e8c547',
});
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [saving, setSaving] = useState(false); const [saving, setSaving] = useState(false);
@@ -200,6 +211,9 @@ const SettingsPage: React.FC = () => {
if (activeTab === 'recaptcha') { if (activeTab === 'recaptcha') {
loadRecaptchaSettings(); loadRecaptchaSettings();
} }
if (activeTab === 'theme') {
loadThemeSettings();
}
}, [activeTab]); }, [activeTab]);
useEffect(() => { useEffect(() => {
@@ -781,6 +795,47 @@ const SettingsPage: React.FC = () => {
} }
}; };
const loadThemeSettings = async () => {
try {
const themeRes = await themeService.getThemeSettings();
setThemeSettings(themeRes.data);
setThemeFormData({
theme_primary_color: themeRes.data.theme_primary_color || '#d4af37',
theme_primary_light: themeRes.data.theme_primary_light || '#f5d76e',
theme_primary_dark: themeRes.data.theme_primary_dark || '#c9a227',
theme_primary_accent: themeRes.data.theme_primary_accent || '#e8c547',
});
} catch (error: any) {
toast.error(
error.response?.data?.detail ||
error.response?.data?.message ||
'Failed to load theme settings'
);
}
};
const handleSaveTheme = async () => {
try {
setSaving(true);
await themeService.updateThemeSettings(themeFormData);
toast.success('Theme settings updated successfully');
await loadThemeSettings();
// Trigger theme refresh in the app
if (typeof window !== 'undefined') {
window.dispatchEvent(new CustomEvent('refreshTheme'));
}
} catch (error: any) {
toast.error(
error.response?.data?.detail ||
error.response?.data?.message ||
'Failed to save theme settings'
);
} finally {
setSaving(false);
}
};
if (loading) { if (loading) {
return <Loading fullScreen={false} text="Loading settings..." />; return <Loading fullScreen={false} text="Loading settings..." />;
} }
@@ -792,6 +847,7 @@ const SettingsPage: React.FC = () => {
{ id: 'payment' as SettingsTab, label: 'Payment', icon: CreditCard }, { id: 'payment' as SettingsTab, label: 'Payment', icon: CreditCard },
{ id: 'smtp' as SettingsTab, label: 'Email Server', icon: Mail }, { id: 'smtp' as SettingsTab, label: 'Email Server', icon: Mail },
{ id: 'company' as SettingsTab, label: 'Company Info', icon: Building2 }, { id: 'company' as SettingsTab, label: 'Company Info', icon: Building2 },
{ id: 'theme' as SettingsTab, label: 'Theme Colors', icon: Palette },
{ id: 'recaptcha' as SettingsTab, label: 'reCAPTCHA', icon: Shield }, { id: 'recaptcha' as SettingsTab, label: 'reCAPTCHA', icon: Shield },
]; ];
@@ -2909,6 +2965,192 @@ const SettingsPage: React.FC = () => {
</div> </div>
</div> </div>
)} )}
{activeTab === 'theme' && (
<div className="space-y-8">
<div className="flex items-center justify-between">
<div>
<h2 className="text-2xl font-bold text-gray-900 flex items-center gap-3">
<Palette className="w-6 h-6 text-amber-600" />
Theme Colors
</h2>
<p className="text-gray-600 mt-2">
Customize the primary color scheme of your frontend pages
</p>
</div>
</div>
<div className="bg-white rounded-xl shadow-lg border border-gray-200 p-8">
<div className="space-y-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="space-y-2">
<label className="flex items-center gap-2 text-sm font-bold text-gray-900 tracking-wide">
<Palette className="w-4 h-4 text-gray-600" />
Primary Color
</label>
<div className="flex gap-3">
<input
type="color"
value={themeFormData.theme_primary_color || '#d4af37'}
onChange={(e) =>
setThemeFormData({
...themeFormData,
theme_primary_color: e.target.value,
})
}
className="w-20 h-12 rounded-lg border-2 border-gray-300 cursor-pointer"
/>
<input
type="text"
value={themeFormData.theme_primary_color || '#d4af37'}
onChange={(e) =>
setThemeFormData({
...themeFormData,
theme_primary_color: e.target.value,
})
}
placeholder="#d4af37"
className="flex-1 px-4 py-3.5 bg-white border border-gray-300 rounded-xl shadow-sm focus:ring-2 focus:ring-amber-500/50 focus:border-amber-500 transition-all duration-200 text-sm font-mono"
/>
</div>
<p className="text-xs text-gray-500">
Main brand color used for buttons, links, and highlights
</p>
</div>
<div className="space-y-2">
<label className="flex items-center gap-2 text-sm font-bold text-gray-900 tracking-wide">
<Palette className="w-4 h-4 text-gray-600" />
Primary Light
</label>
<div className="flex gap-3">
<input
type="color"
value={themeFormData.theme_primary_light || '#f5d76e'}
onChange={(e) =>
setThemeFormData({
...themeFormData,
theme_primary_light: e.target.value,
})
}
className="w-20 h-12 rounded-lg border-2 border-gray-300 cursor-pointer"
/>
<input
type="text"
value={themeFormData.theme_primary_light || '#f5d76e'}
onChange={(e) =>
setThemeFormData({
...themeFormData,
theme_primary_light: e.target.value,
})
}
placeholder="#f5d76e"
className="flex-1 px-4 py-3.5 bg-white border border-gray-300 rounded-xl shadow-sm focus:ring-2 focus:ring-amber-500/50 focus:border-amber-500 transition-all duration-200 text-sm font-mono"
/>
</div>
<p className="text-xs text-gray-500">
Lighter variant for hover states and gradients
</p>
</div>
<div className="space-y-2">
<label className="flex items-center gap-2 text-sm font-bold text-gray-900 tracking-wide">
<Palette className="w-4 h-4 text-gray-600" />
Primary Dark
</label>
<div className="flex gap-3">
<input
type="color"
value={themeFormData.theme_primary_dark || '#c9a227'}
onChange={(e) =>
setThemeFormData({
...themeFormData,
theme_primary_dark: e.target.value,
})
}
className="w-20 h-12 rounded-lg border-2 border-gray-300 cursor-pointer"
/>
<input
type="text"
value={themeFormData.theme_primary_dark || '#c9a227'}
onChange={(e) =>
setThemeFormData({
...themeFormData,
theme_primary_dark: e.target.value,
})
}
placeholder="#c9a227"
className="flex-1 px-4 py-3.5 bg-white border border-gray-300 rounded-xl shadow-sm focus:ring-2 focus:ring-amber-500/50 focus:border-amber-500 transition-all duration-200 text-sm font-mono"
/>
</div>
<p className="text-xs text-gray-500">
Darker variant for borders and shadows
</p>
</div>
<div className="space-y-2">
<label className="flex items-center gap-2 text-sm font-bold text-gray-900 tracking-wide">
<Palette className="w-4 h-4 text-gray-600" />
Primary Accent
</label>
<div className="flex gap-3">
<input
type="color"
value={themeFormData.theme_primary_accent || '#e8c547'}
onChange={(e) =>
setThemeFormData({
...themeFormData,
theme_primary_accent: e.target.value,
})
}
className="w-20 h-12 rounded-lg border-2 border-gray-300 cursor-pointer"
/>
<input
type="text"
value={themeFormData.theme_primary_accent || '#e8c547'}
onChange={(e) =>
setThemeFormData({
...themeFormData,
theme_primary_accent: e.target.value,
})
}
placeholder="#e8c547"
className="flex-1 px-4 py-3.5 bg-white border border-gray-300 rounded-xl shadow-sm focus:ring-2 focus:ring-amber-500/50 focus:border-amber-500 transition-all duration-200 text-sm font-mono"
/>
</div>
<p className="text-xs text-gray-500">
Accent color for special highlights and effects
</p>
</div>
</div>
<div className="bg-blue-50 border border-blue-200 rounded-lg p-4">
<div className="flex items-start gap-3">
<Info className="w-5 h-5 text-blue-600 flex-shrink-0 mt-0.5" />
<div className="text-sm text-blue-800">
<p className="font-semibold mb-1">About Theme Colors</p>
<p className="text-xs">
Changes to theme colors will be applied immediately across all frontend pages.
Use hex color codes (e.g., #d4af37) for best results. The colors will replace the default gold/yellow theme throughout the application.
</p>
</div>
</div>
</div>
<div className="flex justify-end pt-4 border-t border-gray-200">
<button
onClick={handleSaveTheme}
disabled={saving}
className="flex items-center gap-2 px-6 py-3 bg-gradient-to-r from-amber-500 to-amber-600 text-white rounded-xl font-semibold hover:from-amber-600 hover:to-amber-700 transition-all duration-200 shadow-lg hover:shadow-xl disabled:opacity-50 disabled:cursor-not-allowed"
>
<Save className="w-5 h-5" />
{saving ? 'Saving...' : 'Save Theme Settings'}
</button>
</div>
</div>
</div>
</div>
)}
</div> </div>
</div> </div>
); );

View File

@@ -92,7 +92,7 @@ const BoricaReturnPage: React.FC = () => {
<div className="bg-gradient-to-br from-gray-900/40 to-gray-800/20 <div className="bg-gradient-to-br from-gray-900/40 to-gray-800/20
border border-gray-700/50 rounded-xl p-6 sm:p-10 w-full max-w-2xl mx-auto text-center border border-gray-700/50 rounded-xl p-6 sm:p-10 w-full max-w-2xl mx-auto text-center
backdrop-blur-xl shadow-2xl shadow-black/20"> backdrop-blur-xl shadow-2xl shadow-black/20">
<Loader2 className="w-12 h-12 sm:w-16 sm:h-16 animate-spin text-[#d4af37] mx-auto mb-4" /> <Loader2 className="w-12 h-12 sm:w-16 sm:h-16 animate-spin text-[var(--luxury-gold)] mx-auto mb-4" />
<h1 className="text-xl sm:text-2xl font-serif font-semibold text-white mb-2"> <h1 className="text-xl sm:text-2xl font-serif font-semibold text-white mb-2">
Processing Payment... Processing Payment...
</h1> </h1>
@@ -124,11 +124,11 @@ const BoricaReturnPage: React.FC = () => {
</p> </p>
<button <button
onClick={() => navigate(`/bookings/${bookingId}`)} onClick={() => navigate(`/bookings/${bookingId}`)}
className="bg-gradient-to-r from-[#d4af37] to-[#c9a227] className="bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]
text-[#0f0f0f] px-6 py-2 sm:px-8 sm:py-3 rounded-sm text-[#0f0f0f] px-6 py-2 sm:px-8 sm:py-3 rounded-sm
hover:from-[#f5d76e] hover:to-[#d4af37] hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)]
transition-all duration-300 font-medium tracking-wide transition-all duration-300 font-medium tracking-wide
shadow-lg shadow-[#d4af37]/30 text-sm sm:text-base w-full sm:w-auto" shadow-lg shadow-[var(--luxury-gold)]/30 text-sm sm:text-base w-full sm:w-auto"
> >
View Booking View Booking
</button> </button>
@@ -165,11 +165,11 @@ const BoricaReturnPage: React.FC = () => {
</button> </button>
<button <button
onClick={() => navigate('/')} onClick={() => navigate('/')}
className="bg-gradient-to-r from-[#d4af37] to-[#c9a227] className="bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]
text-[#0f0f0f] px-6 py-2 sm:px-8 sm:py-3 rounded-sm text-[#0f0f0f] px-6 py-2 sm:px-8 sm:py-3 rounded-sm
hover:from-[#f5d76e] hover:to-[#d4af37] hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)]
transition-all duration-300 font-medium tracking-wide transition-all duration-300 font-medium tracking-wide
shadow-lg shadow-[#d4af37]/30 text-sm sm:text-base w-full sm:w-auto" shadow-lg shadow-[var(--luxury-gold)]/30 text-sm sm:text-base w-full sm:w-auto"
> >
Go Home Go Home
</button> </button>

View File

@@ -130,7 +130,7 @@ const ComplaintPage: React.FC = () => {
</div> </div>
<button <button
onClick={() => setShowCreateModal(true)} onClick={() => setShowCreateModal(true)}
className="flex items-center space-x-2 px-4 py-2 bg-[#d4af37] text-white rounded-lg hover:bg-[#c9a227] transition-colors" className="flex items-center space-x-2 px-4 py-2 bg-[var(--luxury-gold)] text-white rounded-lg hover:bg-[var(--luxury-gold-dark)] transition-colors"
> >
<Plus className="w-5 h-5" /> <Plus className="w-5 h-5" />
<span>Submit Complaint</span> <span>Submit Complaint</span>
@@ -180,7 +180,7 @@ const ComplaintPage: React.FC = () => {
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium"> <td className="px-6 py-4 whitespace-nowrap text-sm font-medium">
<button <button
onClick={() => handleViewDetails(complaint.id)} onClick={() => handleViewDetails(complaint.id)}
className="text-[#d4af37] hover:text-[#c9a227]" className="text-[var(--luxury-gold)] hover:text-[var(--luxury-gold-dark)]"
> >
<Eye className="w-5 h-5" /> <Eye className="w-5 h-5" />
</button> </button>
@@ -277,7 +277,7 @@ const CreateComplaintModal: React.FC<{
<select <select
value={formData.booking_id} value={formData.booking_id}
onChange={(e) => setFormData({ ...formData, booking_id: e.target.value })} onChange={(e) => setFormData({ ...formData, booking_id: e.target.value })}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-transparent" className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-transparent"
> >
<option value="">Select a booking</option> <option value="">Select a booking</option>
{bookings.map((booking) => ( {bookings.map((booking) => (
@@ -295,7 +295,7 @@ const CreateComplaintModal: React.FC<{
value={formData.category} value={formData.category}
onChange={(e) => setFormData({ ...formData, category: e.target.value })} onChange={(e) => setFormData({ ...formData, category: e.target.value })}
required required
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-transparent" className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-transparent"
> >
<option value="">Select category</option> <option value="">Select category</option>
<option value="room_quality">Room Quality</option> <option value="room_quality">Room Quality</option>
@@ -315,7 +315,7 @@ const CreateComplaintModal: React.FC<{
<select <select
value={formData.priority} value={formData.priority}
onChange={(e) => setFormData({ ...formData, priority: e.target.value })} onChange={(e) => setFormData({ ...formData, priority: e.target.value })}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-transparent" className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-transparent"
> >
<option value="low">Low</option> <option value="low">Low</option>
<option value="medium">Medium</option> <option value="medium">Medium</option>
@@ -332,7 +332,7 @@ const CreateComplaintModal: React.FC<{
value={formData.title} value={formData.title}
onChange={(e) => setFormData({ ...formData, title: e.target.value })} onChange={(e) => setFormData({ ...formData, title: e.target.value })}
required required
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-transparent" className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-transparent"
placeholder="Brief description of the issue" placeholder="Brief description of the issue"
/> />
</div> </div>
@@ -345,7 +345,7 @@ const CreateComplaintModal: React.FC<{
onChange={(e) => setFormData({ ...formData, description: e.target.value })} onChange={(e) => setFormData({ ...formData, description: e.target.value })}
required required
rows={6} rows={6}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#d4af37] focus:border-transparent" className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-transparent"
placeholder="Please provide detailed information about your complaint..." placeholder="Please provide detailed information about your complaint..."
/> />
</div> </div>
@@ -361,7 +361,7 @@ const CreateComplaintModal: React.FC<{
<button <button
type="submit" type="submit"
disabled={submitting} disabled={submitting}
className="px-4 py-2 bg-[#d4af37] text-white rounded-lg hover:bg-[#c9a227] disabled:opacity-50 disabled:cursor-not-allowed" className="px-4 py-2 bg-[var(--luxury-gold)] text-white rounded-lg hover:bg-[var(--luxury-gold-dark)] disabled:opacity-50 disabled:cursor-not-allowed"
> >
{submitting ? 'Submitting...' : 'Submit Complaint'} {submitting ? 'Submitting...' : 'Submit Complaint'}
</button> </button>

View File

@@ -231,11 +231,11 @@ const FullPaymentPage: React.FC = () => {
<Link <Link
to="/bookings" to="/bookings"
className="inline-flex items-center gap-2 className="inline-flex items-center gap-2
bg-gradient-to-r from-[#d4af37] to-[#c9a227] bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]
text-[#0f0f0f] px-6 py-3 rounded-sm text-[#0f0f0f] px-6 py-3 rounded-sm
hover:from-[#f5d76e] hover:to-[#d4af37] hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)]
transition-all duration-300 font-medium transition-all duration-300 font-medium
tracking-wide shadow-lg shadow-[#d4af37]/30" tracking-wide shadow-lg shadow-[var(--luxury-gold)]/30"
> >
<ArrowLeft className="w-4 h-4" /> <ArrowLeft className="w-4 h-4" />
Back to booking list Back to booking list
@@ -270,7 +270,7 @@ const FullPaymentPage: React.FC = () => {
<Link <Link
to={`/bookings/${bookingId}`} to={`/bookings/${bookingId}`}
className="inline-flex items-center gap-2 className="inline-flex items-center gap-2
text-[#d4af37]/80 hover:text-[#d4af37] text-[var(--luxury-gold)]/80 hover:text-[var(--luxury-gold)]
mb-6 transition-all duration-300 mb-6 transition-all duration-300
group font-light tracking-wide" group font-light tracking-wide"
> >
@@ -307,19 +307,19 @@ const FullPaymentPage: React.FC = () => {
{} {}
{!isPaymentCompleted && ( {!isPaymentCompleted && (
<div <div
className="bg-gradient-to-br from-[#d4af37]/10 to-[#c9a227]/5 className="bg-gradient-to-br from-[var(--luxury-gold)]/10 to-[var(--luxury-gold-dark)]/5
border-2 border-[#d4af37]/30 rounded-xl p-6 mb-6 border-2 border-[var(--luxury-gold)]/30 rounded-xl p-6 mb-6
backdrop-blur-xl shadow-2xl shadow-[#d4af37]/10" backdrop-blur-xl shadow-2xl shadow-[var(--luxury-gold)]/10"
> >
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<div <div
className="w-16 h-16 bg-[#d4af37]/20 rounded-full className="w-16 h-16 bg-[var(--luxury-gold)]/20 rounded-full
flex items-center justify-center border border-[#d4af37]/30" flex items-center justify-center border border-[var(--luxury-gold)]/30"
> >
<CreditCard className="w-10 h-10 text-[#d4af37]" /> <CreditCard className="w-10 h-10 text-[var(--luxury-gold)]" />
</div> </div>
<div className="flex-1"> <div className="flex-1">
<h1 className="text-2xl font-serif font-bold text-[#d4af37] mb-1 tracking-wide"> <h1 className="text-2xl font-serif font-bold text-[var(--luxury-gold)] mb-1 tracking-wide">
Complete Payment Complete Payment
</h1> </h1>
<p className="text-gray-300 font-light tracking-wide"> <p className="text-gray-300 font-light tracking-wide">
@@ -336,11 +336,11 @@ const FullPaymentPage: React.FC = () => {
{} {}
<div <div
className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a]
rounded-xl border border-[#d4af37]/20 rounded-xl border border-[var(--luxury-gold)]/20
backdrop-blur-xl shadow-2xl shadow-[#d4af37]/5 p-6" backdrop-blur-xl shadow-2xl shadow-[var(--luxury-gold)]/5 p-6"
> >
<h2 className="text-xl font-serif font-semibold text-[#d4af37] mb-4 flex items-center gap-2"> <h2 className="text-xl font-serif font-semibold text-[var(--luxury-gold)] mb-4 flex items-center gap-2">
<div className="w-1 h-6 bg-gradient-to-b from-[#d4af37] to-[#c9a227]" /> <div className="w-1 h-6 bg-gradient-to-b from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]" />
Payment Information Payment Information
</h2> </h2>
@@ -353,8 +353,8 @@ const FullPaymentPage: React.FC = () => {
</div> </div>
<div <div
className="flex justify-between border-t border-[#d4af37]/20 pt-3 className="flex justify-between border-t border-[var(--luxury-gold)]/20 pt-3
text-[#d4af37]" text-[var(--luxury-gold)]"
> >
<span className="font-medium"> <span className="font-medium">
Amount to Pay Amount to Pay
@@ -386,11 +386,11 @@ const FullPaymentPage: React.FC = () => {
{!isPaymentCompleted && booking && stripePayment && ( {!isPaymentCompleted && booking && stripePayment && (
<div <div
className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a]
rounded-xl border border-[#d4af37]/20 rounded-xl border border-[var(--luxury-gold)]/20
backdrop-blur-xl shadow-2xl shadow-[#d4af37]/5 p-6" backdrop-blur-xl shadow-2xl shadow-[var(--luxury-gold)]/5 p-6"
> >
<h2 className="text-xl font-serif font-semibold text-[#d4af37] mb-4 flex items-center gap-2"> <h2 className="text-xl font-serif font-semibold text-[var(--luxury-gold)] mb-4 flex items-center gap-2">
<div className="w-1 h-6 bg-gradient-to-b from-[#d4af37] to-[#c9a227]" /> <div className="w-1 h-6 bg-gradient-to-b from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]" />
<CreditCard className="w-5 h-5" /> <CreditCard className="w-5 h-5" />
Card Payment Card Payment
</h2> </h2>
@@ -406,11 +406,11 @@ const FullPaymentPage: React.FC = () => {
</p> </p>
<button <button
onClick={() => navigate(`/bookings/${booking.id}`)} onClick={() => navigate(`/bookings/${booking.id}`)}
className="bg-gradient-to-r from-[#d4af37] to-[#c9a227] className="bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]
text-[#0f0f0f] px-6 py-3 rounded-sm text-[#0f0f0f] px-6 py-3 rounded-sm
hover:from-[#f5d76e] hover:to-[#d4af37] hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)]
transition-all duration-300 font-medium transition-all duration-300 font-medium
tracking-wide shadow-lg shadow-[#d4af37]/30" tracking-wide shadow-lg shadow-[var(--luxury-gold)]/30"
> >
View Booking View Booking
</button> </button>
@@ -440,12 +440,12 @@ const FullPaymentPage: React.FC = () => {
<div className="lg:col-span-1"> <div className="lg:col-span-1">
<div <div
className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a]
rounded-xl border border-[#d4af37]/20 rounded-xl border border-[var(--luxury-gold)]/20
backdrop-blur-xl shadow-2xl shadow-[#d4af37]/5 p-6 backdrop-blur-xl shadow-2xl shadow-[var(--luxury-gold)]/5 p-6
sticky top-6" sticky top-6"
> >
<h3 className="text-lg font-serif font-semibold text-[#d4af37] mb-4 flex items-center gap-2"> <h3 className="text-lg font-serif font-semibold text-[var(--luxury-gold)] mb-4 flex items-center gap-2">
<div className="w-1 h-5 bg-gradient-to-b from-[#d4af37] to-[#c9a227]" /> <div className="w-1 h-5 bg-gradient-to-b from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]" />
Booking Summary Booking Summary
</h3> </h3>
@@ -476,9 +476,9 @@ const FullPaymentPage: React.FC = () => {
</p> </p>
</div> </div>
<div className="pt-3 border-t border-[#d4af37]/20"> <div className="pt-3 border-t border-[var(--luxury-gold)]/20">
<span className="text-gray-400 font-light">Total Amount</span> <span className="text-gray-400 font-light">Total Amount</span>
<p className="text-xl font-bold text-[#d4af37]"> <p className="text-xl font-bold text-[var(--luxury-gold)]">
{formatPrice(booking.total_price)} {formatPrice(booking.total_price)}
</p> </p>
</div> </div>
@@ -486,7 +486,7 @@ const FullPaymentPage: React.FC = () => {
{/* PCI DSS Compliance Trust Badge */} {/* PCI DSS Compliance Trust Badge */}
{!isPaymentCompleted && ( {!isPaymentCompleted && (
<div className="mt-6 pt-6 border-t border-[#d4af37]/20"> <div className="mt-6 pt-6 border-t border-[var(--luxury-gold)]/20">
<div className="bg-gradient-to-r from-blue-900/20 to-indigo-900/20 border border-blue-500/30 rounded-lg p-4"> <div className="bg-gradient-to-r from-blue-900/20 to-indigo-900/20 border border-blue-500/30 rounded-lg p-4">
<div className="flex items-start gap-3"> <div className="flex items-start gap-3">
<div className="flex-shrink-0"> <div className="flex-shrink-0">

View File

@@ -195,7 +195,7 @@ const GuestRequestsPage: React.FC = () => {
} }
setShowCreateModal(true); setShowCreateModal(true);
}} }}
className="flex items-center space-x-2 px-6 py-3 bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-white rounded-lg hover:from-[#f5d76e] hover:to-[#d4af37] transition-all duration-300 shadow-lg hover:shadow-xl font-medium" className="flex items-center space-x-2 px-6 py-3 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-white rounded-lg hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] transition-all duration-300 shadow-lg hover:shadow-xl font-medium"
> >
<Plus className="w-5 h-5" /> <Plus className="w-5 h-5" />
<span>New Request</span> <span>New Request</span>
@@ -209,7 +209,7 @@ const GuestRequestsPage: React.FC = () => {
<select <select
value={filterStatus} value={filterStatus}
onChange={(e) => setFilterStatus(e.target.value)} onChange={(e) => setFilterStatus(e.target.value)}
className="border border-gray-300 rounded-lg px-4 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[#d4af37]" className="border border-gray-300 rounded-lg px-4 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)]"
> >
<option value="">All Statuses</option> <option value="">All Statuses</option>
<option value="pending">Pending</option> <option value="pending">Pending</option>
@@ -344,7 +344,7 @@ const GuestRequestsPage: React.FC = () => {
}); });
setSelectedBooking(booking); setSelectedBooking(booking);
}} }}
className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[#d4af37]" className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)]"
required required
> >
<option value="">Select Booking</option> <option value="">Select Booking</option>
@@ -363,7 +363,7 @@ const GuestRequestsPage: React.FC = () => {
<select <select
value={requestForm.request_type} value={requestForm.request_type}
onChange={(e) => setRequestForm({ ...requestForm, request_type: e.target.value })} onChange={(e) => setRequestForm({ ...requestForm, request_type: e.target.value })}
className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[#d4af37]" className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)]"
required required
> >
{requestTypes.map((type) => ( {requestTypes.map((type) => (
@@ -383,7 +383,7 @@ const GuestRequestsPage: React.FC = () => {
value={requestForm.title} value={requestForm.title}
onChange={(e) => setRequestForm({ ...requestForm, title: e.target.value })} onChange={(e) => setRequestForm({ ...requestForm, title: e.target.value })}
placeholder="Brief description of your request" placeholder="Brief description of your request"
className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[#d4af37]" className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)]"
required required
/> />
</div> </div>
@@ -397,7 +397,7 @@ const GuestRequestsPage: React.FC = () => {
onChange={(e) => setRequestForm({ ...requestForm, description: e.target.value })} onChange={(e) => setRequestForm({ ...requestForm, description: e.target.value })}
placeholder="Additional details about your request" placeholder="Additional details about your request"
rows={4} rows={4}
className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[#d4af37]" className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)]"
/> />
</div> </div>
@@ -408,7 +408,7 @@ const GuestRequestsPage: React.FC = () => {
<select <select
value={requestForm.priority} value={requestForm.priority}
onChange={(e) => setRequestForm({ ...requestForm, priority: e.target.value })} onChange={(e) => setRequestForm({ ...requestForm, priority: e.target.value })}
className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[#d4af37]" className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)]"
> >
<option value="low">Low</option> <option value="low">Low</option>
<option value="normal">Normal</option> <option value="normal">Normal</option>
@@ -426,7 +426,7 @@ const GuestRequestsPage: React.FC = () => {
onChange={(e) => setRequestForm({ ...requestForm, guest_notes: e.target.value })} onChange={(e) => setRequestForm({ ...requestForm, guest_notes: e.target.value })}
placeholder="Any special instructions or preferences" placeholder="Any special instructions or preferences"
rows={3} rows={3}
className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[#d4af37]" className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)]"
/> />
</div> </div>
@@ -439,7 +439,7 @@ const GuestRequestsPage: React.FC = () => {
</button> </button>
<button <button
onClick={handleCreateRequest} onClick={handleCreateRequest}
className="px-4 py-2 text-sm text-white bg-gradient-to-r from-[#d4af37] to-[#c9a227] rounded-lg hover:from-[#f5d76e] hover:to-[#d4af37] transition-colors font-medium" className="px-4 py-2 text-sm text-white bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] rounded-lg hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] transition-colors font-medium"
> >
Submit Request Submit Request
</button> </button>

View File

@@ -91,11 +91,11 @@ const PayPalCancelPage: React.FC = () => {
{bookingId && ( {bookingId && (
<button <button
onClick={() => navigate(`/bookings/${bookingId}`)} onClick={() => navigate(`/bookings/${bookingId}`)}
className="flex-1 bg-gradient-to-r from-[#d4af37] to-[#c9a227] className="flex-1 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]
text-[#0f0f0f] px-4 py-2 sm:px-6 sm:py-3 rounded-sm text-[#0f0f0f] px-4 py-2 sm:px-6 sm:py-3 rounded-sm
hover:from-[#f5d76e] hover:to-[#d4af37] hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)]
transition-all duration-300 font-medium tracking-wide transition-all duration-300 font-medium tracking-wide
shadow-lg shadow-[#d4af37]/30 flex items-center justify-center gap-2 shadow-lg shadow-[var(--luxury-gold)]/30 flex items-center justify-center gap-2
disabled:opacity-50 disabled:cursor-not-allowed text-sm sm:text-base" disabled:opacity-50 disabled:cursor-not-allowed text-sm sm:text-base"
disabled={cancelling} disabled={cancelling}
> >
@@ -107,7 +107,7 @@ const PayPalCancelPage: React.FC = () => {
onClick={() => navigate('/bookings')} onClick={() => navigate('/bookings')}
className="flex-1 bg-gradient-to-br from-gray-800/40 to-gray-700/20 className="flex-1 bg-gradient-to-br from-gray-800/40 to-gray-700/20
border border-gray-600/30 text-gray-300 px-4 py-2 sm:px-6 sm:py-3 rounded-sm border border-gray-600/30 text-gray-300 px-4 py-2 sm:px-6 sm:py-3 rounded-sm
hover:border-[#d4af37]/50 hover:text-[#d4af37] hover:border-[var(--luxury-gold)]/50 hover:text-[var(--luxury-gold)]
transition-all duration-300 font-light tracking-wide transition-all duration-300 font-light tracking-wide
backdrop-blur-sm text-sm sm:text-base" backdrop-blur-sm text-sm sm:text-base"
> >

View File

@@ -82,10 +82,10 @@ const PayPalReturnPage: React.FC = () => {
<div className="min-h-screen bg-gradient-to-b from-[#0f0f0f] via-[#1a1a1a] to-[#0f0f0f] <div className="min-h-screen bg-gradient-to-b from-[#0f0f0f] via-[#1a1a1a] to-[#0f0f0f]
flex items-center justify-center py-8 sm:py-12 px-4 sm:px-6 lg:px-8"> flex items-center justify-center py-8 sm:py-12 px-4 sm:px-6 lg:px-8">
<div className="text-center w-full max-w-2xl mx-auto"> <div className="text-center w-full max-w-2xl mx-auto">
<div className="w-16 h-16 sm:w-20 sm:h-20 bg-gradient-to-br from-[#d4af37]/20 to-[#f5d76e]/20 <div className="w-16 h-16 sm:w-20 sm:h-20 bg-gradient-to-br from-[var(--luxury-gold)]/20 to-[var(--luxury-gold-light)]/20
rounded-full flex items-center justify-center mx-auto mb-4 sm:mb-6 rounded-full flex items-center justify-center mx-auto mb-4 sm:mb-6
border border-[#d4af37]/30 shadow-lg shadow-[#d4af37]/20"> border border-[var(--luxury-gold)]/30 shadow-lg shadow-[var(--luxury-gold)]/20">
<Loader2 className="w-10 h-10 sm:w-12 sm:h-12 text-[#d4af37] animate-spin" /> <Loader2 className="w-10 h-10 sm:w-12 sm:h-12 text-[var(--luxury-gold)] animate-spin" />
</div> </div>
<p className="text-gray-300/80 font-light text-base sm:text-lg tracking-wide"> <p className="text-gray-300/80 font-light text-base sm:text-lg tracking-wide">
Processing your payment... Processing your payment...
@@ -115,11 +115,11 @@ const PayPalReturnPage: React.FC = () => {
</p> </p>
<button <button
onClick={() => navigate(`/bookings/${bookingId}`)} onClick={() => navigate(`/bookings/${bookingId}`)}
className="bg-gradient-to-r from-[#d4af37] to-[#c9a227] className="bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]
text-[#0f0f0f] px-6 py-2 sm:px-8 sm:py-3 rounded-sm text-[#0f0f0f] px-6 py-2 sm:px-8 sm:py-3 rounded-sm
hover:from-[#f5d76e] hover:to-[#d4af37] hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)]
transition-all duration-300 font-medium tracking-wide transition-all duration-300 font-medium tracking-wide
shadow-lg shadow-[#d4af37]/30 text-sm sm:text-base w-full sm:w-auto" shadow-lg shadow-[var(--luxury-gold)]/30 text-sm sm:text-base w-full sm:w-auto"
> >
View Booking View Booking
</button> </button>
@@ -149,11 +149,11 @@ const PayPalReturnPage: React.FC = () => {
{bookingId && ( {bookingId && (
<button <button
onClick={() => navigate(`/bookings/${bookingId}`)} onClick={() => navigate(`/bookings/${bookingId}`)}
className="flex-1 bg-gradient-to-r from-[#d4af37] to-[#c9a227] className="flex-1 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]
text-[#0f0f0f] px-4 py-2 sm:px-6 sm:py-3 rounded-sm text-[#0f0f0f] px-4 py-2 sm:px-6 sm:py-3 rounded-sm
hover:from-[#f5d76e] hover:to-[#d4af37] hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)]
transition-all duration-300 font-medium tracking-wide transition-all duration-300 font-medium tracking-wide
shadow-lg shadow-[#d4af37]/30 text-sm sm:text-base" shadow-lg shadow-[var(--luxury-gold)]/30 text-sm sm:text-base"
> >
View Booking View Booking
</button> </button>
@@ -162,7 +162,7 @@ const PayPalReturnPage: React.FC = () => {
onClick={() => navigate('/bookings')} onClick={() => navigate('/bookings')}
className="flex-1 bg-gradient-to-br from-gray-800/40 to-gray-700/20 className="flex-1 bg-gradient-to-br from-gray-800/40 to-gray-700/20
border border-gray-600/30 text-gray-300 px-4 py-2 sm:px-6 sm:py-3 rounded-sm border border-gray-600/30 text-gray-300 px-4 py-2 sm:px-6 sm:py-3 rounded-sm
hover:border-[#d4af37]/50 hover:text-[#d4af37] hover:border-[var(--luxury-gold)]/50 hover:text-[var(--luxury-gold)]
transition-all duration-300 font-light tracking-wide transition-all duration-300 font-light tracking-wide
backdrop-blur-sm text-sm sm:text-base" backdrop-blur-sm text-sm sm:text-base"
> >

View File

@@ -417,7 +417,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div className="mb-6 sm:mb-8 animate-fade-in"> <div className="mb-6 sm:mb-8 animate-fade-in">
<div className="flex items-center gap-2 sm:gap-3 mb-2 sm:mb-3"> <div className="flex items-center gap-2 sm:gap-3 mb-2 sm:mb-3">
<div className="h-1 w-12 sm:w-16 md:w-20 bg-gradient-to-r from-[#d4af37] via-amber-400 to-[#d4af37] rounded-full"></div> <div className="h-1 w-12 sm:w-16 md:w-20 bg-gradient-to-r from-[var(--luxury-gold)] via-amber-400 to-[var(--luxury-gold)] rounded-full"></div>
<h1 className="text-2xl sm:text-3xl lg:text-4xl font-serif font-bold bg-gradient-to-r from-gray-900 via-amber-900/90 to-gray-900 bg-clip-text text-transparent tracking-tight"> <h1 className="text-2xl sm:text-3xl lg:text-4xl font-serif font-bold bg-gradient-to-r from-gray-900 via-amber-900/90 to-gray-900 bg-clip-text text-transparent tracking-tight">
Profile & Settings Profile & Settings
</h1> </h1>
@@ -428,61 +428,61 @@ const ProfilePage: React.FC = () => {
</div> </div>
{} {}
<div className="mb-4 sm:mb-6 border-b border-[#d4af37]/20 overflow-x-auto bg-white/50 backdrop-blur-sm rounded-t-lg sm:rounded-t-xl px-4 sm:px-6"> <div className="mb-4 sm:mb-6 border-b border-[var(--luxury-gold)]/20 overflow-x-auto bg-white/50 backdrop-blur-sm rounded-t-lg sm:rounded-t-xl px-4 sm:px-6">
<div className="flex space-x-4 sm:space-x-8 min-w-max"> <div className="flex space-x-4 sm:space-x-8 min-w-max">
<button <button
onClick={() => setActiveTab('profile')} onClick={() => setActiveTab('profile')}
className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${ className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${
activeTab === 'profile' activeTab === 'profile'
? 'border-[#d4af37] text-[#d4af37] shadow-sm' ? 'border-[var(--luxury-gold)] text-[var(--luxury-gold)] shadow-sm'
: 'border-transparent text-gray-500 hover:text-[#d4af37] hover:border-[#d4af37]/30' : 'border-transparent text-gray-500 hover:text-[var(--luxury-gold)] hover:border-[var(--luxury-gold)]/30'
}`} }`}
> >
<User className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'profile' ? 'text-[#d4af37]' : ''}`} /> <User className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'profile' ? 'text-[var(--luxury-gold)]' : ''}`} />
Profile Information Profile Information
</button> </button>
<button <button
onClick={() => setActiveTab('password')} onClick={() => setActiveTab('password')}
className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${ className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${
activeTab === 'password' activeTab === 'password'
? 'border-[#d4af37] text-[#d4af37] shadow-sm' ? 'border-[var(--luxury-gold)] text-[var(--luxury-gold)] shadow-sm'
: 'border-transparent text-gray-500 hover:text-[#d4af37] hover:border-[#d4af37]/30' : 'border-transparent text-gray-500 hover:text-[var(--luxury-gold)] hover:border-[var(--luxury-gold)]/30'
}`} }`}
> >
<KeyRound className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'password' ? 'text-[#d4af37]' : ''}`} /> <KeyRound className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'password' ? 'text-[var(--luxury-gold)]' : ''}`} />
Change Password Change Password
</button> </button>
<button <button
onClick={() => setActiveTab('mfa')} onClick={() => setActiveTab('mfa')}
className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${ className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${
activeTab === 'mfa' activeTab === 'mfa'
? 'border-[#d4af37] text-[#d4af37] shadow-sm' ? 'border-[var(--luxury-gold)] text-[var(--luxury-gold)] shadow-sm'
: 'border-transparent text-gray-500 hover:text-[#d4af37] hover:border-[#d4af37]/30' : 'border-transparent text-gray-500 hover:text-[var(--luxury-gold)] hover:border-[var(--luxury-gold)]/30'
}`} }`}
> >
<Shield className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'mfa' ? 'text-[#d4af37]' : ''}`} /> <Shield className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'mfa' ? 'text-[var(--luxury-gold)]' : ''}`} />
Two-Factor Authentication Two-Factor Authentication
</button> </button>
<button <button
onClick={() => setActiveTab('sessions')} onClick={() => setActiveTab('sessions')}
className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${ className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${
activeTab === 'sessions' activeTab === 'sessions'
? 'border-[#d4af37] text-[#d4af37] shadow-sm' ? 'border-[var(--luxury-gold)] text-[var(--luxury-gold)] shadow-sm'
: 'border-transparent text-gray-500 hover:text-[#d4af37] hover:border-[#d4af37]/30' : 'border-transparent text-gray-500 hover:text-[var(--luxury-gold)] hover:border-[var(--luxury-gold)]/30'
}`} }`}
> >
<Monitor className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'sessions' ? 'text-[#d4af37]' : ''}`} /> <Monitor className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'sessions' ? 'text-[var(--luxury-gold)]' : ''}`} />
Active Sessions Active Sessions
</button> </button>
<button <button
onClick={() => setActiveTab('gdpr')} onClick={() => setActiveTab('gdpr')}
className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${ className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${
activeTab === 'gdpr' activeTab === 'gdpr'
? 'border-[#d4af37] text-[#d4af37] shadow-sm' ? 'border-[var(--luxury-gold)] text-[var(--luxury-gold)] shadow-sm'
: 'border-transparent text-gray-500 hover:text-[#d4af37] hover:border-[#d4af37]/30' : 'border-transparent text-gray-500 hover:text-[var(--luxury-gold)] hover:border-[var(--luxury-gold)]/30'
}`} }`}
> >
<Database className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'gdpr' ? 'text-[#d4af37]' : ''}`} /> <Database className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'gdpr' ? 'text-[var(--luxury-gold)]' : ''}`} />
Data Privacy Data Privacy
</button> </button>
</div> </div>
@@ -490,7 +490,7 @@ const ProfilePage: React.FC = () => {
{} {}
{activeTab === 'profile' && ( {activeTab === 'profile' && (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl animate-slide-up"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl animate-slide-up">
<form onSubmit={handleSubmitProfile(onSubmitProfile)} className="space-y-5 sm:space-y-6"> <form onSubmit={handleSubmitProfile(onSubmitProfile)} className="space-y-5 sm:space-y-6">
{} {}
<div className="flex flex-col sm:flex-row items-center sm:items-start gap-4 sm:gap-6 pb-5 sm:pb-6 border-b border-gray-200"> <div className="flex flex-col sm:flex-row items-center sm:items-start gap-4 sm:gap-6 pb-5 sm:pb-6 border-b border-gray-200">
@@ -499,20 +499,20 @@ const ProfilePage: React.FC = () => {
<img <img
src={avatarPreview || normalizeImageUrl(userInfo?.avatar)} src={avatarPreview || normalizeImageUrl(userInfo?.avatar)}
alt="Profile" alt="Profile"
className="w-20 h-20 sm:w-24 sm:h-24 rounded-full object-cover ring-4 ring-[#d4af37]/20 shadow-lg" className="w-20 h-20 sm:w-24 sm:h-24 rounded-full object-cover ring-4 ring-[var(--luxury-gold)]/20 shadow-lg"
onError={() => { onError={() => {
// If image fails to load, show default avatar // If image fails to load, show default avatar
setAvatarError(true); setAvatarError(true);
}} }}
/> />
) : ( ) : (
<div className="w-20 h-20 sm:w-24 sm:h-24 rounded-full bg-gradient-to-br from-[#d4af37] to-[#c9a227] flex items-center justify-center ring-4 ring-[#d4af37]/20 shadow-lg"> <div className="w-20 h-20 sm:w-24 sm:h-24 rounded-full bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] flex items-center justify-center ring-4 ring-[var(--luxury-gold)]/20 shadow-lg">
<User className="w-10 h-10 sm:w-12 sm:h-12 text-white" /> <User className="w-10 h-10 sm:w-12 sm:h-12 text-white" />
</div> </div>
)} )}
<label <label
htmlFor="avatar-upload" htmlFor="avatar-upload"
className="absolute bottom-0 right-0 p-2 bg-gradient-to-br from-[#d4af37] to-[#c9a227] rounded-full cursor-pointer hover:from-[#f5d76e] hover:to-[#d4af37] transition-all duration-300 shadow-lg hover:shadow-xl hover:shadow-[#d4af37]/40 hover:-translate-y-0.5 active:translate-y-0" className="absolute bottom-0 right-0 p-2 bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] rounded-full cursor-pointer hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] transition-all duration-300 shadow-lg hover:shadow-xl hover:shadow-[var(--luxury-gold)]/40 hover:-translate-y-0.5 active:translate-y-0"
> >
<Camera className="w-3.5 h-3.5 sm:w-4 sm:h-4 text-white" /> <Camera className="w-3.5 h-3.5 sm:w-4 sm:h-4 text-white" />
<input <input
@@ -528,7 +528,7 @@ const ProfilePage: React.FC = () => {
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<User className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <User className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
Full Name Full Name
<span className="text-red-500 ml-1">*</span> <span className="text-red-500 ml-1">*</span>
</label> </label>
@@ -551,7 +551,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<Mail className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <Mail className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
Email Address Email Address
<span className="text-red-500 ml-1">*</span> <span className="text-red-500 ml-1">*</span>
</label> </label>
@@ -574,7 +574,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<Phone className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <Phone className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
Phone Number Phone Number
<span className="text-red-500 ml-1">*</span> <span className="text-red-500 ml-1">*</span>
</label> </label>
@@ -611,7 +611,7 @@ const ProfilePage: React.FC = () => {
{} {}
{activeTab === 'password' && ( {activeTab === 'password' && (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl animate-slide-up"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl animate-slide-up">
<form onSubmit={handleSubmitPassword(onSubmitPassword)} className="space-y-5 sm:space-y-6"> <form onSubmit={handleSubmitPassword(onSubmitPassword)} className="space-y-5 sm:space-y-6">
{} {}
<div className="bg-gradient-to-r from-blue-50 to-indigo-50 border border-blue-200/60 rounded-sm p-4 sm:p-5"> <div className="bg-gradient-to-r from-blue-50 to-indigo-50 border border-blue-200/60 rounded-sm p-4 sm:p-5">
@@ -640,7 +640,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
Current Password Current Password
<span className="text-red-500 ml-1">*</span> <span className="text-red-500 ml-1">*</span>
</label> </label>
@@ -656,7 +656,7 @@ const ProfilePage: React.FC = () => {
<button <button
type="button" type="button"
onClick={() => setShowPassword({ ...showPassword, current: !showPassword.current })} onClick={() => setShowPassword({ ...showPassword, current: !showPassword.current })}
className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[#d4af37] transition-colors" className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[var(--luxury-gold)] transition-colors"
> >
{showPassword.current ? ( {showPassword.current ? (
<EyeOff className="w-4 h-4 sm:w-5 sm:h-5" /> <EyeOff className="w-4 h-4 sm:w-5 sm:h-5" />
@@ -676,7 +676,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
New Password New Password
<span className="text-red-500 ml-1">*</span> <span className="text-red-500 ml-1">*</span>
</label> </label>
@@ -692,7 +692,7 @@ const ProfilePage: React.FC = () => {
<button <button
type="button" type="button"
onClick={() => setShowPassword({ ...showPassword, new: !showPassword.new })} onClick={() => setShowPassword({ ...showPassword, new: !showPassword.new })}
className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[#d4af37] transition-colors" className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[var(--luxury-gold)] transition-colors"
> >
{showPassword.new ? ( {showPassword.new ? (
<EyeOff className="w-4 h-4 sm:w-5 sm:h-5" /> <EyeOff className="w-4 h-4 sm:w-5 sm:h-5" />
@@ -712,7 +712,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
Confirm New Password Confirm New Password
<span className="text-red-500 ml-1">*</span> <span className="text-red-500 ml-1">*</span>
</label> </label>
@@ -728,7 +728,7 @@ const ProfilePage: React.FC = () => {
<button <button
type="button" type="button"
onClick={() => setShowPassword({ ...showPassword, confirm: !showPassword.confirm })} onClick={() => setShowPassword({ ...showPassword, confirm: !showPassword.confirm })}
className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[#d4af37] transition-colors" className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[var(--luxury-gold)] transition-colors"
> >
{showPassword.confirm ? ( {showPassword.confirm ? (
<EyeOff className="w-4 h-4 sm:w-5 sm:h-5" /> <EyeOff className="w-4 h-4 sm:w-5 sm:h-5" />
@@ -762,11 +762,11 @@ const ProfilePage: React.FC = () => {
{} {}
{activeTab === 'mfa' && ( {activeTab === 'mfa' && (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl animate-slide-up space-y-5 sm:space-y-6"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl animate-slide-up space-y-5 sm:space-y-6">
{} {}
<div> <div>
<h2 className="text-xl sm:text-2xl font-serif font-semibold text-gray-900 mb-2 flex items-center gap-2"> <h2 className="text-xl sm:text-2xl font-serif font-semibold text-gray-900 mb-2 flex items-center gap-2">
<Shield className="w-5 h-5 sm:w-6 sm:h-6 text-[#d4af37]" /> <Shield className="w-5 h-5 sm:w-6 sm:h-6 text-[var(--luxury-gold)]" />
Two-Factor Authentication Two-Factor Authentication
</h2> </h2>
<p className="text-xs sm:text-sm text-gray-600 font-light leading-relaxed"> <p className="text-xs sm:text-sm text-gray-600 font-light leading-relaxed">
@@ -838,7 +838,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div className="bg-white border border-gray-200 rounded-sm p-4 sm:p-5"> <div className="bg-white border border-gray-200 rounded-sm p-4 sm:p-5">
<h3 className="text-sm sm:text-base font-semibold text-gray-900 mb-2 flex items-center gap-2"> <h3 className="text-sm sm:text-base font-semibold text-gray-900 mb-2 flex items-center gap-2">
<RefreshCw className="w-4 h-4 sm:w-5 sm:h-5 text-[#d4af37]" /> <RefreshCw className="w-4 h-4 sm:w-5 sm:h-5 text-[var(--luxury-gold)]" />
Backup Codes Backup Codes
</h3> </h3>
<p className="text-xs sm:text-sm text-gray-600 font-light mb-4 leading-relaxed"> <p className="text-xs sm:text-sm text-gray-600 font-light mb-4 leading-relaxed">
@@ -984,7 +984,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div className="bg-white border border-gray-200 rounded-sm p-4 sm:p-5"> <div className="bg-white border border-gray-200 rounded-sm p-4 sm:p-5">
<h3 className="font-semibold text-gray-900 mb-2 text-sm sm:text-base flex items-center gap-2"> <h3 className="font-semibold text-gray-900 mb-2 text-sm sm:text-base flex items-center gap-2">
<KeyRound className="w-4 h-4 sm:w-5 sm:h-5 text-[#d4af37]" /> <KeyRound className="w-4 h-4 sm:w-5 sm:h-5 text-[var(--luxury-gold)]" />
Step 2: Verify Setup Step 2: Verify Setup
</h3> </h3>
<p className="text-xs sm:text-sm text-gray-600 font-light mb-4 leading-relaxed"> <p className="text-xs sm:text-sm text-gray-600 font-light mb-4 leading-relaxed">
@@ -1110,10 +1110,10 @@ const SessionsTab: React.FC = () => {
}; };
const getDeviceIcon = (userAgent?: string) => { const getDeviceIcon = (userAgent?: string) => {
if (!userAgent) return <Monitor className="w-5 h-5 text-[#d4af37]" />; if (!userAgent) return <Monitor className="w-5 h-5 text-[var(--luxury-gold)]" />;
if (userAgent.includes('Mobile')) return <Smartphone className="w-5 h-5 text-blue-500" />; if (userAgent.includes('Mobile')) return <Smartphone className="w-5 h-5 text-blue-500" />;
if (userAgent.includes('Tablet')) return <Tablet className="w-5 h-5 text-purple-500" />; if (userAgent.includes('Tablet')) return <Tablet className="w-5 h-5 text-purple-500" />;
return <Monitor className="w-5 h-5 text-[#d4af37]" />; return <Monitor className="w-5 h-5 text-[var(--luxury-gold)]" />;
}; };
const getDeviceName = (userAgent?: string) => { const getDeviceName = (userAgent?: string) => {
@@ -1181,17 +1181,17 @@ const SessionsTab: React.FC = () => {
if (loading) { if (loading) {
return ( return (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl">
<Loading text="Loading sessions..." /> <Loading text="Loading sessions..." />
</div> </div>
); );
} }
return ( return (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl animate-slide-up space-y-5 sm:space-y-6"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl animate-slide-up space-y-5 sm:space-y-6">
<div> <div>
<h2 className="text-xl sm:text-2xl font-serif font-semibold text-gray-900 mb-2 flex items-center gap-2"> <h2 className="text-xl sm:text-2xl font-serif font-semibold text-gray-900 mb-2 flex items-center gap-2">
<Monitor className="w-5 h-5 sm:w-6 sm:h-6 text-[#d4af37]" /> <Monitor className="w-5 h-5 sm:w-6 sm:h-6 text-[var(--luxury-gold)]" />
Active Sessions Active Sessions
</h2> </h2>
<p className="text-xs sm:text-sm text-gray-600 font-light"> <p className="text-xs sm:text-sm text-gray-600 font-light">
@@ -1220,11 +1220,11 @@ const SessionsTab: React.FC = () => {
{sessions.map((session) => ( {sessions.map((session) => (
<div <div
key={session.id} key={session.id}
className="bg-gradient-to-r from-slate-50 to-white border border-[#d4af37]/20 rounded-sm p-4 sm:p-5 hover:shadow-lg hover:border-[#d4af37]/40 transition-all duration-300" className="bg-gradient-to-r from-slate-50 to-white border border-[var(--luxury-gold)]/20 rounded-sm p-4 sm:p-5 hover:shadow-lg hover:border-[var(--luxury-gold)]/40 transition-all duration-300"
> >
<div className="flex items-start justify-between gap-4"> <div className="flex items-start justify-between gap-4">
<div className="flex items-start gap-4 flex-1"> <div className="flex items-start gap-4 flex-1">
<div className="p-2 sm:p-3 bg-gradient-to-br from-[#d4af37]/10 to-[#c9a227]/10 rounded-sm flex-shrink-0"> <div className="p-2 sm:p-3 bg-gradient-to-br from-[var(--luxury-gold)]/10 to-[var(--luxury-gold-dark)]/10 rounded-sm flex-shrink-0">
{getDeviceIcon(session.user_agent)} {getDeviceIcon(session.user_agent)}
</div> </div>
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
@@ -1354,17 +1354,17 @@ const GDPRTab: React.FC = () => {
if (loading) { if (loading) {
return ( return (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl">
<Loading text="Loading privacy data..." /> <Loading text="Loading privacy data..." />
</div> </div>
); );
} }
return ( return (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl animate-slide-up space-y-5 sm:space-y-6"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl animate-slide-up space-y-5 sm:space-y-6">
<div> <div>
<h2 className="text-xl sm:text-2xl font-serif font-semibold text-gray-900 mb-2 flex items-center gap-2"> <h2 className="text-xl sm:text-2xl font-serif font-semibold text-gray-900 mb-2 flex items-center gap-2">
<Database className="w-5 h-5 sm:w-6 sm:h-6 text-[#d4af37]" /> <Database className="w-5 h-5 sm:w-6 sm:h-6 text-[var(--luxury-gold)]" />
Data Privacy & GDPR Rights Data Privacy & GDPR Rights
</h2> </h2>
<p className="text-xs sm:text-sm text-gray-600 font-light"> <p className="text-xs sm:text-sm text-gray-600 font-light">
@@ -1431,14 +1431,14 @@ const GDPRTab: React.FC = () => {
{requests.length > 0 && ( {requests.length > 0 && (
<div className="border-t border-gray-200 pt-5 sm:pt-6"> <div className="border-t border-gray-200 pt-5 sm:pt-6">
<h3 className="text-base sm:text-lg font-semibold text-gray-900 mb-4 flex items-center gap-2"> <h3 className="text-base sm:text-lg font-semibold text-gray-900 mb-4 flex items-center gap-2">
<FileText className="w-5 h-5 text-[#d4af37]" /> <FileText className="w-5 h-5 text-[var(--luxury-gold)]" />
Request History Request History
</h3> </h3>
<div className="space-y-3 sm:space-y-4"> <div className="space-y-3 sm:space-y-4">
{requests.map((request) => ( {requests.map((request) => (
<div <div
key={request.id} key={request.id}
className="bg-gradient-to-r from-slate-50 to-white border border-[#d4af37]/20 rounded-sm p-4 sm:p-5 hover:shadow-md hover:border-[#d4af37]/40 transition-all duration-300" className="bg-gradient-to-r from-slate-50 to-white border border-[var(--luxury-gold)]/20 rounded-sm p-4 sm:p-5 hover:shadow-md hover:border-[var(--luxury-gold)]/40 transition-all duration-300"
> >
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3 sm:gap-4"> <div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3 sm:gap-4">
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">

View File

@@ -184,9 +184,9 @@ const RoomDetailPage: React.FC = () => {
> >
<div className="w-full px-2 sm:px-4 md:px-6 lg:px-8 py-8 sm:py-12"> <div className="w-full px-2 sm:px-4 md:px-6 lg:px-8 py-8 sm:py-12">
<div className="animate-pulse space-y-6"> <div className="animate-pulse space-y-6">
<div className="h-[600px] bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-xl border border-[#d4af37]/20" /> <div className="h-[600px] bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-xl border border-[var(--luxury-gold)]/20" />
<div className="h-12 bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-lg w-1/3 border border-[#d4af37]/10" /> <div className="h-12 bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-lg w-1/3 border border-[var(--luxury-gold)]/10" />
<div className="h-6 bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-lg w-2/3 border border-[#d4af37]/10" /> <div className="h-6 bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] rounded-lg w-2/3 border border-[var(--luxury-gold)]/10" />
</div> </div>
</div> </div>
</div> </div>
@@ -217,10 +217,10 @@ const RoomDetailPage: React.FC = () => {
<button <button
onClick={() => navigate('/rooms')} onClick={() => navigate('/rooms')}
className="inline-flex items-center gap-2 bg-gradient-to-r className="inline-flex items-center gap-2 bg-gradient-to-r
from-[#d4af37] to-[#c9a227] text-[#0f0f0f] from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-[#0f0f0f]
px-6 py-3 rounded-sm hover:from-[#f5d76e] px-6 py-3 rounded-sm hover:from-[var(--luxury-gold-light)]
hover:to-[#d4af37] transition-all duration-300 hover:to-[var(--luxury-gold)] transition-all duration-300
font-medium tracking-wide shadow-lg shadow-[#d4af37]/30" font-medium tracking-wide shadow-lg shadow-[var(--luxury-gold)]/30"
> >
<ArrowLeft className="w-5 h-5" /> <ArrowLeft className="w-5 h-5" />
Back to Room List Back to Room List
@@ -251,7 +251,7 @@ const RoomDetailPage: React.FC = () => {
<Link <Link
to="/rooms" to="/rooms"
className="inline-flex items-center gap-1 className="inline-flex items-center gap-1
text-[#d4af37]/80 hover:text-[#d4af37] text-[var(--luxury-gold)]/80 hover:text-[var(--luxury-gold)]
mb-3 transition-all duration-300 mb-3 transition-all duration-300
group font-light tracking-wide text-xs sm:text-sm" group font-light tracking-wide text-xs sm:text-sm"
> >
@@ -281,10 +281,10 @@ const RoomDetailPage: React.FC = () => {
<div className="flex items-center gap-1.5 mb-2"> <div className="flex items-center gap-1.5 mb-2">
{room.featured && ( {room.featured && (
<div className="flex items-center gap-1 <div className="flex items-center gap-1
bg-gradient-to-r from-[#d4af37] to-[#c9a227] bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]
text-[#0f0f0f] px-2 py-0.5 rounded-sm text-[#0f0f0f] px-2 py-0.5 rounded-sm
text-[10px] sm:text-xs font-medium tracking-wide text-[10px] sm:text-xs font-medium tracking-wide
shadow-sm shadow-[#d4af37]/30" shadow-sm shadow-[var(--luxury-gold)]/30"
> >
<Sparkles className="w-2.5 h-2.5" /> <Sparkles className="w-2.5 h-2.5" />
Featured Featured
@@ -315,7 +315,7 @@ const RoomDetailPage: React.FC = () => {
</p> </p>
)} )}
{room.status === 'occupied' && nextAvailableDate && ( {room.status === 'occupied' && nextAvailableDate && (
<p className="text-[9px] sm:text-[10px] text-[#d4af37] font-light leading-tight"> <p className="text-[9px] sm:text-[10px] text-[var(--luxury-gold)] font-light leading-tight">
Available from {nextAvailableDate.toLocaleDateString('en-US', { month: 'short', day: 'numeric' })} Available from {nextAvailableDate.toLocaleDateString('en-US', { month: 'short', day: 'numeric' })}
</p> </p>
)} )}
@@ -324,7 +324,7 @@ const RoomDetailPage: React.FC = () => {
<h1 className="text-xl sm:text-2xl lg:text-3xl font-serif font-semibold <h1 className="text-xl sm:text-2xl lg:text-3xl font-serif font-semibold
text-white mb-2 tracking-tight leading-tight text-white mb-2 tracking-tight leading-tight
bg-gradient-to-r from-white via-[#d4af37] to-white bg-gradient-to-r from-white via-[var(--luxury-gold)] to-white
bg-clip-text text-transparent" bg-clip-text text-transparent"
> >
{roomType?.name} {roomType?.name}
@@ -336,12 +336,12 @@ const RoomDetailPage: React.FC = () => {
<div className="grid grid-cols-1 md:grid-cols-3 gap-2 sm:gap-3 mb-3"> <div className="grid grid-cols-1 md:grid-cols-3 gap-2 sm:gap-3 mb-3">
<div className="flex items-center gap-2 <div className="flex items-center gap-2
p-2 bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] p-2 bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a]
rounded-lg border border-[#d4af37]/20 rounded-lg border border-[var(--luxury-gold)]/20
hover:border-[#d4af37]/40 transition-all duration-300" hover:border-[var(--luxury-gold)]/40 transition-all duration-300"
> >
<div className="p-1 bg-[#d4af37]/10 rounded-lg <div className="p-1 bg-[var(--luxury-gold)]/10 rounded-lg
border border-[#d4af37]/30"> border border-[var(--luxury-gold)]/30">
<MapPin className="w-3.5 h-3.5 text-[#d4af37]" /> <MapPin className="w-3.5 h-3.5 text-[var(--luxury-gold)]" />
</div> </div>
<div> <div>
<p className="text-[10px] sm:text-xs text-gray-400 font-light tracking-wide mb-0.5"> <p className="text-[10px] sm:text-xs text-gray-400 font-light tracking-wide mb-0.5">
@@ -355,11 +355,11 @@ const RoomDetailPage: React.FC = () => {
<div className="flex items-center gap-2 <div className="flex items-center gap-2
p-2 bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] p-2 bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a]
rounded-lg border border-[#d4af37]/20" rounded-lg border border-[var(--luxury-gold)]/20"
> >
<div className="p-1 bg-[#d4af37]/10 rounded-lg <div className="p-1 bg-[var(--luxury-gold)]/10 rounded-lg
border border-[#d4af37]/30"> border border-[var(--luxury-gold)]/30">
<Users className="w-3.5 h-3.5 text-[#d4af37]" /> <Users className="w-3.5 h-3.5 text-[var(--luxury-gold)]" />
</div> </div>
<div> <div>
<p className="text-[10px] sm:text-xs text-gray-400 font-light tracking-wide mb-0.5"> <p className="text-[10px] sm:text-xs text-gray-400 font-light tracking-wide mb-0.5">
@@ -374,12 +374,12 @@ const RoomDetailPage: React.FC = () => {
{room.average_rating != null && ( {room.average_rating != null && (
<div className="flex items-center gap-2 <div className="flex items-center gap-2
p-2 bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] p-2 bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a]
rounded-lg border border-[#d4af37]/20 rounded-lg border border-[var(--luxury-gold)]/20
hover:border-[#d4af37]/40 transition-all duration-300" hover:border-[var(--luxury-gold)]/40 transition-all duration-300"
> >
<div className="p-1 bg-[#d4af37]/10 rounded-lg <div className="p-1 bg-[var(--luxury-gold)]/10 rounded-lg
border border-[#d4af37]/30"> border border-[var(--luxury-gold)]/30">
<Star className="w-3.5 h-3.5 text-[#d4af37] fill-[#d4af37]" /> <Star className="w-3.5 h-3.5 text-[var(--luxury-gold)] fill-[var(--luxury-gold)]" />
</div> </div>
<div> <div>
<p className="text-[10px] sm:text-xs text-gray-400 font-light tracking-wide mb-0.5"> <p className="text-[10px] sm:text-xs text-gray-400 font-light tracking-wide mb-0.5">
@@ -402,13 +402,13 @@ const RoomDetailPage: React.FC = () => {
{} {}
{(room?.description || roomType?.description) && ( {(room?.description || roomType?.description) && (
<div className="p-3 sm:p-4 bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] <div className="p-3 sm:p-4 bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a]
rounded-lg border border-[#d4af37]/20 rounded-lg border border-[var(--luxury-gold)]/20
backdrop-blur-xl shadow-lg shadow-[#d4af37]/5" backdrop-blur-xl shadow-lg shadow-[var(--luxury-gold)]/5"
> >
<div className="flex items-center gap-2 mb-2"> <div className="flex items-center gap-2 mb-2">
<div className="p-1 bg-[#d4af37]/10 rounded-lg <div className="p-1 bg-[var(--luxury-gold)]/10 rounded-lg
border border-[#d4af37]/30"> border border-[var(--luxury-gold)]/30">
<Award className="w-3.5 h-3.5 text-[#d4af37]" /> <Award className="w-3.5 h-3.5 text-[var(--luxury-gold)]" />
</div> </div>
<h2 className="text-sm sm:text-base font-serif font-semibold <h2 className="text-sm sm:text-base font-serif font-semibold
text-white tracking-wide" text-white tracking-wide"
@@ -426,13 +426,13 @@ const RoomDetailPage: React.FC = () => {
{} {}
<div className="p-3 sm:p-4 bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] <div className="p-3 sm:p-4 bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a]
rounded-lg border border-[#d4af37]/20 rounded-lg border border-[var(--luxury-gold)]/20
backdrop-blur-xl shadow-lg shadow-[#d4af37]/5" backdrop-blur-xl shadow-lg shadow-[var(--luxury-gold)]/5"
> >
<div className="flex items-center gap-2 mb-2"> <div className="flex items-center gap-2 mb-2">
<div className="p-1 bg-[#d4af37]/10 rounded-lg <div className="p-1 bg-[var(--luxury-gold)]/10 rounded-lg
border border-[#d4af37]/30"> border border-[var(--luxury-gold)]/30">
<Sparkles className="w-3.5 h-3.5 text-[#d4af37]" /> <Sparkles className="w-3.5 h-3.5 text-[var(--luxury-gold)]" />
</div> </div>
<h2 className="text-sm sm:text-base font-serif font-semibold <h2 className="text-sm sm:text-base font-serif font-semibold
text-white tracking-wide" text-white tracking-wide"
@@ -447,10 +447,10 @@ const RoomDetailPage: React.FC = () => {
: (roomType?.amenities || []) : (roomType?.amenities || [])
} }
/> />
<div className="mt-6 pt-6 border-t border-[#d4af37]/20"> <div className="mt-6 pt-6 border-t border-[var(--luxury-gold)]/20">
<Link <Link
to="/services" to="/services"
className="inline-flex items-center gap-2 px-4 py-2 bg-gradient-to-r from-[#d4af37]/20 to-[#c9a227]/10 hover:from-[#d4af37]/30 hover:to-[#d4af37]/20 text-[#d4af37] rounded-lg font-medium transition-all duration-300 border border-[#d4af37]/30 hover:border-[#d4af37]/50" className="inline-flex items-center gap-2 px-4 py-2 bg-gradient-to-r from-[var(--luxury-gold)]/20 to-[var(--luxury-gold-dark)]/10 hover:from-[var(--luxury-gold)]/30 hover:to-[var(--luxury-gold)]/20 text-[var(--luxury-gold)] rounded-lg font-medium transition-all duration-300 border border-[var(--luxury-gold)]/30 hover:border-[var(--luxury-gold)]/50"
> >
<Award className="w-4 h-4" /> <Award className="w-4 h-4" />
<span className="text-sm">View All Services</span> <span className="text-sm">View All Services</span>
@@ -462,20 +462,20 @@ const RoomDetailPage: React.FC = () => {
{} {}
<aside className="lg:col-span-4"> <aside className="lg:col-span-4">
<div className="bg-gradient-to-br from-[#1a1a1a] via-[#0f0f0f] to-[#1a1a1a] <div className="bg-gradient-to-br from-[#1a1a1a] via-[#0f0f0f] to-[#1a1a1a]
rounded-lg border border-[#d4af37]/30 rounded-lg border border-[var(--luxury-gold)]/30
backdrop-blur-xl shadow-lg shadow-[#d4af37]/20 backdrop-blur-xl shadow-lg shadow-[var(--luxury-gold)]/20
p-3 sm:p-4 sticky top-4" p-3 sm:p-4 sticky top-4"
> >
{} {}
<div className="mb-4 pb-4 border-b border-[#d4af37]/20"> <div className="mb-4 pb-4 border-b border-[var(--luxury-gold)]/20">
<p className="text-[10px] sm:text-xs text-gray-400 font-light tracking-wide mb-1"> <p className="text-[10px] sm:text-xs text-gray-400 font-light tracking-wide mb-1">
Starting from Starting from
</p> </p>
<div className="flex items-baseline gap-1.5"> <div className="flex items-baseline gap-1.5">
<CurrencyIcon className="text-[#d4af37]" size={16} /> <CurrencyIcon className="text-[var(--luxury-gold)]" size={16} />
<div> <div>
<div className="text-2xl sm:text-3xl font-serif font-semibold <div className="text-2xl sm:text-3xl font-serif font-semibold
bg-gradient-to-r from-[#d4af37] to-[#f5d76e] bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-light)]
bg-clip-text text-transparent tracking-tight" bg-clip-text text-transparent tracking-tight"
> >
{formattedPrice} {formattedPrice}
@@ -510,7 +510,7 @@ const RoomDetailPage: React.FC = () => {
tracking-wide relative overflow-hidden group text-xs sm:text-sm tracking-wide relative overflow-hidden group text-xs sm:text-sm
${ ${
room.status === 'available' room.status === 'available'
? 'bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-[#0f0f0f] hover:from-[#f5d76e] hover:to-[#d4af37] shadow-sm shadow-[#d4af37]/30 hover:shadow-[#d4af37]/50' ? 'bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-[#0f0f0f] hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] shadow-sm shadow-[var(--luxury-gold)]/30 hover:shadow-[var(--luxury-gold)]/50'
: 'bg-gray-800 text-gray-500 cursor-not-allowed border border-gray-700' : 'bg-gray-800 text-gray-500 cursor-not-allowed border border-gray-700'
}`} }`}
> >
@@ -525,12 +525,12 @@ const RoomDetailPage: React.FC = () => {
</div> </div>
{room.status === 'available' && ( {room.status === 'available' && (
<div className="flex items-start gap-2 p-2 bg-[#d4af37]/5 <div className="flex items-start gap-2 p-2 bg-[var(--luxury-gold)]/5
rounded-lg border border-[#d4af37]/20 mb-3" rounded-lg border border-[var(--luxury-gold)]/20 mb-3"
> >
<Shield className="w-3.5 h-3.5 text-[#d4af37] mt-0.5 flex-shrink-0" /> <Shield className="w-3.5 h-3.5 text-[var(--luxury-gold)] mt-0.5 flex-shrink-0" />
<p className="text-[10px] sm:text-xs text-gray-300 font-light tracking-wide leading-relaxed"> <p className="text-[10px] sm:text-xs text-gray-300 font-light tracking-wide leading-relaxed">
<strong className="text-[#d4af37]">20% deposit required</strong> to secure your booking. Pay the remaining balance on arrival at the hotel. <strong className="text-[var(--luxury-gold)]">20% deposit required</strong> to secure your booking. Pay the remaining balance on arrival at the hotel.
</p> </p>
</div> </div>
)} )}
@@ -540,27 +540,27 @@ const RoomDetailPage: React.FC = () => {
{} {}
<div className="space-y-2"> <div className="space-y-2">
<div className="flex items-center justify-between <div className="flex items-center justify-between
py-1.5 border-b border-[#d4af37]/10" py-1.5 border-b border-[var(--luxury-gold)]/10"
> >
<span className="text-[10px] sm:text-xs text-gray-400 font-light tracking-wide">Room Type</span> <span className="text-[10px] sm:text-xs text-gray-400 font-light tracking-wide">Room Type</span>
<strong className="text-xs sm:text-sm text-white font-light">{roomType?.name}</strong> <strong className="text-xs sm:text-sm text-white font-light">{roomType?.name}</strong>
</div> </div>
<div className="flex items-center justify-between <div className="flex items-center justify-between
py-1.5 border-b border-[#d4af37]/10" py-1.5 border-b border-[var(--luxury-gold)]/10"
> >
<span className="text-[10px] sm:text-xs text-gray-400 font-light tracking-wide">Max Guests</span> <span className="text-[10px] sm:text-xs text-gray-400 font-light tracking-wide">Max Guests</span>
<span className="text-xs sm:text-sm text-white font-light">{(room?.capacity || roomType?.capacity || 0)} guests</span> <span className="text-xs sm:text-sm text-white font-light">{(room?.capacity || roomType?.capacity || 0)} guests</span>
</div> </div>
{room?.room_size && ( {room?.room_size && (
<div className="flex items-center justify-between <div className="flex items-center justify-between
py-1.5 border-b border-[#d4af37]/10" py-1.5 border-b border-[var(--luxury-gold)]/10"
> >
<span className="text-[10px] sm:text-xs text-gray-400 font-light tracking-wide">Room Size</span> <span className="text-[10px] sm:text-xs text-gray-400 font-light tracking-wide">Room Size</span>
<span className="text-xs sm:text-sm text-white font-light">{room.room_size}</span> <span className="text-xs sm:text-sm text-white font-light">{room.room_size}</span>
</div> </div>
)} )}
{room?.view && ( {room?.view && (
<div className={`flex items-center justify-between ${room?.room_size ? 'py-1.5 border-b border-[#d4af37]/10' : 'py-1.5'}`}> <div className={`flex items-center justify-between ${room?.room_size ? 'py-1.5 border-b border-[var(--luxury-gold)]/10' : 'py-1.5'}`}>
<span className="text-[10px] sm:text-xs text-gray-400 font-light tracking-wide">View</span> <span className="text-[10px] sm:text-xs text-gray-400 font-light tracking-wide">View</span>
<span className="text-xs sm:text-sm text-white font-light">{room.view}</span> <span className="text-xs sm:text-sm text-white font-light">{room.view}</span>
</div> </div>
@@ -572,8 +572,8 @@ const RoomDetailPage: React.FC = () => {
{} {}
<div className="mb-4 p-3 sm:p-4 bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] <div className="mb-4 p-3 sm:p-4 bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a]
rounded-lg border border-[#d4af37]/20 rounded-lg border border-[var(--luxury-gold)]/20
backdrop-blur-xl shadow-lg shadow-[#d4af37]/5" backdrop-blur-xl shadow-lg shadow-[var(--luxury-gold)]/5"
> >
<ReviewSection roomId={room.id} /> <ReviewSection roomId={room.id} />
</div> </div>

View File

@@ -150,17 +150,17 @@ const RoomListPage: React.FC = () => {
{} {}
{/* Promotion Banner */} {/* Promotion Banner */}
{showPromotionBanner && activePromotion && ( {showPromotionBanner && activePromotion && (
<div className="w-full bg-gradient-to-r from-[#d4af37]/20 via-[#f5d76e]/15 to-[#d4af37]/20 border-b border-[#d4af37]/30"> <div className="w-full bg-gradient-to-r from-[var(--luxury-gold)]/20 via-[var(--luxury-gold-light)]/15 to-[var(--luxury-gold)]/20 border-b border-[var(--luxury-gold)]/30">
<div className="w-full max-w-[1920px] mx-auto px-3 sm:px-4 md:px-6 lg:px-8 xl:px-12 2xl:px-16 3xl:px-20 py-4"> <div className="w-full max-w-[1920px] mx-auto px-3 sm:px-4 md:px-6 lg:px-8 xl:px-12 2xl:px-16 3xl:px-20 py-4">
<div className="flex items-center justify-between gap-4 bg-gradient-to-r from-[#1a1a1a] to-[#0f0f0f] border border-[#d4af37]/40 rounded-lg p-4 backdrop-blur-xl shadow-lg"> <div className="flex items-center justify-between gap-4 bg-gradient-to-r from-[#1a1a1a] to-[#0f0f0f] border border-[var(--luxury-gold)]/40 rounded-lg p-4 backdrop-blur-xl shadow-lg">
<div className="flex items-center gap-3 flex-1"> <div className="flex items-center gap-3 flex-1">
<div className="p-2 bg-[#d4af37]/20 rounded-lg border border-[#d4af37]/40"> <div className="p-2 bg-[var(--luxury-gold)]/20 rounded-lg border border-[var(--luxury-gold)]/40">
<Tag className="w-5 h-5 text-[#d4af37]" /> <Tag className="w-5 h-5 text-[var(--luxury-gold)]" />
</div> </div>
<div className="flex-1"> <div className="flex-1">
<div className="flex items-center gap-2 mb-1"> <div className="flex items-center gap-2 mb-1">
<CheckCircle className="w-4 h-4 text-green-400" /> <CheckCircle className="w-4 h-4 text-green-400" />
<span className="text-sm font-semibold text-[#d4af37]"> <span className="text-sm font-semibold text-[var(--luxury-gold)]">
Active Promotion: {activePromotion.code || activePromotion.title} Active Promotion: {activePromotion.code || activePromotion.title}
</span> </span>
</div> </div>
@@ -176,7 +176,7 @@ const RoomListPage: React.FC = () => {
</div> </div>
<button <button
onClick={handleDismissPromotion} onClick={handleDismissPromotion}
className="p-2 hover:bg-[#d4af37]/10 rounded-lg transition-colors" className="p-2 hover:bg-[var(--luxury-gold)]/10 rounded-lg transition-colors"
aria-label="Dismiss promotion" aria-label="Dismiss promotion"
> >
<X className="w-5 h-5 text-gray-400 hover:text-white" /> <X className="w-5 h-5 text-gray-400 hover:text-white" />
@@ -186,19 +186,19 @@ const RoomListPage: React.FC = () => {
</div> </div>
)} )}
<div className="w-full bg-gradient-to-br from-[#1a1a1a] via-[#0f0f0f] to-[#1a1a1a] border-b border-[#d4af37]/10 pt-6 sm:pt-7 md:pt-8"> <div className="w-full bg-gradient-to-br from-[#1a1a1a] via-[#0f0f0f] to-[#1a1a1a] border-b border-[var(--luxury-gold)]/10 pt-6 sm:pt-7 md:pt-8">
<div className="w-full max-w-[1920px] mx-auto px-3 sm:px-4 md:px-6 lg:px-8 xl:px-12 2xl:px-16 3xl:px-20 py-6 sm:py-7 md:py-8 lg:py-10"> <div className="w-full max-w-[1920px] mx-auto px-3 sm:px-4 md:px-6 lg:px-8 xl:px-12 2xl:px-16 3xl:px-20 py-6 sm:py-7 md:py-8 lg:py-10">
{} {}
<Link <Link
to="/" to="/"
className="inline-flex items-center gap-2 className="inline-flex items-center gap-2
bg-gradient-to-r from-[#d4af37] to-[#c9a227] bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]
text-[#0f0f0f] hover:from-[#f5d76e] hover:to-[#d4af37] text-[#0f0f0f] hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)]
active:scale-95 active:scale-95
mb-4 sm:mb-5 md:mb-6 transition-all duration-300 mb-4 sm:mb-5 md:mb-6 transition-all duration-300
group font-medium tracking-wide text-sm group font-medium tracking-wide text-sm
px-4 py-2 rounded-sm px-4 py-2 rounded-sm
shadow-lg shadow-[#d4af37]/30 hover:shadow-xl hover:shadow-[#d4af37]/40 shadow-lg shadow-[var(--luxury-gold)]/30 hover:shadow-xl hover:shadow-[var(--luxury-gold)]/40
touch-manipulation" touch-manipulation"
> >
<ArrowLeft className="w-4 h-4 sm:w-4 sm:h-4 group-hover:-translate-x-1 transition-transform" /> <ArrowLeft className="w-4 h-4 sm:w-4 sm:h-4 group-hover:-translate-x-1 transition-transform" />
@@ -208,13 +208,13 @@ const RoomListPage: React.FC = () => {
{} {}
<div className="text-center max-w-3xl mx-auto px-2"> <div className="text-center max-w-3xl mx-auto px-2">
<div className="inline-flex items-center justify-center gap-2 mb-3 sm:mb-4"> <div className="inline-flex items-center justify-center gap-2 mb-3 sm:mb-4">
<div className="p-2 sm:p-2.5 bg-[#d4af37]/10 rounded-lg border border-[#d4af37]/30 backdrop-blur-sm"> <div className="p-2 sm:p-2.5 bg-[var(--luxury-gold)]/10 rounded-lg border border-[var(--luxury-gold)]/30 backdrop-blur-sm">
<Hotel className="w-5 h-5 sm:w-5 sm:h-5 text-[#d4af37]" /> <Hotel className="w-5 h-5 sm:w-5 sm:h-5 text-[var(--luxury-gold)]" />
</div> </div>
</div> </div>
<h1 className="text-2xl xs:text-3xl sm:text-4xl md:text-5xl font-serif font-semibold <h1 className="text-2xl xs:text-3xl sm:text-4xl md:text-5xl font-serif font-semibold
text-white mb-2 sm:mb-3 tracking-tight leading-tight px-2 text-white mb-2 sm:mb-3 tracking-tight leading-tight px-2
bg-gradient-to-r from-white via-[#d4af37] to-white bg-gradient-to-r from-white via-[var(--luxury-gold)] to-white
bg-clip-text text-transparent" bg-clip-text text-transparent"
> >
Our Rooms & Suites Our Rooms & Suites
@@ -236,24 +236,24 @@ const RoomListPage: React.FC = () => {
<button <button
onClick={() => setIsFilterOpen(!isFilterOpen)} onClick={() => setIsFilterOpen(!isFilterOpen)}
className="w-full bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] className="w-full bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a]
border border-[#d4af37]/30 rounded-xl p-4 border border-[var(--luxury-gold)]/30 rounded-xl p-4
backdrop-blur-xl shadow-lg shadow-[#d4af37]/10 backdrop-blur-xl shadow-lg shadow-[var(--luxury-gold)]/10
flex items-center justify-between gap-3 flex items-center justify-between gap-3
hover:border-[#d4af37]/50 hover:shadow-xl hover:shadow-[#d4af37]/20 hover:border-[var(--luxury-gold)]/50 hover:shadow-xl hover:shadow-[var(--luxury-gold)]/20
transition-all duration-300 touch-manipulation" transition-all duration-300 touch-manipulation"
> >
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<div className="p-2 bg-[#d4af37]/10 rounded-lg border border-[#d4af37]/30"> <div className="p-2 bg-[var(--luxury-gold)]/10 rounded-lg border border-[var(--luxury-gold)]/30">
<Filter className="w-5 h-5 text-[#d4af37]" /> <Filter className="w-5 h-5 text-[var(--luxury-gold)]" />
</div> </div>
<span className="text-white font-medium tracking-wide text-base"> <span className="text-white font-medium tracking-wide text-base">
Filters Filters
</span> </span>
</div> </div>
{isFilterOpen ? ( {isFilterOpen ? (
<ChevronUp className="w-5 h-5 text-[#d4af37]" /> <ChevronUp className="w-5 h-5 text-[var(--luxury-gold)]" />
) : ( ) : (
<ChevronDown className="w-5 h-5 text-[#d4af37]" /> <ChevronDown className="w-5 h-5 text-[var(--luxury-gold)]" />
)} )}
</button> </button>
</div> </div>
@@ -308,10 +308,10 @@ const RoomListPage: React.FC = () => {
<p className="text-red-300 font-light text-sm sm:text-base md:text-lg mb-4 sm:mb-5 md:mb-6 tracking-wide px-2">{error}</p> <p className="text-red-300 font-light text-sm sm:text-base md:text-lg mb-4 sm:mb-5 md:mb-6 tracking-wide px-2">{error}</p>
<button <button
onClick={() => window.location.reload()} onClick={() => window.location.reload()}
className="px-5 sm:px-6 md:px-8 py-2.5 sm:py-3 bg-gradient-to-r from-[#d4af37] to-[#c9a227] className="px-5 sm:px-6 md:px-8 py-2.5 sm:py-3 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]
text-[#0f0f0f] rounded-sm font-medium tracking-wide text-sm sm:text-base text-[#0f0f0f] rounded-sm font-medium tracking-wide text-sm sm:text-base
hover:from-[#f5d76e] hover:to-[#d4af37] active:scale-95 hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] active:scale-95
transition-all duration-300 shadow-lg shadow-[#d4af37]/30 transition-all duration-300 shadow-lg shadow-[var(--luxury-gold)]/30
touch-manipulation min-h-[44px]" touch-manipulation min-h-[44px]"
> >
Try Again Try Again
@@ -321,13 +321,13 @@ const RoomListPage: React.FC = () => {
{!loading && !error && rooms.length === 0 && ( {!loading && !error && rooms.length === 0 && (
<div className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a] <div className="bg-gradient-to-br from-[#1a1a1a] to-[#0a0a0a]
border border-[#d4af37]/20 rounded-xl p-8 sm:p-10 md:p-12 lg:p-16 text-center border border-[var(--luxury-gold)]/20 rounded-xl p-8 sm:p-10 md:p-12 lg:p-16 text-center
backdrop-blur-xl shadow-2xl shadow-[#d4af37]/5" backdrop-blur-xl shadow-2xl shadow-[var(--luxury-gold)]/5"
> >
<div className="inline-flex items-center justify-center w-16 h-16 sm:w-20 sm:h-20 md:w-24 md:h-24 <div className="inline-flex items-center justify-center w-16 h-16 sm:w-20 sm:h-20 md:w-24 md:h-24
bg-[#d4af37]/10 rounded-2xl mb-4 sm:mb-5 md:mb-6 lg:mb-8 border border-[#d4af37]/30" bg-[var(--luxury-gold)]/10 rounded-2xl mb-4 sm:mb-5 md:mb-6 lg:mb-8 border border-[var(--luxury-gold)]/30"
> >
<Hotel className="w-8 h-8 sm:w-10 sm:h-10 md:w-12 md:h-12 text-[#d4af37]" /> <Hotel className="w-8 h-8 sm:w-10 sm:h-10 md:w-12 md:h-12 text-[var(--luxury-gold)]" />
</div> </div>
<h3 className="text-lg sm:text-xl md:text-2xl font-serif font-semibold <h3 className="text-lg sm:text-xl md:text-2xl font-serif font-semibold
text-white mb-3 sm:mb-4 tracking-wide px-2" text-white mb-3 sm:mb-4 tracking-wide px-2"
@@ -339,10 +339,10 @@ const RoomListPage: React.FC = () => {
</p> </p>
<button <button
onClick={() => window.location.href = '/rooms'} onClick={() => window.location.href = '/rooms'}
className="px-5 sm:px-6 md:px-8 py-2.5 sm:py-3 bg-gradient-to-r from-[#d4af37] to-[#c9a227] className="px-5 sm:px-6 md:px-8 py-2.5 sm:py-3 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]
text-[#0f0f0f] rounded-sm font-medium tracking-wide text-sm sm:text-base text-[#0f0f0f] rounded-sm font-medium tracking-wide text-sm sm:text-base
hover:from-[#f5d76e] hover:to-[#d4af37] active:scale-95 hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] active:scale-95
transition-all duration-300 shadow-lg shadow-[#d4af37]/30 transition-all duration-300 shadow-lg shadow-[var(--luxury-gold)]/30
touch-manipulation min-h-[44px]" touch-manipulation min-h-[44px]"
> >
Clear Filters Clear Filters
@@ -355,8 +355,8 @@ const RoomListPage: React.FC = () => {
{} {}
<div className="mb-3 sm:mb-4 md:mb-5 flex flex-col sm:flex-row items-start sm:items-center justify-between gap-2 sm:gap-3"> <div className="mb-3 sm:mb-4 md:mb-5 flex flex-col sm:flex-row items-start sm:items-center justify-between gap-2 sm:gap-3">
<p className="text-gray-400 font-light tracking-wide text-xs sm:text-sm md:text-base"> <p className="text-gray-400 font-light tracking-wide text-xs sm:text-sm md:text-base">
Showing <span className="text-[#d4af37] font-medium">{rooms.length}</span> of{' '} Showing <span className="text-[var(--luxury-gold)] font-medium">{rooms.length}</span> of{' '}
<span className="text-[#d4af37] font-medium">{pagination.total}</span> rooms <span className="text-[var(--luxury-gold)] font-medium">{pagination.total}</span> rooms
</p> </p>
</div> </div>
@@ -370,7 +370,7 @@ const RoomListPage: React.FC = () => {
</div> </div>
{pagination.totalPages > 1 && ( {pagination.totalPages > 1 && (
<div className="mt-4 sm:mt-5 md:mt-6 pt-3 sm:pt-4 border-t border-[#d4af37]/20"> <div className="mt-4 sm:mt-5 md:mt-6 pt-3 sm:pt-4 border-t border-[var(--luxury-gold)]/20">
<Pagination <Pagination
currentPage={pagination.page} currentPage={pagination.page}
totalPages={pagination.totalPages} totalPages={pagination.totalPages}

View File

@@ -94,9 +94,9 @@ const TaskDetailModal: React.FC<TaskModalProps> = ({
/> />
{/* Luxury Modal with enhanced styling - Compact */} {/* Luxury Modal with enhanced styling - Compact */}
<div className="relative w-full max-w-3xl mx-auto my-2 sm:my-3 md:my-4 bg-white rounded-xl sm:rounded-2xl shadow-2xl overflow-hidden animate-scale-in border border-[#d4af37]/20 flex flex-col" style={{ maxHeight: 'calc(100vh - 1rem)' }}> <div className="relative w-full max-w-3xl mx-auto my-2 sm:my-3 md:my-4 bg-white rounded-xl sm:rounded-2xl shadow-2xl overflow-hidden animate-scale-in border border-[var(--luxury-gold)]/20 flex flex-col" style={{ maxHeight: 'calc(100vh - 1rem)' }}>
{/* Luxury Header with enhanced gradient and effects - Compact */} {/* Luxury Header with enhanced gradient and effects - Compact */}
<div className="relative bg-gradient-to-r from-[#d4af37] via-[#c9a227] via-[#d4af37] to-[#c9a227] p-3 sm:p-4 md:p-5 overflow-hidden flex-shrink-0"> <div className="relative bg-gradient-to-r from-[var(--luxury-gold)] via-[var(--luxury-gold-dark)] via-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] p-3 sm:p-4 md:p-5 overflow-hidden flex-shrink-0">
{/* Animated background pattern */} {/* Animated background pattern */}
<div className="absolute inset-0 opacity-10"> <div className="absolute inset-0 opacity-10">
<div className="absolute inset-0" style={{ <div className="absolute inset-0" style={{
@@ -147,9 +147,9 @@ const TaskDetailModal: React.FC<TaskModalProps> = ({
> >
{/* Task Info with luxury cards - Compact */} {/* Task Info with luxury cards - Compact */}
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3"> <div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
<div className="group relative flex items-center space-x-2.5 sm:space-x-3 p-3 sm:p-3.5 bg-gradient-to-br from-gray-50 via-white to-gray-50 rounded-lg sm:rounded-xl border border-gray-200/50 hover:border-[#d4af37]/30 transition-all duration-300 hover:shadow-md overflow-hidden"> <div className="group relative flex items-center space-x-2.5 sm:space-x-3 p-3 sm:p-3.5 bg-gradient-to-br from-gray-50 via-white to-gray-50 rounded-lg sm:rounded-xl border border-gray-200/50 hover:border-[var(--luxury-gold)]/30 transition-all duration-300 hover:shadow-md overflow-hidden">
<div className="absolute inset-0 bg-gradient-to-br from-[#d4af37]/5 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div> <div className="absolute inset-0 bg-gradient-to-br from-[var(--luxury-gold)]/5 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
<div className="relative w-9 h-9 sm:w-10 sm:h-10 rounded-lg bg-gradient-to-br from-[#d4af37] to-[#c9a227] flex items-center justify-center flex-shrink-0 shadow-md group-hover:scale-105 transition-transform duration-300"> <div className="relative w-9 h-9 sm:w-10 sm:h-10 rounded-lg bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] flex items-center justify-center flex-shrink-0 shadow-md group-hover:scale-105 transition-transform duration-300">
<Calendar className="w-4 h-4 sm:w-5 sm:h-5 text-white drop-shadow-md" /> <Calendar className="w-4 h-4 sm:w-5 sm:h-5 text-white drop-shadow-md" />
</div> </div>
<div className="relative min-w-0 flex-1"> <div className="relative min-w-0 flex-1">
@@ -192,16 +192,16 @@ const TaskDetailModal: React.FC<TaskModalProps> = ({
<div className="space-y-2"> <div className="space-y-2">
<div className="flex items-center justify-between gap-3"> <div className="flex items-center justify-between gap-3">
<h3 className="text-sm sm:text-base font-bold text-gray-900 flex items-center space-x-2 min-w-0"> <h3 className="text-sm sm:text-base font-bold text-gray-900 flex items-center space-x-2 min-w-0">
<div className="w-8 h-8 rounded-lg bg-gradient-to-br from-[#d4af37] to-[#c9a227] flex items-center justify-center shadow-md"> <div className="w-8 h-8 rounded-lg bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] flex items-center justify-center shadow-md">
<TrendingUp className="w-4 h-4 sm:w-5 sm:h-5 text-white" /> <TrendingUp className="w-4 h-4 sm:w-5 sm:h-5 text-white" />
</div> </div>
<span className="truncate">Task Progress</span> <span className="truncate">Task Progress</span>
</h3> </h3>
<span className="text-xl sm:text-2xl font-bold bg-gradient-to-r from-[#d4af37] to-[#c9a227] bg-clip-text text-transparent flex-shrink-0">{progress}%</span> <span className="text-xl sm:text-2xl font-bold bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] bg-clip-text text-transparent flex-shrink-0">{progress}%</span>
</div> </div>
<div className="relative w-full h-3 sm:h-3.5 bg-gray-200/50 rounded-full overflow-hidden shadow-inner border border-gray-300/30"> <div className="relative w-full h-3 sm:h-3.5 bg-gray-200/50 rounded-full overflow-hidden shadow-inner border border-gray-300/30">
<div <div
className="absolute inset-y-0 left-0 bg-gradient-to-r from-[#d4af37] via-[#c9a227] to-[#d4af37] rounded-full transition-all duration-700 ease-out shadow-md" className="absolute inset-y-0 left-0 bg-gradient-to-r from-[var(--luxury-gold)] via-[var(--luxury-gold-dark)] to-[var(--luxury-gold)] rounded-full transition-all duration-700 ease-out shadow-md"
style={{ width: `${progress}%` }} style={{ width: `${progress}%` }}
> >
<div className="absolute inset-0 bg-gradient-to-r from-transparent via-white/30 to-transparent animate-shimmer"></div> <div className="absolute inset-0 bg-gradient-to-r from-transparent via-white/30 to-transparent animate-shimmer"></div>
@@ -217,7 +217,7 @@ const TaskDetailModal: React.FC<TaskModalProps> = ({
{task.checklist_items && task.checklist_items.length > 0 && ( {task.checklist_items && task.checklist_items.length > 0 && (
<div className="space-y-2.5"> <div className="space-y-2.5">
<h3 className="text-sm sm:text-base font-bold text-gray-900 flex items-center space-x-2"> <h3 className="text-sm sm:text-base font-bold text-gray-900 flex items-center space-x-2">
<div className="w-8 h-8 rounded-lg bg-gradient-to-br from-[#d4af37] to-[#c9a227] flex items-center justify-center shadow-md"> <div className="w-8 h-8 rounded-lg bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] flex items-center justify-center shadow-md">
<Award className="w-4 h-4 sm:w-5 sm:h-5 text-white" /> <Award className="w-4 h-4 sm:w-5 sm:h-5 text-white" />
</div> </div>
<span>Checklist Items</span> <span>Checklist Items</span>
@@ -229,11 +229,11 @@ const TaskDetailModal: React.FC<TaskModalProps> = ({
className={`group relative flex items-start space-x-2.5 sm:space-x-3 p-2.5 sm:p-3 rounded-lg sm:rounded-xl border transition-all duration-300 cursor-pointer overflow-hidden ${ className={`group relative flex items-start space-x-2.5 sm:space-x-3 p-2.5 sm:p-3 rounded-lg sm:rounded-xl border transition-all duration-300 cursor-pointer overflow-hidden ${
item.completed item.completed
? 'bg-gradient-to-br from-green-50 via-emerald-50/50 to-green-50 border-green-300/50 hover:border-green-400/70' ? 'bg-gradient-to-br from-green-50 via-emerald-50/50 to-green-50 border-green-300/50 hover:border-green-400/70'
: 'bg-white border-gray-200/50 hover:border-[#d4af37]/50 hover:shadow-md hover:bg-gradient-to-br hover:from-[#d4af37]/5 hover:to-transparent' : 'bg-white border-gray-200/50 hover:border-[var(--luxury-gold)]/50 hover:shadow-md hover:bg-gradient-to-br hover:from-[var(--luxury-gold)]/5 hover:to-transparent'
}`} }`}
> >
{!item.completed && ( {!item.completed && (
<div className="absolute inset-0 bg-gradient-to-r from-[#d4af37]/0 via-[#d4af37]/5 to-[#d4af37]/0 opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div> <div className="absolute inset-0 bg-gradient-to-r from-[var(--luxury-gold)]/0 via-[var(--luxury-gold)]/5 to-[var(--luxury-gold)]/0 opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
)} )}
<input <input
type="checkbox" type="checkbox"
@@ -243,7 +243,7 @@ const TaskDetailModal: React.FC<TaskModalProps> = ({
onUpdateChecklist(task, index, e.target.checked); onUpdateChecklist(task, index, e.target.checked);
}} }}
disabled={isUpdating || task.status === 'completed'} disabled={isUpdating || task.status === 'completed'}
className="relative mt-0.5 h-4 w-4 sm:h-5 sm:w-5 text-[#d4af37] focus:ring-2 focus:ring-[#d4af37] focus:ring-offset-1 border-2 border-gray-300 rounded-md disabled:opacity-50 disabled:cursor-not-allowed flex-shrink-0 transition-all duration-200 checked:bg-[#d4af37] checked:border-[#d4af37]" className="relative mt-0.5 h-4 w-4 sm:h-5 sm:w-5 text-[var(--luxury-gold)] focus:ring-2 focus:ring-[var(--luxury-gold)] focus:ring-offset-1 border-2 border-gray-300 rounded-md disabled:opacity-50 disabled:cursor-not-allowed flex-shrink-0 transition-all duration-200 checked:bg-[var(--luxury-gold)] checked:border-[var(--luxury-gold)]"
/> />
<div className="relative flex-1 min-w-0"> <div className="relative flex-1 min-w-0">
<span <span
@@ -284,7 +284,7 @@ const TaskDetailModal: React.FC<TaskModalProps> = ({
<div className="space-y-2.5"> <div className="space-y-2.5">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<h3 className="text-sm sm:text-base font-bold text-gray-900 flex items-center space-x-2"> <h3 className="text-sm sm:text-base font-bold text-gray-900 flex items-center space-x-2">
<div className="w-8 h-8 rounded-lg bg-gradient-to-br from-[#d4af37] to-[#c9a227] flex items-center justify-center shadow-md"> <div className="w-8 h-8 rounded-lg bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] flex items-center justify-center shadow-md">
<Camera className="w-4 h-4 sm:w-5 sm:h-5 text-white" /> <Camera className="w-4 h-4 sm:w-5 sm:h-5 text-white" />
</div> </div>
<span>Photos</span> <span>Photos</span>
@@ -329,7 +329,7 @@ const TaskDetailModal: React.FC<TaskModalProps> = ({
<img <img
src={fullUrl} src={fullUrl}
alt={`Task photo ${index + 1}`} alt={`Task photo ${index + 1}`}
className="w-full h-24 sm:h-32 object-cover rounded-lg border border-gray-200 hover:border-[#d4af37] transition-all duration-200 cursor-pointer" className="w-full h-24 sm:h-32 object-cover rounded-lg border border-gray-200 hover:border-[var(--luxury-gold)] transition-all duration-200 cursor-pointer"
onClick={() => window.open(fullUrl, '_blank')} onClick={() => window.open(fullUrl, '_blank')}
/> />
{task.id && task.status !== 'completed' && ( {task.id && task.status !== 'completed' && (
@@ -358,7 +358,7 @@ const TaskDetailModal: React.FC<TaskModalProps> = ({
)} )}
{uploadingPhoto && ( {uploadingPhoto && (
<div className="text-center py-2"> <div className="text-center py-2">
<RefreshCw className="w-4 h-4 animate-spin text-[#d4af37] mx-auto" /> <RefreshCw className="w-4 h-4 animate-spin text-[var(--luxury-gold)] mx-auto" />
<p className="text-xs text-gray-500 mt-1">Uploading photo...</p> <p className="text-xs text-gray-500 mt-1">Uploading photo...</p>
</div> </div>
)} )}
@@ -367,7 +367,7 @@ const TaskDetailModal: React.FC<TaskModalProps> = ({
{/* Luxury Footer Actions - Sticky and Compact */} {/* Luxury Footer Actions - Sticky and Compact */}
<div className="relative p-3 sm:p-4 bg-gradient-to-br from-gray-50 via-white to-gray-50 border-t border-gray-200/50 flex flex-col sm:flex-row items-stretch sm:items-center justify-between gap-2 sm:gap-3 flex-shrink-0 shadow-lg"> <div className="relative p-3 sm:p-4 bg-gradient-to-br from-gray-50 via-white to-gray-50 border-t border-gray-200/50 flex flex-col sm:flex-row items-stretch sm:items-center justify-between gap-2 sm:gap-3 flex-shrink-0 shadow-lg">
<div className="absolute inset-0 bg-gradient-to-r from-[#d4af37]/5 via-transparent to-[#d4af37]/5 opacity-50"></div> <div className="absolute inset-0 bg-gradient-to-r from-[var(--luxury-gold)]/5 via-transparent to-[var(--luxury-gold)]/5 opacity-50"></div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
{task.id && task.status !== 'completed' && ( {task.id && task.status !== 'completed' && (
<button <button
@@ -1344,12 +1344,12 @@ const HousekeepingDashboardPage: React.FC = () => {
Enterprise Dashboard Enterprise Dashboard
</h1> </h1>
<p className="text-xs sm:text-sm md:text-base text-gray-600 font-light truncate"> <p className="text-xs sm:text-sm md:text-base text-gray-600 font-light truncate">
Welcome back, <span className="font-semibold text-[#d4af37]">{userInfo?.name || userInfo?.email || 'Housekeeping Staff'}</span> Welcome back, <span className="font-semibold text-[var(--luxury-gold)]">{userInfo?.name || userInfo?.email || 'Housekeeping Staff'}</span>
</p> </p>
</div> </div>
<button <button
onClick={() => activeTab === 'tasks' ? fetchTasks() : fetchInspections()} onClick={() => activeTab === 'tasks' ? fetchTasks() : fetchInspections()}
className="w-full sm:w-auto flex items-center justify-center space-x-2 px-4 sm:px-6 py-2 sm:py-3 bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-white rounded-lg hover:from-[#f5d76e] hover:to-[#d4af37] transition-all duration-300 shadow-lg hover:shadow-xl hover:-translate-y-0.5 text-sm sm:text-base font-medium flex-shrink-0" className="w-full sm:w-auto flex items-center justify-center space-x-2 px-4 sm:px-6 py-2 sm:py-3 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-white rounded-lg hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] transition-all duration-300 shadow-lg hover:shadow-xl hover:-translate-y-0.5 text-sm sm:text-base font-medium flex-shrink-0"
> >
<RefreshCw className="w-4 h-4 sm:w-5 sm:h-5" /> <RefreshCw className="w-4 h-4 sm:w-5 sm:h-5" />
<span>Refresh</span> <span>Refresh</span>
@@ -1365,7 +1365,7 @@ const HousekeepingDashboardPage: React.FC = () => {
onClick={() => setActiveTab('tasks')} onClick={() => setActiveTab('tasks')}
className={`flex-1 px-4 sm:px-6 py-2.5 sm:py-3 rounded-lg sm:rounded-xl font-semibold text-sm sm:text-base transition-all duration-300 ${ className={`flex-1 px-4 sm:px-6 py-2.5 sm:py-3 rounded-lg sm:rounded-xl font-semibold text-sm sm:text-base transition-all duration-300 ${
activeTab === 'tasks' activeTab === 'tasks'
? 'bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-white shadow-lg' ? 'bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-white shadow-lg'
: 'bg-white text-gray-700 hover:bg-gray-100' : 'bg-white text-gray-700 hover:bg-gray-100'
}`} }`}
> >
@@ -1378,7 +1378,7 @@ const HousekeepingDashboardPage: React.FC = () => {
onClick={() => setActiveTab('inspections')} onClick={() => setActiveTab('inspections')}
className={`flex-1 px-4 sm:px-6 py-2.5 sm:py-3 rounded-lg sm:rounded-xl font-semibold text-sm sm:text-base transition-all duration-300 ${ className={`flex-1 px-4 sm:px-6 py-2.5 sm:py-3 rounded-lg sm:rounded-xl font-semibold text-sm sm:text-base transition-all duration-300 ${
activeTab === 'inspections' activeTab === 'inspections'
? 'bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-white shadow-lg' ? 'bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-white shadow-lg'
: 'bg-white text-gray-700 hover:bg-gray-100' : 'bg-white text-gray-700 hover:bg-gray-100'
}`} }`}
> >
@@ -1422,7 +1422,7 @@ const HousekeepingDashboardPage: React.FC = () => {
type="date" type="date"
value={filters.date} value={filters.date}
onChange={(e) => setFilters({ ...filters, date: e.target.value })} onChange={(e) => setFilters({ ...filters, date: e.target.value })}
className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[#d4af37]" className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)]"
/> />
</div> </div>
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
@@ -1430,7 +1430,7 @@ const HousekeepingDashboardPage: React.FC = () => {
<select <select
value={filters.status} value={filters.status}
onChange={(e) => setFilters({ ...filters, status: e.target.value })} onChange={(e) => setFilters({ ...filters, status: e.target.value })}
className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[#d4af37]" className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)]"
> >
<option value="">All Statuses</option> <option value="">All Statuses</option>
<option value="pending">Pending</option> <option value="pending">Pending</option>
@@ -1444,7 +1444,7 @@ const HousekeepingDashboardPage: React.FC = () => {
<select <select
value={filters.task_type} value={filters.task_type}
onChange={(e) => setFilters({ ...filters, task_type: e.target.value })} onChange={(e) => setFilters({ ...filters, task_type: e.target.value })}
className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[#d4af37]" className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)]"
> >
<option value="">All Types</option> <option value="">All Types</option>
<option value="checkout">Checkout</option> <option value="checkout">Checkout</option>
@@ -1472,7 +1472,7 @@ const HousekeepingDashboardPage: React.FC = () => {
<div className="enterprise-card p-4 sm:p-5 md:p-6"> <div className="enterprise-card p-4 sm:p-5 md:p-6">
<div className="flex items-center justify-between mb-4 sm:mb-5"> <div className="flex items-center justify-between mb-4 sm:mb-5">
<h2 className="text-lg sm:text-xl md:text-2xl font-serif font-bold text-gray-900 flex items-center gap-2 sm:gap-3"> <h2 className="text-lg sm:text-xl md:text-2xl font-serif font-bold text-gray-900 flex items-center gap-2 sm:gap-3">
<Target className="w-5 h-5 sm:w-6 sm:h-6 text-[#d4af37]" /> <Target className="w-5 h-5 sm:w-6 sm:h-6 text-[var(--luxury-gold)]" />
<span>Your Performance Today</span> <span>Your Performance Today</span>
</h2> </h2>
</div> </div>
@@ -1511,9 +1511,9 @@ const HousekeepingDashboardPage: React.FC = () => {
</p> </p>
<p className="text-[9px] sm:text-xs text-gray-500 mt-1">vs estimated</p> <p className="text-[9px] sm:text-xs text-gray-500 mt-1">vs estimated</p>
</div> </div>
<div className="p-3 sm:p-4 bg-gradient-to-br from-[#d4af37]/10 to-[#c9a227]/10 rounded-lg sm:rounded-xl border border-[#d4af37]/20"> <div className="p-3 sm:p-4 bg-gradient-to-br from-[var(--luxury-gold)]/10 to-[var(--luxury-gold-dark)]/10 rounded-lg sm:rounded-xl border border-[var(--luxury-gold)]/20">
<div className="flex items-center gap-2 mb-2"> <div className="flex items-center gap-2 mb-2">
<Award className="w-4 h-4 sm:w-5 sm:h-5 text-[#d4af37]" /> <Award className="w-4 h-4 sm:w-5 sm:h-5 text-[var(--luxury-gold)]" />
<p className="text-[10px] sm:text-xs text-gray-600 font-medium">Quality</p> <p className="text-[10px] sm:text-xs text-gray-600 font-medium">Quality</p>
</div> </div>
<p className="text-xl sm:text-2xl font-bold text-gray-900"> <p className="text-xl sm:text-2xl font-bold text-gray-900">
@@ -1580,13 +1580,13 @@ const HousekeepingDashboardPage: React.FC = () => {
</div> </div>
<div className="enterprise-card p-4 sm:p-5 md:p-6 relative overflow-hidden group hover:scale-105 transition-transform duration-300"> <div className="enterprise-card p-4 sm:p-5 md:p-6 relative overflow-hidden group hover:scale-105 transition-transform duration-300">
<div className="absolute top-0 right-0 w-24 h-24 sm:w-32 sm:h-32 bg-gradient-to-br from-[#d4af37]/20 to-[#c9a227]/20 rounded-full blur-2xl"></div> <div className="absolute top-0 right-0 w-24 h-24 sm:w-32 sm:h-32 bg-gradient-to-br from-[var(--luxury-gold)]/20 to-[var(--luxury-gold-dark)]/20 rounded-full blur-2xl"></div>
<div className="relative"> <div className="relative">
<div className="flex items-center justify-between mb-3 sm:mb-4"> <div className="flex items-center justify-between mb-3 sm:mb-4">
<div className="w-10 h-10 sm:w-12 sm:h-12 rounded-xl bg-gradient-to-br from-[#d4af37] to-[#c9a227] flex items-center justify-center shadow-lg flex-shrink-0"> <div className="w-10 h-10 sm:w-12 sm:h-12 rounded-xl bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] flex items-center justify-center shadow-lg flex-shrink-0">
<Sparkles className="w-5 h-5 sm:w-6 sm:h-6 text-white" /> <Sparkles className="w-5 h-5 sm:w-6 sm:h-6 text-white" />
</div> </div>
<span className="text-[10px] sm:text-xs font-semibold text-[#c9a227] bg-[#d4af37]/10 px-2 sm:px-3 py-0.5 sm:py-1 rounded-full whitespace-nowrap">TOTAL</span> <span className="text-[10px] sm:text-xs font-semibold text-[var(--luxury-gold-dark)] bg-[var(--luxury-gold)]/10 px-2 sm:px-3 py-0.5 sm:py-1 rounded-full whitespace-nowrap">TOTAL</span>
</div> </div>
<p className="text-xs sm:text-sm font-medium text-gray-600 mb-1">Total Today</p> <p className="text-xs sm:text-sm font-medium text-gray-600 mb-1">Total Today</p>
<p className="text-2xl sm:text-3xl font-bold text-gray-900">{stats.total}</p> <p className="text-2xl sm:text-3xl font-bold text-gray-900">{stats.total}</p>
@@ -1600,7 +1600,7 @@ const HousekeepingDashboardPage: React.FC = () => {
<div className="space-y-4 sm:space-y-5"> <div className="space-y-4 sm:space-y-5">
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3 sm:gap-4"> <div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3 sm:gap-4">
<h2 className="text-xl sm:text-2xl font-serif font-bold text-gray-900 flex items-center gap-2"> <h2 className="text-xl sm:text-2xl font-serif font-bold text-gray-900 flex items-center gap-2">
<Eye className="w-5 h-5 sm:w-6 sm:h-6 text-[#d4af37]" /> <Eye className="w-5 h-5 sm:w-6 sm:h-6 text-[var(--luxury-gold)]" />
<span>Room Inspections</span> <span>Room Inspections</span>
</h2> </h2>
<button <button
@@ -1609,7 +1609,7 @@ const HousekeepingDashboardPage: React.FC = () => {
await fetchRoomsForInspection(); await fetchRoomsForInspection();
setShowCreateInspectionModal(true); setShowCreateInspectionModal(true);
}} }}
className="w-full sm:w-auto flex items-center justify-center space-x-2 px-4 sm:px-6 py-2 sm:py-3 bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-white rounded-lg hover:from-[#f5d76e] hover:to-[#d4af37] transition-all duration-300 shadow-lg hover:shadow-xl text-sm sm:text-base font-medium" className="w-full sm:w-auto flex items-center justify-center space-x-2 px-4 sm:px-6 py-2 sm:py-3 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-white rounded-lg hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] transition-all duration-300 shadow-lg hover:shadow-xl text-sm sm:text-base font-medium"
> >
<Plus className="w-4 h-4 sm:w-5 sm:h-5" /> <Plus className="w-4 h-4 sm:w-5 sm:h-5" />
<span>New Inspection</span> <span>New Inspection</span>
@@ -1620,8 +1620,8 @@ const HousekeepingDashboardPage: React.FC = () => {
<Loading /> <Loading />
) : inspections.length === 0 ? ( ) : inspections.length === 0 ? (
<div className="enterprise-card p-8 sm:p-12 text-center"> <div className="enterprise-card p-8 sm:p-12 text-center">
<div className="w-16 h-16 sm:w-20 sm:h-20 rounded-full bg-gradient-to-br from-[#d4af37]/20 to-[#c9a227]/20 flex items-center justify-center mx-auto mb-3 sm:mb-4"> <div className="w-16 h-16 sm:w-20 sm:h-20 rounded-full bg-gradient-to-br from-[var(--luxury-gold)]/20 to-[var(--luxury-gold-dark)]/20 flex items-center justify-center mx-auto mb-3 sm:mb-4">
<Eye className="w-8 h-8 sm:w-10 sm:h-10 text-[#d4af37]" /> <Eye className="w-8 h-8 sm:w-10 sm:h-10 text-[var(--luxury-gold)]" />
</div> </div>
<h3 className="text-lg sm:text-xl font-semibold text-gray-900 mb-2">No inspections found</h3> <h3 className="text-lg sm:text-xl font-semibold text-gray-900 mb-2">No inspections found</h3>
<p className="text-sm sm:text-base text-gray-500">You don't have any inspections assigned yet.</p> <p className="text-sm sm:text-base text-gray-500">You don't have any inspections assigned yet.</p>
@@ -1640,7 +1640,7 @@ const HousekeepingDashboardPage: React.FC = () => {
<div className="flex items-start justify-between mb-3 sm:mb-4 gap-3"> <div className="flex items-start justify-between mb-3 sm:mb-4 gap-3">
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
<div className="flex items-center space-x-2 sm:space-x-3 mb-2"> <div className="flex items-center space-x-2 sm:space-x-3 mb-2">
<div className="w-8 h-8 sm:w-10 sm:h-10 rounded-lg bg-gradient-to-br from-[#d4af37] to-[#c9a227] flex items-center justify-center shadow-lg flex-shrink-0"> <div className="w-8 h-8 sm:w-10 sm:h-10 rounded-lg bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] flex items-center justify-center shadow-lg flex-shrink-0">
<MapPin className="w-4 h-4 sm:w-5 sm:h-5 text-white" /> <MapPin className="w-4 h-4 sm:w-5 sm:h-5 text-white" />
</div> </div>
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
@@ -1664,7 +1664,7 @@ const HousekeepingDashboardPage: React.FC = () => {
<div className="flex items-center space-x-4 text-xs sm:text-sm text-gray-600 mb-3 sm:mb-4"> <div className="flex items-center space-x-4 text-xs sm:text-sm text-gray-600 mb-3 sm:mb-4">
<div className="flex items-center space-x-1.5"> <div className="flex items-center space-x-1.5">
<Calendar className="w-3.5 h-3.5 sm:w-4 sm:h-4 text-[#d4af37] flex-shrink-0" /> <Calendar className="w-3.5 h-3.5 sm:w-4 sm:h-4 text-[var(--luxury-gold)] flex-shrink-0" />
<span className="text-[10px] sm:text-xs truncate">{formatDate(inspection.scheduled_at)}</span> <span className="text-[10px] sm:text-xs truncate">{formatDate(inspection.scheduled_at)}</span>
</div> </div>
</div> </div>
@@ -1673,11 +1673,11 @@ const HousekeepingDashboardPage: React.FC = () => {
<div className="mb-3 sm:mb-4"> <div className="mb-3 sm:mb-4">
<div className="flex items-center justify-between mb-1.5 sm:mb-2"> <div className="flex items-center justify-between mb-1.5 sm:mb-2">
<span className="text-[10px] sm:text-xs font-medium text-gray-600">Quality Score</span> <span className="text-[10px] sm:text-xs font-medium text-gray-600">Quality Score</span>
<span className="text-xs sm:text-sm font-bold text-[#d4af37]">{inspection.overall_score.toFixed(1)}/5.0</span> <span className="text-xs sm:text-sm font-bold text-[var(--luxury-gold)]">{inspection.overall_score.toFixed(1)}/5.0</span>
</div> </div>
<div className="relative w-full h-1.5 sm:h-2 bg-gray-200 rounded-full overflow-hidden"> <div className="relative w-full h-1.5 sm:h-2 bg-gray-200 rounded-full overflow-hidden">
<div <div
className="absolute inset-y-0 left-0 bg-gradient-to-r from-[#d4af37] to-[#c9a227] rounded-full transition-all duration-500" className="absolute inset-y-0 left-0 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] rounded-full transition-all duration-500"
style={{ width: `${(inspection.overall_score / 5) * 100}%` }} style={{ width: `${(inspection.overall_score / 5) * 100}%` }}
/> />
</div> </div>
@@ -1709,7 +1709,7 @@ const HousekeepingDashboardPage: React.FC = () => {
<div className="space-y-4 sm:space-y-5"> <div className="space-y-4 sm:space-y-5">
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-2 sm:gap-4"> <div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-2 sm:gap-4">
<h2 className="text-xl sm:text-2xl font-serif font-bold text-gray-900 flex items-center gap-2"> <h2 className="text-xl sm:text-2xl font-serif font-bold text-gray-900 flex items-center gap-2">
<Building2 className="w-5 h-5 sm:w-6 sm:h-6 text-[#d4af37]" /> <Building2 className="w-5 h-5 sm:w-6 sm:h-6 text-[var(--luxury-gold)]" />
<span>Today's Tasks by Floor</span> <span>Today's Tasks by Floor</span>
</h2> </h2>
<span className="text-xs sm:text-sm text-gray-500">{tasks.length} task{tasks.length !== 1 ? 's' : ''} across {tasksByFloor.length} floor{tasksByFloor.length !== 1 ? 's' : ''}</span> <span className="text-xs sm:text-sm text-gray-500">{tasks.length} task{tasks.length !== 1 ? 's' : ''} across {tasksByFloor.length} floor{tasksByFloor.length !== 1 ? 's' : ''}</span>
@@ -1717,8 +1717,8 @@ const HousekeepingDashboardPage: React.FC = () => {
{tasks.length === 0 ? ( {tasks.length === 0 ? (
<div className="enterprise-card p-8 sm:p-12 text-center"> <div className="enterprise-card p-8 sm:p-12 text-center">
<div className="w-16 h-16 sm:w-20 sm:h-20 rounded-full bg-gradient-to-br from-[#d4af37]/20 to-[#c9a227]/20 flex items-center justify-center mx-auto mb-3 sm:mb-4"> <div className="w-16 h-16 sm:w-20 sm:h-20 rounded-full bg-gradient-to-br from-[var(--luxury-gold)]/20 to-[var(--luxury-gold-dark)]/20 flex items-center justify-center mx-auto mb-3 sm:mb-4">
<Sparkles className="w-8 h-8 sm:w-10 sm:h-10 text-[#d4af37]" /> <Sparkles className="w-8 h-8 sm:w-10 sm:h-10 text-[var(--luxury-gold)]" />
</div> </div>
<h3 className="text-lg sm:text-xl font-semibold text-gray-900 mb-2">No tasks assigned</h3> <h3 className="text-lg sm:text-xl font-semibold text-gray-900 mb-2">No tasks assigned</h3>
<p className="text-sm sm:text-base text-gray-500">You don't have any housekeeping tasks assigned for today.</p> <p className="text-sm sm:text-base text-gray-500">You don't have any housekeeping tasks assigned for today.</p>
@@ -1743,16 +1743,16 @@ const HousekeepingDashboardPage: React.FC = () => {
onClick={() => setSelectedFloor(floor)} onClick={() => setSelectedFloor(floor)}
className={`relative px-4 sm:px-6 py-2.5 sm:py-3 rounded-lg sm:rounded-xl font-semibold text-sm sm:text-base transition-all duration-300 flex items-center gap-2 sm:gap-3 whitespace-nowrap flex-shrink-0 ${ className={`relative px-4 sm:px-6 py-2.5 sm:py-3 rounded-lg sm:rounded-xl font-semibold text-sm sm:text-base transition-all duration-300 flex items-center gap-2 sm:gap-3 whitespace-nowrap flex-shrink-0 ${
isActive isActive
? 'bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-white shadow-lg scale-105' ? 'bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-white shadow-lg scale-105'
: 'bg-white text-gray-700 hover:bg-gray-100 border border-gray-200/50 hover:border-[#d4af37]/30' : 'bg-white text-gray-700 hover:bg-gray-100 border border-gray-200/50 hover:border-[var(--luxury-gold)]/30'
}`} }`}
> >
<Building2 className={`w-4 h-4 sm:w-5 sm:h-5 ${isActive ? 'text-white' : 'text-[#d4af37]'}`} /> <Building2 className={`w-4 h-4 sm:w-5 sm:h-5 ${isActive ? 'text-white' : 'text-[var(--luxury-gold)]'}`} />
<span className="font-bold">{getFloorDisplayName(floor)}</span> <span className="font-bold">{getFloorDisplayName(floor)}</span>
<span className={`px-2 py-0.5 rounded-full text-[10px] sm:text-xs font-bold ${ <span className={`px-2 py-0.5 rounded-full text-[10px] sm:text-xs font-bold ${
isActive isActive
? 'bg-white/20 text-white' ? 'bg-white/20 text-white'
: 'bg-[#d4af37]/10 text-[#c9a227]' : 'bg-[var(--luxury-gold)]/10 text-[var(--luxury-gold-dark)]'
}`}> }`}>
{floorStats.total} {floorStats.total}
</span> </span>
@@ -1779,10 +1779,10 @@ const HousekeepingDashboardPage: React.FC = () => {
{selectedFloor !== null && ( {selectedFloor !== null && (
<div className="space-y-4 sm:space-y-5"> <div className="space-y-4 sm:space-y-5">
{/* Floor Header with Stats */} {/* Floor Header with Stats */}
<div className="enterprise-card p-4 sm:p-5 bg-gradient-to-r from-[#d4af37]/10 via-[#c9a227]/5 to-[#d4af37]/10 border border-[#d4af37]/20 rounded-xl sm:rounded-2xl"> <div className="enterprise-card p-4 sm:p-5 bg-gradient-to-r from-[var(--luxury-gold)]/10 via-[var(--luxury-gold-dark)]/5 to-[var(--luxury-gold)]/10 border border-[var(--luxury-gold)]/20 rounded-xl sm:rounded-2xl">
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3 sm:gap-4"> <div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3 sm:gap-4">
<div className="flex items-center gap-3 sm:gap-4"> <div className="flex items-center gap-3 sm:gap-4">
<div className="w-10 h-10 sm:w-12 sm:h-12 rounded-xl bg-gradient-to-br from-[#d4af37] to-[#c9a227] flex items-center justify-center shadow-lg"> <div className="w-10 h-10 sm:w-12 sm:h-12 rounded-xl bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] flex items-center justify-center shadow-lg">
<Building2 className="w-5 h-5 sm:w-6 sm:h-6 text-white" /> <Building2 className="w-5 h-5 sm:w-6 sm:h-6 text-white" />
</div> </div>
<div> <div>
@@ -1820,8 +1820,8 @@ const HousekeepingDashboardPage: React.FC = () => {
{/* Tasks Grid */} {/* Tasks Grid */}
{currentFloorTasks.length === 0 ? ( {currentFloorTasks.length === 0 ? (
<div className="enterprise-card p-8 sm:p-12 text-center"> <div className="enterprise-card p-8 sm:p-12 text-center">
<div className="w-16 h-16 sm:w-20 sm:h-20 rounded-full bg-gradient-to-br from-[#d4af37]/20 to-[#c9a227]/20 flex items-center justify-center mx-auto mb-3 sm:mb-4"> <div className="w-16 h-16 sm:w-20 sm:h-20 rounded-full bg-gradient-to-br from-[var(--luxury-gold)]/20 to-[var(--luxury-gold-dark)]/20 flex items-center justify-center mx-auto mb-3 sm:mb-4">
<Sparkles className="w-8 h-8 sm:w-10 sm:h-10 text-[#d4af37]" /> <Sparkles className="w-8 h-8 sm:w-10 sm:h-10 text-[var(--luxury-gold)]" />
</div> </div>
<h3 className="text-lg sm:text-xl font-semibold text-gray-900 mb-2">No tasks on this floor</h3> <h3 className="text-lg sm:text-xl font-semibold text-gray-900 mb-2">No tasks on this floor</h3>
<p className="text-sm sm:text-base text-gray-500">No housekeeping tasks assigned for {getFloorDisplayName(selectedFloor).toLowerCase()}.</p> <p className="text-sm sm:text-base text-gray-500">No housekeeping tasks assigned for {getFloorDisplayName(selectedFloor).toLowerCase()}.</p>
@@ -1845,7 +1845,7 @@ const HousekeepingDashboardPage: React.FC = () => {
<div className="flex items-start justify-between mb-3 sm:mb-4 gap-3"> <div className="flex items-start justify-between mb-3 sm:mb-4 gap-3">
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
<div className="flex items-center space-x-2 sm:space-x-3 mb-2"> <div className="flex items-center space-x-2 sm:space-x-3 mb-2">
<div className="w-8 h-8 sm:w-10 sm:h-10 rounded-lg bg-gradient-to-br from-[#d4af37] to-[#c9a227] flex items-center justify-center shadow-lg flex-shrink-0"> <div className="w-8 h-8 sm:w-10 sm:h-10 rounded-lg bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] flex items-center justify-center shadow-lg flex-shrink-0">
<MapPin className="w-4 h-4 sm:w-5 sm:h-5 text-white" /> <MapPin className="w-4 h-4 sm:w-5 sm:h-5 text-white" />
</div> </div>
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
@@ -1863,7 +1863,7 @@ const HousekeepingDashboardPage: React.FC = () => {
<div className="flex items-center space-x-4 text-xs sm:text-sm text-gray-600 mb-3 sm:mb-4"> <div className="flex items-center space-x-4 text-xs sm:text-sm text-gray-600 mb-3 sm:mb-4">
<div className="flex items-center space-x-1.5"> <div className="flex items-center space-x-1.5">
<Calendar className="w-3.5 h-3.5 sm:w-4 sm:h-4 text-[#d4af37] flex-shrink-0" /> <Calendar className="w-3.5 h-3.5 sm:w-4 sm:h-4 text-[var(--luxury-gold)] flex-shrink-0" />
<span className="text-[10px] sm:text-xs truncate">{formatDate(task.scheduled_time)}</span> <span className="text-[10px] sm:text-xs truncate">{formatDate(task.scheduled_time)}</span>
</div> </div>
</div> </div>
@@ -1872,7 +1872,7 @@ const HousekeepingDashboardPage: React.FC = () => {
<div className="mb-3 sm:mb-4"> <div className="mb-3 sm:mb-4">
<div className="flex items-center justify-between mb-1.5 sm:mb-2"> <div className="flex items-center justify-between mb-1.5 sm:mb-2">
<span className="text-[10px] sm:text-xs font-medium text-gray-600">Progress</span> <span className="text-[10px] sm:text-xs font-medium text-gray-600">Progress</span>
<span className="text-xs sm:text-sm font-bold text-[#d4af37]">{progress}%</span> <span className="text-xs sm:text-sm font-bold text-[var(--luxury-gold)]">{progress}%</span>
</div> </div>
<div className="relative w-full h-1.5 sm:h-2 bg-gray-200 rounded-full overflow-hidden"> <div className="relative w-full h-1.5 sm:h-2 bg-gray-200 rounded-full overflow-hidden">
<div <div
@@ -1961,7 +1961,7 @@ const HousekeepingDashboardPage: React.FC = () => {
<div className="p-6 border-b border-gray-200"> <div className="p-6 border-b border-gray-200">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<h2 className="text-xl font-bold text-gray-900 flex items-center gap-2"> <h2 className="text-xl font-bold text-gray-900 flex items-center gap-2">
<FileCheck className="w-5 h-5 text-[#d4af37]" /> <FileCheck className="w-5 h-5 text-[var(--luxury-gold)]" />
Create Room Inspection Create Room Inspection
</h2> </h2>
<button <button
@@ -1983,7 +1983,7 @@ const HousekeepingDashboardPage: React.FC = () => {
<select <select
value={inspectionForm.room_id} value={inspectionForm.room_id}
onChange={(e) => setInspectionForm({ ...inspectionForm, room_id: e.target.value })} onChange={(e) => setInspectionForm({ ...inspectionForm, room_id: e.target.value })}
className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[#d4af37]" className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)]"
required required
> >
<option value="">Select Room</option> <option value="">Select Room</option>
@@ -2007,7 +2007,7 @@ const HousekeepingDashboardPage: React.FC = () => {
checklist_items: defaultInspectionChecklist[type] || [], checklist_items: defaultInspectionChecklist[type] || [],
}); });
}} }}
className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[#d4af37]" className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)]"
> >
<option value="pre_checkin">Pre Check-in</option> <option value="pre_checkin">Pre Check-in</option>
<option value="post_checkout">Post Checkout</option> <option value="post_checkout">Post Checkout</option>
@@ -2025,7 +2025,7 @@ const HousekeepingDashboardPage: React.FC = () => {
</button> </button>
<button <button
onClick={handleCreateInspection} onClick={handleCreateInspection}
className="px-4 py-2 text-sm text-white bg-gradient-to-r from-[#d4af37] to-[#c9a227] rounded-lg hover:from-[#f5d76e] hover:to-[#d4af37] transition-colors font-medium" className="px-4 py-2 text-sm text-white bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] rounded-lg hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] transition-colors font-medium"
> >
Create Inspection Create Inspection
</button> </button>
@@ -2039,7 +2039,7 @@ const HousekeepingDashboardPage: React.FC = () => {
{isInspectionModalOpen && selectedInspection && ( {isInspectionModalOpen && selectedInspection && (
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm"> <div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm">
<div className="bg-white rounded-xl shadow-2xl max-w-3xl w-full max-h-[90vh] overflow-y-auto"> <div className="bg-white rounded-xl shadow-2xl max-w-3xl w-full max-h-[90vh] overflow-y-auto">
<div className="p-6 border-b border-gray-200 bg-gradient-to-r from-[#d4af37] to-[#c9a227]"> <div className="p-6 border-b border-gray-200 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<h2 className="text-xl font-bold text-white flex items-center gap-2"> <h2 className="text-xl font-bold text-white flex items-center gap-2">
<FileCheck className="w-5 h-5" /> <FileCheck className="w-5 h-5" />
@@ -2107,7 +2107,7 @@ const HousekeepingDashboardPage: React.FC = () => {
{selectedInspection.overall_score && ( {selectedInspection.overall_score && (
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-2">Overall Score</label> <label className="block text-sm font-medium text-gray-700 mb-2">Overall Score</label>
<p className="text-2xl font-bold text-[#d4af37]">{selectedInspection.overall_score.toFixed(1)} / 5.0</p> <p className="text-2xl font-bold text-[var(--luxury-gold)]">{selectedInspection.overall_score.toFixed(1)} / 5.0</p>
</div> </div>
)} )}
</div> </div>

View File

@@ -379,7 +379,7 @@ const HousekeepingProfilePage: React.FC = () => {
{/* Header */} {/* Header */}
<div className="mb-6 sm:mb-8 animate-fade-in"> <div className="mb-6 sm:mb-8 animate-fade-in">
<div className="flex items-center gap-2 sm:gap-3 mb-2 sm:mb-3"> <div className="flex items-center gap-2 sm:gap-3 mb-2 sm:mb-3">
<div className="h-1 w-12 sm:w-16 md:w-20 bg-gradient-to-r from-[#d4af37] via-amber-400 to-[#d4af37] rounded-full"></div> <div className="h-1 w-12 sm:w-16 md:w-20 bg-gradient-to-r from-[var(--luxury-gold)] via-amber-400 to-[var(--luxury-gold)] rounded-full"></div>
<h1 className="text-2xl sm:text-3xl lg:text-4xl font-serif font-bold bg-gradient-to-r from-gray-900 via-amber-900/90 to-gray-900 bg-clip-text text-transparent tracking-tight"> <h1 className="text-2xl sm:text-3xl lg:text-4xl font-serif font-bold bg-gradient-to-r from-gray-900 via-amber-900/90 to-gray-900 bg-clip-text text-transparent tracking-tight">
Housekeeping Profile Housekeeping Profile
</h1> </h1>
@@ -390,50 +390,50 @@ const HousekeepingProfilePage: React.FC = () => {
</div> </div>
{/* Tabs */} {/* Tabs */}
<div className="mb-4 sm:mb-6 border-b border-[#d4af37]/20 overflow-x-auto bg-white/50 backdrop-blur-sm rounded-t-lg sm:rounded-t-xl px-4 sm:px-6"> <div className="mb-4 sm:mb-6 border-b border-[var(--luxury-gold)]/20 overflow-x-auto bg-white/50 backdrop-blur-sm rounded-t-lg sm:rounded-t-xl px-4 sm:px-6">
<div className="flex space-x-4 sm:space-x-8 min-w-max"> <div className="flex space-x-4 sm:space-x-8 min-w-max">
<button <button
onClick={() => setActiveTab('profile')} onClick={() => setActiveTab('profile')}
className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${ className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${
activeTab === 'profile' activeTab === 'profile'
? 'border-[#d4af37] text-[#d4af37] shadow-sm' ? 'border-[var(--luxury-gold)] text-[var(--luxury-gold)] shadow-sm'
: 'border-transparent text-gray-500 hover:text-[#d4af37] hover:border-[#d4af37]/30' : 'border-transparent text-gray-500 hover:text-[var(--luxury-gold)] hover:border-[var(--luxury-gold)]/30'
}`} }`}
> >
<User className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'profile' ? 'text-[#d4af37]' : ''}`} /> <User className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'profile' ? 'text-[var(--luxury-gold)]' : ''}`} />
Profile Profile
</button> </button>
<button <button
onClick={() => setActiveTab('password')} onClick={() => setActiveTab('password')}
className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${ className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${
activeTab === 'password' activeTab === 'password'
? 'border-[#d4af37] text-[#d4af37] shadow-sm' ? 'border-[var(--luxury-gold)] text-[var(--luxury-gold)] shadow-sm'
: 'border-transparent text-gray-500 hover:text-[#d4af37] hover:border-[#d4af37]/30' : 'border-transparent text-gray-500 hover:text-[var(--luxury-gold)] hover:border-[var(--luxury-gold)]/30'
}`} }`}
> >
<KeyRound className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'password' ? 'text-[#d4af37]' : ''}`} /> <KeyRound className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'password' ? 'text-[var(--luxury-gold)]' : ''}`} />
Password Password
</button> </button>
<button <button
onClick={() => setActiveTab('mfa')} onClick={() => setActiveTab('mfa')}
className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${ className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${
activeTab === 'mfa' activeTab === 'mfa'
? 'border-[#d4af37] text-[#d4af37] shadow-sm' ? 'border-[var(--luxury-gold)] text-[var(--luxury-gold)] shadow-sm'
: 'border-transparent text-gray-500 hover:text-[#d4af37] hover:border-[#d4af37]/30' : 'border-transparent text-gray-500 hover:text-[var(--luxury-gold)] hover:border-[var(--luxury-gold)]/30'
}`} }`}
> >
<Shield className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'mfa' ? 'text-[#d4af37]' : ''}`} /> <Shield className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'mfa' ? 'text-[var(--luxury-gold)]' : ''}`} />
Two-Factor Auth Two-Factor Auth
</button> </button>
<button <button
onClick={() => setActiveTab('sessions')} onClick={() => setActiveTab('sessions')}
className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${ className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${
activeTab === 'sessions' activeTab === 'sessions'
? 'border-[#d4af37] text-[#d4af37] shadow-sm' ? 'border-[var(--luxury-gold)] text-[var(--luxury-gold)] shadow-sm'
: 'border-transparent text-gray-500 hover:text-[#d4af37] hover:border-[#d4af37]/30' : 'border-transparent text-gray-500 hover:text-[var(--luxury-gold)] hover:border-[var(--luxury-gold)]/30'
}`} }`}
> >
<Monitor className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'sessions' ? 'text-[#d4af37]' : ''}`} /> <Monitor className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'sessions' ? 'text-[var(--luxury-gold)]' : ''}`} />
Sessions Sessions
</button> </button>
</div> </div>
@@ -441,7 +441,7 @@ const HousekeepingProfilePage: React.FC = () => {
{/* Profile Tab */} {/* Profile Tab */}
{activeTab === 'profile' && ( {activeTab === 'profile' && (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl animate-slide-up"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl animate-slide-up">
<form onSubmit={handleSubmitProfile(onSubmitProfile)} className="space-y-5 sm:space-y-6"> <form onSubmit={handleSubmitProfile(onSubmitProfile)} className="space-y-5 sm:space-y-6">
{/* Avatar Section */} {/* Avatar Section */}
<div className="flex flex-col sm:flex-row items-center sm:items-start gap-4 sm:gap-6 pb-5 sm:pb-6 border-b border-gray-200"> <div className="flex flex-col sm:flex-row items-center sm:items-start gap-4 sm:gap-6 pb-5 sm:pb-6 border-b border-gray-200">
@@ -450,17 +450,17 @@ const HousekeepingProfilePage: React.FC = () => {
<img <img
src={avatarPreview || normalizeImageUrl(userInfo?.avatar)} src={avatarPreview || normalizeImageUrl(userInfo?.avatar)}
alt="Profile" alt="Profile"
className="w-20 h-20 sm:w-24 sm:h-24 rounded-full object-cover ring-4 ring-[#d4af37]/20 shadow-lg" className="w-20 h-20 sm:w-24 sm:h-24 rounded-full object-cover ring-4 ring-[var(--luxury-gold)]/20 shadow-lg"
onError={() => setAvatarError(true)} onError={() => setAvatarError(true)}
/> />
) : ( ) : (
<div className="w-20 h-20 sm:w-24 sm:h-24 rounded-full bg-gradient-to-br from-[#d4af37] to-[#c9a227] flex items-center justify-center ring-4 ring-[#d4af37]/20 shadow-lg"> <div className="w-20 h-20 sm:w-24 sm:h-24 rounded-full bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] flex items-center justify-center ring-4 ring-[var(--luxury-gold)]/20 shadow-lg">
<User className="w-10 h-10 sm:w-12 sm:h-12 text-white" /> <User className="w-10 h-10 sm:w-12 sm:h-12 text-white" />
</div> </div>
)} )}
<label <label
htmlFor="avatar-upload" htmlFor="avatar-upload"
className="absolute bottom-0 right-0 p-2 bg-gradient-to-br from-[#d4af37] to-[#c9a227] rounded-full cursor-pointer hover:from-[#f5d76e] hover:to-[#d4af37] transition-all duration-300 shadow-lg" className="absolute bottom-0 right-0 p-2 bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] rounded-full cursor-pointer hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] transition-all duration-300 shadow-lg"
> >
<Camera className="w-3.5 h-3.5 sm:w-4 sm:h-4 text-white" /> <Camera className="w-3.5 h-3.5 sm:w-4 sm:h-4 text-white" />
<input <input
@@ -477,7 +477,7 @@ const HousekeepingProfilePage: React.FC = () => {
{/* Name Field */} {/* Name Field */}
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<User className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <User className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
Full Name <span className="text-red-500">*</span> Full Name <span className="text-red-500">*</span>
</label> </label>
<input <input
@@ -499,7 +499,7 @@ const HousekeepingProfilePage: React.FC = () => {
{/* Email Field */} {/* Email Field */}
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<Mail className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <Mail className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
Email Address <span className="text-red-500">*</span> Email Address <span className="text-red-500">*</span>
</label> </label>
<input <input
@@ -521,7 +521,7 @@ const HousekeepingProfilePage: React.FC = () => {
{/* Phone Field */} {/* Phone Field */}
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<Phone className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <Phone className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
Phone Number <span className="text-red-500">*</span> Phone Number <span className="text-red-500">*</span>
</label> </label>
<input <input
@@ -556,7 +556,7 @@ const HousekeepingProfilePage: React.FC = () => {
{/* Password Tab */} {/* Password Tab */}
{activeTab === 'password' && ( {activeTab === 'password' && (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl animate-slide-up"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl animate-slide-up">
<form onSubmit={handleSubmitPassword(onSubmitPassword)} className="space-y-5 sm:space-y-6"> <form onSubmit={handleSubmitPassword(onSubmitPassword)} className="space-y-5 sm:space-y-6">
{/* Password Requirements */} {/* Password Requirements */}
<div className="bg-gradient-to-r from-blue-50 to-indigo-50 border border-blue-200/60 rounded-sm p-4 sm:p-5"> <div className="bg-gradient-to-r from-blue-50 to-indigo-50 border border-blue-200/60 rounded-sm p-4 sm:p-5">
@@ -579,7 +579,7 @@ const HousekeepingProfilePage: React.FC = () => {
{/* Current Password */} {/* Current Password */}
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
Current Password <span className="text-red-500">*</span> Current Password <span className="text-red-500">*</span>
</label> </label>
<div className="relative"> <div className="relative">
@@ -594,7 +594,7 @@ const HousekeepingProfilePage: React.FC = () => {
<button <button
type="button" type="button"
onClick={() => setShowPassword({ ...showPassword, current: !showPassword.current })} onClick={() => setShowPassword({ ...showPassword, current: !showPassword.current })}
className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[#d4af37] transition-colors" className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[var(--luxury-gold)] transition-colors"
> >
{showPassword.current ? <EyeOff className="w-4 h-4 sm:w-5 sm:h-5" /> : <Eye className="w-4 h-4 sm:w-5 sm:h-5" />} {showPassword.current ? <EyeOff className="w-4 h-4 sm:w-5 sm:h-5" /> : <Eye className="w-4 h-4 sm:w-5 sm:h-5" />}
</button> </button>
@@ -610,7 +610,7 @@ const HousekeepingProfilePage: React.FC = () => {
{/* New Password */} {/* New Password */}
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
New Password <span className="text-red-500">*</span> New Password <span className="text-red-500">*</span>
</label> </label>
<div className="relative"> <div className="relative">
@@ -625,7 +625,7 @@ const HousekeepingProfilePage: React.FC = () => {
<button <button
type="button" type="button"
onClick={() => setShowPassword({ ...showPassword, new: !showPassword.new })} onClick={() => setShowPassword({ ...showPassword, new: !showPassword.new })}
className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[#d4af37] transition-colors" className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[var(--luxury-gold)] transition-colors"
> >
{showPassword.new ? <EyeOff className="w-4 h-4 sm:w-5 sm:h-5" /> : <Eye className="w-4 h-4 sm:w-5 sm:h-5" />} {showPassword.new ? <EyeOff className="w-4 h-4 sm:w-5 sm:h-5" /> : <Eye className="w-4 h-4 sm:w-5 sm:h-5" />}
</button> </button>
@@ -641,7 +641,7 @@ const HousekeepingProfilePage: React.FC = () => {
{/* Confirm Password */} {/* Confirm Password */}
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
Confirm Password <span className="text-red-500">*</span> Confirm Password <span className="text-red-500">*</span>
</label> </label>
<div className="relative"> <div className="relative">
@@ -656,7 +656,7 @@ const HousekeepingProfilePage: React.FC = () => {
<button <button
type="button" type="button"
onClick={() => setShowPassword({ ...showPassword, confirm: !showPassword.confirm })} onClick={() => setShowPassword({ ...showPassword, confirm: !showPassword.confirm })}
className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[#d4af37] transition-colors" className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[var(--luxury-gold)] transition-colors"
> >
{showPassword.confirm ? <EyeOff className="w-4 h-4 sm:w-5 sm:h-5" /> : <Eye className="w-4 h-4 sm:w-5 sm:h-5" />} {showPassword.confirm ? <EyeOff className="w-4 h-4 sm:w-5 sm:h-5" /> : <Eye className="w-4 h-4 sm:w-5 sm:h-5" />}
</button> </button>
@@ -742,10 +742,10 @@ const MFATab: React.FC<MFATabProps> = ({
setLoading, setLoading,
}) => { }) => {
return ( return (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl animate-slide-up space-y-5 sm:space-y-6"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl animate-slide-up space-y-5 sm:space-y-6">
<div> <div>
<h2 className="text-xl sm:text-2xl font-serif font-semibold text-gray-900 mb-2 flex items-center gap-2"> <h2 className="text-xl sm:text-2xl font-serif font-semibold text-gray-900 mb-2 flex items-center gap-2">
<Shield className="w-5 h-5 sm:w-6 sm:h-6 text-[#d4af37]" /> <Shield className="w-5 h-5 sm:w-6 sm:h-6 text-[var(--luxury-gold)]" />
Two-Factor Authentication Two-Factor Authentication
</h2> </h2>
<p className="text-xs sm:text-sm text-gray-600 font-light"> <p className="text-xs sm:text-sm text-gray-600 font-light">
@@ -894,7 +894,7 @@ const MFATab: React.FC<MFATabProps> = ({
<div className="bg-white border border-gray-200 rounded-sm p-4"> <div className="bg-white border border-gray-200 rounded-sm p-4">
<h3 className="font-semibold text-gray-900 mb-2 flex items-center gap-2"> <h3 className="font-semibold text-gray-900 mb-2 flex items-center gap-2">
<KeyRound className="w-4 h-4 text-[#d4af37]" /> <KeyRound className="w-4 h-4 text-[var(--luxury-gold)]" />
Step 2: Verify Setup Step 2: Verify Setup
</h3> </h3>
<p className="text-sm text-gray-600 mb-4">Enter the 6-digit code from your authenticator app.</p> <p className="text-sm text-gray-600 mb-4">Enter the 6-digit code from your authenticator app.</p>
@@ -992,10 +992,10 @@ const SessionsTab: React.FC = () => {
}; };
const getDeviceIcon = (userAgent?: string) => { const getDeviceIcon = (userAgent?: string) => {
if (!userAgent) return <Monitor className="w-5 h-5 text-[#d4af37]" />; if (!userAgent) return <Monitor className="w-5 h-5 text-[var(--luxury-gold)]" />;
if (userAgent.includes('Mobile')) return <Smartphone className="w-5 h-5 text-blue-500" />; if (userAgent.includes('Mobile')) return <Smartphone className="w-5 h-5 text-blue-500" />;
if (userAgent.includes('Tablet')) return <Tablet className="w-5 h-5 text-purple-500" />; if (userAgent.includes('Tablet')) return <Tablet className="w-5 h-5 text-purple-500" />;
return <Monitor className="w-5 h-5 text-[#d4af37]" />; return <Monitor className="w-5 h-5 text-[var(--luxury-gold)]" />;
}; };
const getDeviceName = (userAgent?: string) => { const getDeviceName = (userAgent?: string) => {
@@ -1053,17 +1053,17 @@ const SessionsTab: React.FC = () => {
if (loading) { if (loading) {
return ( return (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl">
<Loading text="Loading sessions..." /> <Loading text="Loading sessions..." />
</div> </div>
); );
} }
return ( return (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl animate-slide-up space-y-5 sm:space-y-6"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl animate-slide-up space-y-5 sm:space-y-6">
<div> <div>
<h2 className="text-xl sm:text-2xl font-serif font-semibold text-gray-900 mb-2 flex items-center gap-2"> <h2 className="text-xl sm:text-2xl font-serif font-semibold text-gray-900 mb-2 flex items-center gap-2">
<Monitor className="w-5 h-5 sm:w-6 sm:h-6 text-[#d4af37]" /> <Monitor className="w-5 h-5 sm:w-6 sm:h-6 text-[var(--luxury-gold)]" />
Active Sessions Active Sessions
</h2> </h2>
<p className="text-xs sm:text-sm text-gray-600 font-light"> <p className="text-xs sm:text-sm text-gray-600 font-light">
@@ -1092,11 +1092,11 @@ const SessionsTab: React.FC = () => {
{sessions.map((session) => ( {sessions.map((session) => (
<div <div
key={session.id} key={session.id}
className="bg-gradient-to-r from-slate-50 to-white border border-[#d4af37]/20 rounded-sm p-4 sm:p-5 hover:shadow-lg transition-all" className="bg-gradient-to-r from-slate-50 to-white border border-[var(--luxury-gold)]/20 rounded-sm p-4 sm:p-5 hover:shadow-lg transition-all"
> >
<div className="flex items-start justify-between gap-4"> <div className="flex items-start justify-between gap-4">
<div className="flex items-start gap-4 flex-1"> <div className="flex items-start gap-4 flex-1">
<div className="p-2 sm:p-3 bg-gradient-to-br from-[#d4af37]/10 to-[#c9a227]/10 rounded-sm flex-shrink-0"> <div className="p-2 sm:p-3 bg-gradient-to-br from-[var(--luxury-gold)]/10 to-[var(--luxury-gold-dark)]/10 rounded-sm flex-shrink-0">
{getDeviceIcon(session.user_agent)} {getDeviceIcon(session.user_agent)}
</div> </div>
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">

View File

@@ -75,7 +75,7 @@ const HousekeepingShiftViewPage: React.FC = () => {
<div className="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 animate-fade-in"> <div className="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 animate-fade-in">
<div> <div>
<div className="flex items-center gap-3 mb-2"> <div className="flex items-center gap-3 mb-2">
<div className="h-1 w-16 bg-gradient-to-r from-[#d4af37] to-[#c9a227] rounded-full"></div> <div className="h-1 w-16 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] rounded-full"></div>
<h1 className="text-4xl font-bold bg-gradient-to-r from-slate-900 via-slate-800 to-slate-900 bg-clip-text text-transparent tracking-tight"> <h1 className="text-4xl font-bold bg-gradient-to-r from-slate-900 via-slate-800 to-slate-900 bg-clip-text text-transparent tracking-tight">
My Shifts My Shifts
</h1> </h1>
@@ -86,7 +86,7 @@ const HousekeepingShiftViewPage: React.FC = () => {
type="date" type="date"
value={selectedDate.toISOString().split('T')[0]} value={selectedDate.toISOString().split('T')[0]}
onChange={(e) => setSelectedDate(new Date(e.target.value))} onChange={(e) => setSelectedDate(new Date(e.target.value))}
className="px-4 py-2 border-2 border-slate-200 rounded-xl focus:border-[#d4af37] focus:ring-4 focus:ring-yellow-100" className="px-4 py-2 border-2 border-slate-200 rounded-xl focus:border-[var(--luxury-gold)] focus:ring-4 focus:ring-yellow-100"
/> />
</div> </div>
@@ -96,9 +96,9 @@ const HousekeepingShiftViewPage: React.FC = () => {
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div> <div>
<p className="text-slate-600 text-sm font-medium">Upcoming Shifts</p> <p className="text-slate-600 text-sm font-medium">Upcoming Shifts</p>
<p className="text-3xl font-bold text-[#d4af37] mt-2">{getUpcomingShifts()}</p> <p className="text-3xl font-bold text-[var(--luxury-gold)] mt-2">{getUpcomingShifts()}</p>
</div> </div>
<Calendar className="w-12 h-12 text-[#d4af37]" /> <Calendar className="w-12 h-12 text-[var(--luxury-gold)]" />
</div> </div>
</div> </div>
<div className="bg-white/80 backdrop-blur-sm rounded-xl shadow-lg border border-slate-200/60 p-6"> <div className="bg-white/80 backdrop-blur-sm rounded-xl shadow-lg border border-slate-200/60 p-6">
@@ -169,7 +169,7 @@ const HousekeepingShiftViewPage: React.FC = () => {
<select <select
value={shift.status} value={shift.status}
onChange={(e) => handleStatusUpdate(shift.id, e.target.value)} onChange={(e) => handleStatusUpdate(shift.id, e.target.value)}
className="px-4 py-2 border-2 border-slate-200 rounded-xl focus:border-[#d4af37] cursor-pointer" className="px-4 py-2 border-2 border-slate-200 rounded-xl focus:border-[var(--luxury-gold)] cursor-pointer"
> >
<option value="scheduled">Scheduled</option> <option value="scheduled">Scheduled</option>
<option value="in_progress">Start Shift</option> <option value="in_progress">Start Shift</option>

View File

@@ -363,7 +363,7 @@ const ChatManagementPage: React.FC = () => {
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div> <div>
<div className="flex items-center gap-3 mb-2"> <div className="flex items-center gap-3 mb-2">
<div className="h-1 w-16 bg-gradient-to-r from-[#d4af37] to-[#c9a227] rounded-full"></div> <div className="h-1 w-16 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] rounded-full"></div>
<h1 className="text-3xl font-serif font-bold bg-gradient-to-r from-slate-900 via-slate-800 to-slate-900 bg-clip-text text-transparent tracking-tight"> <h1 className="text-3xl font-serif font-bold bg-gradient-to-r from-slate-900 via-slate-800 to-slate-900 bg-clip-text text-transparent tracking-tight">
Chat Management Chat Management
</h1> </h1>
@@ -372,7 +372,7 @@ const ChatManagementPage: React.FC = () => {
</div> </div>
<button <button
onClick={fetchChats} onClick={fetchChats}
className="px-6 py-2.5 bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-slate-900 rounded-lg font-semibold hover:from-[#c9a227] hover:to-[#d4af37] transition-all duration-300 shadow-lg shadow-[#d4af37]/30 hover:shadow-xl hover:shadow-[#d4af37]/40 flex items-center gap-2" className="px-6 py-2.5 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-slate-900 rounded-lg font-semibold hover:from-[var(--luxury-gold-dark)] hover:to-[var(--luxury-gold)] transition-all duration-300 shadow-lg shadow-[var(--luxury-gold)]/30 hover:shadow-xl hover:shadow-[var(--luxury-gold)]/40 flex items-center gap-2"
> >
<RefreshCw className="w-4 h-4" /> <RefreshCw className="w-4 h-4" />
Refresh Refresh
@@ -381,9 +381,9 @@ const ChatManagementPage: React.FC = () => {
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6 h-[calc(100vh-200px)]"> <div className="grid grid-cols-1 lg:grid-cols-3 gap-6 h-[calc(100vh-200px)]">
{} {}
<div className="luxury-glass rounded-xl shadow-2xl border border-[#d4af37]/20 overflow-hidden flex flex-col"> <div className="luxury-glass rounded-xl shadow-2xl border border-[var(--luxury-gold)]/20 overflow-hidden flex flex-col">
<div className="p-4 border-b border-[#d4af37]/20 bg-gradient-to-r from-[#d4af37]/10 via-[#c9a227]/10 to-[#d4af37]/10 relative"> <div className="p-4 border-b border-[var(--luxury-gold)]/20 bg-gradient-to-r from-[var(--luxury-gold)]/10 via-[var(--luxury-gold-dark)]/10 to-[var(--luxury-gold)]/10 relative">
<div className="absolute top-0 left-0 right-0 h-0.5 bg-gradient-to-r from-transparent via-[#d4af37] to-transparent"></div> <div className="absolute top-0 left-0 right-0 h-0.5 bg-gradient-to-r from-transparent via-[var(--luxury-gold)] to-transparent"></div>
<h2 className="font-serif font-semibold text-slate-900 tracking-wide">Chats ({chats.length})</h2> <h2 className="font-serif font-semibold text-slate-900 tracking-wide">Chats ({chats.length})</h2>
</div> </div>
<div className="flex-1 overflow-y-auto"> <div className="flex-1 overflow-y-auto">
@@ -398,9 +398,9 @@ const ChatManagementPage: React.FC = () => {
<div <div
key={chat.id} key={chat.id}
onClick={() => setSelectedChat(chat)} onClick={() => setSelectedChat(chat)}
className={`p-4 cursor-pointer hover:bg-gradient-to-r hover:from-[#d4af37]/5 hover:to-[#c9a227]/5 transition-all duration-300 ${ className={`p-4 cursor-pointer hover:bg-gradient-to-r hover:from-[var(--luxury-gold)]/5 hover:to-[var(--luxury-gold-dark)]/5 transition-all duration-300 ${
selectedChat?.id === chat.id selectedChat?.id === chat.id
? 'bg-gradient-to-r from-[#d4af37]/10 to-[#c9a227]/10 border-l-4 border-[#d4af37] shadow-sm' ? 'bg-gradient-to-r from-[var(--luxury-gold)]/10 to-[var(--luxury-gold-dark)]/10 border-l-4 border-[var(--luxury-gold)] shadow-sm'
: 'border-l-4 border-transparent' : 'border-l-4 border-transparent'
}`} }`}
> >
@@ -425,7 +425,7 @@ const ChatManagementPage: React.FC = () => {
e.stopPropagation(); e.stopPropagation();
handleAcceptChat(chat.id); handleAcceptChat(chat.id);
}} }}
className="mt-2 w-full px-3 py-1.5 bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-slate-900 text-sm font-semibold rounded-lg hover:from-[#c9a227] hover:to-[#d4af37] transition-all duration-300 shadow-md shadow-[#d4af37]/30 hover:shadow-lg" className="mt-2 w-full px-3 py-1.5 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-slate-900 text-sm font-semibold rounded-lg hover:from-[var(--luxury-gold-dark)] hover:to-[var(--luxury-gold)] transition-all duration-300 shadow-md shadow-[var(--luxury-gold)]/30 hover:shadow-lg"
> >
Accept Chat Accept Chat
</button> </button>
@@ -438,11 +438,11 @@ const ChatManagementPage: React.FC = () => {
</div> </div>
{} {}
<div className="lg:col-span-2 luxury-glass rounded-xl shadow-2xl border border-[#d4af37]/20 overflow-hidden flex flex-col"> <div className="lg:col-span-2 luxury-glass rounded-xl shadow-2xl border border-[var(--luxury-gold)]/20 overflow-hidden flex flex-col">
{selectedChat ? ( {selectedChat ? (
<> <>
<div className="p-4 border-b border-[#d4af37]/20 bg-gradient-to-r from-[#d4af37]/10 via-[#c9a227]/10 to-[#d4af37]/10 flex items-center justify-between relative"> <div className="p-4 border-b border-[var(--luxury-gold)]/20 bg-gradient-to-r from-[var(--luxury-gold)]/10 via-[var(--luxury-gold-dark)]/10 to-[var(--luxury-gold)]/10 flex items-center justify-between relative">
<div className="absolute top-0 left-0 right-0 h-0.5 bg-gradient-to-r from-transparent via-[#d4af37] to-transparent"></div> <div className="absolute top-0 left-0 right-0 h-0.5 bg-gradient-to-r from-transparent via-[var(--luxury-gold)] to-transparent"></div>
<div> <div>
<h2 className="font-serif font-semibold text-slate-900 tracking-wide"> <h2 className="font-serif font-semibold text-slate-900 tracking-wide">
{selectedChat.visitor_name || 'Guest'} {selectedChat.visitor_name || 'Guest'}
@@ -451,7 +451,7 @@ const ChatManagementPage: React.FC = () => {
<p className="text-sm text-slate-600 font-light">{selectedChat.visitor_email}</p> <p className="text-sm text-slate-600 font-light">{selectedChat.visitor_email}</p>
)} )}
{selectedChat.staff_name && ( {selectedChat.staff_name && (
<p className="text-xs text-[#d4af37] mt-1 font-medium"> <p className="text-xs text-[var(--luxury-gold)] mt-1 font-medium">
Accepted by: {selectedChat.staff_name} Accepted by: {selectedChat.staff_name}
</p> </p>
)} )}
@@ -489,12 +489,12 @@ const ChatManagementPage: React.FC = () => {
<div <div
className={`max-w-[80%] rounded-xl p-4 shadow-lg ${ className={`max-w-[80%] rounded-xl p-4 shadow-lg ${
message.sender_type === 'staff' message.sender_type === 'staff'
? 'bg-gradient-to-br from-[#d4af37] to-[#c9a227] text-slate-900 border border-[#d4af37]/30' ? 'bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-slate-900 border border-[var(--luxury-gold)]/30'
: 'bg-white text-slate-800 border border-slate-200/60 shadow-sm' : 'bg-white text-slate-800 border border-slate-200/60 shadow-sm'
}`} }`}
> >
{message.sender_type === 'visitor' && ( {message.sender_type === 'visitor' && (
<div className="text-xs font-semibold mb-1.5 text-[#d4af37] tracking-wide"> <div className="text-xs font-semibold mb-1.5 text-[var(--luxury-gold)] tracking-wide">
{message.sender_name || 'Visitor'} {message.sender_name || 'Visitor'}
</div> </div>
)} )}
@@ -521,7 +521,7 @@ const ChatManagementPage: React.FC = () => {
</div> </div>
{selectedChat.status !== 'closed' && ( {selectedChat.status !== 'closed' && (
<div className="p-4 border-t border-[#d4af37]/20 bg-white/90 backdrop-blur-sm"> <div className="p-4 border-t border-[var(--luxury-gold)]/20 bg-white/90 backdrop-blur-sm">
<div className="flex gap-3"> <div className="flex gap-3">
<input <input
type="text" type="text"
@@ -529,13 +529,13 @@ const ChatManagementPage: React.FC = () => {
onChange={(e) => setNewMessage(e.target.value)} onChange={(e) => setNewMessage(e.target.value)}
onKeyPress={handleKeyPress} onKeyPress={handleKeyPress}
placeholder="Type your message..." placeholder="Type your message..."
className="flex-1 px-4 py-3 border-2 border-slate-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-[#d4af37]/30 focus:border-[#d4af37] transition-all duration-200 font-light" className="flex-1 px-4 py-3 border-2 border-slate-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)]/30 focus:border-[var(--luxury-gold)] transition-all duration-200 font-light"
disabled={selectedChat.status === 'pending'} disabled={selectedChat.status === 'pending'}
/> />
<button <button
onClick={handleSendMessage} onClick={handleSendMessage}
disabled={!newMessage.trim() || selectedChat.status === 'pending'} disabled={!newMessage.trim() || selectedChat.status === 'pending'}
className="bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-slate-900 px-5 py-3 rounded-xl hover:from-[#c9a227] hover:to-[#d4af37] disabled:bg-gray-300 disabled:text-gray-500 disabled:cursor-not-allowed transition-all duration-300 flex items-center gap-2 font-semibold shadow-lg shadow-[#d4af37]/30 hover:shadow-xl disabled:shadow-none" className="bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-slate-900 px-5 py-3 rounded-xl hover:from-[var(--luxury-gold-dark)] hover:to-[var(--luxury-gold)] disabled:bg-gray-300 disabled:text-gray-500 disabled:cursor-not-allowed transition-all duration-300 flex items-center gap-2 font-semibold shadow-lg shadow-[var(--luxury-gold)]/30 hover:shadow-xl disabled:shadow-none"
> >
<Send className="w-4 h-4" /> <Send className="w-4 h-4" />
</button> </button>

View File

@@ -417,7 +417,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div className="mb-6 sm:mb-8 animate-fade-in"> <div className="mb-6 sm:mb-8 animate-fade-in">
<div className="flex items-center gap-2 sm:gap-3 mb-2 sm:mb-3"> <div className="flex items-center gap-2 sm:gap-3 mb-2 sm:mb-3">
<div className="h-1 w-12 sm:w-16 md:w-20 bg-gradient-to-r from-[#d4af37] via-amber-400 to-[#d4af37] rounded-full"></div> <div className="h-1 w-12 sm:w-16 md:w-20 bg-gradient-to-r from-[var(--luxury-gold)] via-amber-400 to-[var(--luxury-gold)] rounded-full"></div>
<h1 className="text-2xl sm:text-3xl lg:text-4xl font-serif font-bold bg-gradient-to-r from-gray-900 via-amber-900/90 to-gray-900 bg-clip-text text-transparent tracking-tight"> <h1 className="text-2xl sm:text-3xl lg:text-4xl font-serif font-bold bg-gradient-to-r from-gray-900 via-amber-900/90 to-gray-900 bg-clip-text text-transparent tracking-tight">
Staff Profile & Settings Staff Profile & Settings
</h1> </h1>
@@ -428,61 +428,61 @@ const ProfilePage: React.FC = () => {
</div> </div>
{} {}
<div className="mb-4 sm:mb-6 border-b border-[#d4af37]/20 overflow-x-auto bg-white/50 backdrop-blur-sm rounded-t-lg sm:rounded-t-xl px-4 sm:px-6"> <div className="mb-4 sm:mb-6 border-b border-[var(--luxury-gold)]/20 overflow-x-auto bg-white/50 backdrop-blur-sm rounded-t-lg sm:rounded-t-xl px-4 sm:px-6">
<div className="flex space-x-4 sm:space-x-8 min-w-max"> <div className="flex space-x-4 sm:space-x-8 min-w-max">
<button <button
onClick={() => setActiveTab('profile')} onClick={() => setActiveTab('profile')}
className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${ className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${
activeTab === 'profile' activeTab === 'profile'
? 'border-[#d4af37] text-[#d4af37] shadow-sm' ? 'border-[var(--luxury-gold)] text-[var(--luxury-gold)] shadow-sm'
: 'border-transparent text-gray-500 hover:text-[#d4af37] hover:border-[#d4af37]/30' : 'border-transparent text-gray-500 hover:text-[var(--luxury-gold)] hover:border-[var(--luxury-gold)]/30'
}`} }`}
> >
<User className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'profile' ? 'text-[#d4af37]' : ''}`} /> <User className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'profile' ? 'text-[var(--luxury-gold)]' : ''}`} />
Profile Information Profile Information
</button> </button>
<button <button
onClick={() => setActiveTab('password')} onClick={() => setActiveTab('password')}
className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${ className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${
activeTab === 'password' activeTab === 'password'
? 'border-[#d4af37] text-[#d4af37] shadow-sm' ? 'border-[var(--luxury-gold)] text-[var(--luxury-gold)] shadow-sm'
: 'border-transparent text-gray-500 hover:text-[#d4af37] hover:border-[#d4af37]/30' : 'border-transparent text-gray-500 hover:text-[var(--luxury-gold)] hover:border-[var(--luxury-gold)]/30'
}`} }`}
> >
<KeyRound className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'password' ? 'text-[#d4af37]' : ''}`} /> <KeyRound className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'password' ? 'text-[var(--luxury-gold)]' : ''}`} />
Change Password Change Password
</button> </button>
<button <button
onClick={() => setActiveTab('mfa')} onClick={() => setActiveTab('mfa')}
className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${ className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${
activeTab === 'mfa' activeTab === 'mfa'
? 'border-[#d4af37] text-[#d4af37] shadow-sm' ? 'border-[var(--luxury-gold)] text-[var(--luxury-gold)] shadow-sm'
: 'border-transparent text-gray-500 hover:text-[#d4af37] hover:border-[#d4af37]/30' : 'border-transparent text-gray-500 hover:text-[var(--luxury-gold)] hover:border-[var(--luxury-gold)]/30'
}`} }`}
> >
<Shield className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'mfa' ? 'text-[#d4af37]' : ''}`} /> <Shield className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'mfa' ? 'text-[var(--luxury-gold)]' : ''}`} />
Two-Factor Authentication Two-Factor Authentication
</button> </button>
<button <button
onClick={() => setActiveTab('sessions')} onClick={() => setActiveTab('sessions')}
className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${ className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${
activeTab === 'sessions' activeTab === 'sessions'
? 'border-[#d4af37] text-[#d4af37] shadow-sm' ? 'border-[var(--luxury-gold)] text-[var(--luxury-gold)] shadow-sm'
: 'border-transparent text-gray-500 hover:text-[#d4af37] hover:border-[#d4af37]/30' : 'border-transparent text-gray-500 hover:text-[var(--luxury-gold)] hover:border-[var(--luxury-gold)]/30'
}`} }`}
> >
<Monitor className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'sessions' ? 'text-[#d4af37]' : ''}`} /> <Monitor className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'sessions' ? 'text-[var(--luxury-gold)]' : ''}`} />
Active Sessions Active Sessions
</button> </button>
<button <button
onClick={() => setActiveTab('gdpr')} onClick={() => setActiveTab('gdpr')}
className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${ className={`py-3 sm:py-4 px-2 sm:px-1 border-b-2 font-semibold text-xs sm:text-sm transition-all duration-300 whitespace-nowrap ${
activeTab === 'gdpr' activeTab === 'gdpr'
? 'border-[#d4af37] text-[#d4af37] shadow-sm' ? 'border-[var(--luxury-gold)] text-[var(--luxury-gold)] shadow-sm'
: 'border-transparent text-gray-500 hover:text-[#d4af37] hover:border-[#d4af37]/30' : 'border-transparent text-gray-500 hover:text-[var(--luxury-gold)] hover:border-[var(--luxury-gold)]/30'
}`} }`}
> >
<Database className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'gdpr' ? 'text-[#d4af37]' : ''}`} /> <Database className={`w-4 h-4 sm:w-5 sm:h-5 inline mr-2 ${activeTab === 'gdpr' ? 'text-[var(--luxury-gold)]' : ''}`} />
Data Privacy Data Privacy
</button> </button>
</div> </div>
@@ -490,7 +490,7 @@ const ProfilePage: React.FC = () => {
{} {}
{activeTab === 'profile' && ( {activeTab === 'profile' && (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl animate-slide-up"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl animate-slide-up">
<form onSubmit={handleSubmitProfile(onSubmitProfile)} className="space-y-5 sm:space-y-6"> <form onSubmit={handleSubmitProfile(onSubmitProfile)} className="space-y-5 sm:space-y-6">
{} {}
<div className="flex flex-col sm:flex-row items-center sm:items-start gap-4 sm:gap-6 pb-5 sm:pb-6 border-b border-gray-200"> <div className="flex flex-col sm:flex-row items-center sm:items-start gap-4 sm:gap-6 pb-5 sm:pb-6 border-b border-gray-200">
@@ -499,20 +499,20 @@ const ProfilePage: React.FC = () => {
<img <img
src={avatarPreview || normalizeImageUrl(userInfo?.avatar)} src={avatarPreview || normalizeImageUrl(userInfo?.avatar)}
alt="Profile" alt="Profile"
className="w-20 h-20 sm:w-24 sm:h-24 rounded-full object-cover ring-4 ring-[#d4af37]/20 shadow-lg" className="w-20 h-20 sm:w-24 sm:h-24 rounded-full object-cover ring-4 ring-[var(--luxury-gold)]/20 shadow-lg"
onError={() => { onError={() => {
// If image fails to load, show default avatar // If image fails to load, show default avatar
setAvatarError(true); setAvatarError(true);
}} }}
/> />
) : ( ) : (
<div className="w-20 h-20 sm:w-24 sm:h-24 rounded-full bg-gradient-to-br from-[#d4af37] to-[#c9a227] flex items-center justify-center ring-4 ring-[#d4af37]/20 shadow-lg"> <div className="w-20 h-20 sm:w-24 sm:h-24 rounded-full bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] flex items-center justify-center ring-4 ring-[var(--luxury-gold)]/20 shadow-lg">
<User className="w-10 h-10 sm:w-12 sm:h-12 text-white" /> <User className="w-10 h-10 sm:w-12 sm:h-12 text-white" />
</div> </div>
)} )}
<label <label
htmlFor="avatar-upload" htmlFor="avatar-upload"
className="absolute bottom-0 right-0 p-2 bg-gradient-to-br from-[#d4af37] to-[#c9a227] rounded-full cursor-pointer hover:from-[#f5d76e] hover:to-[#d4af37] transition-all duration-300 shadow-lg hover:shadow-xl hover:shadow-[#d4af37]/40 hover:-translate-y-0.5 active:translate-y-0" className="absolute bottom-0 right-0 p-2 bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] rounded-full cursor-pointer hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] transition-all duration-300 shadow-lg hover:shadow-xl hover:shadow-[var(--luxury-gold)]/40 hover:-translate-y-0.5 active:translate-y-0"
> >
<Camera className="w-3.5 h-3.5 sm:w-4 sm:h-4 text-white" /> <Camera className="w-3.5 h-3.5 sm:w-4 sm:h-4 text-white" />
<input <input
@@ -528,7 +528,7 @@ const ProfilePage: React.FC = () => {
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<User className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <User className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
Full Name Full Name
<span className="text-red-500 ml-1">*</span> <span className="text-red-500 ml-1">*</span>
</label> </label>
@@ -551,7 +551,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<Mail className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <Mail className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
Email Address Email Address
<span className="text-red-500 ml-1">*</span> <span className="text-red-500 ml-1">*</span>
</label> </label>
@@ -574,7 +574,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<Phone className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <Phone className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
Phone Number Phone Number
<span className="text-red-500 ml-1">*</span> <span className="text-red-500 ml-1">*</span>
</label> </label>
@@ -611,7 +611,7 @@ const ProfilePage: React.FC = () => {
{} {}
{activeTab === 'password' && ( {activeTab === 'password' && (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl animate-slide-up"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl animate-slide-up">
<form onSubmit={handleSubmitPassword(onSubmitPassword)} className="space-y-5 sm:space-y-6"> <form onSubmit={handleSubmitPassword(onSubmitPassword)} className="space-y-5 sm:space-y-6">
{} {}
<div className="bg-gradient-to-r from-blue-50 to-indigo-50 border border-blue-200/60 rounded-sm p-4 sm:p-5"> <div className="bg-gradient-to-r from-blue-50 to-indigo-50 border border-blue-200/60 rounded-sm p-4 sm:p-5">
@@ -640,7 +640,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
Current Password Current Password
<span className="text-red-500 ml-1">*</span> <span className="text-red-500 ml-1">*</span>
</label> </label>
@@ -656,7 +656,7 @@ const ProfilePage: React.FC = () => {
<button <button
type="button" type="button"
onClick={() => setShowPassword({ ...showPassword, current: !showPassword.current })} onClick={() => setShowPassword({ ...showPassword, current: !showPassword.current })}
className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[#d4af37] transition-colors" className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[var(--luxury-gold)] transition-colors"
> >
{showPassword.current ? ( {showPassword.current ? (
<EyeOff className="w-4 h-4 sm:w-5 sm:h-5" /> <EyeOff className="w-4 h-4 sm:w-5 sm:h-5" />
@@ -676,7 +676,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
New Password New Password
<span className="text-red-500 ml-1">*</span> <span className="text-red-500 ml-1">*</span>
</label> </label>
@@ -692,7 +692,7 @@ const ProfilePage: React.FC = () => {
<button <button
type="button" type="button"
onClick={() => setShowPassword({ ...showPassword, new: !showPassword.new })} onClick={() => setShowPassword({ ...showPassword, new: !showPassword.new })}
className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[#d4af37] transition-colors" className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[var(--luxury-gold)] transition-colors"
> >
{showPassword.new ? ( {showPassword.new ? (
<EyeOff className="w-4 h-4 sm:w-5 sm:h-5" /> <EyeOff className="w-4 h-4 sm:w-5 sm:h-5" />
@@ -712,7 +712,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div> <div>
<label className="block text-sm sm:text-base font-medium text-gray-700 mb-2"> <label className="block text-sm sm:text-base font-medium text-gray-700 mb-2">
<Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[#d4af37]" /> <Lock className="w-4 h-4 sm:w-5 sm:h-5 inline mr-2 text-[var(--luxury-gold)]" />
Confirm New Password Confirm New Password
<span className="text-red-500 ml-1">*</span> <span className="text-red-500 ml-1">*</span>
</label> </label>
@@ -728,7 +728,7 @@ const ProfilePage: React.FC = () => {
<button <button
type="button" type="button"
onClick={() => setShowPassword({ ...showPassword, confirm: !showPassword.confirm })} onClick={() => setShowPassword({ ...showPassword, confirm: !showPassword.confirm })}
className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[#d4af37] transition-colors" className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-[var(--luxury-gold)] transition-colors"
> >
{showPassword.confirm ? ( {showPassword.confirm ? (
<EyeOff className="w-4 h-4 sm:w-5 sm:h-5" /> <EyeOff className="w-4 h-4 sm:w-5 sm:h-5" />
@@ -762,11 +762,11 @@ const ProfilePage: React.FC = () => {
{} {}
{activeTab === 'mfa' && ( {activeTab === 'mfa' && (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl animate-slide-up space-y-5 sm:space-y-6"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl animate-slide-up space-y-5 sm:space-y-6">
{} {}
<div> <div>
<h2 className="text-xl sm:text-2xl font-serif font-semibold text-gray-900 mb-2 flex items-center gap-2"> <h2 className="text-xl sm:text-2xl font-serif font-semibold text-gray-900 mb-2 flex items-center gap-2">
<Shield className="w-5 h-5 sm:w-6 sm:h-6 text-[#d4af37]" /> <Shield className="w-5 h-5 sm:w-6 sm:h-6 text-[var(--luxury-gold)]" />
Two-Factor Authentication Two-Factor Authentication
</h2> </h2>
<p className="text-xs sm:text-sm text-gray-600 font-light leading-relaxed"> <p className="text-xs sm:text-sm text-gray-600 font-light leading-relaxed">
@@ -838,7 +838,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div className="bg-white border border-gray-200 rounded-sm p-4 sm:p-5"> <div className="bg-white border border-gray-200 rounded-sm p-4 sm:p-5">
<h3 className="text-sm sm:text-base font-semibold text-gray-900 mb-2 flex items-center gap-2"> <h3 className="text-sm sm:text-base font-semibold text-gray-900 mb-2 flex items-center gap-2">
<RefreshCw className="w-4 h-4 sm:w-5 sm:h-5 text-[#d4af37]" /> <RefreshCw className="w-4 h-4 sm:w-5 sm:h-5 text-[var(--luxury-gold)]" />
Backup Codes Backup Codes
</h3> </h3>
<p className="text-xs sm:text-sm text-gray-600 font-light mb-4 leading-relaxed"> <p className="text-xs sm:text-sm text-gray-600 font-light mb-4 leading-relaxed">
@@ -984,7 +984,7 @@ const ProfilePage: React.FC = () => {
{} {}
<div className="bg-white border border-gray-200 rounded-sm p-4 sm:p-5"> <div className="bg-white border border-gray-200 rounded-sm p-4 sm:p-5">
<h3 className="font-semibold text-gray-900 mb-2 text-sm sm:text-base flex items-center gap-2"> <h3 className="font-semibold text-gray-900 mb-2 text-sm sm:text-base flex items-center gap-2">
<KeyRound className="w-4 h-4 sm:w-5 sm:h-5 text-[#d4af37]" /> <KeyRound className="w-4 h-4 sm:w-5 sm:h-5 text-[var(--luxury-gold)]" />
Step 2: Verify Setup Step 2: Verify Setup
</h3> </h3>
<p className="text-xs sm:text-sm text-gray-600 font-light mb-4 leading-relaxed"> <p className="text-xs sm:text-sm text-gray-600 font-light mb-4 leading-relaxed">
@@ -1110,10 +1110,10 @@ const SessionsTab: React.FC = () => {
}; };
const getDeviceIcon = (userAgent?: string) => { const getDeviceIcon = (userAgent?: string) => {
if (!userAgent) return <Monitor className="w-5 h-5 text-[#d4af37]" />; if (!userAgent) return <Monitor className="w-5 h-5 text-[var(--luxury-gold)]" />;
if (userAgent.includes('Mobile')) return <Smartphone className="w-5 h-5 text-blue-500" />; if (userAgent.includes('Mobile')) return <Smartphone className="w-5 h-5 text-blue-500" />;
if (userAgent.includes('Tablet')) return <Tablet className="w-5 h-5 text-purple-500" />; if (userAgent.includes('Tablet')) return <Tablet className="w-5 h-5 text-purple-500" />;
return <Monitor className="w-5 h-5 text-[#d4af37]" />; return <Monitor className="w-5 h-5 text-[var(--luxury-gold)]" />;
}; };
const getDeviceName = (userAgent?: string) => { const getDeviceName = (userAgent?: string) => {
@@ -1181,17 +1181,17 @@ const SessionsTab: React.FC = () => {
if (loading) { if (loading) {
return ( return (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl">
<Loading text="Loading sessions..." /> <Loading text="Loading sessions..." />
</div> </div>
); );
} }
return ( return (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl animate-slide-up space-y-5 sm:space-y-6"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl animate-slide-up space-y-5 sm:space-y-6">
<div> <div>
<h2 className="text-xl sm:text-2xl font-serif font-semibold text-gray-900 mb-2 flex items-center gap-2"> <h2 className="text-xl sm:text-2xl font-serif font-semibold text-gray-900 mb-2 flex items-center gap-2">
<Monitor className="w-5 h-5 sm:w-6 sm:h-6 text-[#d4af37]" /> <Monitor className="w-5 h-5 sm:w-6 sm:h-6 text-[var(--luxury-gold)]" />
Active Sessions Active Sessions
</h2> </h2>
<p className="text-xs sm:text-sm text-gray-600 font-light"> <p className="text-xs sm:text-sm text-gray-600 font-light">
@@ -1220,11 +1220,11 @@ const SessionsTab: React.FC = () => {
{sessions.map((session) => ( {sessions.map((session) => (
<div <div
key={session.id} key={session.id}
className="bg-gradient-to-r from-slate-50 to-white border border-[#d4af37]/20 rounded-sm p-4 sm:p-5 hover:shadow-lg hover:border-[#d4af37]/40 transition-all duration-300" className="bg-gradient-to-r from-slate-50 to-white border border-[var(--luxury-gold)]/20 rounded-sm p-4 sm:p-5 hover:shadow-lg hover:border-[var(--luxury-gold)]/40 transition-all duration-300"
> >
<div className="flex items-start justify-between gap-4"> <div className="flex items-start justify-between gap-4">
<div className="flex items-start gap-4 flex-1"> <div className="flex items-start gap-4 flex-1">
<div className="p-2 sm:p-3 bg-gradient-to-br from-[#d4af37]/10 to-[#c9a227]/10 rounded-sm flex-shrink-0"> <div className="p-2 sm:p-3 bg-gradient-to-br from-[var(--luxury-gold)]/10 to-[var(--luxury-gold-dark)]/10 rounded-sm flex-shrink-0">
{getDeviceIcon(session.user_agent)} {getDeviceIcon(session.user_agent)}
</div> </div>
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
@@ -1354,17 +1354,17 @@ const GDPRTab: React.FC = () => {
if (loading) { if (loading) {
return ( return (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl">
<Loading text="Loading privacy data..." /> <Loading text="Loading privacy data..." />
</div> </div>
); );
} }
return ( return (
<div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[#d4af37]/20 shadow-2xl animate-slide-up space-y-5 sm:space-y-6"> <div className="luxury-glass rounded-sm p-4 sm:p-6 lg:p-8 border border-[var(--luxury-gold)]/20 shadow-2xl animate-slide-up space-y-5 sm:space-y-6">
<div> <div>
<h2 className="text-xl sm:text-2xl font-serif font-semibold text-gray-900 mb-2 flex items-center gap-2"> <h2 className="text-xl sm:text-2xl font-serif font-semibold text-gray-900 mb-2 flex items-center gap-2">
<Database className="w-5 h-5 sm:w-6 sm:h-6 text-[#d4af37]" /> <Database className="w-5 h-5 sm:w-6 sm:h-6 text-[var(--luxury-gold)]" />
Data Privacy & GDPR Rights Data Privacy & GDPR Rights
</h2> </h2>
<p className="text-xs sm:text-sm text-gray-600 font-light"> <p className="text-xs sm:text-sm text-gray-600 font-light">
@@ -1431,14 +1431,14 @@ const GDPRTab: React.FC = () => {
{requests.length > 0 && ( {requests.length > 0 && (
<div className="border-t border-gray-200 pt-5 sm:pt-6"> <div className="border-t border-gray-200 pt-5 sm:pt-6">
<h3 className="text-base sm:text-lg font-semibold text-gray-900 mb-4 flex items-center gap-2"> <h3 className="text-base sm:text-lg font-semibold text-gray-900 mb-4 flex items-center gap-2">
<FileText className="w-5 h-5 text-[#d4af37]" /> <FileText className="w-5 h-5 text-[var(--luxury-gold)]" />
Request History Request History
</h3> </h3>
<div className="space-y-3 sm:space-y-4"> <div className="space-y-3 sm:space-y-4">
{requests.map((request) => ( {requests.map((request) => (
<div <div
key={request.id} key={request.id}
className="bg-gradient-to-r from-slate-50 to-white border border-[#d4af37]/20 rounded-sm p-4 sm:p-5 hover:shadow-md hover:border-[#d4af37]/40 transition-all duration-300" className="bg-gradient-to-r from-slate-50 to-white border border-[var(--luxury-gold)]/20 rounded-sm p-4 sm:p-5 hover:shadow-md hover:border-[var(--luxury-gold)]/40 transition-all duration-300"
> >
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3 sm:gap-4"> <div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3 sm:gap-4">
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">

View File

@@ -2992,10 +2992,10 @@ const ReceptionDashboardPage: React.FC = () => {
{} {}
{showRoomModal && ( {showRoomModal && (
<div className="fixed inset-0 bg-black/80 backdrop-blur-sm flex items-center justify-center z-50 p-4"> <div className="fixed inset-0 bg-black/80 backdrop-blur-sm flex items-center justify-center z-50 p-4">
<div className="bg-gradient-to-br from-[#1a1a1a] via-[#0f0f0f] to-[#1a1a1a] rounded-xl border border-[#d4af37]/30 backdrop-blur-xl shadow-2xl shadow-[#d4af37]/20 p-8 w-full max-w-4xl max-h-[90vh] overflow-y-auto"> <div className="bg-gradient-to-br from-[#1a1a1a] via-[#0f0f0f] to-[#1a1a1a] rounded-xl border border-[var(--luxury-gold)]/30 backdrop-blur-xl shadow-2xl shadow-[var(--luxury-gold)]/20 p-8 w-full max-w-4xl max-h-[90vh] overflow-y-auto">
<div className="flex justify-between items-center mb-6 pb-6 border-b border-[#d4af37]/20"> <div className="flex justify-between items-center mb-6 pb-6 border-b border-[var(--luxury-gold)]/20">
<div> <div>
<h2 className="text-3xl font-serif font-semibold bg-gradient-to-r from-white via-[#d4af37] to-white bg-clip-text text-transparent tracking-wide"> <h2 className="text-3xl font-serif font-semibold bg-gradient-to-r from-white via-[var(--luxury-gold)] to-white bg-clip-text text-transparent tracking-wide">
{editingRoom ? 'Update Room' : 'Add New Room'} {editingRoom ? 'Update Room' : 'Add New Room'}
</h2> </h2>
<p className="text-gray-400 text-sm mt-1 font-light"> <p className="text-gray-400 text-sm mt-1 font-light">
@@ -3004,17 +3004,17 @@ const ReceptionDashboardPage: React.FC = () => {
</div> </div>
<button <button
onClick={() => setShowRoomModal(false)} onClick={() => setShowRoomModal(false)}
className="p-2 hover:bg-[#d4af37]/10 rounded-lg transition-colors border border-[#d4af37]/20 hover:border-[#d4af37]/40" className="p-2 hover:bg-[var(--luxury-gold)]/10 rounded-lg transition-colors border border-[var(--luxury-gold)]/20 hover:border-[var(--luxury-gold)]/40"
> >
<X className="w-6 h-6 text-[#d4af37] hover:text-white transition-colors" /> <X className="w-6 h-6 text-[var(--luxury-gold)] hover:text-white transition-colors" />
</button> </button>
</div> </div>
<form onSubmit={handleRoomSubmit} className="space-y-6"> <form onSubmit={handleRoomSubmit} className="space-y-6">
{} {}
<div className="space-y-4"> <div className="space-y-4">
<h3 className="text-lg font-serif font-semibold text-[#d4af37] mb-4 flex items-center gap-2"> <h3 className="text-lg font-serif font-semibold text-[var(--luxury-gold)] mb-4 flex items-center gap-2">
<div className="w-1 h-6 bg-gradient-to-b from-[#d4af37] to-[#c9a227]" /> <div className="w-1 h-6 bg-gradient-to-b from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]" />
Basic Information Basic Information
</h3> </h3>
@@ -3027,7 +3027,7 @@ const ReceptionDashboardPage: React.FC = () => {
type="text" type="text"
value={roomFormData.room_number} value={roomFormData.room_number}
onChange={(e) => setRoomFormData({ ...roomFormData, room_number: e.target.value })} onChange={(e) => setRoomFormData({ ...roomFormData, room_number: e.target.value })}
className="w-full px-4 py-3 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white placeholder-gray-500 focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37] transition-all duration-300" className="w-full px-4 py-3 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white placeholder-gray-500 focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)] transition-all duration-300"
placeholder="e.g., 1001" placeholder="e.g., 1001"
required required
/> />
@@ -3040,7 +3040,7 @@ const ReceptionDashboardPage: React.FC = () => {
type="number" type="number"
value={roomFormData.floor} value={roomFormData.floor}
onChange={(e) => setRoomFormData({ ...roomFormData, floor: parseInt(e.target.value) })} onChange={(e) => setRoomFormData({ ...roomFormData, floor: parseInt(e.target.value) })}
className="w-full px-4 py-3 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white placeholder-gray-500 focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37] transition-all duration-300" className="w-full px-4 py-3 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white placeholder-gray-500 focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)] transition-all duration-300"
required required
min="1" min="1"
/> />
@@ -3054,7 +3054,7 @@ const ReceptionDashboardPage: React.FC = () => {
<select <select
value={roomFormData.room_type_id} value={roomFormData.room_type_id}
onChange={(e) => setRoomFormData({ ...roomFormData, room_type_id: parseInt(e.target.value) })} onChange={(e) => setRoomFormData({ ...roomFormData, room_type_id: parseInt(e.target.value) })}
className="w-full px-4 py-3 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37] transition-all duration-300" className="w-full px-4 py-3 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)] transition-all duration-300"
required required
> >
{roomTypes.length > 0 ? ( {roomTypes.length > 0 ? (
@@ -3076,7 +3076,7 @@ const ReceptionDashboardPage: React.FC = () => {
<select <select
value={roomFormData.status} value={roomFormData.status}
onChange={(e) => setRoomFormData({ ...roomFormData, status: e.target.value as any })} onChange={(e) => setRoomFormData({ ...roomFormData, status: e.target.value as any })}
className="w-full px-4 py-3 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37] transition-all duration-300" className="w-full px-4 py-3 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)] transition-all duration-300"
required required
> >
<option value="available" className="bg-[#1a1a1a]">Available</option> <option value="available" className="bg-[#1a1a1a]">Available</option>
@@ -3085,13 +3085,13 @@ const ReceptionDashboardPage: React.FC = () => {
</select> </select>
</div> </div>
<div className="flex items-center gap-3 p-4 bg-[#0a0a0a] rounded-lg border border-[#d4af37]/20"> <div className="flex items-center gap-3 p-4 bg-[#0a0a0a] rounded-lg border border-[var(--luxury-gold)]/20">
<input <input
type="checkbox" type="checkbox"
id="featured" id="featured"
checked={roomFormData.featured} checked={roomFormData.featured}
onChange={(e) => setRoomFormData({ ...roomFormData, featured: e.target.checked })} onChange={(e) => setRoomFormData({ ...roomFormData, featured: e.target.checked })}
className="w-5 h-5 text-[#d4af37] bg-[#1a1a1a] border-[#d4af37]/30 rounded focus:ring-[#d4af37]/50 focus:ring-2 cursor-pointer transition-all" className="w-5 h-5 text-[var(--luxury-gold)] bg-[#1a1a1a] border-[var(--luxury-gold)]/30 rounded focus:ring-[var(--luxury-gold)]/50 focus:ring-2 cursor-pointer transition-all"
/> />
<label htmlFor="featured" className="text-sm text-gray-300 cursor-pointer font-medium"> <label htmlFor="featured" className="text-sm text-gray-300 cursor-pointer font-medium">
Featured Room Featured Room
@@ -3108,7 +3108,7 @@ const ReceptionDashboardPage: React.FC = () => {
min="0" min="0"
value={roomFormData.price} value={roomFormData.price}
onChange={(e) => setRoomFormData({ ...roomFormData, price: e.target.value })} onChange={(e) => setRoomFormData({ ...roomFormData, price: e.target.value })}
className="w-full px-4 py-3 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white placeholder-gray-500 focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37] transition-all duration-300" className="w-full px-4 py-3 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white placeholder-gray-500 focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)] transition-all duration-300"
placeholder="e.g., 150.00" placeholder="e.g., 150.00"
/> />
</div> </div>
@@ -3121,7 +3121,7 @@ const ReceptionDashboardPage: React.FC = () => {
value={roomFormData.description} value={roomFormData.description}
onChange={(e) => setRoomFormData({ ...roomFormData, description: e.target.value })} onChange={(e) => setRoomFormData({ ...roomFormData, description: e.target.value })}
rows={4} rows={4}
className="w-full px-4 py-3 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white placeholder-gray-500 focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37] transition-all duration-300 resize-none" className="w-full px-4 py-3 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white placeholder-gray-500 focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)] transition-all duration-300 resize-none"
placeholder="Enter the actual description for this specific room..." placeholder="Enter the actual description for this specific room..."
/> />
</div> </div>
@@ -3136,7 +3136,7 @@ const ReceptionDashboardPage: React.FC = () => {
min="1" min="1"
value={roomFormData.capacity} value={roomFormData.capacity}
onChange={(e) => setRoomFormData({ ...roomFormData, capacity: e.target.value })} onChange={(e) => setRoomFormData({ ...roomFormData, capacity: e.target.value })}
className="w-full px-4 py-3 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white placeholder-gray-500 focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37] transition-all duration-300" className="w-full px-4 py-3 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white placeholder-gray-500 focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)] transition-all duration-300"
placeholder="e.g., 4" placeholder="e.g., 4"
/> />
</div> </div>
@@ -3149,7 +3149,7 @@ const ReceptionDashboardPage: React.FC = () => {
type="text" type="text"
value={roomFormData.room_size} value={roomFormData.room_size}
onChange={(e) => setRoomFormData({ ...roomFormData, room_size: e.target.value })} onChange={(e) => setRoomFormData({ ...roomFormData, room_size: e.target.value })}
className="w-full px-4 py-3 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white placeholder-gray-500 focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37] transition-all duration-300" className="w-full px-4 py-3 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white placeholder-gray-500 focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)] transition-all duration-300"
placeholder="e.g., 1 Room, 50 sqm" placeholder="e.g., 1 Room, 50 sqm"
/> />
</div> </div>
@@ -3163,7 +3163,7 @@ const ReceptionDashboardPage: React.FC = () => {
type="text" type="text"
value={roomFormData.view} value={roomFormData.view}
onChange={(e) => setRoomFormData({ ...roomFormData, view: e.target.value })} onChange={(e) => setRoomFormData({ ...roomFormData, view: e.target.value })}
className="w-full px-4 py-3 bg-[#0a0a0a] border border-[#d4af37]/20 rounded-lg text-white placeholder-gray-500 focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37] transition-all duration-300" className="w-full px-4 py-3 bg-[#0a0a0a] border border-[var(--luxury-gold)]/20 rounded-lg text-white placeholder-gray-500 focus:ring-2 focus:ring-[var(--luxury-gold)]/50 focus:border-[var(--luxury-gold)] transition-all duration-300"
placeholder="e.g., City View, Ocean View, Mountain View" placeholder="e.g., City View, Ocean View, Mountain View"
/> />
</div> </div>
@@ -3171,12 +3171,12 @@ const ReceptionDashboardPage: React.FC = () => {
{} {}
<div className="space-y-4"> <div className="space-y-4">
<h3 className="text-lg font-serif font-semibold text-[#d4af37] mb-4 flex items-center gap-2"> <h3 className="text-lg font-serif font-semibold text-[var(--luxury-gold)] mb-4 flex items-center gap-2">
<div className="w-1 h-6 bg-gradient-to-b from-[#d4af37] to-[#c9a227]" /> <div className="w-1 h-6 bg-gradient-to-b from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]" />
Amenities & Features Amenities & Features
</h3> </h3>
<div className="border border-[#d4af37]/20 rounded-lg p-4 max-h-80 overflow-y-auto bg-[#0a0a0a]/50 backdrop-blur-sm"> <div className="border border-[var(--luxury-gold)]/20 rounded-lg p-4 max-h-80 overflow-y-auto bg-[#0a0a0a]/50 backdrop-blur-sm">
{availableAmenities.length === 0 ? ( {availableAmenities.length === 0 ? (
<p className="text-sm text-gray-400 text-center py-4">Loading amenities...</p> <p className="text-sm text-gray-400 text-center py-4">Loading amenities...</p>
) : ( ) : (
@@ -3188,8 +3188,8 @@ const ReceptionDashboardPage: React.FC = () => {
key={amenity} key={amenity}
className={`flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all duration-300 ${ className={`flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all duration-300 ${
isSelected isSelected
? 'bg-gradient-to-r from-[#d4af37]/20 to-[#c9a227]/20 border-2 border-[#d4af37] shadow-lg shadow-[#d4af37]/20' ? 'bg-gradient-to-r from-[var(--luxury-gold)]/20 to-[var(--luxury-gold-dark)]/20 border-2 border-[var(--luxury-gold)] shadow-lg shadow-[var(--luxury-gold)]/20'
: 'bg-[#1a1a1a]/50 border-2 border-[#333] hover:border-[#d4af37]/30 hover:bg-[#1a1a1a]' : 'bg-[#1a1a1a]/50 border-2 border-[#333] hover:border-[var(--luxury-gold)]/30 hover:bg-[#1a1a1a]'
}`} }`}
> >
<input <input
@@ -3200,14 +3200,14 @@ const ReceptionDashboardPage: React.FC = () => {
/> />
<div className={`w-5 h-5 rounded border-2 flex items-center justify-center transition-all duration-300 ${ <div className={`w-5 h-5 rounded border-2 flex items-center justify-center transition-all duration-300 ${
isSelected isSelected
? 'bg-[#d4af37] border-[#d4af37] shadow-lg shadow-[#d4af37]/30' ? 'bg-[var(--luxury-gold)] border-[var(--luxury-gold)] shadow-lg shadow-[var(--luxury-gold)]/30'
: 'border-gray-600 bg-transparent' : 'border-gray-600 bg-transparent'
}`}> }`}>
{isSelected && <Check className="w-3 h-3 text-[#0f0f0f] font-bold" />} {isSelected && <Check className="w-3 h-3 text-[#0f0f0f] font-bold" />}
</div> </div>
<span className={`text-sm flex-1 transition-colors ${ <span className={`text-sm flex-1 transition-colors ${
isSelected isSelected
? 'font-semibold text-[#d4af37]' ? 'font-semibold text-[var(--luxury-gold)]'
: 'text-gray-400 hover:text-gray-300' : 'text-gray-400 hover:text-gray-300'
}`}> }`}>
{amenity} {amenity}
@@ -3226,17 +3226,17 @@ const ReceptionDashboardPage: React.FC = () => {
</div> </div>
{} {}
<div className="flex gap-4 pt-4 border-t border-[#d4af37]/20"> <div className="flex gap-4 pt-4 border-t border-[var(--luxury-gold)]/20">
<button <button
type="button" type="button"
onClick={() => setShowRoomModal(false)} onClick={() => setShowRoomModal(false)}
className="flex-1 px-6 py-3 border border-[#d4af37]/30 text-gray-300 rounded-lg hover:bg-[#d4af37]/10 hover:border-[#d4af37] transition-all duration-300 font-medium" className="flex-1 px-6 py-3 border border-[var(--luxury-gold)]/30 text-gray-300 rounded-lg hover:bg-[var(--luxury-gold)]/10 hover:border-[var(--luxury-gold)] transition-all duration-300 font-medium"
> >
Cancel Cancel
</button> </button>
<button <button
type="submit" type="submit"
className="flex-1 px-6 py-3 bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-[#0f0f0f] rounded-lg hover:from-[#f5d76e] hover:to-[#d4af37] transition-all duration-300 font-semibold shadow-lg shadow-[#d4af37]/30 hover:shadow-xl hover:shadow-[#d4af37]/40" className="flex-1 px-6 py-3 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-[#0f0f0f] rounded-lg hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] transition-all duration-300 font-semibold shadow-lg shadow-[var(--luxury-gold)]/30 hover:shadow-xl hover:shadow-[var(--luxury-gold)]/40"
> >
{editingRoom ? 'Update Room' : 'Add Room'} {editingRoom ? 'Update Room' : 'Add Room'}
</button> </button>
@@ -3245,9 +3245,9 @@ const ReceptionDashboardPage: React.FC = () => {
{} {}
{editingRoom && ( {editingRoom && (
<div className="mt-8 pt-8 border-t border-[#d4af37]/20"> <div className="mt-8 pt-8 border-t border-[var(--luxury-gold)]/20">
<h3 className="text-lg font-serif font-semibold text-[#d4af37] mb-6 flex items-center gap-2"> <h3 className="text-lg font-serif font-semibold text-[var(--luxury-gold)] mb-6 flex items-center gap-2">
<div className="w-1 h-6 bg-gradient-to-b from-[#d4af37] to-[#c9a227]" /> <div className="w-1 h-6 bg-gradient-to-b from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]" />
<ImageIcon className="w-5 h-5" /> <ImageIcon className="w-5 h-5" />
Room Images Room Images
</h3> </h3>
@@ -3316,8 +3316,8 @@ const ReceptionDashboardPage: React.FC = () => {
return ( return (
<div key={index} className="relative group"> <div key={index} className="relative group">
<div className="overflow-hidden rounded-lg border border-[#d4af37]/20 <div className="overflow-hidden rounded-lg border border-[var(--luxury-gold)]/20
hover:border-[#d4af37] transition-all duration-300"> hover:border-[var(--luxury-gold)] transition-all duration-300">
<img <img
src={imageUrl} src={imageUrl}
alt={`Room Image ${index + 1}`} alt={`Room Image ${index + 1}`}
@@ -3331,7 +3331,7 @@ const ReceptionDashboardPage: React.FC = () => {
</div> </div>
{isRoomImage && ( {isRoomImage && (
<> <>
<div className="absolute top-2 left-2 bg-[#d4af37]/90 backdrop-blur-sm <div className="absolute top-2 left-2 bg-[var(--luxury-gold)]/90 backdrop-blur-sm
text-[#0f0f0f] px-2 py-1 rounded text-xs font-semibold text-[#0f0f0f] px-2 py-1 rounded text-xs font-semibold
opacity-0 group-hover:opacity-100 transition-opacity duration-300"> opacity-0 group-hover:opacity-100 transition-opacity duration-300">
Room Image Room Image
@@ -3354,7 +3354,7 @@ const ReceptionDashboardPage: React.FC = () => {
</div> </div>
</div> </div>
) : ( ) : (
<div className="mb-6 p-8 bg-[#0a0a0a]/50 rounded-lg border border-[#d4af37]/10 text-center"> <div className="mb-6 p-8 bg-[#0a0a0a]/50 rounded-lg border border-[var(--luxury-gold)]/10 text-center">
<ImageIcon className="w-12 h-12 text-gray-600 mx-auto mb-3" /> <ImageIcon className="w-12 h-12 text-gray-600 mx-auto mb-3" />
<p className="text-sm text-gray-400 font-light"> <p className="text-sm text-gray-400 font-light">
No images uploaded yet. Upload images below to display them here. No images uploaded yet. Upload images below to display them here.
@@ -3380,10 +3380,10 @@ const ReceptionDashboardPage: React.FC = () => {
className="w-full text-sm text-gray-400 className="w-full text-sm text-gray-400
file:mr-4 file:py-3 file:px-6 file:rounded-lg file:border-0 file:mr-4 file:py-3 file:px-6 file:rounded-lg file:border-0
file:text-sm file:font-semibold file:text-sm file:font-semibold
file:bg-gradient-to-r file:from-[#d4af37]/20 file:to-[#c9a227]/20 file:bg-gradient-to-r file:from-[var(--luxury-gold)]/20 file:to-[var(--luxury-gold-dark)]/20
file:text-[#d4af37] file:border file:border-[#d4af37]/30 file:text-[var(--luxury-gold)] file:border file:border-[var(--luxury-gold)]/30
hover:file:from-[#d4af37]/30 hover:file:to-[#c9a227]/30 hover:file:from-[var(--luxury-gold)]/30 hover:file:to-[var(--luxury-gold-dark)]/30
hover:file:border-[#d4af37] file:cursor-pointer hover:file:border-[var(--luxury-gold)] file:cursor-pointer
transition-all duration-300 bg-[#0a0a0a] rounded-lg" transition-all duration-300 bg-[#0a0a0a] rounded-lg"
/> />
</div> </div>
@@ -3397,7 +3397,7 @@ const ReceptionDashboardPage: React.FC = () => {
type="button" type="button"
onClick={handleUploadImages} onClick={handleUploadImages}
disabled={uploadingImages} disabled={uploadingImages}
className="px-6 py-2 bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-[#0f0f0f] rounded-lg hover:from-[#f5d76e] hover:to-[#d4af37] transition-all duration-300 font-semibold shadow-lg shadow-[#d4af37]/30 hover:shadow-xl hover:shadow-[#d4af37]/40 disabled:opacity-50 disabled:cursor-not-allowed" className="px-6 py-2 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-[#0f0f0f] rounded-lg hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] transition-all duration-300 font-semibold shadow-lg shadow-[var(--luxury-gold)]/30 hover:shadow-xl hover:shadow-[var(--luxury-gold)]/40 disabled:opacity-50 disabled:cursor-not-allowed"
> >
{uploadingImages ? 'Uploading...' : 'Upload Images'} {uploadingImages ? 'Uploading...' : 'Upload Images'}
</button> </button>
@@ -3407,7 +3407,7 @@ const ReceptionDashboardPage: React.FC = () => {
</div> </div>
)} )}
<div className="mt-8 pt-6 border-t border-[#d4af37]/20 flex justify-end"> <div className="mt-8 pt-6 border-t border-[var(--luxury-gold)]/20 flex justify-end">
<button <button
type="button" type="button"
onClick={() => { onClick={() => {

View File

@@ -11,7 +11,7 @@ const AdminDashboardPage = lazy(() => import('../pages/admin/DashboardPage'));
const UserManagementPage = lazy(() => import('../pages/admin/UserManagementPage')); const UserManagementPage = lazy(() => import('../pages/admin/UserManagementPage'));
const GuestProfilePage = lazy(() => import('../pages/admin/GuestProfilePage')); const GuestProfilePage = lazy(() => import('../pages/admin/GuestProfilePage'));
const GroupBookingManagementPage = lazy(() => import('../pages/admin/GroupBookingManagementPage')); const GroupBookingManagementPage = lazy(() => import('../pages/admin/GroupBookingManagementPage'));
const BusinessDashboardPage = lazy(() => import('../pages/admin/BusinessDashboardPage')); const PromotionsManagementPage = lazy(() => import('../pages/admin/PromotionsManagementPage'));
const ReceptionDashboardPage = lazy(() => import('../pages/admin/ReceptionDashboardPage')); const ReceptionDashboardPage = lazy(() => import('../pages/admin/ReceptionDashboardPage'));
const AdvancedRoomManagementPage = lazy(() => import('../pages/admin/AdvancedRoomManagementPage')); const AdvancedRoomManagementPage = lazy(() => import('../pages/admin/AdvancedRoomManagementPage'));
const PageContentDashboardPage = lazy(() => import('../pages/admin/PageContentDashboard')); const PageContentDashboardPage = lazy(() => import('../pages/admin/PageContentDashboard'));
@@ -39,7 +39,7 @@ const adminRoutes: RouteObject[] = [
{ path: 'users', element: <UserManagementPage /> }, { path: 'users', element: <UserManagementPage /> },
{ path: 'guest-profiles', element: <GuestProfilePage /> }, { path: 'guest-profiles', element: <GuestProfilePage /> },
{ path: 'group-bookings', element: <GroupBookingManagementPage /> }, { path: 'group-bookings', element: <GroupBookingManagementPage /> },
{ path: 'business', element: <BusinessDashboardPage /> }, { path: 'promotions', element: <PromotionsManagementPage /> },
{ path: 'reception', element: <ReceptionDashboardPage /> }, { path: 'reception', element: <ReceptionDashboardPage /> },
{ path: 'advanced-rooms', element: <AdvancedRoomManagementPage /> }, { path: 'advanced-rooms', element: <AdvancedRoomManagementPage /> },
{ path: 'page-content', element: <PageContentDashboardPage /> }, { path: 'page-content', element: <PageContentDashboardPage /> },

View File

@@ -57,11 +57,11 @@ const ConfirmationDialog: React.FC<ConfirmationDialogProps> = ({
{} {}
<div className="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0"> <div className="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
<div className="relative transform overflow-hidden rounded-sm bg-gradient-to-b from-white to-gray-50 text-left shadow-2xl border border-[#d4af37]/20 transition-all sm:my-8 sm:w-full sm:max-w-lg animate-fade-in"> <div className="relative transform overflow-hidden rounded-sm bg-gradient-to-b from-white to-gray-50 text-left shadow-2xl border border-[var(--luxury-gold)]/20 transition-all sm:my-8 sm:w-full sm:max-w-lg animate-fade-in">
{} {}
<button <button
onClick={onClose} onClick={onClose}
className="absolute right-4 top-4 text-gray-400 hover:text-[#d4af37] focus:outline-none focus:ring-2 focus:ring-[#d4af37]/50 rounded-sm p-1 transition-colors" className="absolute right-4 top-4 text-gray-400 hover:text-[var(--luxury-gold)] focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)]/50 rounded-sm p-1 transition-colors"
aria-label="Close" aria-label="Close"
> >
<X className="w-5 h-5" /> <X className="w-5 h-5" />
@@ -74,8 +74,8 @@ const ConfirmationDialog: React.FC<ConfirmationDialogProps> = ({
variant === 'danger' variant === 'danger'
? 'bg-red-100 border-2 border-red-200' ? 'bg-red-100 border-2 border-red-200'
: variant === 'warning' : variant === 'warning'
? 'bg-[#d4af37]/20 border-2 border-[#d4af37]/40' ? 'bg-[var(--luxury-gold)]/20 border-2 border-[var(--luxury-gold)]/40'
: 'bg-[#d4af37]/20 border-2 border-[#d4af37]/40' : 'bg-[var(--luxury-gold)]/20 border-2 border-[var(--luxury-gold)]/40'
} sm:mx-0 sm:h-10 sm:w-10`} } sm:mx-0 sm:h-10 sm:w-10`}
> >
<AlertTriangle <AlertTriangle
@@ -83,8 +83,8 @@ const ConfirmationDialog: React.FC<ConfirmationDialogProps> = ({
variant === 'danger' variant === 'danger'
? 'text-red-600' ? 'text-red-600'
: variant === 'warning' : variant === 'warning'
? 'text-[#d4af37]' ? 'text-[var(--luxury-gold)]'
: 'text-[#d4af37]' : 'text-[var(--luxury-gold)]'
}`} }`}
aria-hidden="true" aria-hidden="true"
/> />
@@ -111,8 +111,8 @@ const ConfirmationDialog: React.FC<ConfirmationDialogProps> = ({
variant === 'danger' variant === 'danger'
? 'bg-red-600 hover:bg-red-700 focus:ring-red-500' ? 'bg-red-600 hover:bg-red-700 focus:ring-red-500'
: variant === 'warning' : variant === 'warning'
? 'bg-gradient-to-r from-[#d4af37] to-[#c9a227] hover:from-[#f5d76e] hover:to-[#d4af37] focus:ring-[#d4af37]' ? '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:ring-[var(--luxury-gold)]'
: 'btn-luxury-primary focus:ring-[#d4af37]' : 'btn-luxury-primary focus:ring-[var(--luxury-gold)]'
}`} }`}
> >
{isLoading ? ( {isLoading ? (
@@ -147,7 +147,7 @@ const ConfirmationDialog: React.FC<ConfirmationDialogProps> = ({
type="button" type="button"
onClick={onClose} onClick={onClose}
disabled={isLoading} disabled={isLoading}
className="mt-3 inline-flex w-full justify-center rounded-sm bg-white/80 backdrop-blur-sm px-4 py-2.5 text-sm font-medium tracking-wide text-gray-700 shadow-sm border border-gray-300 hover:bg-white hover:border-[#d4af37]/30 hover:text-[#d4af37] sm:mt-0 sm:w-auto disabled:opacity-50 disabled:cursor-not-allowed transition-all" className="mt-3 inline-flex w-full justify-center rounded-sm bg-white/80 backdrop-blur-sm px-4 py-2.5 text-sm font-medium tracking-wide text-gray-700 shadow-sm border border-gray-300 hover:bg-white hover:border-[var(--luxury-gold)]/30 hover:text-[var(--luxury-gold)] sm:mt-0 sm:w-auto disabled:opacity-50 disabled:cursor-not-allowed transition-all"
> >
{cancelText} {cancelText}
</button> </button>

View File

@@ -60,10 +60,10 @@ const CookieConsentBanner: React.FC = () => {
}; };
return ( return (
<div className="pointer-events-none fixed inset-x-0 bottom-0 z-40 flex justify-center px-4 pb-4 sm:px-6 sm:pb-6"> <div className="pointer-events-none fixed inset-x-0 bottom-0 z-[9998] flex justify-center px-4 pb-4 sm:px-6 sm:pb-6">
<div className="pointer-events-auto relative w-full max-w-4xl overflow-hidden rounded-2xl bg-gradient-to-r from-black/85 via-zinc-900/90 to-black/85 p-[1px] shadow-[0_24px_60px_rgba(0,0,0,0.8)]"> <div className="pointer-events-auto relative w-full max-w-4xl overflow-hidden rounded-2xl bg-gradient-to-r from-black/85 via-zinc-900/90 to-black/85 p-[1px] shadow-[0_24px_60px_rgba(0,0,0,0.8)]">
{} {}
<div className="absolute inset-0 rounded-2xl border border-[#d4af37]/40" /> <div className="absolute inset-0 rounded-2xl border border-[var(--luxury-gold)]/40" />
{} {}
<div className="pointer-events-none absolute -inset-8 bg-[radial-gradient(circle_at_top,_rgba(212,175,55,0.18),_transparent_55%),radial-gradient(circle_at_bottom,_rgba(0,0,0,0.8),_transparent_60%)] opacity-80" /> <div className="pointer-events-none absolute -inset-8 bg-[radial-gradient(circle_at_top,_rgba(212,175,55,0.18),_transparent_55%),radial-gradient(circle_at_bottom,_rgba(0,0,0,0.8),_transparent_60%)] opacity-80" />
@@ -71,8 +71,8 @@ const CookieConsentBanner: React.FC = () => {
<div className="relative flex flex-col gap-4 bg-gradient-to-br from-zinc-950/80 via-zinc-900/90 to-black/90 px-4 py-4 sm:px-6 sm:py-5 lg:px-8 lg:py-6 sm:flex-row sm:items-start sm:justify-between"> <div className="relative flex flex-col gap-4 bg-gradient-to-br from-zinc-950/80 via-zinc-900/90 to-black/90 px-4 py-4 sm:px-6 sm:py-5 lg:px-8 lg:py-6 sm:flex-row sm:items-start sm:justify-between">
{} {}
<div className="space-y-3 sm:max-w-xl"> <div className="space-y-3 sm:max-w-xl">
<div className="inline-flex items-center gap-2 rounded-full bg-black/60 px-3 py-1 text-[11px] font-medium uppercase tracking-[0.16em] text-[#d4af37]/90 ring-1 ring-[#d4af37]/30"> <div className="inline-flex items-center gap-2 rounded-full bg-black/60 px-3 py-1 text-[11px] font-medium uppercase tracking-[0.16em] text-[var(--luxury-gold)]/90 ring-1 ring-[var(--luxury-gold)]/30">
<span className="h-1.5 w-1.5 rounded-full bg-[#d4af37]" /> <span className="h-1.5 w-1.5 rounded-full bg-[var(--luxury-gold)]" />
Privacy Suite Privacy Suite
</div> </div>
@@ -90,14 +90,14 @@ const CookieConsentBanner: React.FC = () => {
<div className="flex flex-wrap items-center gap-3"> <div className="flex flex-wrap items-center gap-3">
<button <button
type="button" type="button"
className="text-[11px] font-semibold uppercase tracking-[0.16em] text-[#d4af37] underline underline-offset-4 hover:text-[#f6e7b4]" className="text-[11px] font-semibold uppercase tracking-[0.16em] text-[var(--luxury-gold)] underline underline-offset-4 hover:text-[#f6e7b4]"
onClick={() => setShowDetails((prev) => !prev)} onClick={() => setShowDetails((prev) => !prev)}
> >
{showDetails ? 'Hide detailed preferences' : 'Fine-tune preferences'} {showDetails ? 'Hide detailed preferences' : 'Fine-tune preferences'}
</button> </button>
<Link <Link
to="/gdpr" to="/gdpr"
className="text-[11px] font-semibold uppercase tracking-[0.16em] text-[#d4af37] underline underline-offset-4 hover:text-[#f6e7b4]" className="text-[11px] font-semibold uppercase tracking-[0.16em] text-[var(--luxury-gold)] underline underline-offset-4 hover:text-[#f6e7b4]"
> >
Data Privacy (GDPR) Data Privacy (GDPR)
</Link> </Link>
@@ -107,7 +107,7 @@ const CookieConsentBanner: React.FC = () => {
<div className="mt-1.5 space-y-3 rounded-xl bg-black/40 p-3 ring-1 ring-zinc-800/80 backdrop-blur-md sm:p-4"> <div className="mt-1.5 space-y-3 rounded-xl bg-black/40 p-3 ring-1 ring-zinc-800/80 backdrop-blur-md sm:p-4">
<div className="flex flex-col gap-2 text-xs text-zinc-200 sm:text-[13px]"> <div className="flex flex-col gap-2 text-xs text-zinc-200 sm:text-[13px]">
<div className="flex items-start gap-3"> <div className="flex items-start gap-3">
<div className="mt-0.5 h-4 w-4 rounded border border-[#d4af37]/50 bg-[#d4af37]/20" /> <div className="mt-0.5 h-4 w-4 rounded border border-[var(--luxury-gold)]/50 bg-[var(--luxury-gold)]/20" />
<div> <div>
<p className="font-semibold text-zinc-50">Strictly necessary</p> <p className="font-semibold text-zinc-50">Strictly necessary</p>
<p className="text-[11px] text-zinc-400"> <p className="text-[11px] text-zinc-400">
@@ -121,7 +121,7 @@ const CookieConsentBanner: React.FC = () => {
<input <input
id="cookie-analytics" id="cookie-analytics"
type="checkbox" type="checkbox"
className="mt-0.5 h-4 w-4 rounded border-zinc-500 bg-black/40 text-[#d4af37] focus:ring-[#d4af37]" className="mt-0.5 h-4 w-4 rounded border-zinc-500 bg-black/40 text-[var(--luxury-gold)] focus:ring-[var(--luxury-gold)]"
checked={analyticsChecked} checked={analyticsChecked}
onChange={(e) => setAnalyticsChecked(e.target.checked)} onChange={(e) => setAnalyticsChecked(e.target.checked)}
/> />
@@ -138,7 +138,7 @@ const CookieConsentBanner: React.FC = () => {
<input <input
id="cookie-marketing" id="cookie-marketing"
type="checkbox" type="checkbox"
className="mt-0.5 h-4 w-4 rounded border-zinc-500 bg-black/40 text-[#d4af37] focus:ring-[#d4af37]" className="mt-0.5 h-4 w-4 rounded border-zinc-500 bg-black/40 text-[var(--luxury-gold)] focus:ring-[var(--luxury-gold)]"
checked={marketingChecked} checked={marketingChecked}
onChange={(e) => setMarketingChecked(e.target.checked)} onChange={(e) => setMarketingChecked(e.target.checked)}
/> />
@@ -155,7 +155,7 @@ const CookieConsentBanner: React.FC = () => {
<input <input
id="cookie-preferences" id="cookie-preferences"
type="checkbox" type="checkbox"
className="mt-0.5 h-4 w-4 rounded border-zinc-500 bg-black/40 text-[#d4af37] focus:ring-[#d4af37]" className="mt-0.5 h-4 w-4 rounded border-zinc-500 bg-black/40 text-[var(--luxury-gold)] focus:ring-[var(--luxury-gold)]"
checked={preferencesChecked} checked={preferencesChecked}
onChange={(e) => setPreferencesChecked(e.target.checked)} onChange={(e) => setPreferencesChecked(e.target.checked)}
/> />
@@ -176,7 +176,7 @@ const CookieConsentBanner: React.FC = () => {
<div className="mt-2 flex flex-col gap-2 sm:mt-0 sm:w-56"> <div className="mt-2 flex flex-col gap-2 sm:mt-0 sm:w-56">
<button <button
type="button" type="button"
className="inline-flex w-full items-center justify-center rounded-full bg-gradient-to-r from-[#d4af37] via-[#f2cf74] to-[#d4af37] px-4 py-2.5 text-xs font-semibold uppercase tracking-[0.16em] text-black shadow-[0_10px_30px_rgba(0,0,0,0.6)] transition hover:from-[#f8e4a6] hover:via-[#ffe6a3] hover:to-[#f2cf74] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#d4af37]/70" className="inline-flex w-full items-center justify-center rounded-full bg-gradient-to-r from-[var(--luxury-gold)] via-[#f2cf74] to-[var(--luxury-gold)] px-4 py-2.5 text-xs font-semibold uppercase tracking-[0.16em] text-black shadow-[0_10px_30px_rgba(0,0,0,0.6)] transition hover:from-[#f8e4a6] hover:via-[#ffe6a3] hover:to-[#f2cf74] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--luxury-gold)]/70"
onClick={handleAcceptAll} onClick={handleAcceptAll}
> >
Accept all & continue Accept all & continue
@@ -191,7 +191,7 @@ const CookieConsentBanner: React.FC = () => {
{showDetails && ( {showDetails && (
<button <button
type="button" type="button"
className="inline-flex w-full items-center justify-center rounded-full border border-zinc-700 bg-zinc-900/80 px-4 py-2.5 text-xs font-semibold uppercase tracking-[0.16em] text-zinc-100 shadow-[0_8px_22px_rgba(0,0,0,0.6)] transition hover:border-[#d4af37]/60 hover:text-[#f5e9c6] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#d4af37]/70" className="inline-flex w-full items-center justify-center rounded-full border border-zinc-700 bg-zinc-900/80 px-4 py-2.5 text-xs font-semibold uppercase tracking-[0.16em] text-zinc-100 shadow-[0_8px_22px_rgba(0,0,0,0.6)] transition hover:border-[var(--luxury-gold)]/60 hover:text-[#f5e9c6] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--luxury-gold)]/70"
onClick={handleSaveSelection} onClick={handleSaveSelection}
> >
Save my selection Save my selection

View File

@@ -9,7 +9,7 @@ const CookiePreferencesLink: React.FC = () => {
<button <button
type="button" type="button"
onClick={handleClick} onClick={handleClick}
className="hover:text-[#d4af37] transition-colors cursor-pointer font-light tracking-wide text-gray-700" className="hover:text-[var(--luxury-gold)] transition-colors cursor-pointer font-light tracking-wide text-gray-700"
> >
Cookie Preferences Cookie Preferences
</button> </button>

View File

@@ -79,10 +79,10 @@ const CookiePreferencesModal: React.FC = () => {
}; };
return ( return (
<div className="fixed inset-0 z-50 overflow-y-auto" aria-labelledby="modal-title" role="dialog" aria-modal="true"> <div className="fixed inset-0 z-[10000] overflow-y-auto" aria-labelledby="modal-title" role="dialog" aria-modal="true">
{/* Backdrop */} {/* Backdrop */}
<div <div
className="fixed inset-0 bg-black/70 backdrop-blur-sm transition-opacity" className="fixed inset-0 bg-black/70 backdrop-blur-sm transition-opacity z-[10000]"
onClick={() => setIsOpen(false)} onClick={() => setIsOpen(false)}
aria-hidden="true" aria-hidden="true"
/> />
@@ -91,7 +91,7 @@ const CookiePreferencesModal: React.FC = () => {
<div className="flex min-h-full items-center justify-center p-4 text-center sm:p-0"> <div className="flex min-h-full items-center justify-center p-4 text-center sm:p-0">
<div <div
ref={modalRef} ref={modalRef}
className="relative transform overflow-hidden rounded-2xl bg-gradient-to-br from-zinc-950/95 via-zinc-900/95 to-black/95 text-left shadow-2xl border border-[#d4af37]/30 transition-all sm:my-8 sm:w-full sm:max-w-2xl" className="relative transform overflow-hidden rounded-2xl bg-gradient-to-br from-zinc-950/95 via-zinc-900/95 to-black/95 text-left shadow-2xl border border-[var(--luxury-gold)]/30 transition-all sm:my-8 sm:w-full sm:max-w-2xl"
> >
{/* Close button */} {/* Close button */}
<button <button
@@ -105,8 +105,8 @@ const CookiePreferencesModal: React.FC = () => {
<div className="px-6 py-6 sm:px-8 sm:py-8"> <div className="px-6 py-6 sm:px-8 sm:py-8">
{/* Header */} {/* Header */}
<div className="mb-6"> <div className="mb-6">
<div className="inline-flex items-center gap-2 rounded-full bg-black/60 px-3 py-1 text-[11px] font-medium uppercase tracking-[0.16em] text-[#d4af37]/90 ring-1 ring-[#d4af37]/30 mb-4"> <div className="inline-flex items-center gap-2 rounded-full bg-black/60 px-3 py-1 text-[11px] font-medium uppercase tracking-[0.16em] text-[var(--luxury-gold)]/90 ring-1 ring-[var(--luxury-gold)]/30 mb-4">
<span className="h-1.5 w-1.5 rounded-full bg-[#d4af37]" /> <span className="h-1.5 w-1.5 rounded-full bg-[var(--luxury-gold)]" />
Privacy Suite Privacy Suite
</div> </div>
<h2 className="text-2xl font-elegant font-bold text-white mb-2"> <h2 className="text-2xl font-elegant font-bold text-white mb-2">
@@ -121,8 +121,8 @@ const CookiePreferencesModal: React.FC = () => {
<div className="space-y-4 mb-6"> <div className="space-y-4 mb-6">
<div className="rounded-xl bg-black/40 p-4 ring-1 ring-zinc-800/80 backdrop-blur-md"> <div className="rounded-xl bg-black/40 p-4 ring-1 ring-zinc-800/80 backdrop-blur-md">
<div className="flex items-start gap-3"> <div className="flex items-start gap-3">
<div className="mt-0.5 h-5 w-5 rounded border border-[#d4af37]/50 bg-[#d4af37]/20 flex items-center justify-center"> <div className="mt-0.5 h-5 w-5 rounded border border-[var(--luxury-gold)]/50 bg-[var(--luxury-gold)]/20 flex items-center justify-center">
<span className="text-[#d4af37] text-xs"></span> <span className="text-[var(--luxury-gold)] text-xs"></span>
</div> </div>
<div className="flex-1"> <div className="flex-1">
<p className="font-semibold text-zinc-50 mb-1">Strictly necessary</p> <p className="font-semibold text-zinc-50 mb-1">Strictly necessary</p>
@@ -138,7 +138,7 @@ const CookiePreferencesModal: React.FC = () => {
<input <input
id="cookie-analytics-modal" id="cookie-analytics-modal"
type="checkbox" type="checkbox"
className="mt-0.5 h-5 w-5 rounded border-zinc-500 bg-black/40 text-[#d4af37] focus:ring-[#d4af37] cursor-pointer" className="mt-0.5 h-5 w-5 rounded border-zinc-500 bg-black/40 text-[var(--luxury-gold)] focus:ring-[var(--luxury-gold)] cursor-pointer"
checked={analyticsChecked} checked={analyticsChecked}
onChange={(e) => setAnalyticsChecked(e.target.checked)} onChange={(e) => setAnalyticsChecked(e.target.checked)}
/> />
@@ -156,7 +156,7 @@ const CookiePreferencesModal: React.FC = () => {
<input <input
id="cookie-marketing-modal" id="cookie-marketing-modal"
type="checkbox" type="checkbox"
className="mt-0.5 h-5 w-5 rounded border-zinc-500 bg-black/40 text-[#d4af37] focus:ring-[#d4af37] cursor-pointer" className="mt-0.5 h-5 w-5 rounded border-zinc-500 bg-black/40 text-[var(--luxury-gold)] focus:ring-[var(--luxury-gold)] cursor-pointer"
checked={marketingChecked} checked={marketingChecked}
onChange={(e) => setMarketingChecked(e.target.checked)} onChange={(e) => setMarketingChecked(e.target.checked)}
/> />
@@ -174,7 +174,7 @@ const CookiePreferencesModal: React.FC = () => {
<input <input
id="cookie-preferences-modal" id="cookie-preferences-modal"
type="checkbox" type="checkbox"
className="mt-0.5 h-5 w-5 rounded border-zinc-500 bg-black/40 text-[#d4af37] focus:ring-[#d4af37] cursor-pointer" className="mt-0.5 h-5 w-5 rounded border-zinc-500 bg-black/40 text-[var(--luxury-gold)] focus:ring-[var(--luxury-gold)] cursor-pointer"
checked={preferencesChecked} checked={preferencesChecked}
onChange={(e) => setPreferencesChecked(e.target.checked)} onChange={(e) => setPreferencesChecked(e.target.checked)}
/> />
@@ -193,7 +193,7 @@ const CookiePreferencesModal: React.FC = () => {
<button <button
type="button" type="button"
onClick={handleAcceptAll} onClick={handleAcceptAll}
className="flex-1 inline-flex items-center justify-center rounded-full bg-gradient-to-r from-[#d4af37] via-[#f2cf74] to-[#d4af37] px-6 py-3 text-sm font-semibold uppercase tracking-[0.16em] text-black shadow-lg transition hover:from-[#f8e4a6] hover:via-[#ffe6a3] hover:to-[#f2cf74] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#d4af37]/70" className="flex-1 inline-flex items-center justify-center rounded-full bg-gradient-to-r from-[var(--luxury-gold)] via-[#f2cf74] to-[var(--luxury-gold)] px-6 py-3 text-sm font-semibold uppercase tracking-[0.16em] text-black shadow-lg transition hover:from-[#f8e4a6] hover:via-[#ffe6a3] hover:to-[#f2cf74] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--luxury-gold)]/70"
> >
Accept all Accept all
</button> </button>
@@ -207,7 +207,7 @@ const CookiePreferencesModal: React.FC = () => {
<button <button
type="button" type="button"
onClick={handleSaveSelection} onClick={handleSaveSelection}
className="flex-1 inline-flex items-center justify-center rounded-full border border-[#d4af37]/60 bg-zinc-900/80 px-6 py-3 text-sm font-semibold uppercase tracking-[0.16em] text-[#d4af37] shadow-lg transition hover:border-[#d4af37] hover:bg-zinc-800/80 hover:text-[#f5e9c6] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#d4af37]/70" className="flex-1 inline-flex items-center justify-center rounded-full border border-[var(--luxury-gold)]/60 bg-zinc-900/80 px-6 py-3 text-sm font-semibold uppercase tracking-[0.16em] text-[var(--luxury-gold)] shadow-lg transition hover:border-[var(--luxury-gold)] hover:bg-zinc-800/80 hover:text-[#f5e9c6] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--luxury-gold)]/70"
> >
Save selection Save selection
</button> </button>

View File

@@ -83,7 +83,7 @@ const CurrencySelector: React.FC<CurrencySelectorProps> = ({
<select <select
value={currency} value={currency}
onChange={handleChange} onChange={handleChange}
className="appearance-none bg-white border border-gray-300 rounded-lg px-4 py-2 pr-8 text-sm font-medium text-gray-900 focus:outline-none focus:ring-2 focus:ring-[#d4af37] focus:border-[#d4af37] transition-colors cursor-pointer" className="appearance-none bg-white border border-gray-300 rounded-lg px-4 py-2 pr-8 text-sm font-medium text-gray-900 focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-[var(--luxury-gold)] transition-colors cursor-pointer"
> >
{supportedCurrencies.map((curr) => ( {supportedCurrencies.map((curr) => (
<option key={curr} value={curr}> <option key={curr} value={curr}>
@@ -110,7 +110,7 @@ const CurrencySelector: React.FC<CurrencySelectorProps> = ({
<select <select
value={currency} value={currency}
onChange={handleChange} onChange={handleChange}
className="px-3 py-1.5 border border-gray-300 rounded-md text-sm font-medium text-gray-900 bg-white focus:outline-none focus:ring-2 focus:ring-[#d4af37] focus:border-[#d4af37] transition-colors cursor-pointer" className="px-3 py-1.5 border border-gray-300 rounded-md text-sm font-medium text-gray-900 bg-white focus:outline-none focus:ring-2 focus:ring-[var(--luxury-gold)] focus:border-[var(--luxury-gold)] transition-colors cursor-pointer"
> >
{supportedCurrencies.map((curr) => ( {supportedCurrencies.map((curr) => (
<option key={curr} value={curr}> <option key={curr} value={curr}>

View File

@@ -194,7 +194,7 @@ const Footer: React.FC = () => {
return ( return (
<footer className="relative bg-gradient-to-b from-[#0f0f0f] via-[#1a1a1a] to-black text-gray-300 overflow-hidden"> <footer className="relative bg-gradient-to-b from-[#0f0f0f] via-[#1a1a1a] to-black text-gray-300 overflow-hidden">
{/* Top Gold Accent Line */} {/* Top Gold Accent Line */}
<div className="absolute top-0 left-0 right-0 h-[2px] bg-gradient-to-r from-transparent via-[#d4af37] to-transparent shadow-lg shadow-[#d4af37]/50"></div> <div className="absolute top-0 left-0 right-0 h-[2px] bg-gradient-to-r from-transparent via-[var(--luxury-gold)] to-transparent shadow-lg shadow-[var(--luxury-gold)]/50"></div>
{/* Decorative Pattern Overlay */} {/* Decorative Pattern Overlay */}
<div className="absolute inset-0 opacity-[0.03]" style={{ <div className="absolute inset-0 opacity-[0.03]" style={{
@@ -212,7 +212,7 @@ const Footer: React.FC = () => {
<div className="flex items-center space-x-4 mb-6 sm:mb-8"> <div className="flex items-center space-x-4 mb-6 sm:mb-8">
{logoUrl ? ( {logoUrl ? (
<div className="relative group"> <div className="relative group">
<div className="absolute inset-0 bg-gradient-to-r from-[#d4af37]/20 to-transparent rounded-lg blur-xl opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div> <div className="absolute inset-0 bg-gradient-to-r from-[var(--luxury-gold)]/20 to-transparent rounded-lg blur-xl opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
<img <img
src={logoUrl} src={logoUrl}
alt={settings.company_name} alt={settings.company_name}
@@ -221,17 +221,17 @@ const Footer: React.FC = () => {
</div> </div>
) : ( ) : (
<div className="relative group"> <div className="relative group">
<div className="p-3 bg-gradient-to-br from-[#d4af37]/10 to-[#c9a227]/5 rounded-lg border border-[#d4af37]/20 backdrop-blur-sm"> <div className="p-3 bg-gradient-to-br from-[var(--luxury-gold)]/10 to-[var(--luxury-gold-dark)]/5 rounded-lg border border-[var(--luxury-gold)]/20 backdrop-blur-sm">
<Hotel className="w-8 h-8 sm:w-10 sm:h-10 text-[#d4af37] relative z-10 drop-shadow-lg" /> <Hotel className="w-8 h-8 sm:w-10 sm:h-10 text-[var(--luxury-gold)] relative z-10 drop-shadow-lg" />
</div> </div>
<div className="absolute inset-0 bg-[#d4af37]/20 blur-2xl opacity-50 group-hover:opacity-75 transition-opacity duration-500"></div> <div className="absolute inset-0 bg-[var(--luxury-gold)]/20 blur-2xl opacity-50 group-hover:opacity-75 transition-opacity duration-500"></div>
</div> </div>
)} )}
<div> <div>
<h2 className="text-2xl sm:text-3xl font-display font-semibold text-white tracking-tight mb-1"> <h2 className="text-2xl sm:text-3xl font-display font-semibold text-white tracking-tight mb-1">
{settings.company_name || pageContent?.title || 'Luxury Hotel'} {settings.company_name || pageContent?.title || 'Luxury Hotel'}
</h2> </h2>
<p className="text-xs sm:text-sm text-[#d4af37] font-light tracking-[3px] sm:tracking-[4px] uppercase"> <p className="text-xs sm:text-sm text-[var(--luxury-gold)] font-light tracking-[3px] sm:tracking-[4px] uppercase">
{settings.company_tagline || 'Excellence Redefined'} {settings.company_tagline || 'Excellence Redefined'}
</p> </p>
</div> </div>
@@ -249,10 +249,10 @@ const Footer: React.FC = () => {
return ( return (
<div <div
key={index} key={index}
className="group flex items-center space-x-2 px-3 py-2 bg-gradient-to-r from-[#d4af37]/5 to-transparent border border-[#d4af37]/10 rounded-lg hover:border-[#d4af37]/30 hover:from-[#d4af37]/10 transition-all duration-300" className="group flex items-center space-x-2 px-3 py-2 bg-gradient-to-r from-[var(--luxury-gold)]/5 to-transparent border border-[var(--luxury-gold)]/10 rounded-lg hover:border-[var(--luxury-gold)]/30 hover:from-[var(--luxury-gold)]/10 transition-all duration-300"
> >
<BadgeIcon className="w-4 h-4 sm:w-5 sm:h-5 text-[#d4af37] group-hover:scale-110 transition-transform duration-300" /> <BadgeIcon className="w-4 h-4 sm:w-5 sm:h-5 text-[var(--luxury-gold)] group-hover:scale-110 transition-transform duration-300" />
<span className="text-xs sm:text-sm font-medium tracking-wide text-gray-300 group-hover:text-[#d4af37] transition-colors">{badge.text}</span> <span className="text-xs sm:text-sm font-medium tracking-wide text-gray-300 group-hover:text-[var(--luxury-gold)] transition-colors">{badge.text}</span>
</div> </div>
); );
})} })}
@@ -266,11 +266,11 @@ const Footer: React.FC = () => {
href={pageContent.social_links.facebook} href={pageContent.social_links.facebook}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
className="group relative w-12 h-12 sm:w-14 sm:h-14 flex items-center justify-center rounded-lg bg-gradient-to-br from-gray-800/60 to-gray-900/60 backdrop-blur-sm border border-gray-700/50 hover:border-[#d4af37]/60 transition-all duration-300 hover:bg-gradient-to-br hover:from-[#d4af37]/10 hover:to-[#c9a227]/10 hover:shadow-lg hover:shadow-[#d4af37]/20 hover:-translate-y-0.5" className="group relative w-12 h-12 sm:w-14 sm:h-14 flex items-center justify-center rounded-lg bg-gradient-to-br from-gray-800/60 to-gray-900/60 backdrop-blur-sm border border-gray-700/50 hover:border-[var(--luxury-gold)]/60 transition-all duration-300 hover:bg-gradient-to-br hover:from-[var(--luxury-gold)]/10 hover:to-[var(--luxury-gold-dark)]/10 hover:shadow-lg hover:shadow-[var(--luxury-gold)]/20 hover:-translate-y-0.5"
aria-label="Facebook" aria-label="Facebook"
> >
<Facebook className="w-5 h-5 sm:w-6 sm:h-6 text-gray-400 group-hover:text-[#d4af37] transition-all duration-300 group-hover:scale-110" /> <Facebook className="w-5 h-5 sm:w-6 sm:h-6 text-gray-400 group-hover:text-[var(--luxury-gold)] transition-all duration-300 group-hover:scale-110" />
<div className="absolute inset-0 rounded-lg bg-[#d4af37]/0 group-hover:bg-[#d4af37]/10 blur-xl transition-all duration-500"></div> <div className="absolute inset-0 rounded-lg bg-[var(--luxury-gold)]/0 group-hover:bg-[var(--luxury-gold)]/10 blur-xl transition-all duration-500"></div>
</a> </a>
)} )}
{pageContent?.social_links?.twitter && ( {pageContent?.social_links?.twitter && (
@@ -278,11 +278,11 @@ const Footer: React.FC = () => {
href={pageContent.social_links.twitter} href={pageContent.social_links.twitter}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
className="group relative w-12 h-12 sm:w-14 sm:h-14 flex items-center justify-center rounded-lg bg-gradient-to-br from-gray-800/60 to-gray-900/60 backdrop-blur-sm border border-gray-700/50 hover:border-[#d4af37]/60 transition-all duration-300 hover:bg-gradient-to-br hover:from-[#d4af37]/10 hover:to-[#c9a227]/10 hover:shadow-lg hover:shadow-[#d4af37]/20 hover:-translate-y-0.5" className="group relative w-12 h-12 sm:w-14 sm:h-14 flex items-center justify-center rounded-lg bg-gradient-to-br from-gray-800/60 to-gray-900/60 backdrop-blur-sm border border-gray-700/50 hover:border-[var(--luxury-gold)]/60 transition-all duration-300 hover:bg-gradient-to-br hover:from-[var(--luxury-gold)]/10 hover:to-[var(--luxury-gold-dark)]/10 hover:shadow-lg hover:shadow-[var(--luxury-gold)]/20 hover:-translate-y-0.5"
aria-label="Twitter" aria-label="Twitter"
> >
<Twitter className="w-5 h-5 sm:w-6 sm:h-6 text-gray-400 group-hover:text-[#d4af37] transition-all duration-300 group-hover:scale-110" /> <Twitter className="w-5 h-5 sm:w-6 sm:h-6 text-gray-400 group-hover:text-[var(--luxury-gold)] transition-all duration-300 group-hover:scale-110" />
<div className="absolute inset-0 rounded-lg bg-[#d4af37]/0 group-hover:bg-[#d4af37]/10 blur-xl transition-all duration-500"></div> <div className="absolute inset-0 rounded-lg bg-[var(--luxury-gold)]/0 group-hover:bg-[var(--luxury-gold)]/10 blur-xl transition-all duration-500"></div>
</a> </a>
)} )}
{pageContent?.social_links?.instagram && ( {pageContent?.social_links?.instagram && (
@@ -290,11 +290,11 @@ const Footer: React.FC = () => {
href={pageContent.social_links.instagram} href={pageContent.social_links.instagram}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
className="group relative w-12 h-12 sm:w-14 sm:h-14 flex items-center justify-center rounded-lg bg-gradient-to-br from-gray-800/60 to-gray-900/60 backdrop-blur-sm border border-gray-700/50 hover:border-[#d4af37]/60 transition-all duration-300 hover:bg-gradient-to-br hover:from-[#d4af37]/10 hover:to-[#c9a227]/10 hover:shadow-lg hover:shadow-[#d4af37]/20 hover:-translate-y-0.5" className="group relative w-12 h-12 sm:w-14 sm:h-14 flex items-center justify-center rounded-lg bg-gradient-to-br from-gray-800/60 to-gray-900/60 backdrop-blur-sm border border-gray-700/50 hover:border-[var(--luxury-gold)]/60 transition-all duration-300 hover:bg-gradient-to-br hover:from-[var(--luxury-gold)]/10 hover:to-[var(--luxury-gold-dark)]/10 hover:shadow-lg hover:shadow-[var(--luxury-gold)]/20 hover:-translate-y-0.5"
aria-label="Instagram" aria-label="Instagram"
> >
<Instagram className="w-5 h-5 sm:w-6 sm:h-6 text-gray-400 group-hover:text-[#d4af37] transition-all duration-300 group-hover:scale-110" /> <Instagram className="w-5 h-5 sm:w-6 sm:h-6 text-gray-400 group-hover:text-[var(--luxury-gold)] transition-all duration-300 group-hover:scale-110" />
<div className="absolute inset-0 rounded-lg bg-[#d4af37]/0 group-hover:bg-[#d4af37]/10 blur-xl transition-all duration-500"></div> <div className="absolute inset-0 rounded-lg bg-[var(--luxury-gold)]/0 group-hover:bg-[var(--luxury-gold)]/10 blur-xl transition-all duration-500"></div>
</a> </a>
)} )}
{pageContent?.social_links?.linkedin && ( {pageContent?.social_links?.linkedin && (
@@ -302,11 +302,11 @@ const Footer: React.FC = () => {
href={pageContent.social_links.linkedin} href={pageContent.social_links.linkedin}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
className="group relative w-12 h-12 sm:w-14 sm:h-14 flex items-center justify-center rounded-lg bg-gradient-to-br from-gray-800/60 to-gray-900/60 backdrop-blur-sm border border-gray-700/50 hover:border-[#d4af37]/60 transition-all duration-300 hover:bg-gradient-to-br hover:from-[#d4af37]/10 hover:to-[#c9a227]/10 hover:shadow-lg hover:shadow-[#d4af37]/20 hover:-translate-y-0.5" className="group relative w-12 h-12 sm:w-14 sm:h-14 flex items-center justify-center rounded-lg bg-gradient-to-br from-gray-800/60 to-gray-900/60 backdrop-blur-sm border border-gray-700/50 hover:border-[var(--luxury-gold)]/60 transition-all duration-300 hover:bg-gradient-to-br hover:from-[var(--luxury-gold)]/10 hover:to-[var(--luxury-gold-dark)]/10 hover:shadow-lg hover:shadow-[var(--luxury-gold)]/20 hover:-translate-y-0.5"
aria-label="LinkedIn" aria-label="LinkedIn"
> >
<Linkedin className="w-5 h-5 sm:w-6 sm:h-6 text-gray-400 group-hover:text-[#d4af37] transition-all duration-300 group-hover:scale-110" /> <Linkedin className="w-5 h-5 sm:w-6 sm:h-6 text-gray-400 group-hover:text-[var(--luxury-gold)] transition-all duration-300 group-hover:scale-110" />
<div className="absolute inset-0 rounded-lg bg-[#d4af37]/0 group-hover:bg-[#d4af37]/10 blur-xl transition-all duration-500"></div> <div className="absolute inset-0 rounded-lg bg-[var(--luxury-gold)]/0 group-hover:bg-[var(--luxury-gold)]/10 blur-xl transition-all duration-500"></div>
</a> </a>
)} )}
{pageContent?.social_links?.youtube && ( {pageContent?.social_links?.youtube && (
@@ -314,11 +314,11 @@ const Footer: React.FC = () => {
href={pageContent.social_links.youtube} href={pageContent.social_links.youtube}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
className="group relative w-12 h-12 sm:w-14 sm:h-14 flex items-center justify-center rounded-lg bg-gradient-to-br from-gray-800/60 to-gray-900/60 backdrop-blur-sm border border-gray-700/50 hover:border-[#d4af37]/60 transition-all duration-300 hover:bg-gradient-to-br hover:from-[#d4af37]/10 hover:to-[#c9a227]/10 hover:shadow-lg hover:shadow-[#d4af37]/20 hover:-translate-y-0.5" className="group relative w-12 h-12 sm:w-14 sm:h-14 flex items-center justify-center rounded-lg bg-gradient-to-br from-gray-800/60 to-gray-900/60 backdrop-blur-sm border border-gray-700/50 hover:border-[var(--luxury-gold)]/60 transition-all duration-300 hover:bg-gradient-to-br hover:from-[var(--luxury-gold)]/10 hover:to-[var(--luxury-gold-dark)]/10 hover:shadow-lg hover:shadow-[var(--luxury-gold)]/20 hover:-translate-y-0.5"
aria-label="YouTube" aria-label="YouTube"
> >
<Youtube className="w-5 h-5 sm:w-6 sm:h-6 text-gray-400 group-hover:text-[#d4af37] transition-all duration-300 group-hover:scale-110" /> <Youtube className="w-5 h-5 sm:w-6 sm:h-6 text-gray-400 group-hover:text-[var(--luxury-gold)] transition-all duration-300 group-hover:scale-110" />
<div className="absolute inset-0 rounded-lg bg-[#d4af37]/0 group-hover:bg-[#d4af37]/10 blur-xl transition-all duration-500"></div> <div className="absolute inset-0 rounded-lg bg-[var(--luxury-gold)]/0 group-hover:bg-[var(--luxury-gold)]/10 blur-xl transition-all duration-500"></div>
</a> </a>
)} )}
</div> </div>
@@ -329,16 +329,16 @@ const Footer: React.FC = () => {
<div className="lg:col-span-2"> <div className="lg:col-span-2">
<h3 className="text-white font-elegant font-semibold text-lg sm:text-xl mb-4 sm:mb-6 relative inline-block tracking-wide"> <h3 className="text-white font-elegant font-semibold text-lg sm:text-xl mb-4 sm:mb-6 relative inline-block tracking-wide">
<span className="relative z-10">Quick Links</span> <span className="relative z-10">Quick Links</span>
<span className="absolute bottom-0 left-0 w-full h-[2px] bg-gradient-to-r from-[#d4af37] via-[#d4af37]/50 to-transparent"></span> <span className="absolute bottom-0 left-0 w-full h-[2px] bg-gradient-to-r from-[var(--luxury-gold)] via-[var(--luxury-gold)]/50 to-transparent"></span>
</h3> </h3>
<ul className="space-y-3 sm:space-y-4"> <ul className="space-y-3 sm:space-y-4">
{quickLinks.map((link) => ( {quickLinks.map((link) => (
<li key={link.url}> <li key={link.url}>
<Link <Link
to={link.url} to={link.url}
className="group flex items-center text-sm sm:text-base text-gray-400 hover:text-[#d4af37] transition-all duration-300 relative font-light tracking-wide" className="group flex items-center text-sm sm:text-base text-gray-400 hover:text-[var(--luxury-gold)] transition-all duration-300 relative font-light tracking-wide"
> >
<span className="absolute left-0 w-0 h-[2px] bg-gradient-to-r from-[#d4af37] to-[#c9a227] group-hover:w-8 transition-all duration-300 rounded-full"></span> <span className="absolute left-0 w-0 h-[2px] bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] group-hover:w-8 transition-all duration-300 rounded-full"></span>
<span className="ml-10 group-hover:translate-x-2 transition-transform duration-300 group-hover:font-medium">{link.label}</span> <span className="ml-10 group-hover:translate-x-2 transition-transform duration-300 group-hover:font-medium">{link.label}</span>
</Link> </Link>
</li> </li>
@@ -352,16 +352,16 @@ const Footer: React.FC = () => {
<div className="lg:col-span-2"> <div className="lg:col-span-2">
<h3 className="text-white font-elegant font-semibold text-lg sm:text-xl mb-4 sm:mb-6 relative inline-block tracking-wide"> <h3 className="text-white font-elegant font-semibold text-lg sm:text-xl mb-4 sm:mb-6 relative inline-block tracking-wide">
<span className="relative z-10">Guest Services</span> <span className="relative z-10">Guest Services</span>
<span className="absolute bottom-0 left-0 w-full h-[2px] bg-gradient-to-r from-[#d4af37] via-[#d4af37]/50 to-transparent"></span> <span className="absolute bottom-0 left-0 w-full h-[2px] bg-gradient-to-r from-[var(--luxury-gold)] via-[var(--luxury-gold)]/50 to-transparent"></span>
</h3> </h3>
<ul className="space-y-3 sm:space-y-4"> <ul className="space-y-3 sm:space-y-4">
{supportLinks.map((link) => ( {supportLinks.map((link) => (
<li key={link.url}> <li key={link.url}>
<Link <Link
to={link.url} to={link.url}
className="group flex items-center text-sm sm:text-base text-gray-400 hover:text-[#d4af37] transition-all duration-300 relative font-light tracking-wide" className="group flex items-center text-sm sm:text-base text-gray-400 hover:text-[var(--luxury-gold)] transition-all duration-300 relative font-light tracking-wide"
> >
<span className="absolute left-0 w-0 h-[2px] bg-gradient-to-r from-[#d4af37] to-[#c9a227] group-hover:w-8 transition-all duration-300 rounded-full"></span> <span className="absolute left-0 w-0 h-[2px] bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] group-hover:w-8 transition-all duration-300 rounded-full"></span>
<span className="ml-10 group-hover:translate-x-2 transition-transform duration-300 group-hover:font-medium">{link.label}</span> <span className="ml-10 group-hover:translate-x-2 transition-transform duration-300 group-hover:font-medium">{link.label}</span>
</Link> </Link>
</li> </li>
@@ -374,7 +374,7 @@ const Footer: React.FC = () => {
<div className="lg:col-span-2"> <div className="lg:col-span-2">
<h3 className="text-white font-elegant font-semibold text-lg sm:text-xl mb-6 sm:mb-8 relative inline-block tracking-wide"> <h3 className="text-white font-elegant font-semibold text-lg sm:text-xl mb-6 sm:mb-8 relative inline-block tracking-wide">
<span className="relative z-10">{homePageContent?.newsletter_section_title || 'Newsletter'}</span> <span className="relative z-10">{homePageContent?.newsletter_section_title || 'Newsletter'}</span>
<span className="absolute bottom-0 left-0 w-full h-[2px] bg-gradient-to-r from-[#d4af37] via-[#d4af37]/50 to-transparent"></span> <span className="absolute bottom-0 left-0 w-full h-[2px] bg-gradient-to-r from-[var(--luxury-gold)] via-[var(--luxury-gold)]/50 to-transparent"></span>
</h3> </h3>
{homePageContent?.newsletter_section_subtitle && ( {homePageContent?.newsletter_section_subtitle && (
<p className="text-sm text-gray-400 mb-4 font-light leading-relaxed"> <p className="text-sm text-gray-400 mb-4 font-light leading-relaxed">
@@ -416,14 +416,14 @@ const Footer: React.FC = () => {
value={newsletterEmail} value={newsletterEmail}
onChange={(e) => setNewsletterEmail(e.target.value)} onChange={(e) => setNewsletterEmail(e.target.value)}
placeholder={homePageContent?.newsletter_placeholder || 'Enter your email'} placeholder={homePageContent?.newsletter_placeholder || 'Enter your email'}
className="w-full px-4 py-2.5 rounded-lg border border-gray-700 bg-gray-800/50 text-white placeholder-gray-400 focus:border-[#d4af37] focus:ring-2 focus:ring-[#d4af37]/20 transition-all disabled:opacity-50 disabled:cursor-not-allowed text-sm" className="w-full px-4 py-2.5 rounded-lg border border-gray-700 bg-gray-800/50 text-white placeholder-gray-400 focus:border-[var(--luxury-gold)] focus:ring-2 focus:ring-[var(--luxury-gold)]/20 transition-all disabled:opacity-50 disabled:cursor-not-allowed text-sm"
required required
disabled={newsletterSubmitting} disabled={newsletterSubmitting}
/> />
<button <button
type="submit" type="submit"
disabled={newsletterSubmitting || !newsletterEmail} disabled={newsletterSubmitting || !newsletterEmail}
className="w-full px-4 py-2.5 bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-[#0f0f0f] rounded-lg font-semibold hover:from-[#f5d76e] hover:to-[#d4af37] transition-all duration-300 shadow-lg shadow-[#d4af37]/30 hover:shadow-xl hover:shadow-[#d4af37]/40 disabled:opacity-50 disabled:cursor-not-allowed text-sm" className="w-full px-4 py-2.5 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-[#0f0f0f] rounded-lg font-semibold hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] transition-all duration-300 shadow-lg shadow-[var(--luxury-gold)]/30 hover:shadow-xl hover:shadow-[var(--luxury-gold)]/40 disabled:opacity-50 disabled:cursor-not-allowed text-sm"
> >
{newsletterSubmitting ? 'Subscribing...' : (homePageContent?.newsletter_button_text || 'Subscribe')} {newsletterSubmitting ? 'Subscribing...' : (homePageContent?.newsletter_button_text || 'Subscribe')}
</button> </button>
@@ -443,17 +443,17 @@ const Footer: React.FC = () => {
<div className="lg:col-span-2"> <div className="lg:col-span-2">
<h3 className="text-white font-elegant font-semibold text-lg sm:text-xl mb-4 sm:mb-6 relative inline-block tracking-wide"> <h3 className="text-white font-elegant font-semibold text-lg sm:text-xl mb-4 sm:mb-6 relative inline-block tracking-wide">
<span className="relative z-10">Contact</span> <span className="relative z-10">Contact</span>
<span className="absolute bottom-0 left-0 w-full h-[2px] bg-gradient-to-r from-[#d4af37] via-[#d4af37]/50 to-transparent"></span> <span className="absolute bottom-0 left-0 w-full h-[2px] bg-gradient-to-r from-[var(--luxury-gold)] via-[var(--luxury-gold)]/50 to-transparent"></span>
</h3> </h3>
{(displayAddress || displayPhone || displayEmail) && ( {(displayAddress || displayPhone || displayEmail) && (
<ul className="space-y-5 sm:space-y-6"> <ul className="space-y-5 sm:space-y-6">
{displayAddress && ( {displayAddress && (
<li className="flex items-start space-x-4 group"> <li className="flex items-start space-x-4 group">
<div className="relative mt-1 flex-shrink-0"> <div className="relative mt-1 flex-shrink-0">
<div className="p-2 bg-gradient-to-br from-[#d4af37]/10 to-[#c9a227]/5 rounded-lg border border-[#d4af37]/20 group-hover:border-[#d4af37]/40 transition-all duration-300"> <div className="p-2 bg-gradient-to-br from-[var(--luxury-gold)]/10 to-[var(--luxury-gold-dark)]/5 rounded-lg border border-[var(--luxury-gold)]/20 group-hover:border-[var(--luxury-gold)]/40 transition-all duration-300">
<MapPin className="w-4 h-4 sm:w-5 sm:h-5 text-[#d4af37] transition-all duration-300 group-hover:scale-110" /> <MapPin className="w-4 h-4 sm:w-5 sm:h-5 text-[var(--luxury-gold)] transition-all duration-300 group-hover:scale-110" />
</div> </div>
<div className="absolute inset-0 bg-[#d4af37]/20 blur-xl opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div> <div className="absolute inset-0 bg-[var(--luxury-gold)]/20 blur-xl opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
</div> </div>
<span className="text-sm sm:text-base text-gray-400 group-hover:text-gray-300 transition-colors leading-relaxed font-light pt-1"> <span className="text-sm sm:text-base text-gray-400 group-hover:text-gray-300 transition-colors leading-relaxed font-light pt-1">
{displayAddress {displayAddress
@@ -469,12 +469,12 @@ const Footer: React.FC = () => {
{displayPhone && ( {displayPhone && (
<li className="flex items-center space-x-4 group"> <li className="flex items-center space-x-4 group">
<div className="relative flex-shrink-0"> <div className="relative flex-shrink-0">
<div className="p-2 bg-gradient-to-br from-[#d4af37]/10 to-[#c9a227]/5 rounded-lg border border-[#d4af37]/20 group-hover:border-[#d4af37]/40 transition-all duration-300"> <div className="p-2 bg-gradient-to-br from-[var(--luxury-gold)]/10 to-[var(--luxury-gold-dark)]/5 rounded-lg border border-[var(--luxury-gold)]/20 group-hover:border-[var(--luxury-gold)]/40 transition-all duration-300">
<Phone className="w-4 h-4 sm:w-5 sm:h-5 text-[#d4af37] transition-all duration-300 group-hover:scale-110" /> <Phone className="w-4 h-4 sm:w-5 sm:h-5 text-[var(--luxury-gold)] transition-all duration-300 group-hover:scale-110" />
</div> </div>
<div className="absolute inset-0 bg-[#d4af37]/20 blur-xl opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div> <div className="absolute inset-0 bg-[var(--luxury-gold)]/20 blur-xl opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
</div> </div>
<a href={phoneHref} className="text-sm sm:text-base text-gray-400 group-hover:text-[#d4af37] transition-colors font-light tracking-wide"> <a href={phoneHref} className="text-sm sm:text-base text-gray-400 group-hover:text-[var(--luxury-gold)] transition-colors font-light tracking-wide">
{displayPhone} {displayPhone}
</a> </a>
</li> </li>
@@ -482,12 +482,12 @@ const Footer: React.FC = () => {
{displayEmail && ( {displayEmail && (
<li className="flex items-center space-x-4 group"> <li className="flex items-center space-x-4 group">
<div className="relative flex-shrink-0"> <div className="relative flex-shrink-0">
<div className="p-2 bg-gradient-to-br from-[#d4af37]/10 to-[#c9a227]/5 rounded-lg border border-[#d4af37]/20 group-hover:border-[#d4af37]/40 transition-all duration-300"> <div className="p-2 bg-gradient-to-br from-[var(--luxury-gold)]/10 to-[var(--luxury-gold-dark)]/5 rounded-lg border border-[var(--luxury-gold)]/20 group-hover:border-[var(--luxury-gold)]/40 transition-all duration-300">
<Mail className="w-4 h-4 sm:w-5 sm:h-5 text-[#d4af37] transition-all duration-300 group-hover:scale-110" /> <Mail className="w-4 h-4 sm:w-5 sm:h-5 text-[var(--luxury-gold)] transition-all duration-300 group-hover:scale-110" />
</div> </div>
<div className="absolute inset-0 bg-[#d4af37]/20 blur-xl opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div> <div className="absolute inset-0 bg-[var(--luxury-gold)]/20 blur-xl opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
</div> </div>
<a href={`mailto:${displayEmail}`} className="text-sm sm:text-base text-gray-400 group-hover:text-[#d4af37] transition-colors font-light tracking-wide break-all"> <a href={`mailto:${displayEmail}`} className="text-sm sm:text-base text-gray-400 group-hover:text-[var(--luxury-gold)] transition-colors font-light tracking-wide break-all">
{displayEmail} {displayEmail}
</a> </a>
</li> </li>
@@ -499,7 +499,7 @@ const Footer: React.FC = () => {
<div className="mt-8 sm:mt-10 pt-6 sm:pt-8 border-t border-gray-800/50"> <div className="mt-8 sm:mt-10 pt-6 sm:pt-8 border-t border-gray-800/50">
<div className="flex items-center space-x-1 mb-3"> <div className="flex items-center space-x-1 mb-3">
{[...Array(5)].map((_, i) => ( {[...Array(5)].map((_, i) => (
<Star key={i} className="w-4 h-4 sm:w-5 sm:h-5 fill-[#d4af37] text-[#d4af37] drop-shadow-lg" /> <Star key={i} className="w-4 h-4 sm:w-5 sm:h-5 fill-[var(--luxury-gold)] text-[var(--luxury-gold)] drop-shadow-lg" />
))} ))}
</div> </div>
<p className="text-xs sm:text-sm text-gray-500 font-light tracking-wide">Rated 5.0 by 10,000+ guests</p> <p className="text-xs sm:text-sm text-gray-500 font-light tracking-wide">Rated 5.0 by 10,000+ guests</p>
@@ -514,7 +514,7 @@ const Footer: React.FC = () => {
</div> </div>
<div className="relative flex justify-center"> <div className="relative flex justify-center">
<div className="bg-gradient-to-b from-[#0f0f0f] to-[#1a1a1a] px-6"> <div className="bg-gradient-to-b from-[#0f0f0f] to-[#1a1a1a] px-6">
<div className="w-24 sm:w-32 h-[2px] bg-gradient-to-r from-transparent via-[#d4af37]/50 to-transparent shadow-lg shadow-[#d4af37]/30"></div> <div className="w-24 sm:w-32 h-[2px] bg-gradient-to-r from-transparent via-[var(--luxury-gold)]/50 to-transparent shadow-lg shadow-[var(--luxury-gold)]/30"></div>
</div> </div>
</div> </div>
</div> </div>
@@ -530,11 +530,11 @@ const Footer: React.FC = () => {
})()} })()}
</div> </div>
<div className="flex items-center space-x-4 sm:space-x-6 text-xs sm:text-sm text-gray-600"> <div className="flex items-center space-x-4 sm:space-x-6 text-xs sm:text-sm text-gray-600">
<Link to="/privacy" className="hover:text-[#d4af37] transition-colors cursor-pointer font-light tracking-wide">Privacy</Link> <Link to="/privacy" className="hover:text-[var(--luxury-gold)] transition-colors cursor-pointer font-light tracking-wide">Privacy</Link>
<span className="text-gray-700"></span> <span className="text-gray-700"></span>
<Link to="/terms" className="hover:text-[#d4af37] transition-colors cursor-pointer font-light tracking-wide">Terms</Link> <Link to="/terms" className="hover:text-[var(--luxury-gold)] transition-colors cursor-pointer font-light tracking-wide">Terms</Link>
<span className="text-gray-700"></span> <span className="text-gray-700"></span>
<Link to="/refunds" className="hover:text-[#d4af37] transition-colors cursor-pointer font-light tracking-wide">Refunds</Link> <Link to="/refunds" className="hover:text-[var(--luxury-gold)] transition-colors cursor-pointer font-light tracking-wide">Refunds</Link>
<span className="text-gray-700"></span> <span className="text-gray-700"></span>
<CookiePreferencesLink /> <CookiePreferencesLink />
</div> </div>
@@ -542,7 +542,7 @@ const Footer: React.FC = () => {
</div> </div>
{/* Bottom Gold Accent Line */} {/* Bottom Gold Accent Line */}
<div className="absolute bottom-0 left-0 right-0 h-[2px] bg-gradient-to-r from-transparent via-[#d4af37] to-transparent shadow-lg shadow-[#d4af37]/50"></div> <div className="absolute bottom-0 left-0 right-0 h-[2px] bg-gradient-to-r from-transparent via-[var(--luxury-gold)] to-transparent shadow-lg shadow-[var(--luxury-gold)]/50"></div>
{/* Chat Widget */} {/* Chat Widget */}
<ChatWidget /> <ChatWidget />

View File

@@ -1,5 +1,5 @@
import React, { useState, useRef } from 'react'; import React, { useState, useRef, useEffect } from 'react';
import { Link } from 'react-router-dom'; import { Link, useLocation } from 'react-router-dom';
import { import {
Hotel, Hotel,
User, User,
@@ -41,6 +41,7 @@ const Header: React.FC<HeaderProps> = ({
}) => { }) => {
const { settings } = useCompanySettings(); const { settings } = useCompanySettings();
const { openModal } = useAuthModal(); const { openModal } = useAuthModal();
const location = useLocation();
const displayPhone = settings.company_phone || '+1 (234) 567-890'; const displayPhone = settings.company_phone || '+1 (234) 567-890';
@@ -55,6 +56,23 @@ const Header: React.FC<HeaderProps> = ({
const [isUserMenuOpen, setIsUserMenuOpen] = useState(false); const [isUserMenuOpen, setIsUserMenuOpen] = useState(false);
const userMenuRef = useRef<HTMLDivElement>(null); const userMenuRef = useRef<HTMLDivElement>(null);
// Track previous pathname to detect actual navigation
const prevPathnameRef = useRef(location.pathname);
// Close menu when navigation happens
useEffect(() => {
const prevPathname = prevPathnameRef.current;
const currentPathname = location.pathname;
// Only close menu if it's an actual navigation (pathname changed)
if (prevPathname !== currentPathname && isMobileMenuOpen) {
setIsMobileMenuOpen(false);
}
// Update ref for next comparison
prevPathnameRef.current = currentPathname;
}, [location.pathname, isMobileMenuOpen]);
useClickOutside(userMenuRef, () => { useClickOutside(userMenuRef, () => {
if (isUserMenuOpen) { if (isUserMenuOpen) {
@@ -84,32 +102,42 @@ const Header: React.FC<HeaderProps> = ({
{!isAuthenticated ? ( {!isAuthenticated ? (
<> <>
<button <button
onClick={() => { onClick={(e) => {
setIsMobileMenuOpen(false); e.stopPropagation();
setTimeout(() => setIsMobileMenuOpen(false), 100);
openModal('login'); openModal('login');
}} }}
onTouchStart={(e) => {
e.stopPropagation();
}}
className="flex items-center className="flex items-center
space-x-2 px-4 py-3 text-white/90 space-x-2 px-4 py-3.5 text-white/95
hover:bg-[#d4af37]/10 hover:text-[#d4af37] hover:bg-[rgba(var(--luxury-gold-rgb),0.15)] hover:text-[var(--luxury-gold)]
rounded-sm transition-all duration-300 rounded-md transition-all duration-300
border-l-2 border-transparent border-l-2 border-transparent
hover:border-[#d4af37] font-light tracking-wide w-full text-left" hover:border-[var(--luxury-gold)] font-light tracking-wider text-sm w-full text-left group relative mx-2 cursor-pointer"
style={{ touchAction: 'manipulation' }}
> >
<LogIn className="w-4 h-4" /> <LogIn className="w-4 h-4" />
<span>Login</span> <span>Login</span>
</button> </button>
<button <button
onClick={() => { onClick={(e) => {
setIsMobileMenuOpen(false); e.stopPropagation();
setTimeout(() => setIsMobileMenuOpen(false), 100);
openModal('register'); openModal('register');
}} }}
onTouchStart={(e) => {
e.stopPropagation();
}}
className="flex items-center className="flex items-center
space-x-2 px-4 py-3 bg-gradient-to-r space-x-2 px-4 py-3.5 bg-gradient-to-r
from-[#d4af37] to-[#c9a227] text-[#0f0f0f] from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-[#0f0f0f]
rounded-sm hover:from-[#f5d76e] rounded-md hover:from-[var(--luxury-gold-light)]
hover:to-[#d4af37] transition-all hover:to-[var(--luxury-gold)] transition-all
duration-300 font-medium tracking-wide duration-300 font-medium tracking-wider text-sm
mt-2 w-full text-left" mt-2 w-full text-left mx-2 cursor-pointer"
style={{ touchAction: 'manipulation' }}
> >
<UserPlus className="w-4 h-4" /> <UserPlus className="w-4 h-4" />
<span>Register</span> <span>Register</span>
@@ -118,21 +146,26 @@ const Header: React.FC<HeaderProps> = ({
) : ( ) : (
<> <>
<div className="px-4 py-2 text-sm <div className="px-4 py-2 text-sm
text-[#d4af37]/70 font-light tracking-wide" text-text-[rgba(var(--luxury-gold-rgb),0.7)] font-light tracking-wide"
> >
Hello, {userInfo?.name} Hello, {userInfo?.name}
</div> </div>
<Link <Link
to="/profile" to="/profile"
onClick={() => onClick={(e) => {
setIsMobileMenuOpen(false) e.stopPropagation();
} setTimeout(() => setIsMobileMenuOpen(false), 100);
}}
onTouchStart={(e) => {
e.stopPropagation();
}}
className="flex items-center className="flex items-center
space-x-2 px-4 py-3 text-white/90 space-x-2 px-4 py-3.5 text-white/95
hover:bg-[#d4af37]/10 hover:text-[#d4af37] hover:bg-[rgba(var(--luxury-gold-rgb),0.15)] hover:text-[var(--luxury-gold)]
rounded-sm transition-all duration-300 rounded-md transition-all duration-300
border-l-2 border-transparent border-l-2 border-transparent
hover:border-[#d4af37] font-light tracking-wide" hover:border-[var(--luxury-gold)] font-light tracking-wider text-sm group relative mx-2"
style={{ touchAction: 'manipulation' }}
> >
<User className="w-4 h-4" /> <User className="w-4 h-4" />
<span>Profile</span> <span>Profile</span>
@@ -141,120 +174,160 @@ const Header: React.FC<HeaderProps> = ({
<> <>
<Link <Link
to="/dashboard" to="/dashboard"
onClick={() => onClick={(e) => {
setIsMobileMenuOpen(false) e.stopPropagation();
} setTimeout(() => setIsMobileMenuOpen(false), 100);
}}
onTouchStart={(e) => {
e.stopPropagation();
}}
className="flex items-center className="flex items-center
space-x-2 px-4 py-3 text-white/90 space-x-2 px-4 py-3 text-white/90
hover:bg-[#d4af37]/10 hover:text-[#d4af37] hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)]
rounded-sm transition-all duration-300 rounded-sm transition-all duration-300
border-l-2 border-transparent border-l-2 border-transparent
hover:border-[#d4af37] font-light tracking-wide" hover:border-[var(--luxury-gold)] font-light tracking-wide"
style={{ touchAction: 'manipulation' }}
> >
<Calendar className="w-4 h-4" /> <Calendar className="w-4 h-4" />
<span>Dashboard</span> <span>Dashboard</span>
</Link> </Link>
<Link <Link
to="/favorites" to="/favorites"
onClick={() => onClick={(e) => {
setIsMobileMenuOpen(false) e.stopPropagation();
} setTimeout(() => setIsMobileMenuOpen(false), 100);
}}
onTouchStart={(e) => {
e.stopPropagation();
}}
className="flex items-center className="flex items-center
space-x-2 px-4 py-3 text-white/90 space-x-2 px-4 py-3 text-white/90
hover:bg-[#d4af37]/10 hover:text-[#d4af37] hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)]
rounded-sm transition-all duration-300 rounded-sm transition-all duration-300
border-l-2 border-transparent border-l-2 border-transparent
hover:border-[#d4af37] font-light tracking-wide" hover:border-[var(--luxury-gold)] font-light tracking-wide"
style={{ touchAction: 'manipulation' }}
> >
<Heart className="w-4 h-4" /> <Heart className="w-4 h-4" />
<span>Favorites</span> <span>Favorites</span>
</Link> </Link>
<Link <Link
to="/bookings" to="/bookings"
onClick={() => onClick={(e) => {
setIsMobileMenuOpen(false) e.stopPropagation();
} setTimeout(() => setIsMobileMenuOpen(false), 100);
}}
onTouchStart={(e) => {
e.stopPropagation();
}}
className="flex items-center className="flex items-center
space-x-2 px-4 py-3 text-white/90 space-x-2 px-4 py-3 text-white/90
hover:bg-[#d4af37]/10 hover:text-[#d4af37] hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)]
rounded-sm transition-all duration-300 rounded-sm transition-all duration-300
border-l-2 border-transparent border-l-2 border-transparent
hover:border-[#d4af37] font-light tracking-wide" hover:border-[var(--luxury-gold)] font-light tracking-wide"
style={{ touchAction: 'manipulation' }}
> >
<Calendar className="w-4 h-4" /> <Calendar className="w-4 h-4" />
<span>My Bookings</span> <span>My Bookings</span>
</Link> </Link>
<Link <Link
to="/loyalty" to="/loyalty"
onClick={() => onClick={(e) => {
setIsMobileMenuOpen(false) e.stopPropagation();
} setTimeout(() => setIsMobileMenuOpen(false), 100);
}}
onTouchStart={(e) => {
e.stopPropagation();
}}
className="flex items-center className="flex items-center
space-x-2 px-4 py-3 text-white/90 space-x-2 px-4 py-3 text-white/90
hover:bg-[#d4af37]/10 hover:text-[#d4af37] hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)]
rounded-sm transition-all duration-300 rounded-sm transition-all duration-300
border-l-2 border-transparent border-l-2 border-transparent
hover:border-[#d4af37] font-light tracking-wide" hover:border-[var(--luxury-gold)] font-light tracking-wide"
style={{ touchAction: 'manipulation' }}
> >
<Star className="w-4 h-4" /> <Star className="w-4 h-4" />
<span>Loyalty Program</span> <span>Loyalty Program</span>
</Link> </Link>
<Link <Link
to="/group-bookings" to="/group-bookings"
onClick={() => onClick={(e) => {
setIsMobileMenuOpen(false) e.stopPropagation();
} setTimeout(() => setIsMobileMenuOpen(false), 100);
}}
onTouchStart={(e) => {
e.stopPropagation();
}}
className="flex items-center className="flex items-center
space-x-2 px-4 py-3 text-white/90 space-x-2 px-4 py-3 text-white/90
hover:bg-[#d4af37]/10 hover:text-[#d4af37] hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)]
rounded-sm transition-all duration-300 rounded-sm transition-all duration-300
border-l-2 border-transparent border-l-2 border-transparent
hover:border-[#d4af37] font-light tracking-wide" hover:border-[var(--luxury-gold)] font-light tracking-wide"
style={{ touchAction: 'manipulation' }}
> >
<Users className="w-4 h-4" /> <Users className="w-4 h-4" />
<span>Group Bookings</span> <span>Group Bookings</span>
</Link> </Link>
<Link <Link
to="/complaints" to="/complaints"
onClick={() => onClick={(e) => {
setIsMobileMenuOpen(false) e.stopPropagation();
} setTimeout(() => setIsMobileMenuOpen(false), 100);
}}
onTouchStart={(e) => {
e.stopPropagation();
}}
className="flex items-center className="flex items-center
space-x-2 px-4 py-3 text-white/90 space-x-2 px-4 py-3 text-white/90
hover:bg-[#d4af37]/10 hover:text-[#d4af37] hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)]
rounded-sm transition-all duration-300 rounded-sm transition-all duration-300
border-l-2 border-transparent border-l-2 border-transparent
hover:border-[#d4af37] font-light tracking-wide" hover:border-[var(--luxury-gold)] font-light tracking-wide"
style={{ touchAction: 'manipulation' }}
> >
<AlertCircle className="w-4 h-4" /> <AlertCircle className="w-4 h-4" />
<span>Complaints</span> <span>Complaints</span>
</Link> </Link>
<Link <Link
to="/guest-requests" to="/guest-requests"
onClick={() => onClick={(e) => {
setIsMobileMenuOpen(false) e.stopPropagation();
} setTimeout(() => setIsMobileMenuOpen(false), 100);
}}
onTouchStart={(e) => {
e.stopPropagation();
}}
className="flex items-center className="flex items-center
space-x-2 px-4 py-3 text-white/90 space-x-2 px-4 py-3 text-white/90
hover:bg-[#d4af37]/10 hover:text-[#d4af37] hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)]
rounded-sm transition-all duration-300 rounded-sm transition-all duration-300
border-l-2 border-transparent border-l-2 border-transparent
hover:border-[#d4af37] font-light tracking-wide" hover:border-[var(--luxury-gold)] font-light tracking-wide"
style={{ touchAction: 'manipulation' }}
> >
<Bell className="w-4 h-4" /> <Bell className="w-4 h-4" />
<span>Guest Requests</span> <span>Guest Requests</span>
</Link> </Link>
<Link <Link
to="/gdpr" to="/gdpr"
onClick={() => onClick={(e) => {
setIsMobileMenuOpen(false) e.stopPropagation();
} setTimeout(() => setIsMobileMenuOpen(false), 100);
}}
onTouchStart={(e) => {
e.stopPropagation();
}}
className="flex items-center className="flex items-center
space-x-2 px-4 py-3 text-white/90 space-x-2 px-4 py-3 text-white/90
hover:bg-[#d4af37]/10 hover:text-[#d4af37] hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)]
rounded-sm transition-all duration-300 rounded-sm transition-all duration-300
border-l-2 border-transparent border-l-2 border-transparent
hover:border-[#d4af37] font-light tracking-wide" hover:border-[var(--luxury-gold)] font-light tracking-wide"
style={{ touchAction: 'manipulation' }}
> >
<Shield className="w-4 h-4" /> <Shield className="w-4 h-4" />
<span>Privacy & Data</span> <span>Privacy & Data</span>
@@ -264,15 +337,20 @@ const Header: React.FC<HeaderProps> = ({
{userInfo?.role === 'admin' && ( {userInfo?.role === 'admin' && (
<Link <Link
to="/admin" to="/admin"
onClick={() => onClick={(e) => {
setIsMobileMenuOpen(false) e.stopPropagation();
} setTimeout(() => setIsMobileMenuOpen(false), 100);
}}
onTouchStart={(e) => {
e.stopPropagation();
}}
className="flex items-center className="flex items-center
space-x-2 px-4 py-3 text-white/90 space-x-2 px-4 py-3 text-white/90
hover:bg-[#d4af37]/10 hover:text-[#d4af37] hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)]
rounded-sm transition-all duration-300 rounded-sm transition-all duration-300
border-l-2 border-transparent border-l-2 border-transparent
hover:border-[#d4af37] font-light tracking-wide" hover:border-[var(--luxury-gold)] font-light tracking-wide"
style={{ touchAction: 'manipulation' }}
> >
<User className="w-4 h-4" /> <User className="w-4 h-4" />
<span>Admin</span> <span>Admin</span>
@@ -281,15 +359,20 @@ const Header: React.FC<HeaderProps> = ({
{userInfo?.role === 'staff' && ( {userInfo?.role === 'staff' && (
<Link <Link
to="/staff" to="/staff"
onClick={() => onClick={(e) => {
setIsMobileMenuOpen(false) e.stopPropagation();
} setTimeout(() => setIsMobileMenuOpen(false), 100);
}}
onTouchStart={(e) => {
e.stopPropagation();
}}
className="flex items-center className="flex items-center
space-x-2 px-4 py-3 text-white/90 space-x-2 px-4 py-3 text-white/90
hover:bg-[#d4af37]/10 hover:text-[#d4af37] hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)]
rounded-sm transition-all duration-300 rounded-sm transition-all duration-300
border-l-2 border-transparent border-l-2 border-transparent
hover:border-[#d4af37] font-light tracking-wide" hover:border-[var(--luxury-gold)] font-light tracking-wide"
style={{ touchAction: 'manipulation' }}
> >
<User className="w-4 h-4" /> <User className="w-4 h-4" />
<span>Staff Dashboard</span> <span>Staff Dashboard</span>
@@ -298,15 +381,20 @@ const Header: React.FC<HeaderProps> = ({
{userInfo?.role === 'accountant' && ( {userInfo?.role === 'accountant' && (
<Link <Link
to="/accountant" to="/accountant"
onClick={() => onClick={(e) => {
setIsMobileMenuOpen(false) e.stopPropagation();
} setTimeout(() => setIsMobileMenuOpen(false), 100);
}}
onTouchStart={(e) => {
e.stopPropagation();
}}
className="flex items-center className="flex items-center
space-x-2 px-4 py-3 text-white/90 space-x-2 px-4 py-3 text-white/90
hover:bg-[#d4af37]/10 hover:text-[#d4af37] hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)]
rounded-sm transition-all duration-300 rounded-sm transition-all duration-300
border-l-2 border-transparent border-l-2 border-transparent
hover:border-[#d4af37] font-light tracking-wide" hover:border-[var(--luxury-gold)] font-light tracking-wide"
style={{ touchAction: 'manipulation' }}
> >
<User className="w-4 h-4" /> <User className="w-4 h-4" />
<span>Accountant Dashboard</span> <span>Accountant Dashboard</span>
@@ -315,30 +403,38 @@ const Header: React.FC<HeaderProps> = ({
{userInfo?.role === 'housekeeping' && ( {userInfo?.role === 'housekeeping' && (
<Link <Link
to="/housekeeping" to="/housekeeping"
onClick={() => onClick={(e) => {
setIsMobileMenuOpen(false) e.stopPropagation();
} setTimeout(() => setIsMobileMenuOpen(false), 100);
}}
onTouchStart={(e) => {
e.stopPropagation();
}}
className="flex items-center className="flex items-center
space-x-2 px-4 py-3 text-white/90 space-x-2 px-4 py-3 text-white/90
hover:bg-[#d4af37]/10 hover:text-[#d4af37] hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)]
rounded-sm transition-all duration-300 rounded-sm transition-all duration-300
border-l-2 border-transparent border-l-2 border-transparent
hover:border-[#d4af37] font-light tracking-wide" hover:border-[var(--luxury-gold)] font-light tracking-wide"
style={{ touchAction: 'manipulation' }}
> >
<User className="w-4 h-4" /> <User className="w-4 h-4" />
<span>Housekeeping Dashboard</span> <span>Housekeeping Dashboard</span>
</Link> </Link>
)} )}
<div className="border-t border-[#d4af37]/20 my-2"></div> <div className="border-t border-[rgba(var(--luxury-gold-rgb),0.2)] my-2"></div>
<button <button
onClick={handleLogout} onClick={(e) => {
e.stopPropagation();
handleLogout();
}}
className="w-full flex items-center className="w-full flex items-center
space-x-2 px-4 py-3 text-red-400/90 space-x-2 px-4 py-3 text-red-400/90
hover:bg-red-500/10 hover:text-red-400 hover:bg-red-500/10 hover:text-red-400
rounded-sm transition-all duration-300 rounded-sm transition-all duration-300
border-l-2 border-transparent border-l-2 border-transparent
hover:border-red-500/50 text-left hover:border-red-500/50 text-left
font-light tracking-wide" font-light tracking-wide cursor-pointer"
> >
<LogOut className="w-4 h-4" /> <LogOut className="w-4 h-4" />
<span>Logout</span> <span>Logout</span>
@@ -349,18 +445,20 @@ const Header: React.FC<HeaderProps> = ({
); );
return ( return (
<header className="bg-gradient-to-b from-[#1a1a1a] to-[#0f0f0f] sticky top-0 z-50 border-b border-[#d4af37]/20 shadow-2xl"> <header
<div className="hidden lg:block bg-[#0a0a0a]/50 border-b border-[#d4af37]/10"> className="bg-gradient-to-b from-[#0f0f0f] via-[#1a1a1a] to-[#0f0f0f] sticky top-0 z-50 border-b border-[rgba(var(--luxury-gold-rgb),0.15)] shadow-[0_8px_32px_rgba(0,0,0,0.4)] backdrop-blur-sm"
>
<div className="hidden lg:block bg-[#0a0a0a]/50 border-b border-[rgba(var(--luxury-gold-rgb),0.1)]">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-2"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-2">
<div className="flex items-center justify-end space-x-6 text-sm"> <div className="flex items-center justify-end space-x-6 text-sm">
{displayPhone && ( {displayPhone && (
<a href={`tel:${displayPhone.replace(/\s+/g, '').replace(/[()]/g, '')}`} className="flex items-center space-x-2 text-[#d4af37] hover:text-[#f5d76e] transition-colors duration-300 font-light"> <a href={`tel:${displayPhone.replace(/\s+/g, '').replace(/[()]/g, '')}`} className="flex items-center space-x-2 text-[var(--luxury-gold)] hover:text-[var(--luxury-gold-light)] transition-colors duration-300 font-light">
<Phone className="w-3.5 h-3.5" /> <Phone className="w-3.5 h-3.5" />
<span className="tracking-wide">{displayPhone}</span> <span className="tracking-wide">{displayPhone}</span>
</a> </a>
)} )}
{displayEmail && ( {displayEmail && (
<a href={`mailto:${displayEmail}`} className="flex items-center space-x-2 text-[#d4af37] hover:text-[#f5d76e] transition-colors duration-300 font-light"> <a href={`mailto:${displayEmail}`} className="flex items-center space-x-2 text-[var(--luxury-gold)] hover:text-[var(--luxury-gold-light)] transition-colors duration-300 font-light">
<Mail className="w-3.5 h-3.5" /> <Mail className="w-3.5 h-3.5" />
<span className="tracking-wide">{displayEmail}</span> <span className="tracking-wide">{displayEmail}</span>
</a> </a>
@@ -369,96 +467,120 @@ const Header: React.FC<HeaderProps> = ({
</div> </div>
</div> </div>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4"> <div className="w-full py-3 sm:py-4 md:py-5">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between relative w-full">
<Link {/* Logo - Left - Always visible on all screens, flush with left edge */}
to="/" <div className="flex items-center flex-shrink-0 pl-2 sm:pl-4 md:pl-6 lg:pl-8 max-w-[50%] sm:max-w-none">
className="flex items-center space-x-3 <Link
group transition-all duration-300 hover:opacity-90" to="/"
> className="flex items-center space-x-1.5 sm:space-x-2 md:space-x-3
{logoUrl ? ( group transition-all duration-300 hover:opacity-90 z-10"
<div className="relative"> >
<img {logoUrl ? (
src={logoUrl} <div className="relative flex-shrink-0">
alt={settings.company_name} <div className="absolute inset-0 bg-gradient-to-br from-[var(--luxury-gold)]/20 to-transparent rounded-lg blur-xl opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
className="h-10 w-auto object-contain drop-shadow-lg" <img
/> src={logoUrl}
alt={settings.company_name}
className="h-8 w-8 sm:h-10 sm:w-10 md:h-12 md:w-auto object-contain drop-shadow-[0_4px_12px_rgba(var(--luxury-gold-rgb),0.3)] relative z-10 transition-transform duration-300 group-hover:scale-105"
/>
</div>
) : (
<div className="relative flex-shrink-0">
<div className="absolute inset-0 bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] rounded-full blur-xl opacity-30 group-hover:opacity-50 transition-opacity duration-500"></div>
<Hotel className="relative w-8 h-8 sm:w-10 sm:h-10 md:w-12 md:h-12 text-[var(--luxury-gold)] drop-shadow-[0_4px_12px_rgba(var(--luxury-gold-rgb),0.4)] transition-transform duration-300 group-hover:scale-110" />
</div>
)}
<div className="flex flex-col min-w-0">
<span className="text-sm sm:text-base md:text-lg lg:text-xl xl:text-2xl font-display font-semibold text-white tracking-tight leading-tight bg-gradient-to-r from-white to-white/90 bg-clip-text truncate">
{settings.company_name}
</span>
<span className="text-[8px] sm:text-[9px] md:text-[10px] text-[var(--luxury-gold)] tracking-[0.25em] uppercase font-light hidden sm:block">
{settings.company_tagline || 'Excellence Redefined'}
</span>
</div> </div>
) : ( </Link>
<div className="relative"> </div>
<div className="absolute inset-0 bg-gradient-to-br from-[#d4af37] to-[#f5d76e] rounded-full blur-md opacity-30 group-hover:opacity-50 transition-opacity duration-300"></div>
<Hotel className="relative w-10 h-10 text-[#d4af37] drop-shadow-lg" />
</div>
)}
<div className="flex flex-col">
<span className="text-2xl font-display font-semibold text-white tracking-tight leading-tight">
{settings.company_name}
</span>
<span className="text-[10px] text-[#d4af37] tracking-[0.2em] uppercase font-light">
{settings.company_tagline || 'Excellence Redefined'}
</span>
</div>
</Link>
<Navbar {/* Navigation Links - Center */}
isMobileMenuOpen={isMobileMenuOpen} <div className="absolute left-1/2 transform -translate-x-1/2 hidden md:block z-20">
onMobileMenuToggle={toggleMobileMenu} <Navbar
onLinkClick={() => setIsMobileMenuOpen(false)} isMobileMenuOpen={isMobileMenuOpen}
mobileMenuContent={mobileMenuContent} onMobileMenuToggle={toggleMobileMenu}
/> onLinkClick={() => setIsMobileMenuOpen(false)}
mobileMenuContent={mobileMenuContent}
/>
</div>
{/* Mobile Menu Button - Right (for smaller screens) */}
<div className="flex items-center justify-end md:hidden z-20 pr-2 sm:pr-4">
<Navbar
isMobileMenuOpen={isMobileMenuOpen}
onMobileMenuToggle={toggleMobileMenu}
onLinkClick={() => setIsMobileMenuOpen(false)}
mobileMenuContent={mobileMenuContent}
/>
</div>
{/* Login/Register - Right */}
<div className="hidden md:flex items-center <div className="hidden md:flex items-center
space-x-3" justify-end space-x-4 z-10 flex-shrink-0 pr-4 sm:pr-6 lg:pr-8"
> >
{!isAuthenticated ? ( {!isAuthenticated ? (
<> <>
<button <button
onClick={() => openModal('login')} onClick={() => openModal('login')}
className="flex items-center space-x-2 className="flex items-center space-x-2
px-5 py-2 text-white/90 px-6 py-2.5 text-white/95
hover:text-[#d4af37] transition-all duration-300 hover:text-[var(--luxury-gold)] transition-all duration-300
font-light tracking-wide relative group" font-light tracking-wider relative group overflow-hidden"
> >
<LogIn className="w-4 h-4 relative z-10" /> <span className="absolute inset-0 border border-[rgba(var(--luxury-gold-rgb),0.2)] rounded-md opacity-0 group-hover:opacity-100 transition-all duration-300 group-hover:border-[rgba(var(--luxury-gold-rgb),0.5)]"></span>
<span className="relative z-10">Login</span> <span className="absolute inset-0 bg-gradient-to-r from-[rgba(var(--luxury-gold-rgb),0.05)] to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></span>
<span className="absolute inset-0 border border-[#d4af37]/30 rounded-sm opacity-0 group-hover:opacity-100 transition-opacity duration-300"></span> <LogIn className="w-4 h-4 relative z-10 transition-transform duration-300 group-hover:scale-110" />
<span className="relative z-10 text-sm">Login</span>
</button> </button>
<button <button
onClick={() => openModal('register')} onClick={() => openModal('register')}
className="flex items-center space-x-2 className="flex items-center space-x-2
px-6 py-2.5 bg-gradient-to-r from-[#d4af37] to-[#c9a227] px-7 py-2.5 bg-gradient-to-r from-[var(--luxury-gold)] via-[var(--luxury-gold-light)] to-[var(--luxury-gold)]
text-[#0f0f0f] rounded-sm hover:from-[#f5d76e] text-[#0f0f0f] rounded-md hover:from-[var(--luxury-gold-light)]
hover:to-[#d4af37] transition-all duration-300 hover:via-[var(--luxury-gold)] hover:to-[var(--luxury-gold-dark)] transition-all duration-500
font-medium tracking-wide shadow-lg shadow-[#d4af37]/20 font-medium tracking-wider shadow-[0_4px_20px_rgba(var(--luxury-gold-rgb),0.3)]
hover:shadow-[#d4af37]/30 relative overflow-hidden group" hover:shadow-[0_6px_30px_rgba(var(--luxury-gold-rgb),0.5)] relative overflow-hidden group
transform hover:scale-105 transition-transform duration-300"
> >
<span className="absolute inset-0 bg-gradient-to-r from-white/0 via-white/20 to-white/0 translate-x-[-100%] group-hover:translate-x-[100%] transition-transform duration-700"></span> <span className="absolute inset-0 bg-gradient-to-r from-white/0 via-white/30 to-white/0 translate-x-[-100%] group-hover:translate-x-[100%] transition-transform duration-1000"></span>
<UserPlus className="w-4 h-4 relative z-10" /> <UserPlus className="w-4 h-4 relative z-10 transition-transform duration-300 group-hover:rotate-12" />
<span className="relative z-10">Register</span> <span className="relative z-10 text-sm">Register</span>
</button> </button>
</> </>
) : ( ) : (
<div className="flex items-center gap-3"> <div className="flex items-center gap-3 justify-end w-full">
{isAuthenticated && <InAppNotificationBell />} {isAuthenticated && <InAppNotificationBell />}
<div className="relative" ref={userMenuRef}> <div className="relative" ref={userMenuRef}>
<button <button
onClick={toggleUserMenu} onClick={toggleUserMenu}
className="flex items-center space-x-3 className="flex items-center space-x-3
px-3 py-2 rounded-sm hover:bg-white/10 px-4 py-2.5 rounded-md hover:bg-[rgba(var(--luxury-gold-rgb),0.1)]
transition-all duration-300 border border-transparent transition-all duration-300 border border-transparent
hover:border-[#d4af37]/30" hover:border-[rgba(var(--luxury-gold-rgb),0.3)] group"
> >
{userInfo?.avatar ? ( {userInfo?.avatar ? (
<img <img
src={normalizeImageUrl(userInfo.avatar)} src={normalizeImageUrl(userInfo.avatar)}
alt={userInfo.name} alt={userInfo.name}
className="w-9 h-9 rounded-full className="w-10 h-10 rounded-full
object-cover ring-2 ring-[#d4af37]/50" object-cover ring-2 ring-[var(--luxury-gold)]/50
transition-all duration-300 group-hover:ring-[var(--luxury-gold)]/80
group-hover:scale-105 shadow-lg"
/> />
) : ( ) : (
<div className="w-9 h-9 bg-gradient-to-br from-[#d4af37] to-[#c9a227] <div className="w-10 h-10 bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)]
rounded-full flex items-center rounded-full flex items-center
justify-center ring-2 ring-[#d4af37]/50 shadow-lg" justify-center ring-2 ring-[var(--luxury-gold)]/50 shadow-lg
transition-all duration-300 group-hover:ring-[var(--luxury-gold)]/80
group-hover:scale-105"
> >
<span className="text-[#0f0f0f] <span className="text-[#0f0f0f]
font-semibold text-sm" font-semibold text-sm"
@@ -468,28 +590,29 @@ const Header: React.FC<HeaderProps> = ({
</span> </span>
</div> </div>
)} )}
<span className="font-light text-white/90 tracking-wide"> <span className="font-light text-white/95 tracking-wider text-sm">
{userInfo?.name} {userInfo?.name}
</span> </span>
</button> </button>
{isUserMenuOpen && ( {isUserMenuOpen && (
<div className="absolute right-0 mt-2 <div className="absolute right-0 mt-3
w-52 bg-gradient-to-b from-[#1a1a1a] to-[#0f0f0f] w-56 bg-gradient-to-b from-[#0f0f0f] via-[#1a1a1a] to-[#0f0f0f]
rounded-sm shadow-2xl py-2 border border-[#d4af37]/20 rounded-lg shadow-[0_8px_32px_rgba(0,0,0,0.6)] py-3 border border-[rgba(var(--luxury-gold-rgb),0.2)]
z-50 backdrop-blur-xl animate-fade-in" z-[9999] backdrop-blur-xl animate-fade-in"
> >
<Link <Link
to="/profile" to="/profile"
onClick={() => setIsUserMenuOpen(false)} onClick={() => setIsUserMenuOpen(false)}
className="flex items-center space-x-3 className="flex items-center space-x-3
px-4 py-2.5 text-white/90 px-5 py-3 text-white/95
hover:bg-[#d4af37]/10 hover:text-[#d4af37] hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)]
transition-all duration-300 border-l-2 border-transparent transition-all duration-300 border-l-2 border-transparent
hover:border-[#d4af37]" hover:border-[var(--luxury-gold)] rounded-md group relative"
> >
<User className="w-4 h-4" /> <span className="absolute left-0 top-0 bottom-0 w-0 bg-gradient-to-r from-[rgba(var(--luxury-gold-rgb),0.1)] to-transparent group-hover:w-full transition-all duration-300 rounded-md"></span>
<span className="font-light tracking-wide">Profile</span> <User className="w-4 h-4 relative z-10 transition-transform duration-300 group-hover:scale-110" />
<span className="font-light tracking-wider text-sm relative z-10">Profile</span>
</Link> </Link>
{userInfo?.role !== 'admin' && userInfo?.role !== 'staff' && userInfo?.role !== 'accountant' && userInfo?.role !== 'housekeeping' && ( {userInfo?.role !== 'admin' && userInfo?.role !== 'staff' && userInfo?.role !== 'accountant' && userInfo?.role !== 'housekeeping' && (
<> <>
@@ -497,97 +620,105 @@ const Header: React.FC<HeaderProps> = ({
to="/dashboard" to="/dashboard"
onClick={() => setIsUserMenuOpen(false)} onClick={() => setIsUserMenuOpen(false)}
className="flex items-center space-x-3 className="flex items-center space-x-3
px-4 py-2.5 text-white/90 px-5 py-3 text-white/95
hover:bg-[#d4af37]/10 hover:text-[#d4af37] hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)]
transition-all duration-300 border-l-2 border-transparent transition-all duration-300 border-l-2 border-transparent
hover:border-[#d4af37]" hover:border-[var(--luxury-gold)] rounded-md group relative"
> >
<Calendar className="w-4 h-4" /> <span className="absolute left-0 top-0 bottom-0 w-0 bg-gradient-to-r from-[rgba(var(--luxury-gold-rgb),0.1)] to-transparent group-hover:w-full transition-all duration-300 rounded-md"></span>
<span className="font-light tracking-wide">Dashboard</span> <Calendar className="w-4 h-4 relative z-10 transition-transform duration-300 group-hover:scale-110" />
<span className="font-light tracking-wider text-sm relative z-10">Dashboard</span>
</Link> </Link>
<Link <Link
to="/favorites" to="/favorites"
onClick={() => setIsUserMenuOpen(false)} onClick={() => setIsUserMenuOpen(false)}
className="flex items-center space-x-3 className="flex items-center space-x-3
px-4 py-2.5 text-white/90 px-5 py-3 text-white/95
hover:bg-[#d4af37]/10 hover:text-[#d4af37] hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)]
transition-all duration-300 border-l-2 border-transparent transition-all duration-300 border-l-2 border-transparent
hover:border-[#d4af37]" hover:border-[var(--luxury-gold)] rounded-md group relative"
> >
<Heart className="w-4 h-4" /> <span className="absolute left-0 top-0 bottom-0 w-0 bg-gradient-to-r from-[rgba(var(--luxury-gold-rgb),0.1)] to-transparent group-hover:w-full transition-all duration-300 rounded-md"></span>
<span className="font-light tracking-wide">Favorites</span> <Heart className="w-4 h-4 relative z-10 transition-transform duration-300 group-hover:scale-110" />
<span className="font-light tracking-wider text-sm relative z-10">Favorites</span>
</Link> </Link>
<Link <Link
to="/bookings" to="/bookings"
onClick={() => setIsUserMenuOpen(false)} onClick={() => setIsUserMenuOpen(false)}
className="flex items-center space-x-3 className="flex items-center space-x-3
px-4 py-2.5 text-white/90 px-5 py-3 text-white/95
hover:bg-[#d4af37]/10 hover:text-[#d4af37] hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)]
transition-all duration-300 border-l-2 border-transparent transition-all duration-300 border-l-2 border-transparent
hover:border-[#d4af37]" hover:border-[var(--luxury-gold)] rounded-md group relative"
> >
<Calendar className="w-4 h-4" /> <span className="absolute left-0 top-0 bottom-0 w-0 bg-gradient-to-r from-[rgba(var(--luxury-gold-rgb),0.1)] to-transparent group-hover:w-full transition-all duration-300 rounded-md"></span>
<span className="font-light tracking-wide">My Bookings</span> <Calendar className="w-4 h-4 relative z-10 transition-transform duration-300 group-hover:scale-110" />
<span className="font-light tracking-wider text-sm relative z-10">My Bookings</span>
</Link> </Link>
<Link <Link
to="/loyalty" to="/loyalty"
onClick={() => setIsUserMenuOpen(false)} onClick={() => setIsUserMenuOpen(false)}
className="flex items-center space-x-3 className="flex items-center space-x-3
px-4 py-2.5 text-white/90 px-5 py-3 text-white/95
hover:bg-[#d4af37]/10 hover:text-[#d4af37] hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)]
transition-all duration-300 border-l-2 border-transparent transition-all duration-300 border-l-2 border-transparent
hover:border-[#d4af37]" hover:border-[var(--luxury-gold)] rounded-md group relative"
> >
<Star className="w-4 h-4" /> <span className="absolute left-0 top-0 bottom-0 w-0 bg-gradient-to-r from-[rgba(var(--luxury-gold-rgb),0.1)] to-transparent group-hover:w-full transition-all duration-300 rounded-md"></span>
<span className="font-light tracking-wide">Loyalty Program</span> <Star className="w-4 h-4 relative z-10 transition-transform duration-300 group-hover:scale-110" />
<span className="font-light tracking-wider text-sm relative z-10">Loyalty Program</span>
</Link> </Link>
<Link <Link
to="/group-bookings" to="/group-bookings"
onClick={() => setIsUserMenuOpen(false)} onClick={() => setIsUserMenuOpen(false)}
className="flex items-center space-x-3 className="flex items-center space-x-3
px-4 py-2.5 text-white/90 px-5 py-3 text-white/95
hover:bg-[#d4af37]/10 hover:text-[#d4af37] hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)]
transition-all duration-300 border-l-2 border-transparent transition-all duration-300 border-l-2 border-transparent
hover:border-[#d4af37]" hover:border-[var(--luxury-gold)] rounded-md group relative"
> >
<Users className="w-4 h-4" /> <span className="absolute left-0 top-0 bottom-0 w-0 bg-gradient-to-r from-[rgba(var(--luxury-gold-rgb),0.1)] to-transparent group-hover:w-full transition-all duration-300 rounded-md"></span>
<span className="font-light tracking-wide">Group Bookings</span> <Users className="w-4 h-4 relative z-10 transition-transform duration-300 group-hover:scale-110" />
<span className="font-light tracking-wider text-sm relative z-10">Group Bookings</span>
</Link> </Link>
<Link <Link
to="/complaints" to="/complaints"
onClick={() => setIsUserMenuOpen(false)} onClick={() => setIsUserMenuOpen(false)}
className="flex items-center space-x-3 className="flex items-center space-x-3
px-4 py-2.5 text-white/90 px-5 py-3 text-white/95
hover:bg-[#d4af37]/10 hover:text-[#d4af37] hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)]
transition-all duration-300 border-l-2 border-transparent transition-all duration-300 border-l-2 border-transparent
hover:border-[#d4af37]" hover:border-[var(--luxury-gold)] rounded-md group relative"
> >
<AlertCircle className="w-4 h-4" /> <span className="absolute left-0 top-0 bottom-0 w-0 bg-gradient-to-r from-[rgba(var(--luxury-gold-rgb),0.1)] to-transparent group-hover:w-full transition-all duration-300 rounded-md"></span>
<span className="font-light tracking-wide">Complaints</span> <AlertCircle className="w-4 h-4 relative z-10 transition-transform duration-300 group-hover:scale-110" />
<span className="font-light tracking-wider text-sm relative z-10">Complaints</span>
</Link> </Link>
<Link <Link
to="/guest-requests" to="/guest-requests"
onClick={() => setIsUserMenuOpen(false)} onClick={() => setIsUserMenuOpen(false)}
className="flex items-center space-x-3 className="flex items-center space-x-3
px-4 py-2.5 text-white/90 px-5 py-3 text-white/95
hover:bg-[#d4af37]/10 hover:text-[#d4af37] hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)]
transition-all duration-300 border-l-2 border-transparent transition-all duration-300 border-l-2 border-transparent
hover:border-[#d4af37]" hover:border-[var(--luxury-gold)] rounded-md group relative"
> >
<Bell className="w-4 h-4" /> <span className="absolute left-0 top-0 bottom-0 w-0 bg-gradient-to-r from-[rgba(var(--luxury-gold-rgb),0.1)] to-transparent group-hover:w-full transition-all duration-300 rounded-md"></span>
<span className="font-light tracking-wide">Guest Requests</span> <Bell className="w-4 h-4 relative z-10 transition-transform duration-300 group-hover:scale-110" />
<span className="font-light tracking-wider text-sm relative z-10">Guest Requests</span>
</Link> </Link>
<Link <Link
to="/gdpr" to="/gdpr"
onClick={() => setIsUserMenuOpen(false)} onClick={() => setIsUserMenuOpen(false)}
className="flex items-center space-x-3 className="flex items-center space-x-3
px-4 py-2.5 text-white/90 px-5 py-3 text-white/95
hover:bg-[#d4af37]/10 hover:text-[#d4af37] hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)]
transition-all duration-300 border-l-2 border-transparent transition-all duration-300 border-l-2 border-transparent
hover:border-[#d4af37]" hover:border-[var(--luxury-gold)] rounded-md group relative"
> >
<Shield className="w-4 h-4" /> <span className="absolute left-0 top-0 bottom-0 w-0 bg-gradient-to-r from-[rgba(var(--luxury-gold-rgb),0.1)] to-transparent group-hover:w-full transition-all duration-300 rounded-md"></span>
<span className="font-light tracking-wide">Privacy & Data</span> <Shield className="w-4 h-4 relative z-10 transition-transform duration-300 group-hover:scale-110" />
<span className="font-light tracking-wider text-sm relative z-10">Privacy & Data</span>
</Link> </Link>
</> </>
)} )}
@@ -598,13 +729,14 @@ const Header: React.FC<HeaderProps> = ({
setIsUserMenuOpen(false) setIsUserMenuOpen(false)
} }
className="flex items-center className="flex items-center
space-x-3 px-4 py-2.5 text-white/90 space-x-3 px-5 py-3 text-white/95
hover:bg-[#d4af37]/10 hover:text-[#d4af37] hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)]
transition-all duration-300 border-l-2 border-transparent transition-all duration-300 border-l-2 border-transparent
hover:border-[#d4af37]" hover:border-[var(--luxury-gold)] rounded-md group relative"
> >
<User className="w-4 h-4" /> <span className="absolute left-0 top-0 bottom-0 w-0 bg-gradient-to-r from-[rgba(var(--luxury-gold-rgb),0.1)] to-transparent group-hover:w-full transition-all duration-300 rounded-md"></span>
<span className="font-light tracking-wide">Admin</span> <User className="w-4 h-4 relative z-10 transition-transform duration-300 group-hover:scale-110" />
<span className="font-light tracking-wider text-sm relative z-10">Admin</span>
</Link> </Link>
)} )}
{userInfo?.role === 'staff' && ( {userInfo?.role === 'staff' && (
@@ -614,13 +746,14 @@ const Header: React.FC<HeaderProps> = ({
setIsUserMenuOpen(false) setIsUserMenuOpen(false)
} }
className="flex items-center className="flex items-center
space-x-3 px-4 py-2.5 text-white/90 space-x-3 px-5 py-3 text-white/95
hover:bg-[#d4af37]/10 hover:text-[#d4af37] hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)]
transition-all duration-300 border-l-2 border-transparent transition-all duration-300 border-l-2 border-transparent
hover:border-[#d4af37]" hover:border-[var(--luxury-gold)] rounded-md group relative"
> >
<User className="w-4 h-4" /> <span className="absolute left-0 top-0 bottom-0 w-0 bg-gradient-to-r from-[rgba(var(--luxury-gold-rgb),0.1)] to-transparent group-hover:w-full transition-all duration-300 rounded-md"></span>
<span className="font-light tracking-wide">Staff Dashboard</span> <User className="w-4 h-4 relative z-10 transition-transform duration-300 group-hover:scale-110" />
<span className="font-light tracking-wider text-sm relative z-10">Staff Dashboard</span>
</Link> </Link>
)} )}
{userInfo?.role === 'accountant' && ( {userInfo?.role === 'accountant' && (
@@ -630,13 +763,14 @@ const Header: React.FC<HeaderProps> = ({
setIsUserMenuOpen(false) setIsUserMenuOpen(false)
} }
className="flex items-center className="flex items-center
space-x-3 px-4 py-2.5 text-white/90 space-x-3 px-5 py-3 text-white/95
hover:bg-[#d4af37]/10 hover:text-[#d4af37] hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)]
transition-all duration-300 border-l-2 border-transparent transition-all duration-300 border-l-2 border-transparent
hover:border-[#d4af37]" hover:border-[var(--luxury-gold)] rounded-md group relative"
> >
<User className="w-4 h-4" /> <span className="absolute left-0 top-0 bottom-0 w-0 bg-gradient-to-r from-[rgba(var(--luxury-gold-rgb),0.1)] to-transparent group-hover:w-full transition-all duration-300 rounded-md"></span>
<span className="font-light tracking-wide">Accountant Dashboard</span> <User className="w-4 h-4 relative z-10 transition-transform duration-300 group-hover:scale-110" />
<span className="font-light tracking-wider text-sm relative z-10">Accountant Dashboard</span>
</Link> </Link>
)} )}
{userInfo?.role === 'housekeeping' && ( {userInfo?.role === 'housekeeping' && (
@@ -646,26 +780,28 @@ const Header: React.FC<HeaderProps> = ({
setIsUserMenuOpen(false) setIsUserMenuOpen(false)
} }
className="flex items-center className="flex items-center
space-x-3 px-4 py-2.5 text-white/90 space-x-3 px-5 py-3 text-white/95
hover:bg-[#d4af37]/10 hover:text-[#d4af37] hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)]
transition-all duration-300 border-l-2 border-transparent transition-all duration-300 border-l-2 border-transparent
hover:border-[#d4af37]" hover:border-[var(--luxury-gold)] rounded-md group relative"
> >
<User className="w-4 h-4" /> <span className="absolute left-0 top-0 bottom-0 w-0 bg-gradient-to-r from-[rgba(var(--luxury-gold-rgb),0.1)] to-transparent group-hover:w-full transition-all duration-300 rounded-md"></span>
<span className="font-light tracking-wide">Housekeeping Dashboard</span> <User className="w-4 h-4 relative z-10 transition-transform duration-300 group-hover:scale-110" />
<span className="font-light tracking-wider text-sm relative z-10">Housekeeping Dashboard</span>
</Link> </Link>
)} )}
<div className="border-t border-[#d4af37]/20 my-1"></div> <div className="border-t border-[rgba(var(--luxury-gold-rgb),0.2)] my-2"></div>
<button <button
onClick={handleLogout} onClick={handleLogout}
className="w-full flex items-center className="w-full flex items-center
space-x-3 px-4 py-2.5 text-red-400/90 space-x-3 px-5 py-3 text-red-400/95
hover:bg-red-500/10 hover:text-red-400 hover:bg-red-500/10 hover:text-red-400
transition-all duration-300 border-l-2 border-transparent transition-all duration-300 border-l-2 border-transparent
hover:border-red-500/50 text-left" hover:border-red-500/50 text-left rounded-md group relative"
> >
<LogOut className="w-4 h-4" /> <span className="absolute left-0 top-0 bottom-0 w-0 bg-gradient-to-r from-red-500/10 to-transparent group-hover:w-full transition-all duration-300 rounded-md"></span>
<span className="font-light tracking-wide">Logout</span> <LogOut className="w-4 h-4 relative z-10 transition-transform duration-300 group-hover:scale-110" />
<span className="font-light tracking-wider text-sm relative z-10">Logout</span>
</button> </button>
</div> </div>
)} )}

View File

@@ -1,7 +1,7 @@
import React, { useRef } from 'react'; import React, { useRef } from 'react';
import { createPortal } from 'react-dom';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { Menu, X } from 'lucide-react'; import { Menu, X } from 'lucide-react';
import { useClickOutside } from '../hooks/useClickOutside';
interface NavbarProps { interface NavbarProps {
isMobileMenuOpen: boolean; isMobileMenuOpen: boolean;
@@ -28,12 +28,50 @@ const Navbar: React.FC<NavbarProps> = ({
mobileMenuContent mobileMenuContent
}) => { }) => {
const mobileMenuContainerRef = useRef<HTMLDivElement>(null); const mobileMenuContainerRef = useRef<HTMLDivElement>(null);
const mobileMenuDropdownRef = useRef<HTMLDivElement>(null);
useClickOutside(mobileMenuContainerRef, () => { // Handle click outside for the portal-rendered dropdown
if (isMobileMenuOpen) { // Note: We don't use useClickOutside here because the dropdown is rendered via portal
React.useEffect(() => {
if (!isMobileMenuOpen) return;
const handleClickOutside = (event: MouseEvent | TouchEvent) => {
const target = event.target as Node;
const targetElement = target as Element;
// Check if click is on a link - if so, don't close (let navigation happen)
const linkElement = targetElement.closest('a');
if (linkElement && mobileMenuDropdownRef.current?.contains(linkElement)) {
return; // Let the link handle navigation
}
// Check if click is inside the dropdown menu
if (mobileMenuDropdownRef.current?.contains(target)) {
return; // Don't close if clicking inside menu
}
// Check if click is on the menu button
if (mobileMenuContainerRef.current?.contains(target)) {
return; // Don't close if clicking the menu button
}
// Close menu if clicking outside
onMobileMenuToggle(); onMobileMenuToggle();
} };
});
// Use a delay to avoid interfering with link clicks
// This ensures link navigation happens before the handler is active
const timeoutId = setTimeout(() => {
document.addEventListener('mousedown', handleClickOutside);
document.addEventListener('touchstart', handleClickOutside);
}, 300);
return () => {
clearTimeout(timeoutId);
document.removeEventListener('mousedown', handleClickOutside);
document.removeEventListener('touchstart', handleClickOutside);
};
}, [isMobileMenuOpen, onMobileMenuToggle]);
const handleLinkClick = () => { const handleLinkClick = () => {
if (onLinkClick) { if (onLinkClick) {
@@ -51,10 +89,10 @@ const Navbar: React.FC<NavbarProps> = ({
to={link.to} to={link.to}
onClick={handleLinkClick} onClick={handleLinkClick}
className="px-4 py-3 text-white/90 className="px-4 py-3 text-white/90
hover:bg-[#d4af37]/10 hover:text-[#d4af37] hover:bg-[var(--luxury-gold)]/10 hover:text-[var(--luxury-gold)]
rounded-sm transition-all duration-300 rounded-sm transition-all duration-300
border-l-2 border-transparent border-l-2 border-transparent
hover:border-[#d4af37] font-light tracking-wide" hover:border-[var(--luxury-gold)] font-light tracking-wide"
> >
{link.label} {link.label}
</Link> </Link>
@@ -66,17 +104,24 @@ const Navbar: React.FC<NavbarProps> = ({
return ( return (
<div className="relative" ref={mobileMenuContainerRef}> <div className="relative" ref={mobileMenuContainerRef}>
{/* Desktop Navigation */} {/* Desktop Navigation */}
<nav className="hidden md:flex items-center space-x-1"> <nav className="hidden md:flex items-center space-x-2">
{navLinks.map((link) => ( {navLinks.map((link) => (
<Link <Link
key={link.to} key={link.to}
to={link.to} to={link.to}
className="text-white/90 hover:text-[#d4af37] className="text-white/95 hover:text-[var(--luxury-gold)]
transition-all duration-300 font-light px-4 py-2 transition-all duration-300 font-light px-5 py-2.5
relative group tracking-wide" relative group tracking-wider text-sm uppercase"
> >
<span className="relative z-10">{link.label}</span> <span className="relative z-10 transition-all duration-300 group-hover:tracking-widest">
<span className="absolute inset-0 bg-gradient-to-r from-[#d4af37]/0 via-[#d4af37]/10 to-[#d4af37]/0 opacity-0 group-hover:opacity-100 transition-opacity duration-300"></span> {link.label}
</span>
{/* Underline effect */}
<span className="absolute bottom-0 left-0 w-0 h-[1px] bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-light)] group-hover:w-full transition-all duration-500"></span>
{/* Background glow on hover */}
<span className="absolute inset-0 bg-gradient-to-r from-[rgba(var(--luxury-gold-rgb),0.05)] via-[rgba(var(--luxury-gold-rgb),0.1)] to-[rgba(var(--luxury-gold-rgb),0.05)] opacity-0 group-hover:opacity-100 transition-opacity duration-300 rounded-sm"></span>
{/* Subtle border on hover */}
<span className="absolute inset-0 border border-[rgba(var(--luxury-gold-rgb),0.1)] rounded-sm opacity-0 group-hover:opacity-100 transition-opacity duration-300"></span>
</Link> </Link>
))} ))}
</nav> </nav>
@@ -84,49 +129,138 @@ const Navbar: React.FC<NavbarProps> = ({
{/* Mobile Menu Button */} {/* Mobile Menu Button */}
<button <button
onClick={onMobileMenuToggle} onClick={onMobileMenuToggle}
className="md:hidden p-2 rounded-sm className="md:hidden p-3 rounded-lg
hover:bg-white/10 border border-transparent bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:bg-[rgba(var(--luxury-gold-rgb),0.2)]
hover:border-[#d4af37]/30 transition-all duration-300" border border-[rgba(var(--luxury-gold-rgb),0.3)]
hover:border-[rgba(var(--luxury-gold-rgb),0.5)] transition-all duration-300
group shadow-lg"
aria-label="Toggle menu"
> >
{isMobileMenuOpen ? ( {isMobileMenuOpen ? (
<X className="w-6 h-6 text-[#d4af37]" /> <X className="w-6 h-6 text-[var(--luxury-gold)] transition-transform duration-300 group-hover:rotate-90" />
) : ( ) : (
<Menu className="w-6 h-6 text-white/90" /> <Menu className="w-6 h-6 text-[var(--luxury-gold)] group-hover:text-[var(--luxury-gold-light)] transition-colors duration-300" />
)} )}
</button> </button>
{/* Mobile Menu Dropdown - Absolute positioned */} {/* Mobile Menu Backdrop and Dropdown - Rendered via Portal */}
{isMobileMenuOpen && ( {isMobileMenuOpen && typeof document !== 'undefined' && createPortal(
<div <>
className="md:hidden absolute right-0 mt-2 w-64 {/* Mobile Menu Backdrop */}
bg-gradient-to-b from-[#1a1a1a] to-[#0f0f0f] <div
rounded-sm shadow-2xl py-2 border border-[#d4af37]/20 className="md:hidden fixed inset-0 bg-black/70 backdrop-blur-sm"
z-50 backdrop-blur-xl animate-fade-in max-h-[calc(100vh-120px)] style={{
overflow-y-auto" top: '73px',
> zIndex: 99998,
<div className="flex flex-col space-y-1"> position: 'fixed',
{navLinks.map((link) => ( pointerEvents: 'auto'
<Link } as React.CSSProperties}
key={link.to} onClick={(e) => {
to={link.to} // Only close if clicking directly on backdrop, not on dropdown content
onClick={handleLinkClick} const target = e.target as HTMLElement;
className="px-4 py-3 text-white/90 if (target === e.currentTarget) {
hover:bg-[#d4af37]/10 hover:text-[#d4af37] onMobileMenuToggle();
rounded-sm transition-all duration-300 }
border-l-2 border-transparent }}
hover:border-[#d4af37] font-light tracking-wide" onTouchStart={(e) => {
> // Prevent backdrop from interfering with touch events on links
{link.label} const target = e.target as HTMLElement;
</Link> if (mobileMenuDropdownRef.current?.contains(target)) {
))} e.stopPropagation();
{mobileMenuContent && ( }
<> }}
<div className="border-t border-[#d4af37]/20 my-2"></div> />
{mobileMenuContent}
</> {/* Mobile Menu Dropdown - Right side on mobile */}
)} <div
ref={mobileMenuDropdownRef}
className="md:hidden fixed top-[73px] right-0 w-80 max-w-[85vw]
bg-gradient-to-b from-[#0f0f0f] via-[#1a1a1a] to-[#0f0f0f]
shadow-[0_8px_32px_rgba(0,0,0,0.9),_-4px_0_20px_rgba(var(--luxury-gold-rgb),0.2)]
py-4 border-l-2 border-[rgba(var(--luxury-gold-rgb),0.4)]
backdrop-blur-xl animate-fade-in
overflow-y-auto h-[calc(100vh-73px)]"
style={{
zIndex: 99999,
position: 'fixed',
touchAction: 'auto',
pointerEvents: 'auto'
} as React.CSSProperties}
onClick={(e) => {
// Stop propagation to prevent backdrop from closing menu when clicking inside
e.stopPropagation();
}}
onTouchStart={(e) => {
// Stop touch events from propagating to backdrop
e.stopPropagation();
}}
onTouchEnd={(e) => {
// Stop touch end events from propagating
e.stopPropagation();
}}
>
<div className="flex flex-col space-y-1 px-2">
{navLinks.map((link) => (
<Link
key={link.to}
to={link.to}
onClick={(e) => {
// Stop propagation to prevent backdrop from closing menu
e.stopPropagation();
// Close mobile menu after navigation starts
setTimeout(() => {
if (handleLinkClick) {
handleLinkClick();
}
}, 150);
}}
onTouchStart={(e) => {
// Stop touch events from propagating to backdrop
e.stopPropagation();
}}
onTouchEnd={(e) => {
// Ensure touch end doesn't trigger backdrop
e.stopPropagation();
}}
onMouseDown={(e) => {
// Ensure mouse events work
e.stopPropagation();
}}
className="px-4 py-3.5 text-white/95
hover:bg-[rgba(var(--luxury-gold-rgb),0.15)] hover:text-[var(--luxury-gold)]
rounded-md transition-all duration-300
border-l-2 border-transparent
hover:border-[var(--luxury-gold)] font-light tracking-wider text-sm uppercase
group relative mx-2 cursor-pointer text-left w-full block"
style={{
touchAction: 'manipulation',
WebkitTapHighlightColor: 'transparent',
pointerEvents: 'auto'
}}
>
<span
className="relative z-10"
style={{ pointerEvents: 'none' }}
>
{link.label}
</span>
<span
className="absolute left-0 top-0 bottom-0 w-0 bg-gradient-to-r from-[rgba(var(--luxury-gold-rgb),0.15)] to-transparent group-hover:w-full transition-all duration-300 rounded-md"
style={{ pointerEvents: 'none' }}
></span>
</Link>
))}
{mobileMenuContent && (
<>
<div className="border-t border-[var(--luxury-gold)]/20 my-2"></div>
{mobileMenuContent}
</>
)}
</div>
</div> </div>
</div> </>,
document.body
)} )}
</div> </div>
); );

View File

@@ -14,19 +14,19 @@ const OfflineIndicator: React.FC = () => {
aria-live="polite" aria-live="polite"
> >
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 pb-4 sm:pb-6"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 pb-4 sm:pb-6">
<div className="relative overflow-hidden rounded-lg shadow-2xl border border-[#d4af37]/30 backdrop-blur-xl bg-gradient-to-r from-slate-900/95 via-slate-800/95 to-slate-900/95"> <div className="relative overflow-hidden rounded-lg shadow-2xl border border-[var(--luxury-gold)]/30 backdrop-blur-xl bg-gradient-to-r from-slate-900/95 via-slate-800/95 to-slate-900/95">
{/* Gold accent border top */} {/* Gold accent border top */}
<div className="absolute top-0 left-0 right-0 h-0.5 bg-gradient-to-r from-transparent via-[#d4af37] to-transparent"></div> <div className="absolute top-0 left-0 right-0 h-0.5 bg-gradient-to-r from-transparent via-[var(--luxury-gold)] to-transparent"></div>
{/* Subtle glow effect */} {/* Subtle glow effect */}
<div className="absolute inset-0 bg-gradient-to-r from-[#d4af37]/5 via-transparent to-[#d4af37]/5 pointer-events-none"></div> <div className="absolute inset-0 bg-gradient-to-r from-[var(--luxury-gold)]/5 via-transparent to-[var(--luxury-gold)]/5 pointer-events-none"></div>
{/* Content */} {/* Content */}
<div className="relative px-6 py-4 sm:px-8 sm:py-5 flex items-center justify-center gap-3 sm:gap-4"> <div className="relative px-6 py-4 sm:px-8 sm:py-5 flex items-center justify-center gap-3 sm:gap-4">
{/* Icon with gold accent */} {/* Icon with gold accent */}
<div className="relative flex-shrink-0"> <div className="relative flex-shrink-0">
<div className="absolute inset-0 bg-[#d4af37]/20 blur-xl rounded-full"></div> <div className="absolute inset-0 bg-[var(--luxury-gold)]/20 blur-xl rounded-full"></div>
<div className="relative bg-gradient-to-br from-[#d4af37] to-[#c9a227] p-2.5 rounded-full shadow-lg shadow-[#d4af37]/30"> <div className="relative bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] p-2.5 rounded-full shadow-lg shadow-[var(--luxury-gold)]/30">
<WifiOff className="w-5 h-5 sm:w-6 sm:h-6 text-slate-900" strokeWidth={2.5} /> <WifiOff className="w-5 h-5 sm:w-6 sm:h-6 text-slate-900" strokeWidth={2.5} />
</div> </div>
</div> </div>
@@ -43,9 +43,9 @@ const OfflineIndicator: React.FC = () => {
{/* Decorative elements */} {/* Decorative elements */}
<div className="hidden sm:flex absolute right-6 top-1/2 -translate-y-1/2 items-center gap-1 opacity-30"> <div className="hidden sm:flex absolute right-6 top-1/2 -translate-y-1/2 items-center gap-1 opacity-30">
<div className="w-1 h-1 rounded-full bg-[#d4af37] animate-pulse"></div> <div className="w-1 h-1 rounded-full bg-[var(--luxury-gold)] animate-pulse"></div>
<div className="w-1 h-1 rounded-full bg-[#d4af37] animate-pulse" style={{ animationDelay: '0.2s' }}></div> <div className="w-1 h-1 rounded-full bg-[var(--luxury-gold)] animate-pulse" style={{ animationDelay: '0.2s' }}></div>
<div className="w-1 h-1 rounded-full bg-[#d4af37] animate-pulse" style={{ animationDelay: '0.4s' }}></div> <div className="w-1 h-1 rounded-full bg-[var(--luxury-gold)] animate-pulse" style={{ animationDelay: '0.4s' }}></div>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -177,6 +177,11 @@ const SidebarAdmin: React.FC<SidebarAdminProps> = ({
icon: FileText, icon: FileText,
label: 'Invoices' label: 'Invoices'
}, },
{
path: '/admin/promotions',
icon: Tag,
label: 'Promotions'
},
{ {
path: '/admin/financial-audit', path: '/admin/financial-audit',
icon: FileCheck, icon: FileCheck,
@@ -193,11 +198,6 @@ const SidebarAdmin: React.FC<SidebarAdminProps> = ({
icon: BarChart3, icon: BarChart3,
label: 'Reports & Analytics' label: 'Reports & Analytics'
}, },
{
path: '/admin/business',
icon: TrendingUp,
label: 'Business Insights'
},
] ]
}, },
{ {
@@ -367,7 +367,7 @@ const SidebarAdmin: React.FC<SidebarAdminProps> = ({
const isActive = (path: string) => { const isActive = (path: string) => {
if (location.pathname === path) return true; if (location.pathname === path) return true;
if (path === '/admin/settings' || path === '/admin/analytics' || path === '/admin/business' || path === '/admin/reception' || path === '/admin/advanced-rooms' || path === '/admin/page-content' || path === '/admin/loyalty') { if (path === '/admin/settings' || path === '/admin/analytics' || path === '/admin/reception' || path === '/admin/advanced-rooms' || path === '/admin/page-content' || path === '/admin/loyalty') {
return location.pathname === path; return location.pathname === path;
} }

View File

@@ -0,0 +1,162 @@
import React, {
createContext,
useContext,
useEffect,
useState,
ReactNode,
} from 'react';
import { themeService } from '../../features/system/services/systemSettingsService';
type ThemeColors = {
primary: string;
primaryLight: string;
primaryDark: string;
primaryAccent: string;
};
type ThemeContextValue = {
colors: ThemeColors;
isLoading: boolean;
refreshTheme: () => Promise<void>;
updateColors: (colors: Partial<ThemeColors>) => void;
};
const defaultColors: ThemeColors = {
primary: '#d4af37',
primaryLight: '#f5d76e',
primaryDark: '#c9a227',
primaryAccent: '#e8c547',
};
const ThemeContext = createContext<ThemeContextValue | undefined>(undefined);
export const useTheme = () => {
const context = useContext(ThemeContext);
if (!context) {
throw new Error('useTheme must be used within ThemeProvider');
}
return context;
};
interface ThemeProviderProps {
children: ReactNode;
}
/**
* Converts hex color to RGB values
*/
const hexToRgb = (hex: string): string => {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result
? `${parseInt(result[1], 16)}, ${parseInt(result[2], 16)}, ${parseInt(result[3], 16)}`
: '212, 175, 55'; // Default gold RGB
};
/**
* Applies theme colors as CSS variables to the document root
*/
const applyThemeColors = (colors: ThemeColors) => {
const root = document.documentElement;
// Apply CSS variables
root.style.setProperty('--luxury-gold', colors.primary);
root.style.setProperty('--luxury-gold-light', colors.primaryLight);
root.style.setProperty('--luxury-gold-dark', colors.primaryDark);
root.style.setProperty('--luxury-gold-accent', colors.primaryAccent);
// Add RGB versions for rgba() usage
root.style.setProperty('--luxury-gold-rgb', hexToRgb(colors.primary));
root.style.setProperty('--luxury-gold-light-rgb', hexToRgb(colors.primaryLight));
root.style.setProperty('--luxury-gold-dark-rgb', hexToRgb(colors.primaryDark));
root.style.setProperty('--luxury-gold-accent-rgb', hexToRgb(colors.primaryAccent));
// Also update gradient variables
root.style.setProperty(
'--gradient-gold',
`linear-gradient(135deg, ${colors.primary} 0%, ${colors.primaryLight} 100%)`
);
root.style.setProperty(
'--gradient-gold-dark',
`linear-gradient(135deg, ${colors.primaryDark} 0%, ${colors.primary} 100%)`
);
// Update shadow variables with proper opacity
const primaryRgb = hexToRgb(colors.primary);
root.style.setProperty(
'--shadow-luxury',
`0 4px 20px rgba(${primaryRgb}, 0.15)`
);
root.style.setProperty(
'--shadow-luxury-gold',
`0 8px 30px rgba(${primaryRgb}, 0.25)`
);
};
export const ThemeProvider: React.FC<ThemeProviderProps> = ({ children }) => {
const [colors, setColors] = useState<ThemeColors>(defaultColors);
const [isLoading, setIsLoading] = useState<boolean>(true);
const loadTheme = async () => {
try {
setIsLoading(true);
const response = await themeService.getThemeSettings();
if (response.data) {
const newColors: ThemeColors = {
primary: response.data.theme_primary_color || defaultColors.primary,
primaryLight: response.data.theme_primary_light || defaultColors.primaryLight,
primaryDark: response.data.theme_primary_dark || defaultColors.primaryDark,
primaryAccent: response.data.theme_primary_accent || defaultColors.primaryAccent,
};
setColors(newColors);
applyThemeColors(newColors);
}
} catch (error) {
console.error('Error loading theme settings:', error);
// Apply default colors on error
applyThemeColors(defaultColors);
setColors(defaultColors);
} finally {
setIsLoading(false);
}
};
useEffect(() => {
loadTheme();
// Listen for theme refresh events
const handleRefresh = () => {
loadTheme();
};
if (typeof window !== 'undefined') {
window.addEventListener('refreshTheme', handleRefresh);
return () => {
window.removeEventListener('refreshTheme', handleRefresh);
};
}
}, []);
const refreshTheme = async () => {
await loadTheme();
};
const updateColors = (newColors: Partial<ThemeColors>) => {
const updatedColors = { ...colors, ...newColors };
setColors(updatedColors);
applyThemeColors(updatedColors);
};
return (
<ThemeContext.Provider
value={{
colors,
isLoading,
refreshTheme,
updateColors,
}}
>
{children}
</ThemeContext.Provider>
);
};

View File

@@ -29,23 +29,23 @@ const NotFoundPage: React.FC = () => {
style={{ filter: 'drop-shadow(0 4px 6px rgba(0,0,0,0.1))' }} style={{ filter: 'drop-shadow(0 4px 6px rgba(0,0,0,0.1))' }}
/> />
) : ( ) : (
<div className="relative p-4 sm:p-5 bg-gradient-to-br from-[#d4af37] to-[#c9a227] rounded-full shadow-lg shadow-[#d4af37]/30"> <div className="relative p-4 sm:p-5 bg-gradient-to-br from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] rounded-full shadow-lg shadow-[var(--luxury-gold)]/30">
<Hotel className="w-12 h-12 sm:w-16 sm:h-16 lg:w-20 lg:h-20 text-[#0f0f0f] relative z-10" /> <Hotel className="w-12 h-12 sm:w-16 sm:h-16 lg:w-20 lg:h-20 text-[#0f0f0f] relative z-10" />
<div className="absolute inset-0 bg-gradient-to-br from-[#f5d76e] to-[#d4af37] rounded-full blur-xl opacity-50"></div> <div className="absolute inset-0 bg-gradient-to-br from-[var(--luxury-gold-light)] to-[var(--luxury-gold)] rounded-full blur-xl opacity-50"></div>
</div> </div>
)} )}
</div> </div>
{/* Tagline */} {/* Tagline */}
{settings.company_tagline && ( {settings.company_tagline && (
<p className="text-xs sm:text-sm text-[#d4af37] uppercase tracking-[2px] sm:tracking-[3px] mb-3 sm:mb-4 font-light"> <p className="text-xs sm:text-sm text-[var(--luxury-gold)] uppercase tracking-[2px] sm:tracking-[3px] mb-3 sm:mb-4 font-light">
{settings.company_tagline} {settings.company_tagline}
</p> </p>
)} )}
{/* 404 Number */} {/* 404 Number */}
<div className="mb-6 sm:mb-8"> <div className="mb-6 sm:mb-8">
<h1 className="text-8xl sm:text-9xl lg:text-[12rem] font-display font-bold text-transparent bg-clip-text bg-gradient-to-r from-[#d4af37] via-[#f5d76e] to-[#d4af37] leading-none tracking-tight"> <h1 className="text-8xl sm:text-9xl lg:text-[12rem] font-display font-bold text-transparent bg-clip-text bg-gradient-to-r from-[var(--luxury-gold)] via-[var(--luxury-gold-light)] to-[var(--luxury-gold)] leading-none tracking-tight">
404 404
</h1> </h1>
</div> </div>
@@ -78,7 +78,7 @@ const NotFoundPage: React.FC = () => {
<div className="flex flex-col sm:flex-row items-center justify-center gap-4"> <div className="flex flex-col sm:flex-row items-center justify-center gap-4">
<Link <Link
to="/" to="/"
className="inline-flex items-center justify-center gap-2 px-8 py-3.5 sm:px-10 sm:py-4 bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-[#0f0f0f] font-semibold text-sm sm:text-base rounded-lg shadow-lg shadow-[#d4af37]/30 hover:from-[#f5d76e] hover:to-[#d4af37] hover:shadow-xl hover:shadow-[#d4af37]/40 transition-all duration-300 ease-out hover:-translate-y-0.5 active:translate-y-0 relative overflow-hidden group" className="inline-flex items-center justify-center gap-2 px-8 py-3.5 sm:px-10 sm:py-4 bg-gradient-to-r from-[var(--luxury-gold)] to-[var(--luxury-gold-dark)] text-[#0f0f0f] font-semibold text-sm sm:text-base rounded-lg shadow-lg shadow-[var(--luxury-gold)]/30 hover:from-[var(--luxury-gold-light)] hover:to-[var(--luxury-gold)] hover:shadow-xl hover:shadow-[var(--luxury-gold)]/40 transition-all duration-300 ease-out hover:-translate-y-0.5 active:translate-y-0 relative overflow-hidden group"
> >
<span className="absolute inset-0 bg-gradient-to-r from-white/0 via-white/20 to-white/0 translate-x-[-100%] group-hover:translate-x-[100%] transition-transform duration-700"></span> <span className="absolute inset-0 bg-gradient-to-r from-white/0 via-white/20 to-white/0 translate-x-[-100%] group-hover:translate-x-[100%] transition-transform duration-700"></span>
<Home className="w-5 h-5 sm:w-6 sm:h-6 relative z-10" /> <Home className="w-5 h-5 sm:w-6 sm:h-6 relative z-10" />
@@ -88,9 +88,9 @@ const NotFoundPage: React.FC = () => {
{/* Decorative Elements */} {/* Decorative Elements */}
<div className="mt-12 sm:mt-16 flex justify-center gap-2"> <div className="mt-12 sm:mt-16 flex justify-center gap-2">
<div className="w-2 h-2 rounded-full bg-[#d4af37]/30"></div> <div className="w-2 h-2 rounded-full bg-[var(--luxury-gold)]/30"></div>
<div className="w-2 h-2 rounded-full bg-[#d4af37]/50"></div> <div className="w-2 h-2 rounded-full bg-[var(--luxury-gold)]/50"></div>
<div className="w-2 h-2 rounded-full bg-[#d4af37]/30"></div> <div className="w-2 h-2 rounded-full bg-[var(--luxury-gold)]/30"></div>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -37,11 +37,11 @@
--shadow-luxury-gold: 0 8px 30px rgba(212, 175, 55, 0.25); --shadow-luxury-gold: 0 8px 30px rgba(212, 175, 55, 0.25);
--gradient-gold: linear-gradient(135deg, #d4af37 0%, #f5d76e 100%); --gradient-gold: linear-gradient(135deg, var(--luxury-gold) 0%, var(--luxury-gold-light) 100%);
--gradient-gold-dark: linear-gradient(135deg, #c9a227 0%, #d4af37 100%); --gradient-gold-dark: linear-gradient(135deg, var(--luxury-gold-dark) 0%, var(--luxury-gold) 100%);
--gradient-dark: linear-gradient(180deg, #1a1a1a 0%, #0f0f0f 100%); --gradient-dark: linear-gradient(180deg, #1a1a1a 0%, #0f0f0f 100%);
--gradient-overlay: linear-gradient(180deg, rgba(15, 15, 15, 0.8) 0%, rgba(15, 15, 15, 0.4) 100%); --gradient-overlay: linear-gradient(180deg, rgba(15, 15, 15, 0.8) 0%, rgba(15, 15, 15, 0.4) 100%);
--gradient-gold-overlay: linear-gradient(135deg, rgba(212, 175, 55, 0.1) 0%, rgba(245, 215, 110, 0.05) 100%); --gradient-gold-overlay: linear-gradient(135deg, var(--luxury-gold)1a 0%, var(--luxury-gold-light)0d 100%);
} }
::-webkit-scrollbar { ::-webkit-scrollbar {
@@ -158,8 +158,12 @@ h3, h4, h5, h6 {
.luxury-card { .luxury-card {
@apply bg-white rounded-sm shadow-lg border border-gray-100; @apply bg-white rounded-sm shadow-lg border border-gray-100;
@apply transition-all duration-300 ease-out; @apply transition-all duration-300 ease-out;
@apply hover:shadow-xl hover:shadow-[#d4af37]/10;
@apply hover:-translate-y-1; @apply hover:-translate-y-1;
box-shadow: var(--shadow-lg), 0 0 0 0 transparent;
}
.luxury-card:hover {
box-shadow: var(--shadow-xl), 0 0 20px rgba(var(--luxury-gold-rgb), 0.1);
} }
@@ -167,35 +171,46 @@ h3, h4, h5, h6 {
@apply bg-white rounded-sm shadow-lg; @apply bg-white rounded-sm shadow-lg;
@apply relative overflow-hidden; @apply relative overflow-hidden;
@apply transition-all duration-300 ease-out; @apply transition-all duration-300 ease-out;
@apply hover:shadow-xl hover:shadow-[#d4af37]/20; border-top: 2px solid var(--luxury-gold);
@apply border-t-2 border-[#d4af37]; }
.luxury-card-gold:hover {
box-shadow: var(--shadow-xl), 0 0 30px rgba(var(--luxury-gold-rgb), 0.2);
} }
.luxury-card-dark { .luxury-card-dark {
@apply bg-gradient-to-b from-[#1a1a1a] to-[#0f0f0f] rounded-sm shadow-2xl; @apply bg-gradient-to-b from-[#1a1a1a] to-[#0f0f0f] rounded-sm shadow-2xl;
@apply border border-[#d4af37]/20;
@apply transition-all duration-300 ease-out; @apply transition-all duration-300 ease-out;
@apply hover:shadow-[#d4af37]/30 hover:border-[#d4af37]/40; border: 1px solid rgba(var(--luxury-gold-rgb), 0.2);
}
.luxury-card-dark:hover {
box-shadow: 0 0 40px rgba(var(--luxury-gold-rgb), 0.3);
border-color: rgba(var(--luxury-gold-rgb), 0.4);
} }
.btn-luxury-primary { .btn-luxury-primary {
@apply px-6 py-3 rounded-sm font-medium tracking-wide; @apply px-6 py-3 rounded-sm font-medium tracking-wide;
@apply bg-gradient-to-r from-[#d4af37] to-[#c9a227] text-[#0f0f0f]; @apply text-[#0f0f0f];
@apply shadow-lg shadow-[#d4af37]/30;
@apply transition-all duration-300 ease-out; @apply transition-all duration-300 ease-out;
@apply hover:from-[#f5d76e] hover:to-[#d4af37];
@apply hover:shadow-xl hover:shadow-[#d4af37]/40;
@apply hover:-translate-y-0.5; @apply hover:-translate-y-0.5;
@apply active:translate-y-0; @apply active:translate-y-0;
@apply disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:translate-y-0; @apply disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:translate-y-0;
@apply relative overflow-hidden; @apply relative overflow-hidden;
background: var(--gradient-gold-dark);
box-shadow: var(--shadow-lg), 0 0 30px rgba(var(--luxury-gold-rgb), 0.3);
font-family: 'Poppins', 'Inter', sans-serif; font-family: 'Poppins', 'Inter', sans-serif;
font-weight: 500; font-weight: 500;
letter-spacing: 0.05em; letter-spacing: 0.05em;
} }
.btn-luxury-primary:hover {
background: var(--gradient-gold);
box-shadow: var(--shadow-xl), 0 0 40px rgba(var(--luxury-gold-rgb), 0.4);
}
.btn-luxury-primary::before { .btn-luxury-primary::before {
content: ''; content: '';
@apply absolute inset-0 bg-gradient-to-r from-white/0 via-white/20 to-white/0; @apply absolute inset-0 bg-gradient-to-r from-white/0 via-white/20 to-white/0;
@@ -209,16 +224,23 @@ h3, h4, h5, h6 {
.btn-luxury-secondary { .btn-luxury-secondary {
@apply px-6 py-3 rounded-sm font-medium tracking-wide; @apply px-6 py-3 rounded-sm font-medium tracking-wide;
@apply bg-white/10 backdrop-blur-sm text-white border border-[#d4af37]/30; @apply bg-white/10 backdrop-blur-sm text-white;
@apply transition-all duration-300 ease-out; @apply transition-all duration-300 ease-out;
@apply hover:bg-[#d4af37]/10 hover:border-[#d4af37] hover:text-[#d4af37];
@apply hover:-translate-y-0.5; @apply hover:-translate-y-0.5;
@apply active:translate-y-0; @apply active:translate-y-0;
border: 1px solid rgba(var(--luxury-gold-rgb), 0.3);
}
.btn-luxury-secondary:hover {
background-color: rgba(var(--luxury-gold-rgb), 0.1);
border-color: var(--luxury-gold);
color: var(--luxury-gold);
} }
.luxury-section-header { .luxury-section-header {
@apply mb-8 pb-4 border-b border-[#d4af37]/20; @apply mb-8 pb-4;
border-bottom: 1px solid rgba(var(--luxury-gold-rgb), 0.2);
} }
.luxury-section-title { .luxury-section-title {
@@ -254,7 +276,7 @@ h3, h4, h5, h6 {
.luxury-table thead { .luxury-table thead {
@apply bg-gradient-to-r from-gray-50 to-gray-100; @apply bg-gradient-to-r from-gray-50 to-gray-100;
@apply border-b-2 border-[#d4af37]/30; border-bottom: 2px solid rgba(var(--luxury-gold-rgb), 0.3);
} }
.luxury-table th { .luxury-table th {
@@ -270,7 +292,10 @@ h3, h4, h5, h6 {
.luxury-table tbody tr { .luxury-table tbody tr {
@apply transition-colors duration-150; @apply transition-colors duration-150;
@apply hover:bg-[#d4af37]/5; }
.luxury-table tbody tr:hover {
background-color: rgba(var(--luxury-gold-rgb), 0.05);
} }
@@ -278,13 +303,14 @@ h3, h4, h5, h6 {
@apply inline-flex items-center px-3 py-1 rounded-sm; @apply inline-flex items-center px-3 py-1 rounded-sm;
@apply text-xs font-medium tracking-wide; @apply text-xs font-medium tracking-wide;
@apply transition-all duration-200; @apply transition-all duration-200;
@apply bg-[#d4af37]/10 text-[#c9a227] border border-[#d4af37]/30; color: var(--luxury-gold-dark);
background-color: rgba(var(--luxury-gold-rgb), 0.1);
border: 1px solid rgba(var(--luxury-gold-rgb), 0.3);
} }
.luxury-input { .luxury-input {
@apply w-full px-4 py-3 rounded-sm border border-gray-300; @apply w-full px-4 py-3 rounded-sm border border-gray-300;
@apply focus:ring-2 focus:ring-[#d4af37]/50 focus:border-[#d4af37];
@apply transition-all duration-200; @apply transition-all duration-200;
@apply bg-white text-gray-900; @apply bg-white text-gray-900;
@apply placeholder:text-gray-400; @apply placeholder:text-gray-400;
@@ -293,6 +319,13 @@ h3, h4, h5, h6 {
letter-spacing: 0.01em; letter-spacing: 0.01em;
} }
.luxury-input:focus {
outline: none;
ring: 2px;
ring-color: rgba(var(--luxury-gold-rgb), 0.5);
border-color: var(--luxury-gold);
}
.luxury-gradient-bg { .luxury-gradient-bg {
background: var(--gradient-gold); background: var(--gradient-gold);
@@ -301,8 +334,8 @@ h3, h4, h5, h6 {
.luxury-glass { .luxury-glass {
@apply bg-white/90 backdrop-blur-xl; @apply bg-white/90 backdrop-blur-xl;
@apply border border-[#d4af37]/20;
@apply shadow-2xl; @apply shadow-2xl;
border: 1px solid rgba(var(--luxury-gold-rgb), 0.2);
} }
@@ -310,15 +343,18 @@ h3, h4, h5, h6 {
@apply bg-white rounded-lg shadow-xl border border-gray-200/60; @apply bg-white rounded-lg shadow-xl border border-gray-200/60;
@apply relative overflow-hidden; @apply relative overflow-hidden;
@apply transition-all duration-300 ease-out; @apply transition-all duration-300 ease-out;
@apply hover:shadow-2xl hover:shadow-[#d4af37]/10;
@apply hover:-translate-y-0.5; @apply hover:-translate-y-0.5;
@apply backdrop-blur-sm; @apply backdrop-blur-sm;
} }
.enterprise-card:hover {
box-shadow: var(--shadow-2xl), 0 0 30px rgba(var(--luxury-gold-rgb), 0.1);
}
.enterprise-card::before { .enterprise-card::before {
content: ''; content: '';
@apply absolute top-0 left-0 right-0 h-0.5; @apply absolute top-0 left-0 right-0 h-0.5;
background: linear-gradient(90deg, transparent 0%, #d4af37 50%, transparent 100%); background: linear-gradient(90deg, transparent 0%, var(--luxury-gold) 50%, transparent 100%);
opacity: 0; opacity: 0;
transition: opacity 0.3s ease-out; transition: opacity 0.3s ease-out;
} }
@@ -344,15 +380,19 @@ h3, h4, h5, h6 {
.btn-enterprise-primary { .btn-enterprise-primary {
@apply px-8 py-3.5 rounded-lg font-semibold tracking-wide text-sm; @apply px-8 py-3.5 rounded-lg font-semibold tracking-wide text-sm;
@apply bg-gradient-to-r from-[#d4af37] via-[#e8c547] to-[#d4af37]; @apply text-[#0f0f0f];
@apply text-[#0f0f0f] shadow-lg shadow-[#d4af37]/30;
@apply transition-all duration-300 ease-out; @apply transition-all duration-300 ease-out;
@apply hover:from-[#f5d76e] hover:via-[#d4af37] hover:to-[#f5d76e];
@apply hover:shadow-xl hover:shadow-[#d4af37]/40;
@apply hover:-translate-y-0.5 hover:scale-[1.02]; @apply hover:-translate-y-0.5 hover:scale-[1.02];
@apply active:translate-y-0 active:scale-100; @apply active:translate-y-0 active:scale-100;
@apply disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:translate-y-0 disabled:hover:scale-100; @apply disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:translate-y-0 disabled:hover:scale-100;
@apply relative overflow-hidden; @apply relative overflow-hidden;
background: linear-gradient(to right, var(--luxury-gold), var(--luxury-gold-accent), var(--luxury-gold));
box-shadow: var(--shadow-lg), 0 0 30px rgba(var(--luxury-gold-rgb), 0.3);
}
.btn-enterprise-primary:hover {
background: linear-gradient(to right, var(--luxury-gold-light), var(--luxury-gold), var(--luxury-gold-light));
box-shadow: var(--shadow-xl), 0 0 40px rgba(var(--luxury-gold-rgb), 0.4);
} }
.btn-enterprise-primary::before { .btn-enterprise-primary::before {
@@ -371,17 +411,21 @@ h3, h4, h5, h6 {
@apply bg-white border-2 border-gray-300 text-gray-700; @apply bg-white border-2 border-gray-300 text-gray-700;
@apply shadow-md shadow-gray-200/50; @apply shadow-md shadow-gray-200/50;
@apply transition-all duration-300 ease-out; @apply transition-all duration-300 ease-out;
@apply hover:bg-gray-50 hover:border-[#d4af37] hover:text-[#c9a227];
@apply hover:shadow-lg hover:shadow-[#d4af37]/20;
@apply hover:-translate-y-0.5; @apply hover:-translate-y-0.5;
@apply active:translate-y-0; @apply active:translate-y-0;
@apply disabled:opacity-50 disabled:cursor-not-allowed; @apply disabled:opacity-50 disabled:cursor-not-allowed;
} }
.btn-enterprise-secondary:hover {
@apply hover:bg-gray-50;
border-color: var(--luxury-gold);
color: var(--luxury-gold-dark);
box-shadow: var(--shadow-lg), 0 0 20px rgba(var(--luxury-gold-rgb), 0.2);
}
.enterprise-input { .enterprise-input {
@apply w-full px-4 py-3 rounded-lg border-2 border-gray-200; @apply w-full px-4 py-3 rounded-lg border-2 border-gray-200;
@apply focus:ring-2 focus:ring-[#d4af37]/30 focus:border-[#d4af37];
@apply transition-all duration-200; @apply transition-all duration-200;
@apply bg-white text-gray-900; @apply bg-white text-gray-900;
@apply placeholder:text-gray-400; @apply placeholder:text-gray-400;
@@ -390,7 +434,11 @@ h3, h4, h5, h6 {
} }
.enterprise-input:focus { .enterprise-input:focus {
@apply shadow-md shadow-[#d4af37]/10; outline: none;
ring: 2px;
ring-color: rgba(var(--luxury-gold-rgb), 0.3);
border-color: var(--luxury-gold);
box-shadow: var(--shadow-md), 0 0 20px rgba(var(--luxury-gold-rgb), 0.1);
} }
} }
@@ -399,6 +447,46 @@ h3, h4, h5, h6 {
text-wrap: balance; text-wrap: balance;
} }
/* Theme color utilities with opacity support */
.bg-luxury-gold {
background-color: var(--luxury-gold);
}
.bg-luxury-gold\/10 {
background-color: rgba(var(--luxury-gold-rgb), 0.1);
}
.bg-luxury-gold\/20 {
background-color: rgba(var(--luxury-gold-rgb), 0.2);
}
.text-luxury-gold {
color: var(--luxury-gold);
}
.text-luxury-gold\/70 {
color: rgba(var(--luxury-gold-rgb), 0.7);
}
.border-luxury-gold {
border-color: var(--luxury-gold);
}
.border-luxury-gold\/10 {
border-color: rgba(var(--luxury-gold-rgb), 0.1);
}
.border-luxury-gold\/20 {
border-color: rgba(var(--luxury-gold-rgb), 0.2);
}
.border-luxury-gold\/30 {
border-color: rgba(var(--luxury-gold-rgb), 0.3);
}
.border-luxury-gold\/40 {
border-color: rgba(var(--luxury-gold-rgb), 0.4);
}
.shadow-luxury { .shadow-luxury {
box-shadow: var(--shadow-luxury); box-shadow: var(--shadow-luxury);
@@ -409,7 +497,7 @@ h3, h4, h5, h6 {
} }
.shadow-luxury-gold { .shadow-luxury-gold {
box-shadow: 0 8px 30px rgba(212, 175, 55, 0.25); box-shadow: var(--shadow-luxury-gold);
} }
@@ -523,8 +611,11 @@ h3, h4, h5, h6 {
.text-gradient-luxury { .text-gradient-luxury {
@apply bg-gradient-to-r from-[#d4af37] via-[#f5d76e] to-[#d4af37]; background: linear-gradient(to right, var(--luxury-gold), var(--luxury-gold-light), var(--luxury-gold));
@apply bg-clip-text text-transparent; -webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent;
} }
.text-gradient-luxury-dark { .text-gradient-luxury-dark {
@@ -581,11 +672,11 @@ img[loading="lazy"]:not([src]) {
.prose.prose-invert strong, .prose.prose-invert strong,
.prose.prose-invert b { .prose.prose-invert b {
color: #d4af37 !important; color: var(--luxury-gold) !important;
} }
.prose.prose-invert a { .prose.prose-invert a {
color: #d4af37 !important; color: var(--luxury-gold) !important;
} }
/* Custom luxury scrollbar for modals */ /* Custom luxury scrollbar for modals */
@@ -599,11 +690,11 @@ img[loading="lazy"]:not([src]) {
} }
.custom-scrollbar::-webkit-scrollbar-thumb { .custom-scrollbar::-webkit-scrollbar-thumb {
background: linear-gradient(180deg, #d4af37 0%, #c9a227 100%); background: linear-gradient(180deg, var(--luxury-gold) 0%, var(--luxury-gold-dark) 100%);
border-radius: 10px; border-radius: 10px;
border: 2px solid #f3f4f6; border: 2px solid #f3f4f6;
} }
.custom-scrollbar::-webkit-scrollbar-thumb:hover { .custom-scrollbar::-webkit-scrollbar-thumb:hover {
background: linear-gradient(180deg, #f5d76e 0%, #d4af37 100%); background: linear-gradient(180deg, var(--luxury-gold-light) 0%, var(--luxury-gold) 100%);
} }

View File

@@ -15,9 +15,10 @@ export default {
}, },
colors: { colors: {
luxury: { luxury: {
gold: '#d4af37', gold: 'var(--luxury-gold)',
'gold-light': '#f5d76e', 'gold-light': 'var(--luxury-gold-light)',
'gold-dark': '#c9a227', 'gold-dark': 'var(--luxury-gold-dark)',
'gold-accent': 'var(--luxury-gold-accent)',
black: '#0f0f0f', black: '#0f0f0f',
'black-light': '#1a1a1a', 'black-light': '#1a1a1a',
}, },