diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 5879a9e..b67f2c0 100644 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -1433,6 +1433,8 @@ $routes->group('setting', static function($routes) { $routes->post('admin/ipd-examination-fields/save', 'Setting\IpdExaminationFields::save', ['filter' => ['permission:ipd_discharge.master.manage', 'csrf']]); $routes->post('admin/ipd-examination-fields/toggle/(:num)', 'Setting\IpdExaminationFields::toggle/$1', ['filter' => ['permission:ipd_discharge.master.manage', 'csrf']]); $routes->get('admin/hospital-profile', 'Setting\\HospitalProfile::index'); + $routes->get('admin/login-settings', 'Setting\\HospitalProfile::loginSettings'); + $routes->post('admin/login-settings/save', 'Setting\\HospitalProfile::saveLoginSettings'); $routes->get('admin/system-ops', 'SystemOps::index', ['filter' => $settingsAdminFilter]); $routes->get('admin/system-ops/panel', 'SystemOps::panel', ['filter' => $settingsAdminFilter]); $routes->get('admin/system-ops/diagnose', 'SystemOps::diagnose', ['filter' => $settingsAdminFilter]); diff --git a/app/Controllers/Setting/HospitalProfile.php b/app/Controllers/Setting/HospitalProfile.php index d6bc79b..1832a62 100644 --- a/app/Controllers/Setting/HospitalProfile.php +++ b/app/Controllers/Setting/HospitalProfile.php @@ -211,6 +211,132 @@ class HospitalProfile extends BaseController ]); } + public function loginSettings() + { + if (! $this->canManageHospitalProfile()) { + return $this->response->setStatusCode(403)->setBody('Access denied'); + } + + $wallpaper = $this->readSettingValue('H_login_wallpaper'); + $logo = $this->readSettingValue('H_logo'); + + $presets = [ + [ + 'file' => 'hospital_wallpaper_20261027_203745_bf800456.jpg', + 'title' => 'Client Deep Teal (Current)', + 'desc' => 'Dark teal background with smooth geometric accents', + ], + [ + 'file' => 'hospital_wallpaper_soft_teal_leaves.jpg', + 'title' => 'Johri Soft Teal Botanical', + 'desc' => 'Ivory canvas with organic soft teal curved leaves (Brand Guide Option 02)', + ], + [ + 'file' => 'hospital_wallpaper_modern_facade.jpg', + 'title' => 'Modern Hospital Facade', + 'desc' => 'High-end architectural medical tower with landscaped grounds', + ], + ]; + + return view('Setting/Admin/login_settings', [ + 'hospital_name' => $this->readSettingValue('H_Name'), + 'hospital_logo' => $logo, + 'hospital_logo_url' => $logo !== '' ? base_url('assets/images/' . rawurlencode($logo)) : '', + 'hospital_wallpaper' => $wallpaper, + 'hospital_wallpaper_url' => $wallpaper !== '' ? base_url('assets/images/' . rawurlencode($wallpaper)) : '', + 'login_panel_position' => $this->readSettingValue('LOGIN_PANEL_POSITION') ?: 'right', + 'login_hero_theme' => $this->readSettingValue('LOGIN_HERO_THEME') ?: 'light', + 'login_logo_style' => $this->readSettingValue('LOGIN_LOGO_STYLE') ?: '3d_box', + 'login_hero_overlay' => $this->readSettingValue('LOGIN_HERO_OVERLAY') ?: 'dark', + 'login_show_subtitle' => $this->readSettingValue('LOGIN_SHOW_SUBTITLE') !== '' ? $this->readSettingValue('LOGIN_SHOW_SUBTITLE') : '1', + 'login_show_contact_meta' => $this->readSettingValue('LOGIN_SHOW_CONTACT_META') !== '' ? $this->readSettingValue('LOGIN_SHOW_CONTACT_META') : '1', + 'login_show_pwa_card' => $this->readSettingValue('LOGIN_SHOW_PWA_CARD') !== '' ? $this->readSettingValue('LOGIN_SHOW_PWA_CARD') : '1', + 'presets' => $presets, + ]); + } + + public function saveLoginSettings() + { + if (! $this->request->isAJAX()) { + return $this->response->setJSON(['update' => 0, 'error_text' => 'Invalid request']); + } + + if (! $this->canManageHospitalProfile()) { + return $this->response->setStatusCode(403)->setJSON(['update' => 0, 'error_text' => 'Access denied']); + } + + $panelPos = strtolower(trim((string) $this->request->getPost('login_panel_position'))); + if (! in_array($panelPos, ['left', 'center', 'right'], true)) { + $panelPos = 'right'; + } + + $heroTheme = strtolower(trim((string) $this->request->getPost('login_hero_theme'))); + if (! in_array($heroTheme, ['light', 'dark'], true)) { + $heroTheme = 'light'; + } + + $logoStyle = strtolower(trim((string) $this->request->getPost('login_logo_style'))); + if (! in_array($logoStyle, ['3d_box', 'glass', 'transparent'], true)) { + $logoStyle = '3d_box'; + } + + $heroOverlay = strtolower(trim((string) $this->request->getPost('login_hero_overlay'))); + if (! in_array($heroOverlay, ['dark', 'light', 'none'], true)) { + $heroOverlay = 'dark'; + } + + $showSubtitle = $this->request->getPost('login_show_subtitle') === '1' ? '1' : '0'; + $showContactMeta = $this->request->getPost('login_show_contact_meta') === '1' ? '1' : '0'; + $showPwaCard = $this->request->getPost('login_show_pwa_card') === '1' ? '1' : '0'; + + $this->upsertSettingValue('LOGIN_PANEL_POSITION', $panelPos); + $this->upsertSettingValue('LOGIN_HERO_THEME', $heroTheme); + $this->upsertSettingValue('LOGIN_LOGO_STYLE', $logoStyle); + $this->upsertSettingValue('LOGIN_HERO_OVERLAY', $heroOverlay); + $this->upsertSettingValue('LOGIN_SHOW_SUBTITLE', $showSubtitle); + $this->upsertSettingValue('LOGIN_SHOW_CONTACT_META', $showContactMeta); + $this->upsertSettingValue('LOGIN_SHOW_PWA_CARD', $showPwaCard); + + // Check if preset selected + $presetWallpaper = trim((string) $this->request->getPost('preset_wallpaper')); + if ($presetWallpaper !== '') { + $presetFile = basename($presetWallpaper); + if (is_file(FCPATH . 'assets/images/' . $presetFile)) { + $this->upsertSettingValue('H_login_wallpaper', $presetFile); + } + } + + // Process new wallpaper upload if present + $wpFile = $this->request->getFile('hospital_wallpaper'); + if ($wpFile && $wpFile->isValid() && ! $wpFile->hasMoved()) { + $wallpaperResult = $this->processLogoUpload( + $wpFile, + 'hospital_wallpaper', + 'H_login_wallpaper', + 'Login wallpaper' + ); + if (! $wallpaperResult['ok']) { + return $this->response->setJSON([ + 'update' => 0, + 'error_text' => $wallpaperResult['error'], + 'csrfName' => csrf_token(), + 'csrfHash' => csrf_hash(), + ]); + } + } + + $currentWallpaper = $this->readSettingValue('H_login_wallpaper'); + + return $this->response->setJSON([ + 'update' => 1, + 'error_text' => 'Login page settings saved successfully.', + 'wallpaper_url' => $currentWallpaper !== '' ? base_url('assets/images/' . rawurlencode($currentWallpaper)) : '', + 'wallpaper_name' => $currentWallpaper, + 'csrfName' => csrf_token(), + 'csrfHash' => csrf_hash(), + ]); + } + public function deleteLogo() { if (! $this->request->isAJAX()) { diff --git a/app/Views/Setting/Admin/hospital_profile.php b/app/Views/Setting/Admin/hospital_profile.php index 0cf5b15..ce9491d 100644 --- a/app/Views/Setting/Admin/hospital_profile.php +++ b/app/Views/Setting/Admin/hospital_profile.php @@ -84,6 +84,15 @@ +
+
+
+ Login Page Customizer: Set Left, Center, or Right panel layout, 3D/glass logo styling, dark/light font colors, and preview presets. +
+ Open Login Page Customizer → +
+
+

Pharmacy Information
diff --git a/app/Views/Setting/Admin/index.php b/app/Views/Setting/Admin/index.php index 52d23a1..75fed86 100644 --- a/app/Views/Setting/Admin/index.php +++ b/app/Views/Setting/Admin/index.php @@ -114,6 +114,12 @@ Hospital Profile
+
+ + + Login Settings + +
diff --git a/app/Views/Setting/Admin/login_settings.php b/app/Views/Setting/Admin/login_settings.php new file mode 100644 index 0000000..30ccf7a --- /dev/null +++ b/app/Views/Setting/Admin/login_settings.php @@ -0,0 +1,472 @@ +
+ + +
+ + + + +
+ +
+ +
Choose whether the login credentials form appears on the Left, Center, or Right side of the screen.
+ +
+ +
+
+
+
+
+
+
+
+
+
+ Branding +
+
+
+
+ Left Panel + Form on Left, Wallpaper on Right +
+ > +
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+ Center Modal + Full wallpaper, Centered floating card +
+ > +
+
+
+ + +
+
+
+
+ Branding +
+
+
+
+
+
+
+
+
+
+ Right Panel Standard + Wallpaper on Left, Form on Right +
+ > +
+
+
+
+
+ +
+ + +
+ +
Select how the transparent hospital logo is mounted so it always stands out clearly.
+ +
+
+ +
+ +
+ +
+ +
+ +
+
+
+ +
+ + +
+ +
Select text color scheme so heading and labels never blend into or drown in the background.
+ +
+
+ +
+ +
+ +
+
+
+ +
+ + +
+ +
Controls the subtle gradient shading overlaid onto the wallpaper to balance text readability.
+ +
+
+ +
+ +
+ +
+ +
+ +
+
+
+ +
+ + +
+ +
Turn on or off specific branding elements on the login page.
+ +
+
+
+ + > +
+
+ +
+
+ + > +
+
+ +
+
+ + > +
+
+
+
+ +
+ + +
+ +
Select from curated wallpapers or upload a new custom background.
+ +
+ + + +
+
+
+ <?= esc($p['title']) ?> +
+
+ + + Active + +
+
+
+
+ + +
+ + + +
+
+ + +
Recommended size: 1920x1080 (PNG, JPG, WEBP).
+
+
+ +
+ + Wallpaper +
+ + No wallpaper active + +
+
+
+
+ + +
+ + + Open Login Page + +
+ +
+
+
+
+ + diff --git a/app/Views/auth/login.php b/app/Views/auth/login.php index b50415e..48cf5ad 100644 --- a/app/Views/auth/login.php +++ b/app/Views/auth/login.php @@ -10,6 +10,15 @@ $hospitalHfrId = hospital_setting_value('H_HFR_ID', ''); $hospitalLogo = hospital_setting_value('H_logo', ''); $hospitalWallpaper = hospital_setting_value('H_login_wallpaper', ''); +// Login Customizer Settings +$loginPanelPosition = hospital_setting_value('LOGIN_PANEL_POSITION', 'right'); // 'left', 'center', 'right' +$loginHeroTheme = hospital_setting_value('LOGIN_HERO_THEME', 'light'); // 'light', 'dark' +$loginLogoStyle = hospital_setting_value('LOGIN_LOGO_STYLE', '3d_box'); // '3d_box', 'glass', 'transparent' +$loginHeroOverlay = hospital_setting_value('LOGIN_HERO_OVERLAY', 'dark'); // 'dark', 'light', 'none' +$loginShowSubtitle = hospital_setting_value('LOGIN_SHOW_SUBTITLE', '1') !== '0'; +$loginShowContactMeta = hospital_setting_value('LOGIN_SHOW_CONTACT_META', '1') !== '0'; +$loginShowPwaCard = hospital_setting_value('LOGIN_SHOW_PWA_CARD', '1') !== '0'; + $hasLogo = false; $logoUrl = ''; if ($hospitalLogo !== '' && is_file(FCPATH . 'assets/images/' . $hospitalLogo)) { @@ -88,6 +97,56 @@ $footerVersion = hms_footer_version(); background-color: #f1f5f9; } + /* Layout Positions */ + .login-page-wrapper.panel-right { + flex-direction: row; + } + + .login-page-wrapper.panel-left { + flex-direction: row-reverse; + } + .login-page-wrapper.panel-left .login-hero-section { + border-right: none; + border-left: 1px solid #e2e8f0; + } + .login-page-wrapper.panel-left .login-form-section { + border-left: none; + border-right: 1px solid #e2e8f0; + box-shadow: 10px 0 40px rgba(0, 0, 0, 0.05); + } + + .login-page-wrapper.panel-center { + flex-direction: column; + justify-content: center; + align-items: center; + padding: 2.5rem 1rem; + position: relative; + background-size: cover; + background-position: center center; + background-repeat: no-repeat; + } + .login-page-wrapper.panel-center .login-hero-section { + display: none !important; + } + .login-page-wrapper.panel-center .login-form-section { + width: 100%; + max-width: 480px; + min-height: auto; + border: 1px solid rgba(255, 255, 255, 0.6); + border-radius: 20px; + box-shadow: 0 25px 60px rgba(0, 0, 0, 0.28); + background: rgba(255, 255, 255, 0.96); + backdrop-filter: blur(16px); + -webkit-backdrop-filter: blur(16px); + padding: 2.25rem 2rem 1.5rem; + margin: auto; + position: relative; + z-index: 5; + } + .login-page-wrapper.panel-center .login-form-container { + max-width: 100%; + } + /* Left Hero/Branding section */ .login-hero-section { flex: 1; @@ -108,14 +167,30 @@ $footerVersion = hms_footer_version(); color: #ffffff; } - .login-hero-section.has-wallpaper::before { + /* Overlay Shading Options */ + .login-hero-section.has-wallpaper.overlay-dark::before, + .login-page-wrapper.panel-center.overlay-dark::before { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; - background: linear-gradient(180deg, rgba(7, 24, 43, 0.18) 0%, rgba(7, 24, 43, 0.42) 50%, rgba(7, 24, 43, 0.8) 100%); + background: linear-gradient(180deg, rgba(7, 24, 43, 0.2) 0%, rgba(7, 24, 43, 0.45) 50%, rgba(7, 24, 43, 0.82) 100%); z-index: 1; } + .login-hero-section.has-wallpaper.overlay-light::before, + .login-page-wrapper.panel-center.overlay-light::before { + content: ''; + position: absolute; + top: 0; left: 0; right: 0; bottom: 0; + background: linear-gradient(180deg, rgba(255, 255, 255, 0.28) 0%, rgba(255, 255, 255, 0.58) 50%, rgba(255, 255, 255, 0.88) 100%); + z-index: 1; + } + + .login-hero-section.has-wallpaper.overlay-none::before, + .login-page-wrapper.panel-center.overlay-none::before { + display: none; + } + .login-hero-inner { position: relative; z-index: 2; @@ -125,11 +200,16 @@ $footerVersion = hms_footer_version(); height: 100%; } - /* 3D Format Box for Hospital Logo with curved corners */ + /* Hospital Logo Wrap Styles */ .login-hero-logo-wrap { display: inline-flex; align-items: center; justify-content: center; + transition: transform 0.25s ease, box-shadow 0.25s ease; + } + + /* Style: 3D Raised Plaque (Default) */ + .login-hero-logo-wrap.style-3d_box { padding: 16px 26px; border-radius: 20px; background: linear-gradient(150deg, #ffffff 0%, #edf6f7 100%); @@ -139,10 +219,8 @@ $footerVersion = hms_footer_version(); 0 4px 10px rgba(0, 0, 0, 0.22), inset 0 2px 1px rgba(255, 255, 255, 1), inset 0 -2px 4px rgba(7, 34, 53, 0.08); - transition: transform 0.25s ease, box-shadow 0.25s ease; } - - .login-hero-logo-wrap:hover { + .login-hero-logo-wrap.style-3d_box:hover { transform: translateY(-2px); box-shadow: 0 20px 42px rgba(0, 0, 0, 0.42), @@ -151,6 +229,32 @@ $footerVersion = hms_footer_version(); inset 0 -2px 4px rgba(7, 34, 53, 0.08); } + /* Style: Frosted Glass Plate */ + .login-hero-logo-wrap.style-glass { + padding: 16px 26px; + border-radius: 20px; + background: rgba(255, 255, 255, 0.25); + backdrop-filter: blur(16px); + -webkit-backdrop-filter: blur(16px); + border: 1px solid rgba(255, 255, 255, 0.5); + box-shadow: 0 12px 30px rgba(0, 0, 0, 0.2); + } + .login-hero-logo-wrap.style-glass:hover { + transform: translateY(-2px); + background: rgba(255, 255, 255, 0.35); + } + + /* Style: Seamless / Direct */ + .login-hero-logo-wrap.style-transparent { + padding: 6px 0; + background: transparent; + border: none; + box-shadow: none; + } + .login-hero-logo-wrap.style-transparent .login-hero-logo-img { + filter: drop-shadow(0 4px 12px rgba(0, 0, 0, 0.45)); + } + .login-hero-logo-img { max-height: 85px; max-width: 260px; @@ -161,12 +265,16 @@ $footerVersion = hms_footer_version(); transition: transform 0.2s ease; } - /* Radiant, crisp heading on dark background with dark outline and ambient glow */ + /* Heading & Typography Base */ .login-hero-title { font-size: clamp(2.2rem, 3.8vw, 3.4rem); font-weight: 800; line-height: 1.18; letter-spacing: -0.015em; + } + + /* Theme: Radiant White (Dark Backgrounds) */ + .login-page-wrapper.theme-light .login-hero-title { color: #ffffff; -webkit-text-stroke: 1.2px #061c2e; paint-order: stroke fill; @@ -175,20 +283,40 @@ $footerVersion = hms_footer_version(); 0 8px 24px rgba(0, 0, 0, 0.6), 0 0 32px rgba(45, 212, 191, 0.3); } - - .login-hero-subtitle { + .login-page-wrapper.theme-light .login-hero-subtitle { font-size: 1.15rem; color: #e2e8f0; text-shadow: 0 2px 8px rgba(0, 0, 0, 0.7); max-width: 620px; } - - .login-hero-meta { + .login-page-wrapper.theme-light .login-hero-meta { color: #f1f5f9; text-shadow: 0 1px 4px rgba(0, 0, 0, 0.85); font-weight: 500; } + /* Theme: Architectural Navy (Light / Ivory Backgrounds) */ + .login-page-wrapper.theme-dark .login-hero-title { + color: #0c4a6e; + -webkit-text-stroke: 0.8px rgba(255, 255, 255, 0.95); + paint-order: stroke fill; + text-shadow: + 0 2px 8px rgba(255, 255, 255, 0.9), + 0 1px 4px rgba(12, 74, 110, 0.25); + } + .login-page-wrapper.theme-dark .login-hero-subtitle { + font-size: 1.15rem; + color: #1e3a5f; + text-shadow: 0 1px 2px rgba(255, 255, 255, 0.8); + font-weight: 500; + max-width: 620px; + } + .login-page-wrapper.theme-dark .login-hero-meta { + color: #0f172a; + text-shadow: none; + font-weight: 600; + } + /* Hero Blank / Neutral State (First time / No Wallpaper) */ .login-hero-section.no-wallpaper { background: linear-gradient(135deg, #f8fafc 0%, #eef2f6 100%); @@ -206,7 +334,7 @@ $footerVersion = hms_footer_version(); text-shadow: none; } - /* Right Side Form Panel */ + /* Form Panel Section */ .login-form-section { width: 460px; max-width: 100%; @@ -230,7 +358,7 @@ $footerVersion = hms_footer_version(); @media (max-width: 991.98px) { .login-page-wrapper { - flex-direction: column; + flex-direction: column !important; } .login-hero-section { min-height: auto; @@ -241,11 +369,14 @@ $footerVersion = hms_footer_version(); display: none; } .login-form-section { - width: 100%; - min-height: auto; - border-left: none; - box-shadow: none; - padding: 1.5rem 1rem; + width: 100% !important; + max-width: 100% !important; + min-height: auto !important; + border-left: none !important; + border-right: none !important; + box-shadow: none !important; + padding: 1.5rem 1rem !important; + border-radius: 0 !important; } } @@ -253,16 +384,16 @@ $footerVersion = hms_footer_version(); -
+
> -