From ac96fe49defcc5eb8231d41060ae05d3d3a903a6 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sat, 21 Feb 2026 10:00:21 +0000 Subject: [PATCH] Autosave: 20260221-100021 --- assets/css/custom.css | 152 +++++++++++++++--- assets/js/main.js | 9 +- db/migrations/20260221_add_theme_to_users.sql | 2 + index.php | 145 ++++++++++------- post_debug.log | 13 ++ 5 files changed, 234 insertions(+), 87 deletions(-) create mode 100644 db/migrations/20260221_add_theme_to_users.sql diff --git a/assets/css/custom.css b/assets/css/custom.css index 1b2dfec..6a5a1b6 100644 --- a/assets/css/custom.css +++ b/assets/css/custom.css @@ -22,6 +22,39 @@ body.theme-dark { --border: #334155; } +body.theme-nord { + --primary: #2e3440; + --primary-light: #3b4252; + --accent: #88c0d0; + --bg: #eceff4; + --surface: #ffffff; + --text: #2e3440; + --text-muted: #4c566a; + --border: #d8dee9; +} + +body.theme-dracula { + --primary: #282a36; + --primary-light: #44475a; + --accent: #bd93f9; + --bg: #1e1f29; + --surface: #282a36; + --text: #f8f8f2; + --text-muted: #6272a4; + --border: #44475a; +} + +body.theme-citrus { + --primary: #365314; + --primary-light: #4d7c0f; + --accent: #84cc16; + --bg: #f7fee7; + --surface: #ffffff; + --text: #1a2e05; + --text-muted: #65a30d; + --border: #ecfccb; +} + body.theme-ocean { --primary: #083344; --primary-light: #164e63; @@ -79,9 +112,13 @@ body { z-index: 1000; } +/* Base positioning for desktop */ @media (min-width: 1200px) { - [dir="ltr"] .sidebar { left: 0; } - [dir="rtl"] .sidebar { right: 0; } + [dir="ltr"] .sidebar { left: 0 !important; right: auto !important; } + [dir="rtl"] .sidebar { right: 0 !important; left: auto !important; } + + [dir="ltr"] .main-content { margin-left: var(--sidebar-width) !important; margin-right: 0 !important; } + [dir="rtl"] .main-content { margin-left: 0 !important; margin-right: var(--sidebar-width) !important; } } .sidebar-header { @@ -157,7 +194,7 @@ body { } .pos-cart { width: 400px; - background: #fff; + background: var(--surface); border-radius: 12px; box-shadow: 0 4px 15px rgba(0,0,0,0.05); display: flex; @@ -170,9 +207,9 @@ body { gap: 15px; } .product-card { - background: #fff; + background: var(--surface); border-radius: 10px; - border: 1px solid #edf2f7; + border: 1px solid var(--border); padding: 15px; text-align: center; cursor: pointer; @@ -184,7 +221,7 @@ body { .product-card:hover { transform: translateY(-5px); box-shadow: 0 10px 20px rgba(0,0,0,0.05); - border-color: #3b82f6; + border-color: var(--accent); } .product-card img { width: 100%; @@ -195,7 +232,7 @@ body { } .product-card .price { font-weight: 700; - color: #2d3748; + color: var(--text); } .cart-items { flex: 1; @@ -208,11 +245,11 @@ body { align-items: center; margin-bottom: 15px; padding-bottom: 15px; - border-bottom: 1px solid #edf2f7; + border-bottom: 1px solid var(--border); } .cart-total { padding: 20px; - background: #f8fafc; + background: var(--bg); border-bottom-left-radius: 12px; border-bottom-right-radius: 12px; } @@ -225,16 +262,17 @@ body { width: 24px; height: 24px; border-radius: 50%; - border: 1px solid #e2e8f0; - background: #fff; + border: 1px solid var(--border); + background: var(--surface); display: flex; align-items: center; justify-content: center; cursor: pointer; font-size: 14px; + color: var(--text); } .qty-btn:hover { - background: #edf2f7; + background: var(--bg); } [dir="rtl"] .nav-link i { @@ -244,7 +282,6 @@ body { /* Main Content */ .main-content { - margin-left: var(--sidebar-width); padding: 2rem; transition: all 0.3s; min-height: 100vh; @@ -252,26 +289,24 @@ body { flex-direction: column; } -[dir="rtl"] .main-content { - margin-left: 0; - margin-right: var(--sidebar-width); -} +/* Desktop margins handled in the top @media block */ @media (max-width: 1199.98px) { [dir="ltr"] .sidebar { - left: calc(-1 * var(--sidebar-width)); + left: calc(-1 * var(--sidebar-width)) !important; } [dir="ltr"] .sidebar.show { - left: 0; - box-shadow: 0 0 50px rgba(0,0,0,0.3); + left: 0 !important; + box-shadow: 0 0 50px rgba(0,0,0,0.3) !important; } [dir="rtl"] .sidebar { - right: calc(-1 * var(--sidebar-width)); - left: auto; + right: calc(-1 * var(--sidebar-width)) !important; + left: auto !important; } [dir="rtl"] .sidebar.show { - right: 0; - box-shadow: 0 0 50px rgba(0,0,0,0.3); + right: 0 !important; + left: auto !important; + box-shadow: 0 0 50px rgba(0,0,0,0.3) !important; } .main-content { margin-left: 0 !important; @@ -348,6 +383,75 @@ body { } /* RTL Adjustments */ +/* Theme Compatibility Overrides */ +body.theme-dark, body.theme-dracula { + color-scheme: dark; +} + +body:not(.theme-default) .text-dark { + color: var(--text) !important; +} + +body:not(.theme-default) .bg-light, +body:not(.theme-default) .bg-white { + background-color: var(--surface) !important; +} + +body:not(.theme-default) .border-dark { + border-color: var(--border) !important; +} + +body:not(.theme-default) .list-group-item { + background-color: var(--surface); + color: var(--text); + border-color: var(--border); +} + +body:not(.theme-default) .list-group-item-action:hover { + background-color: var(--bg); + color: var(--accent); +} + +body:not(.theme-default) .dropdown-menu { + background-color: var(--surface); + border-color: var(--border); +} + +body:not(.theme-default) .dropdown-item { + color: var(--text); +} + +body:not(.theme-default) .dropdown-item:hover { + background-color: var(--primary-light); + color: #fff; +} + +body:not(.theme-default) .alert-warning { + background-color: var(--primary-light); + border-color: var(--accent); + color: var(--text); +} + +body:not(.theme-default) .modal-content { + background-color: var(--surface); + color: var(--text); + border-color: var(--border); +} + +body:not(.theme-default) .form-control, +body:not(.theme-default) .form-select { + background-color: var(--bg); + border-color: var(--border); + color: var(--text); +} + +body:not(.theme-default) .form-control:focus, +body:not(.theme-default) .form-select:focus { + background-color: var(--bg); + border-color: var(--accent); + color: var(--text); +} + [dir="rtl"] .ms-auto { margin-right: auto !important; margin-left: 0 !important; diff --git a/assets/js/main.js b/assets/js/main.js index 71b4bf4..2975cea 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -1,9 +1,9 @@ document.addEventListener('DOMContentLoaded', function() { const langToggle = document.getElementById('langToggle'); - // Check for saved language - const currentLang = localStorage.getItem('lang') || 'en'; - setLanguage(currentLang); + // Use the language set by PHP as initial source of truth + const initialLang = document.documentElement.lang || 'ar'; + localStorage.setItem('lang', initialLang); if (langToggle) { langToggle.addEventListener('click', function() { @@ -63,7 +63,7 @@ document.addEventListener('DOMContentLoaded', function() { const theme = this.getAttribute('data-theme'); // Remove all existing theme classes - const themes = ['theme-default', 'theme-dark', 'theme-ocean', 'theme-forest', 'theme-sunset']; + const themes = ['theme-default', 'theme-dark', 'theme-ocean', 'theme-forest', 'theme-sunset', 'theme-nord', 'theme-dracula', 'theme-citrus']; document.body.classList.remove(...themes); // Add new theme class @@ -92,6 +92,7 @@ document.addEventListener('DOMContentLoaded', function() { function setLanguage(lang) { document.documentElement.lang = lang; document.documentElement.dir = lang === 'ar' ? 'rtl' : 'ltr'; + document.body.dir = lang === 'ar' ? 'rtl' : 'ltr'; localStorage.setItem('lang', lang); // Update UI text diff --git a/db/migrations/20260221_add_theme_to_users.sql b/db/migrations/20260221_add_theme_to_users.sql new file mode 100644 index 0000000..3547ce1 --- /dev/null +++ b/db/migrations/20260221_add_theme_to_users.sql @@ -0,0 +1,2 @@ +-- Add theme column to users table +ALTER TABLE users ADD COLUMN theme VARCHAR(20) DEFAULT 'default' AFTER profile_pic; \ No newline at end of file diff --git a/index.php b/index.php index 92ac092..fa958fa 100644 --- a/index.php +++ b/index.php @@ -463,7 +463,7 @@ if (isset($_GET['action']) || isset($_POST['action'])) { exit; } $theme = $_POST['theme'] ?? 'default'; - $allowed = ['default', 'dark', 'ocean', 'forest', 'sunset']; + $allowed = ['default', 'dark', 'ocean', 'forest', 'sunset', 'nord', 'dracula', 'citrus']; if (!in_array($theme, $allowed)) $theme = 'default'; $stmt = db()->prepare("UPDATE users SET theme = ? WHERE id = ?"); @@ -2095,67 +2095,67 @@ $data = [ ]; $permission_groups = [ - 'General' => ['dashboard' => 'Dashboard'], + 'General' => ['dashboard' => __('dashboard')], 'Inventory' => [ - 'items' => 'Items', - 'categories' => 'Categories', - 'units' => 'Units' + 'items' => __('items'), + 'categories' => __('categories'), + 'units' => __('units') ], 'Customers' => [ - 'customers' => 'Customers' + 'customers' => __('customers') ], 'Suppliers' => [ - 'suppliers' => 'Suppliers' + 'suppliers' => __('suppliers') ], 'POS' => [ - 'pos' => 'POS' + 'pos' => __('pos') ], 'Sales' => [ - 'sales' => 'Sales', - 'sales_returns' => 'Sales Returns', - 'quotations' => 'Quotations' + 'sales' => __('sales'), + 'sales_returns' => __('sales_returns'), + 'quotations' => __('quotations') ], 'Purchases' => [ - 'purchases' => 'Purchases', - 'lpos' => 'LPOs', - 'purchase_returns' => 'Purchase Returns' + 'purchases' => __('purchases'), + 'lpos' => __('lpos'), + 'purchase_returns' => __('purchase_returns') ], 'Expenses' => [ - 'expense_categories' => 'Expense Categories', - 'expenses' => 'Expenses' + 'expense_categories' => __('expense_categories'), + 'expenses' => __('expenses') ], 'Accounting' => [ - 'accounting' => 'Journal Entries', - 'trial_balance' => 'Trial Balance', - 'profit_loss' => 'Profit & Loss', - 'balance_sheet' => 'Balance Sheet', - 'vat_report' => 'VAT Report' + 'accounting' => __('accounting'), + 'trial_balance' => __('trial_balance'), + 'profit_loss' => __('profit_loss'), + 'balance_sheet' => __('balance_sheet'), + 'vat_report' => __('vat_report') ], 'HR' => [ - 'hr_departments' => 'Departments', - 'hr_employees' => 'Employees', - 'hr_attendance' => 'Attendance', - 'hr_payroll' => 'Payroll' + 'hr_departments' => __('departments'), + 'hr_employees' => __('employees'), + 'hr_attendance' => __('attendance'), + 'hr_payroll' => __('payroll') ], 'Reports' => [ - 'customer_statement' => 'Customer Statement', - 'supplier_statement' => 'Supplier Statement', - 'expense_report' => 'Expense Report', - 'cashflow_report' => 'Cashflow Report', - 'expiry_report' => 'Expiry Report', - 'low_stock_report' => 'Low Stock Report', - 'loyalty_history' => 'Loyalty History' + 'customer_statement' => __('customer_statement'), + 'supplier_statement' => __('supplier_statement'), + 'expense_report' => __('expense_report'), + 'cashflow_report' => __('cashflow_report'), + 'expiry_report' => __('expiry_report'), + 'low_stock_report' => __('low_stock_report'), + 'loyalty_history' => __('loyalty_history') ], 'Settings' => [ - 'payment_methods' => 'Payment Methods', - 'devices' => 'Biometric Devices', - 'settings' => 'Company Settings' + 'payment_methods' => __('payment_methods'), + 'devices' => __('devices'), + 'settings' => __('settings') ], 'Administration' => [ - 'role_groups' => 'Role Groups', - 'users' => 'Users', - 'cash_registers' => 'Cash Registers', - 'register_sessions' => 'Register Sessions', + 'role_groups' => __('role_groups'), + 'users' => __('users'), + 'cash_registers' => __('cash_registers'), + 'register_sessions' => __('register_sessions'), 'logs' => 'System Logs' ] ]; @@ -2992,6 +2992,30 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';