feat(auth): add Login Page Configuration Panel with Left/Center/Right layout and styling controls
This commit is contained in:
parent
aac71afc70
commit
2ed2bfa99c
|
|
@ -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]);
|
||||
|
|
|
|||
|
|
@ -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()) {
|
||||
|
|
|
|||
|
|
@ -84,6 +84,15 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="alert alert-info py-2 px-3 small d-flex align-items-center justify-content-between flex-wrap gap-2 mb-0">
|
||||
<div>
|
||||
<i class="bi bi-palette-fill me-1 text-primary"></i> <strong>Login Page Customizer:</strong> Set Left, Center, or Right panel layout, 3D/glass logo styling, dark/light font colors, and preview presets.
|
||||
</div>
|
||||
<a href="javascript:openAdminSubPage('<?= base_url('setting/admin/login-settings') ?>','Login Page Settings');" class="btn btn-sm btn-primary">Open Login Page Customizer →</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 mt-3"><hr><h6 class="mb-2">Pharmacy Information</h6></div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Pharmacy Name</label>
|
||||
|
|
|
|||
|
|
@ -114,6 +114,12 @@
|
|||
<span>Hospital Profile</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-6 col-md-2 col-lg-2">
|
||||
<a class="admin-tile" href="javascript:openAdminSubPage('<?= base_url('setting/admin/login-settings') ?>','Login Page Settings');">
|
||||
<i class="bi bi-palette" style="color:#059669;"></i>
|
||||
<span>Login Settings</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-6 col-md-2 col-lg-2">
|
||||
<a class="admin-tile" href="javascript:openAdminSubPage('<?= base_url('setting/admin/insurance') ?>','Insurance Master');">
|
||||
<i class="bi bi-shield-check"></i>
|
||||
|
|
|
|||
472
app/Views/Setting/Admin/login_settings.php
Normal file
472
app/Views/Setting/Admin/login_settings.php
Normal file
|
|
@ -0,0 +1,472 @@
|
|||
<div class="card shadow-sm border-0">
|
||||
<div class="card-header bg-white border-bottom py-3 d-flex align-items-center justify-content-between flex-wrap gap-2">
|
||||
<div>
|
||||
<h4 class="card-title mb-1 fw-bold text-dark"><i class="bi bi-palette2 text-primary me-2"></i>Login Page Customizer</h4>
|
||||
<div class="text-muted small">Configure layout positioning (Left, Center, Right), logo styling, color themes, and wallpapers for the software login page.</div>
|
||||
</div>
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<a href="<?= base_url('login') ?>" target="_blank" class="btn btn-outline-primary btn-sm">
|
||||
<i class="bi bi-box-arrow-up-right me-1"></i> Preview Live Login Page
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body p-4">
|
||||
<?= csrf_field() ?>
|
||||
|
||||
<style>
|
||||
.layout-choice-card {
|
||||
border: 2px solid #e2e8f0;
|
||||
border-radius: 12px;
|
||||
padding: 14px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
background: #f8fafc;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.layout-choice-card:hover {
|
||||
border-color: #94a3b8;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
.layout-choice-card.active {
|
||||
border-color: #0d6efd;
|
||||
background: #eff6ff;
|
||||
box-shadow: 0 0 0 3px rgba(13, 110, 253, 0.15);
|
||||
}
|
||||
.layout-wireframe {
|
||||
height: 70px;
|
||||
border-radius: 6px;
|
||||
background: #e2e8f0;
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
padding: 5px;
|
||||
margin-bottom: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.wire-hero {
|
||||
background: #0d3b66;
|
||||
border-radius: 4px;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #ffffff;
|
||||
font-size: 8px;
|
||||
}
|
||||
.wire-form {
|
||||
width: 38%;
|
||||
background: #ffffff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 3px;
|
||||
padding: 4px;
|
||||
}
|
||||
.wire-input-bar {
|
||||
height: 4px;
|
||||
width: 80%;
|
||||
background: #cbd5e1;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.wire-center-card {
|
||||
width: 55%;
|
||||
margin: auto;
|
||||
background: #ffffff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 6px rgba(0,0,0,0.15);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 6px 4px;
|
||||
gap: 3px;
|
||||
}
|
||||
.preset-thumb-card {
|
||||
border: 2px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
padding: 8px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
background: #ffffff;
|
||||
}
|
||||
.preset-thumb-card:hover {
|
||||
border-color: #0d6efd;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
.preset-thumb-card.active {
|
||||
border-color: #0d6efd;
|
||||
box-shadow: 0 0 0 3px rgba(13, 110, 253, 0.2);
|
||||
}
|
||||
</style>
|
||||
|
||||
<form id="form_login_settings">
|
||||
<!-- 1. Layout & Placement Selection -->
|
||||
<div class="mb-4">
|
||||
<label class="form-label fw-bold text-dark fs-6 mb-1">
|
||||
<i class="bi bi-layout-sidebar-inset text-primary me-1"></i> 1. Login Panel Placement
|
||||
</label>
|
||||
<div class="text-muted small mb-3">Choose whether the login credentials form appears on the Left, Center, or Right side of the screen.</div>
|
||||
|
||||
<div class="row g-3">
|
||||
<!-- Left -->
|
||||
<div class="col-md-4">
|
||||
<div class="layout-choice-card <?= ($login_panel_position ?? 'right') === 'left' ? 'active' : '' ?>" data-position="left">
|
||||
<div class="layout-wireframe">
|
||||
<div class="wire-form">
|
||||
<div class="wire-input-bar" style="background:#0d6efd; width:50%;"></div>
|
||||
<div class="wire-input-bar"></div>
|
||||
<div class="wire-input-bar"></div>
|
||||
<div class="wire-input-bar" style="background:#0d6efd; height:5px;"></div>
|
||||
</div>
|
||||
<div class="wire-hero">
|
||||
<span>Branding</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex align-items-center justify-content-between">
|
||||
<div>
|
||||
<span class="fw-bold d-block text-dark">Left Panel</span>
|
||||
<span class="text-muted small" style="font-size: 11px;">Form on Left, Wallpaper on Right</span>
|
||||
</div>
|
||||
<input type="radio" name="login_panel_position" value="left" class="form-check-input" <?= ($login_panel_position ?? 'right') === 'left' ? 'checked' : '' ?>>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Center -->
|
||||
<div class="col-md-4">
|
||||
<div class="layout-choice-card <?= ($login_panel_position ?? 'right') === 'center' ? 'active' : '' ?>" data-position="center">
|
||||
<div class="layout-wireframe" style="background: #0d3b66;">
|
||||
<div class="wire-center-card">
|
||||
<div class="wire-input-bar" style="background:#0d6efd; width:50%;"></div>
|
||||
<div class="wire-input-bar"></div>
|
||||
<div class="wire-input-bar"></div>
|
||||
<div class="wire-input-bar" style="background:#0d6efd; height:5px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex align-items-center justify-content-between">
|
||||
<div>
|
||||
<span class="fw-bold d-block text-dark">Center Modal</span>
|
||||
<span class="text-muted small" style="font-size: 11px;">Full wallpaper, Centered floating card</span>
|
||||
</div>
|
||||
<input type="radio" name="login_panel_position" value="center" class="form-check-input" <?= ($login_panel_position ?? 'right') === 'center' ? 'checked' : '' ?>>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right (Default) -->
|
||||
<div class="col-md-4">
|
||||
<div class="layout-choice-card <?= ($login_panel_position ?? 'right') === 'right' ? 'active' : '' ?>" data-position="right">
|
||||
<div class="layout-wireframe">
|
||||
<div class="wire-hero">
|
||||
<span>Branding</span>
|
||||
</div>
|
||||
<div class="wire-form">
|
||||
<div class="wire-input-bar" style="background:#0d6efd; width:50%;"></div>
|
||||
<div class="wire-input-bar"></div>
|
||||
<div class="wire-input-bar"></div>
|
||||
<div class="wire-input-bar" style="background:#0d6efd; height:5px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex align-items-center justify-content-between">
|
||||
<div>
|
||||
<span class="fw-bold d-block text-dark">Right Panel <span class="badge bg-secondary ms-1">Standard</span></span>
|
||||
<span class="text-muted small" style="font-size: 11px;">Wallpaper on Left, Form on Right</span>
|
||||
</div>
|
||||
<input type="radio" name="login_panel_position" value="right" class="form-check-input" <?= ($login_panel_position ?? 'right') === 'right' ? 'checked' : '' ?>>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-4">
|
||||
|
||||
<!-- 2. Logo Presentation & 3D Plaque -->
|
||||
<div class="mb-4">
|
||||
<label class="form-label fw-bold text-dark fs-6 mb-1">
|
||||
<i class="bi bi-box text-primary me-1"></i> 2. Hospital Logo Container Style
|
||||
</label>
|
||||
<div class="text-muted small mb-3">Select how the transparent hospital logo is mounted so it always stands out clearly.</div>
|
||||
|
||||
<div class="row g-3">
|
||||
<div class="col-md-4">
|
||||
<label class="p-3 border rounded-3 w-100 h-100 d-flex align-items-center gap-3 cursor-pointer bg-light">
|
||||
<input type="radio" name="login_logo_style" value="3d_box" class="form-check-input flex-shrink-0" <?= ($login_logo_style ?? '3d_box') === '3d_box' ? 'checked' : '' ?>>
|
||||
<div>
|
||||
<span class="fw-bold d-block text-dark">3D Raised Plaque</span>
|
||||
<span class="text-muted small" style="font-size: 12px;">Curved corners, tactile bevel highlight, deep 3D drop shadow (Recommended for dark/photo wallpapers).</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="p-3 border rounded-3 w-100 h-100 d-flex align-items-center gap-3 cursor-pointer bg-light">
|
||||
<input type="radio" name="login_logo_style" value="glass" class="form-check-input flex-shrink-0" <?= ($login_logo_style ?? '3d_box') === 'glass' ? 'checked' : '' ?>>
|
||||
<div>
|
||||
<span class="fw-bold d-block text-dark">Frosted Glass Plate</span>
|
||||
<span class="text-muted small" style="font-size: 12px;">Semi-transparent frosted glass with backdrop blur and sleek borders.</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="p-3 border rounded-3 w-100 h-100 d-flex align-items-center gap-3 cursor-pointer bg-light">
|
||||
<input type="radio" name="login_logo_style" value="transparent" class="form-check-input flex-shrink-0" <?= ($login_logo_style ?? '3d_box') === 'transparent' ? 'checked' : '' ?>>
|
||||
<div>
|
||||
<span class="fw-bold d-block text-dark">Seamless / Direct</span>
|
||||
<span class="text-muted small" style="font-size: 12px;">No box/mount. Logo rests directly on the wallpaper (Best for white/ivory canvas backgrounds).</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-4">
|
||||
|
||||
<!-- 3. Text & Typography Theme -->
|
||||
<div class="mb-4">
|
||||
<label class="form-label fw-bold text-dark fs-6 mb-1">
|
||||
<i class="bi bi-type text-primary me-1"></i> 3. Typography & Heading Color Theme
|
||||
</label>
|
||||
<div class="text-muted small mb-3">Select text color scheme so heading and labels never blend into or drown in the background.</div>
|
||||
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<label class="p-3 border rounded-3 w-100 h-100 d-flex align-items-center gap-3 cursor-pointer" style="background:#0f273d;">
|
||||
<input type="radio" name="login_hero_theme" value="light" class="form-check-input flex-shrink-0" <?= ($login_hero_theme ?? 'light') === 'light' ? 'checked' : '' ?>>
|
||||
<div>
|
||||
<span class="fw-bold d-block text-white">Radiant White (Dark Backgrounds)</span>
|
||||
<span class="text-white-50 small" style="font-size: 12px;">White font, crisp dark contour outline, and soft ambient glow. Highly visible against teal, blue, or dark photos.</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label class="p-3 border rounded-3 w-100 h-100 d-flex align-items-center gap-3 cursor-pointer" style="background:#f8fafc;">
|
||||
<input type="radio" name="login_hero_theme" value="dark" class="form-check-input flex-shrink-0" <?= ($login_hero_theme ?? 'light') === 'dark' ? 'checked' : '' ?>>
|
||||
<div>
|
||||
<span class="fw-bold d-block text-dark">Architectural Navy (Light Backgrounds)</span>
|
||||
<span class="text-muted small" style="font-size: 12px;">Deep corporate navy font (`#0b2545`). Pristine contrast on ivory, white, or botanical wallpapers.</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-4">
|
||||
|
||||
<!-- 4. Hero Background Overlay Vignette -->
|
||||
<div class="mb-4">
|
||||
<label class="form-label fw-bold text-dark fs-6 mb-1">
|
||||
<i class="bi bi-brightness-high text-primary me-1"></i> 4. Background Overlay Shading
|
||||
</label>
|
||||
<div class="text-muted small mb-3">Controls the subtle gradient shading overlaid onto the wallpaper to balance text readability.</div>
|
||||
|
||||
<div class="row g-3">
|
||||
<div class="col-md-4">
|
||||
<label class="p-3 border rounded-3 w-100 h-100 d-flex align-items-center gap-3 cursor-pointer bg-light">
|
||||
<input type="radio" name="login_hero_overlay" value="dark" class="form-check-input flex-shrink-0" <?= ($login_hero_overlay ?? 'dark') === 'dark' ? 'checked' : '' ?>>
|
||||
<div>
|
||||
<span class="fw-bold d-block text-dark">Dark Vignette (Default)</span>
|
||||
<span class="text-muted small" style="font-size: 12px;">Deepens contrast naturally towards the bottom text area.</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="p-3 border rounded-3 w-100 h-100 d-flex align-items-center gap-3 cursor-pointer bg-light">
|
||||
<input type="radio" name="login_hero_overlay" value="light" class="form-check-input flex-shrink-0" <?= ($login_hero_overlay ?? 'dark') === 'light' ? 'checked' : '' ?>>
|
||||
<div>
|
||||
<span class="fw-bold d-block text-dark">Light Ambient Wash</span>
|
||||
<span class="text-muted small" style="font-size: 12px;">Soft daylight sheen, ideal for botanical or ivory branding.</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="p-3 border rounded-3 w-100 h-100 d-flex align-items-center gap-3 cursor-pointer bg-light">
|
||||
<input type="radio" name="login_hero_overlay" value="none" class="form-check-input flex-shrink-0" <?= ($login_hero_overlay ?? 'dark') === 'none' ? 'checked' : '' ?>>
|
||||
<div>
|
||||
<span class="fw-bold d-block text-dark">None / Pure Wallpaper</span>
|
||||
<span class="text-muted small" style="font-size: 12px;">No shading filter. Wallpaper shows in 100% natural colors.</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-4">
|
||||
|
||||
<!-- 5. Display Toggles -->
|
||||
<div class="mb-4">
|
||||
<label class="form-label fw-bold text-dark fs-6 mb-1">
|
||||
<i class="bi bi-eye text-primary me-1"></i> 5. Show / Hide Content Elements
|
||||
</label>
|
||||
<div class="text-muted small mb-3">Turn on or off specific branding elements on the login page.</div>
|
||||
|
||||
<div class="row g-3">
|
||||
<div class="col-md-4">
|
||||
<div class="form-check form-switch p-3 border rounded-3 bg-light d-flex align-items-center justify-content-between">
|
||||
<label class="form-check-label fw-semibold text-dark mb-0" for="toggle_subtitle">Show Tagline Subtitle</label>
|
||||
<input class="form-check-input ms-2" type="checkbox" id="toggle_subtitle" name="login_show_subtitle" value="1" <?= ($login_show_subtitle ?? '1') === '1' ? 'checked' : '' ?>>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="form-check form-switch p-3 border rounded-3 bg-light d-flex align-items-center justify-content-between">
|
||||
<label class="form-check-label fw-semibold text-dark mb-0" for="toggle_contact">Show Address & Phone</label>
|
||||
<input class="form-check-input ms-2" type="checkbox" id="toggle_contact" name="login_show_contact_meta" value="1" <?= ($login_show_contact_meta ?? '1') === '1' ? 'checked' : '' ?>>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="form-check form-switch p-3 border rounded-3 bg-light d-flex align-items-center justify-content-between">
|
||||
<label class="form-check-label fw-semibold text-dark mb-0" for="toggle_pwa">Show Mobile PWA Card</label>
|
||||
<input class="form-check-input ms-2" type="checkbox" id="toggle_pwa" name="login_show_pwa_card" value="1" <?= ($login_show_pwa_card ?? '1') === '1' ? 'checked' : '' ?>>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-4">
|
||||
|
||||
<!-- 6. Wallpaper Selection & Upload -->
|
||||
<div class="mb-4">
|
||||
<label class="form-label fw-bold text-dark fs-6 mb-1">
|
||||
<i class="bi bi-image text-primary me-1"></i> 6. Wallpaper Library & Upload
|
||||
</label>
|
||||
<div class="text-muted small mb-3">Select from curated wallpapers or upload a new custom background.</div>
|
||||
|
||||
<div class="row g-3 mb-3">
|
||||
<?php if (!empty($presets)): ?>
|
||||
<?php foreach ($presets as $p): ?>
|
||||
<?php $isCurrent = ($hospital_wallpaper ?? '') === $p['file']; ?>
|
||||
<div class="col-md-4">
|
||||
<div class="preset-thumb-card <?= $isCurrent ? 'active' : '' ?>" data-preset-file="<?= esc($p['file']) ?>">
|
||||
<div style="height: 100px; border-radius: 6px; overflow: hidden; background: #e2e8f0; margin-bottom: 6px;">
|
||||
<img src="<?= base_url('assets/images/' . rawurlencode($p['file'])) ?>" alt="<?= esc($p['title']) ?>" style="width: 100%; height: 100%; object-fit: cover;">
|
||||
</div>
|
||||
<div class="fw-bold small text-dark d-flex align-items-center justify-content-between">
|
||||
<span><?= esc($p['title']) ?></span>
|
||||
<?php if ($isCurrent): ?>
|
||||
<span class="badge bg-primary">Active</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="text-muted small" style="font-size: 11px;"><?= esc($p['desc'] ?? ($p['subtitle'] ?? '')) ?></div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<input type="hidden" id="preset_wallpaper" name="preset_wallpaper" value="">
|
||||
|
||||
<div class="row g-3 align-items-center">
|
||||
<div class="col-md-7">
|
||||
<label class="form-label fw-semibold text-dark">Upload New Custom Wallpaper</label>
|
||||
<input type="file" class="form-control" id="custom_hospital_wallpaper" name="hospital_wallpaper" accept=".png,.jpg,.jpeg,.webp">
|
||||
<div class="form-text">Recommended size: 1920x1080 (PNG, JPG, WEBP).</div>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<label class="form-label fw-semibold text-dark">Current Wallpaper Active</label>
|
||||
<div id="active_wallpaper_display" class="border rounded p-2 text-center bg-light">
|
||||
<?php if (!empty($hospital_wallpaper_url ?? '')): ?>
|
||||
<img src="<?= esc((string) $hospital_wallpaper_url) ?>" alt="Wallpaper" style="max-height:60px; max-width:100%; object-fit:cover; border-radius:4px;">
|
||||
<div class="small text-muted mt-1 text-truncate"><?= esc((string) ($hospital_wallpaper ?? '')) ?></div>
|
||||
<?php else: ?>
|
||||
<span class="text-muted small">No wallpaper active</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Submit Controls -->
|
||||
<div class="d-flex align-items-center gap-2 flex-wrap pt-3 border-top">
|
||||
<button type="button" class="btn btn-primary px-4 py-2 fw-semibold" id="btn_save_login_settings">
|
||||
<i class="bi bi-check-circle me-1"></i> Save Configuration
|
||||
</button>
|
||||
<a href="<?= base_url('login') ?>" target="_blank" class="btn btn-outline-secondary px-3 py-2">
|
||||
<i class="bi bi-eye me-1"></i> Open Login Page
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div id="login_settings_msg" class="mt-3"></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
// 1. Layout card click handler
|
||||
$('.layout-choice-card').on('click', function() {
|
||||
$('.layout-choice-card').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
$(this).find('input[type="radio"]').prop('checked', true);
|
||||
});
|
||||
|
||||
// 2. Preset wallpaper click handler
|
||||
$('.preset-thumb-card').on('click', function() {
|
||||
$('.preset-thumb-card').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
var file = $(this).data('preset-file');
|
||||
$('#preset_wallpaper').val(file);
|
||||
});
|
||||
|
||||
// 3. Save AJAX
|
||||
$('#btn_save_login_settings').on('click', function() {
|
||||
var $btn = $(this);
|
||||
var $msg = $('#login_settings_msg');
|
||||
$msg.empty();
|
||||
|
||||
$btn.prop('disabled', true).html('<span class="spinner-border spinner-border-sm me-1" role="status"></span> Saving...');
|
||||
|
||||
var formEl = document.getElementById('form_login_settings');
|
||||
var fd = new FormData(formEl);
|
||||
|
||||
// Append CSRF token
|
||||
var csrfName = $('input[name="csrf_test_name"]').attr('name') || 'csrf_test_name';
|
||||
var csrfVal = $('input[name="csrf_test_name"]').val();
|
||||
if (csrfVal) {
|
||||
fd.append(csrfName, csrfVal);
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: '<?= base_url('setting/admin/login-settings/save') ?>',
|
||||
type: 'POST',
|
||||
data: fd,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
dataType: 'json',
|
||||
success: function(resp) {
|
||||
$btn.prop('disabled', false).html('<i class="bi bi-check-circle me-1"></i> Save Configuration');
|
||||
|
||||
if (resp.csrfName && resp.csrfHash) {
|
||||
$('input[name="' + resp.csrfName + '"]').val(resp.csrfHash);
|
||||
}
|
||||
|
||||
if (resp.update === 1) {
|
||||
$msg.html('<div class="alert alert-success d-flex align-items-center py-2 px-3"><i class="bi bi-check-circle-fill me-2 fs-5"></i><div><strong>Saved!</strong> ' + (resp.error_text || 'Login page configuration updated successfully.') + ' <a href="<?= base_url('login') ?>" target="_blank" class="alert-link ms-2">View Login Page →</a></div></div>');
|
||||
|
||||
if (resp.wallpaper_url) {
|
||||
$('#active_wallpaper_display').html('<img src="' + resp.wallpaper_url + '" alt="Wallpaper" style="max-height:60px; max-width:100%; object-fit:cover; border-radius:4px;"><div class="small text-muted mt-1 text-truncate">' + resp.wallpaper_name + '</div>');
|
||||
}
|
||||
} else {
|
||||
$msg.html('<div class="alert alert-danger py-2 px-3"><i class="bi bi-exclamation-triangle-fill me-2"></i>' + (resp.error_text || 'An error occurred while saving.') + '</div>');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
$btn.prop('disabled', false).html('<i class="bi bi-check-circle me-1"></i> Save Configuration');
|
||||
$msg.html('<div class="alert alert-danger py-2 px-3"><i class="bi bi-x-circle-fill me-2"></i>Failed to save settings. Please try again.</div>');
|
||||
}
|
||||
});
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -253,16 +384,16 @@ $footerVersion = hms_footer_version();
|
|||
|
||||
<body>
|
||||
|
||||
<main class="login-page-wrapper">
|
||||
<main class="login-page-wrapper panel-<?= esc($loginPanelPosition) ?> theme-<?= esc($loginHeroTheme) ?><?= ($loginPanelPosition === 'center' && $hasWallpaper) ? ' overlay-' . esc($loginHeroOverlay) : '' ?>"<?= ($loginPanelPosition === 'center' && $hasWallpaper) ? ' style="background-image: url(\'' . esc($wallpaperUrl) . '\');"' : '' ?>>
|
||||
|
||||
<?php if ($hasWallpaper): ?>
|
||||
<!-- Left Branding / Wallpaper Hero Section -->
|
||||
<section class="login-hero-section has-wallpaper" style="background-image: url('<?= esc($wallpaperUrl) ?>');">
|
||||
<section class="login-hero-section has-wallpaper overlay-<?= esc($loginHeroOverlay) ?>" style="background-image: url('<?= esc($wallpaperUrl) ?>');">
|
||||
<div class="login-hero-inner">
|
||||
<!-- Top Header / Hospital Logo (Logo only, prominent with soft drop shadow) -->
|
||||
<div>
|
||||
<?php if ($hasLogo): ?>
|
||||
<div class="login-hero-logo-wrap">
|
||||
<div class="login-hero-logo-wrap style-<?= esc($loginLogoStyle) ?>">
|
||||
<img src="<?= esc($logoUrl) ?>" alt="<?= esc($hospitalName) ?> Logo" class="login-hero-logo-img">
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
|
@ -276,11 +407,13 @@ $footerVersion = hms_footer_version();
|
|||
<h1 class="login-hero-title mb-3">Hospital Information Management System</h1>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($loginShowSubtitle): ?>
|
||||
<p class="login-hero-subtitle mb-4">
|
||||
Secure Healthcare Delivery, Digital EMR & Clinical Management Portal
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($hospitalAddress1) || !empty($hospitalPhone) || !empty($hospitalHfrId)): ?>
|
||||
<?php if ($loginShowContactMeta && (!empty($hospitalAddress1) || !empty($hospitalPhone) || !empty($hospitalHfrId))): ?>
|
||||
<div class="d-flex flex-wrap gap-3 align-items-center text-white small login-hero-meta">
|
||||
<?php if (!empty($hospitalAddress1)): ?>
|
||||
<span class="d-inline-flex align-items-center gap-1">
|
||||
|
|
@ -314,10 +447,28 @@ $footerVersion = hms_footer_version();
|
|||
</section>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Right Side Login Form Section -->
|
||||
<!-- Form Section -->
|
||||
<section class="login-form-section">
|
||||
<div class="login-form-container">
|
||||
|
||||
<?php if ($loginPanelPosition === 'center'): ?>
|
||||
<!-- Centered Hospital Branding Showcase -->
|
||||
<div class="text-center mb-3">
|
||||
<?php if ($hasLogo): ?>
|
||||
<div class="mb-2">
|
||||
<div class="login-hero-logo-wrap style-<?= esc($loginLogoStyle) ?>">
|
||||
<img src="<?= esc($logoUrl) ?>" alt="<?= esc($hospitalName) ?> Logo" class="login-hero-logo-img" style="max-height: 70px;">
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($hospitalName)): ?>
|
||||
<h4 class="fw-bold text-dark mb-1" style="font-size: 1.35rem;"><?= esc($hospitalName) ?></h4>
|
||||
<?php endif; ?>
|
||||
<?php if ($loginShowSubtitle): ?>
|
||||
<p class="text-muted small mb-0" style="font-size: 12px;">Secure Healthcare Delivery & Clinical Management Portal</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<!-- System / E-Atria Branding Header -->
|
||||
<div class="text-center mb-2">
|
||||
<a href="/" class="logo d-inline-flex align-items-center justify-content-center text-decoration-none">
|
||||
|
|
@ -325,6 +476,7 @@ $footerVersion = hms_footer_version();
|
|||
<span class="fs-4 fw-bold text-primary ms-2">E-Atria</span>
|
||||
</a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Login Card -->
|
||||
<div class="card mb-2 border-0 shadow-sm" style="border-radius: 12px; background: #ffffff;">
|
||||
|
|
@ -447,6 +599,7 @@ $footerVersion = hms_footer_version();
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ($loginShowPwaCard): ?>
|
||||
<!-- Mobile Application QR & PWA Installation Card -->
|
||||
<div class="card border-0 shadow-sm mt-1 mb-2 w-100 text-center" style="background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%); border-radius: 12px; color: white;">
|
||||
<div class="card-body p-3">
|
||||
|
|
@ -463,6 +616,7 @@ $footerVersion = hms_footer_version();
|
|||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="text-center mt-1 mb-2">
|
||||
<a href="<?= base_url('HMS_FEATURES_PRESENTATION.html') ?>" target="_blank" rel="noopener"
|
||||
|
|
|
|||
|
|
@ -53,19 +53,58 @@ final class HospitalProfileWallpaperTest extends CIUnitTestCase
|
|||
$this->assertStringContainsString('renderWallpaper', $html);
|
||||
}
|
||||
|
||||
public function testLoginViewRendersWithRightSideLayoutAndKeyElements(): void
|
||||
public function testLoginSettingsViewRendersAllConfigurationControls(): void
|
||||
{
|
||||
$html = view('auth/login');
|
||||
$viewData = [
|
||||
'login_panel_position' => 'left',
|
||||
'login_hero_theme' => 'light',
|
||||
'login_logo_style' => '3d_box',
|
||||
'login_hero_overlay' => 'dark',
|
||||
'login_show_subtitle' => '1',
|
||||
'login_show_contact_meta' => '1',
|
||||
'login_show_pwa_card' => '1',
|
||||
'hospital_wallpaper' => 'hospital_wallpaper_soft_teal_leaves.jpg',
|
||||
'hospital_wallpaper_url' => 'http://localhost:8080/assets/images/hospital_wallpaper_soft_teal_leaves.jpg',
|
||||
'presets' => [
|
||||
[
|
||||
'file' => 'hospital_wallpaper_20261027_203745_bf800456.jpg',
|
||||
'title' => 'Client Deep Teal',
|
||||
'subtitle' => 'Original curated rich hospital theme',
|
||||
'tag' => 'Active Default',
|
||||
'url' => 'http://localhost:8080/assets/images/hospital_wallpaper_20261027_203745_bf800456.jpg',
|
||||
],
|
||||
],
|
||||
'hospital_logo' => 'logo.png',
|
||||
'hospital_logo_url' => 'http://localhost:8080/assets/images/logo.png',
|
||||
'hospital_name' => 'Johri Hospital',
|
||||
];
|
||||
|
||||
// Check right side layout container
|
||||
$this->assertStringContainsString('login-page-wrapper', $html);
|
||||
$this->assertStringContainsString('login-form-section', $html);
|
||||
$this->assertStringContainsString('login-hero-section', $html);
|
||||
$html = view('Setting/Admin/login_settings', $viewData);
|
||||
|
||||
// Verify key login elements exist in the right panel
|
||||
$this->assertStringContainsString('floatingUsernameInput', $html);
|
||||
$this->assertStringContainsString('floatingPasswordInput', $html);
|
||||
$this->assertStringContainsString('captchaInput', $html);
|
||||
$this->assertStringContainsString('loginMobileAppsModal', $html);
|
||||
// Layout position controls
|
||||
$this->assertStringContainsString('name="login_panel_position"', $html);
|
||||
$this->assertStringContainsString('value="left"', $html);
|
||||
$this->assertStringContainsString('value="center"', $html);
|
||||
$this->assertStringContainsString('value="right"', $html);
|
||||
|
||||
// Logo style controls
|
||||
$this->assertStringContainsString('name="login_logo_style"', $html);
|
||||
$this->assertStringContainsString('value="3d_box"', $html);
|
||||
$this->assertStringContainsString('value="glass"', $html);
|
||||
$this->assertStringContainsString('value="transparent"', $html);
|
||||
|
||||
// Typography theme & overlay
|
||||
$this->assertStringContainsString('name="login_hero_theme"', $html);
|
||||
$this->assertStringContainsString('name="login_hero_overlay"', $html);
|
||||
|
||||
// Feature switches
|
||||
$this->assertStringContainsString('name="login_show_subtitle"', $html);
|
||||
$this->assertStringContainsString('name="login_show_contact_meta"', $html);
|
||||
$this->assertStringContainsString('name="login_show_pwa_card"', $html);
|
||||
|
||||
// Presets and save button
|
||||
$this->assertStringContainsString('Client Deep Teal', $html);
|
||||
$this->assertStringContainsString('id="btn_save_login_settings"', $html);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user