diff --git a/assets/js/main.js b/assets/js/main.js index 896034f..a827a5d 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -30,6 +30,19 @@ document.addEventListener('DOMContentLoaded', function() { sidebar.classList.remove('show'); overlay.classList.remove('show'); }); + + // Sidebar Accordion logic: Close other collapses when one is opened + const sidebarCollapses = document.querySelectorAll('.sidebar .collapse'); + sidebarCollapses.forEach(collapseEl => { + collapseEl.addEventListener('show.bs.collapse', function () { + sidebarCollapses.forEach(otherCollapse => { + if (otherCollapse !== collapseEl && otherCollapse.classList.contains('show')) { + const bsCollapse = bootstrap.Collapse.getOrCreateInstance(otherCollapse); + bsCollapse.hide(); + } + }); + }); + }); }); function setLanguage(lang) { diff --git a/check_settings.php b/check_settings.php new file mode 100644 index 0000000..864bd7e --- /dev/null +++ b/check_settings.php @@ -0,0 +1,4 @@ +query("SELECT * FROM settings")->fetchAll(PDO::FETCH_KEY_PAIR); +echo json_encode($settings, JSON_PRETTY_PRINT); diff --git a/index.php b/index.php index 8823d98..fb081e3 100644 --- a/index.php +++ b/index.php @@ -106,6 +106,27 @@ function can(string $permission): bool { return is_array($perms) && in_array($permission, $perms); } +// Missing helper functions +function getLoyaltyMultiplier($tier) { + switch (strtolower((string)$tier)) { + case 'gold': return 2.0; + case 'silver': return 1.5; + default: return 1.0; + } +} + +function numberToWords($num) { + $num = (int)$num; + if ($num == 0) return "zero"; + $ones = ["", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"]; + $tens = ["", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"]; + if ($num < 20) return $ones[$num]; + if ($num < 100) return $tens[(int)($num / 10)] . ($num % 10 ? "-" . $ones[$num % 10] : ""); + if ($num < 1000) return $ones[(int)($num / 100)] . " hundred" . ($num % 100 ? " and " . numberToWords($num % 100) : ""); + if ($num < 1000000) return numberToWords((int)($num / 1000)) . " thousand" . ($num % 1000 ? " " . numberToWords($num % 1000) : ""); + return (string)$num; +} + // Login Logic $login_error = ''; if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['login'])) { @@ -719,6 +740,39 @@ if (isset($_POST['add_hr_department'])) { } } + if (isset($_POST['update_settings'])) { + if (can('settings_view')) { + $db = db(); + if (isset($_POST['settings']) && is_array($_POST['settings'])) { + foreach ($_POST['settings'] as $key => $value) { + $stmt = $db->prepare("INSERT INTO settings (`key`, `value`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `value` = ?"); + $stmt->execute([$key, $value, $value]); + } + } + + // Handle file uploads + $files = ['company_logo', 'favicon', 'manager_signature']; + foreach ($files as $file_key) { + if (isset($_FILES[$file_key]) && $_FILES[$file_key]['error'] === 0) { + $ext = pathinfo($_FILES[$file_key]['name'], PATHINFO_EXTENSION); + $filename = 'uploads/' . $file_key . '_' . time() . '.' . $ext; + if (!is_dir('uploads')) mkdir('uploads', 0777, true); + if (move_uploaded_file($_FILES[$file_key]['tmp_name'], $filename)) { + $stmt = $db->prepare("INSERT INTO settings (`key`, `value`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `value` = ?"); + $stmt->execute([$file_key, $filename, $filename]); + } + } + } + $message = "Settings updated successfully!"; + + // Reload settings for current request + $settings_raw = db()->query("SELECT * FROM settings")->fetchAll(); + foreach ($settings_raw as $s) { + $data['settings'][$s['key']] = $s['value']; + } + } + } + // --- Backup Handlers --- if (isset($_POST['create_backup'])) { if (can('users_view')) { // Admin check @@ -1825,10 +1879,13 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System'; + +