diff --git a/app/Controllers/Setting/HospitalProfile.php b/app/Controllers/Setting/HospitalProfile.php
index 634f8b8..d6bc79b 100644
--- a/app/Controllers/Setting/HospitalProfile.php
+++ b/app/Controllers/Setting/HospitalProfile.php
@@ -15,6 +15,7 @@ class HospitalProfile extends BaseController
$logo = $this->readSettingValue('H_logo');
$pharmacyLogo = $this->readSettingValue('H_Med_logo');
+ $wallpaper = $this->readSettingValue('H_login_wallpaper');
helper('common');
return view('Setting/Admin/hospital_profile', [
@@ -29,6 +30,8 @@ class HospitalProfile extends BaseController
: hms_default_version_id(),
'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)) : '',
'pharmacy_name' => $this->readSettingValue('H_Med_Name'),
'pharmacy_address' => $this->readSettingValue('H_Med_address_1'),
'pharmacy_phone' => $this->readSettingValue('H_Med_phone_No'),
@@ -158,6 +161,24 @@ class HospitalProfile extends BaseController
$savedCount++;
}
+ $wallpaperResult = $this->processLogoUpload(
+ $this->request->getFile('hospital_wallpaper'),
+ '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(),
+ ]);
+ }
+ if ($wallpaperResult['changed']) {
+ $savedCount++;
+ }
+
$pharmacyLogoResult = $this->processLogoUpload(
$this->request->getFile('pharmacy_logo'),
'pharmacy_logo',
@@ -181,6 +202,8 @@ class HospitalProfile extends BaseController
'error_text' => $savedCount > 0 ? 'Hospital profile saved successfully.' : 'No changes detected.',
'logo_url' => ($logo = $this->readSettingValue('H_logo')) !== '' ? base_url('assets/images/' . rawurlencode($logo)) : '',
'logo_name' => $this->readSettingValue('H_logo'),
+ 'wallpaper_url' => ($wp = $this->readSettingValue('H_login_wallpaper')) !== '' ? base_url('assets/images/' . rawurlencode($wp)) : '',
+ 'wallpaper_name' => $this->readSettingValue('H_login_wallpaper'),
'pharmacy_logo_url' => ($logo = $this->readSettingValue('H_Med_logo')) !== '' ? base_url('assets/images/' . rawurlencode($logo)) : '',
'pharmacy_logo_name' => $this->readSettingValue('H_Med_logo'),
'csrfName' => csrf_token(),
@@ -199,24 +222,30 @@ class HospitalProfile extends BaseController
}
$type = strtolower(trim((string) $this->request->getPost('type')));
- if ($type !== 'pharmacy') {
+ if ($type === 'pharmacy') {
+ $settingKey = 'H_Med_logo';
+ } elseif ($type === 'wallpaper') {
+ $settingKey = 'H_login_wallpaper';
+ } else {
$type = 'hospital';
+ $settingKey = 'H_logo';
}
- $settingKey = $type === 'pharmacy' ? 'H_Med_logo' : 'H_logo';
- $oldLogo = $this->readSettingValue($settingKey);
+ $oldFile = $this->readSettingValue($settingKey);
$ok = $this->upsertSettingValue($settingKey, '');
- if ($oldLogo !== '') {
- $oldPath = FCPATH . 'assets/images/' . basename($oldLogo);
+ if ($oldFile !== '') {
+ $oldPath = FCPATH . 'assets/images/' . basename($oldFile);
if (is_file($oldPath)) {
@unlink($oldPath);
}
}
+ $label = $type === 'wallpaper' ? 'Login wallpaper' : ucfirst($type) . ' logo';
+
return $this->response->setJSON([
'update' => $ok ? 1 : 0,
- 'error_text' => $ok ? ucfirst($type) . ' logo deleted.' : 'Unable to delete logo.',
+ 'error_text' => $ok ? $label . ' deleted.' : 'Unable to delete ' . strtolower($label) . '.',
'csrfName' => csrf_token(),
'csrfHash' => csrf_hash(),
]);
@@ -234,6 +263,7 @@ class HospitalProfile extends BaseController
$logo = $this->readSettingValue('H_logo');
$pharmacyLogo = $this->readSettingValue('H_Med_logo');
+ $wallpaper = $this->readSettingValue('H_login_wallpaper');
$this->db->table('hospital_setting')->whereIn('s_name', [
'H_Name',
'H_address_1',
@@ -243,6 +273,7 @@ class HospitalProfile extends BaseController
'H_HFR_ID',
'HMS_UPDATE_ID',
'H_logo',
+ 'H_login_wallpaper',
'H_Med_Name',
'H_Med_address_1',
'H_Med_phone_No',
@@ -266,6 +297,13 @@ class HospitalProfile extends BaseController
}
}
+ if ($wallpaper !== '') {
+ $wpPath = FCPATH . 'assets/images/' . basename($wallpaper);
+ if (is_file($wpPath)) {
+ @unlink($wpPath);
+ }
+ }
+
return $this->response->setJSON([
'update' => 1,
'error_text' => 'Hospital profile settings reset.',
diff --git a/app/Views/Setting/Admin/hospital_profile.php b/app/Views/Setting/Admin/hospital_profile.php
index bb30e18..0cf5b15 100644
--- a/app/Views/Setting/Admin/hospital_profile.php
+++ b/app/Views/Setting/Admin/hospital_profile.php
@@ -67,6 +67,23 @@
+
+
+
+
Displayed on the software login page. Recommended: 1920x1080 or 1280x720 (PNG, JPG, WEBP).
+
+
+
+
+
+
 $hospital_wallpaper_url) ?>)
+
= esc((string) ($hospital_wallpaper ?? '')) ?>
+
+
No wallpaper uploaded (Login page uses blank/neutral)
+
+
+
+
Pharmacy Information
@@ -105,6 +122,7 @@
+
@@ -149,6 +167,17 @@
wrap.html(html);
}
+ function renderWallpaper(targetId, url, name) {
+ var wrap = $('#' + targetId);
+ if (!url) {
+ wrap.html('
No wallpaper uploaded (Login page uses blank/neutral)');
+ return;
+ }
+ var html = '

'
+ + '
' + $('
').text(name || '').html() + '
';
+ wrap.html(html);
+ }
+
$('#btn_hospital_profile_save').on('click', function() {
var name = ($('#hospital_name').val() || '').trim();
var address = ($('#hospital_address_1').val() || '').trim();
@@ -178,6 +207,10 @@
if (fileInput && fileInput.files && fileInput.files.length > 0) {
fd.append('hospital_logo', fileInput.files[0]);
}
+ var wallpaperInput = document.getElementById('hospital_wallpaper');
+ if (wallpaperInput && wallpaperInput.files && wallpaperInput.files.length > 0) {
+ fd.append('hospital_wallpaper', wallpaperInput.files[0]);
+ }
var pharmacyLogoInput = document.getElementById('pharmacy_logo');
if (pharmacyLogoInput && pharmacyLogoInput.files && pharmacyLogoInput.files.length > 0) {
fd.append('pharmacy_logo', pharmacyLogoInput.files[0]);
@@ -200,10 +233,14 @@
if (fileInput) {
fileInput.value = '';
}
+ if (wallpaperInput) {
+ wallpaperInput.value = '';
+ }
if (pharmacyLogoInput) {
pharmacyLogoInput.value = '';
}
renderLogo('hospital_logo_preview', data.logo_url || '', data.logo_name || '');
+ renderWallpaper('hospital_wallpaper_preview', data.wallpaper_url || '', data.wallpaper_name || '');
renderLogo('pharmacy_logo_preview', data.pharmacy_logo_url || '', data.pharmacy_logo_name || '');
}).fail(function(xhr) {
var data = (xhr && xhr.responseJSON) ? xhr.responseJSON : {};
@@ -237,6 +274,30 @@
});
});
+ $('#btn_hospital_wallpaper_delete').on('click', function() {
+ if (!confirm('Delete hospital login wallpaper?')) {
+ return;
+ }
+ var csrf = getCsrfPair();
+ var payload = {};
+ payload[csrf.name] = csrf.value;
+ payload.type = 'wallpaper';
+
+ $.post('= base_url('setting/admin/hospital-profile/delete-logo') ?>', payload, function(data) {
+ updateCsrf(data || {});
+ if ((data.update || 0) !== 1) {
+ showMessage('error', data.error_text || 'Unable to delete wallpaper.');
+ return;
+ }
+ showMessage('success', data.error_text || 'Wallpaper deleted.');
+ renderWallpaper('hospital_wallpaper_preview', '', '');
+ }, 'json').fail(function(xhr) {
+ var data = (xhr && xhr.responseJSON) ? xhr.responseJSON : {};
+ updateCsrf(data || {});
+ showMessage('error', data.error_text || 'Server error while deleting wallpaper.');
+ });
+ });
+
$('#btn_pharmacy_logo_delete').on('click', function() {
if (!confirm('Delete pharmacy logo?')) {
return;
@@ -293,11 +354,16 @@
if (fileInput) {
fileInput.value = '';
}
+ var wallpaperInput = document.getElementById('hospital_wallpaper');
+ if (wallpaperInput) {
+ wallpaperInput.value = '';
+ }
var pharmacyLogoInput = document.getElementById('pharmacy_logo');
if (pharmacyLogoInput) {
pharmacyLogoInput.value = '';
}
renderLogo('hospital_logo_preview', '', '');
+ renderWallpaper('hospital_wallpaper_preview', '', '');
renderLogo('pharmacy_logo_preview', '', '');
showMessage('success', data.error_text || 'Profile reset completed.');
}, 'json').fail(function(xhr) {
diff --git a/app/Views/auth/login.php b/app/Views/auth/login.php
index 9a51969..88385e3 100644
--- a/app/Views/auth/login.php
+++ b/app/Views/auth/login.php
@@ -1,4 +1,31 @@
-
+
@@ -6,7 +33,7 @@
-
= lang('Auth.login') ?>
+
= lang('Auth.login') ?> - = esc($hospitalName !== '' ? $hospitalName : 'E-Atria HMS') ?>
@@ -18,186 +45,441 @@
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
= lang('Auth.loginTitle') ?>
-
= lang('Auth.loginSubtitle') ?>
-
-
-
-
= esc(session('error')) ?>
-
-
-
-
- = esc($error) ?>
-
-
-
- = esc(session('errors')) ?>
-
-
-
-
-
-
= esc(session('message')) ?>
-
-
-
-
-
-
-
-
-
-
-
- Mobile PWA Suite
- Installable Apps
-
-
Hospital Mobile Apps & QR Codes
-
- Instant home-screen installation on Android & iPhone. Scan QR code to launch Nursing, Doctor, Pharmacy POS & Token Queue apps.
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
 ?>)
+
+
= esc($hospitalName) ?>
+
+
+
+
+ = esc($hospitalName) ?>
+
+
+
+
+
+
+
+
= esc($hospitalName) ?>
+
+
Hospital Information Management System
+
+
+
+ Secure Healthcare Delivery, Digital EMR & Clinical Management Portal
+
+
+
+
+
+
+ = esc($hospitalAddress1) ?>= !empty($hospitalAddress2) ? ', ' . esc($hospitalAddress2) : '' ?>
+
+
+
+
+ = esc($hospitalPhone) ?>
+
+
+
+
+ HFR ID: = esc($hospitalHfrId) ?>
+
+
+
+
+
+
+
+ ABDM M1, M2 & M3 Integrated
+
+
+ OPD, IPD & E-Prescription
+
+
+ Mobile PWA & Bedside Care
+
-
+
+
+ Government of India ABDM Compliant • Digital Health Mission
+
+
+
+
+
+
+
+
+
+
-
-
-
diff --git a/public/assets/images/sample_hospital_wallpaper.jpg b/public/assets/images/sample_hospital_wallpaper.jpg
new file mode 100644
index 0000000..d262fbd
Binary files /dev/null and b/public/assets/images/sample_hospital_wallpaper.jpg differ
diff --git a/tests/unit/HospitalProfileWallpaperTest.php b/tests/unit/HospitalProfileWallpaperTest.php
new file mode 100644
index 0000000..204bf0c
--- /dev/null
+++ b/tests/unit/HospitalProfileWallpaperTest.php
@@ -0,0 +1,71 @@
+query("CREATE TABLE IF NOT EXISTS db_hospital_setting (id INTEGER PRIMARY KEY AUTOINCREMENT, s_name TEXT, s_value TEXT)");
+ $db->query("CREATE TABLE IF NOT EXISTS db_settings (id INTEGER PRIMARY KEY AUTOINCREMENT, class TEXT, key TEXT, value TEXT, type TEXT, context TEXT, created_at TEXT, updated_at TEXT)");
+ }
+
+ public function testHospitalProfileViewContainsWallpaperControls(): void
+ {
+ $viewData = [
+ 'hospital_name' => 'City Hospital',
+ 'hospital_address_1' => '123 Medical Road',
+ 'hospital_address_2' => 'Civil Lines',
+ 'hospital_phone' => '9876543210',
+ 'hospital_email' => 'admin@cityhospital.in',
+ 'hospital_hfr_id' => 'IN0510000871',
+ 'footer_version' => '2026.01',
+ 'hospital_logo' => 'test_logo.png',
+ 'hospital_logo_url' => 'http://localhost:8080/assets/images/test_logo.png',
+ 'hospital_wallpaper' => 'test_wallpaper.jpg',
+ 'hospital_wallpaper_url' => 'http://localhost:8080/assets/images/test_wallpaper.jpg',
+ 'pharmacy_name' => 'City Hospital Pharmacy',
+ 'pharmacy_address' => 'Ground Floor',
+ 'pharmacy_phone' => '9876543211',
+ 'pharmacy_gst' => '05ABIPR7922F1ZJ',
+ 'pharmacy_logo' => '',
+ 'pharmacy_logo_url' => '',
+ 'sidebar_auto_hide_seconds' => '7',
+ 'allow_image_preupload_edit' => '0',
+ ];
+
+ $html = view('Setting/Admin/hospital_profile', $viewData);
+
+ $this->assertStringContainsString('id="hospital_wallpaper"', $html);
+ $this->assertStringContainsString('id="hospital_wallpaper_preview"', $html);
+ $this->assertStringContainsString('id="btn_hospital_wallpaper_delete"', $html);
+ $this->assertStringContainsString('test_wallpaper.jpg', $html);
+ $this->assertStringContainsString('renderWallpaper', $html);
+ }
+
+ public function testLoginViewRendersWithRightSideLayoutAndKeyElements(): void
+ {
+ $html = view('auth/login');
+
+ // Check right side layout container
+ $this->assertStringContainsString('login-page-wrapper', $html);
+ $this->assertStringContainsString('login-form-section', $html);
+ $this->assertStringContainsString('login-hero-section', $html);
+
+ // 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);
+ }
+}