diff --git a/Dockerfile b/Dockerfile index fbeac6b..5615025 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,18 @@ FROM php:8.2-apache -# Install required extensions -RUN docker-php-ext-install mysqli pdo pdo_mysql +# Set Philippines timezone +ENV TZ=Asia/Manila + +# Install required packages + PHP extensions +RUN apt-get update && apt-get install -y tzdata && \ + docker-php-ext-install mysqli pdo pdo_mysql + +# Configure system timezone +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \ + echo $TZ > /etc/timezone + +# Set PHP timezone +RUN echo "date.timezone = Asia/Manila" > /usr/local/etc/php/conf.d/timezone.ini # Enable Apache modules RUN a2enmod rewrite headers @@ -9,19 +20,19 @@ RUN a2enmod rewrite headers # Copy project COPY . /var/www/html/ -# Fix permissions (IMPORTANT FIXED TYPO) +# Fix permissions RUN chown -R www-data:www-data /var/www/html/ -# Ensure Apache allows .htaccess (API routing support) +# Ensure Apache allows .htaccess RUN sed -i 's/AllowOverride None/AllowOverride All/g' /etc/apache2/apache2.conf -# Optional: clean API-friendly Apache config +# Optional Apache config RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf -# Copy the default production PHP configuration +# Copy production PHP config RUN cp "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" -# Force PHP to allow Environment Variables in the $_ENV array +# Allow environment variables in PHP RUN sed -i 's/variables_order = "GPCS"/variables_order = "EGPCS"/g' "$PHP_INI_DIR/php.ini" EXPOSE 80 diff --git a/asalskdasd/sadasdsettings.local.json b/asalskdasd/sadasdsettings.local.json new file mode 100644 index 0000000..6db371f --- /dev/null +++ b/asalskdasd/sadasdsettings.local.json @@ -0,0 +1,8 @@ +{ + "env": { + "ANTHROPIC_BASE_URL": "https://openrouter.ai/api", + "ANTHROPIC_AUTH_TOKEN": "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", + "ANTHROPIC_API_KEY": "", + "ANTHROPIC_MODEL": "openrouter/free" + } +} diff --git a/assets/css/style.css b/assets/css/style.css index a223727..b82d8dd 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -1,131 +1,157 @@ -:root { - --bg-color: #f3f4f6; - --card-bg: #ffffff; - --primary-accent: #4f46e5; - --primary-hover: #4338ca; - --text-main: #1f2937; - --text-muted: #6b7280; - } - - body { - font-family: "Inter", sans-serif; - background-color: var(--bg-color); - color: var(--text-main); - padding-bottom: 2rem; - } - - /* Navbar Modernization */ - .navbar-custom { - background-color: rgba(255, 255, 255, 0.9); - backdrop-filter: blur(10px); - border-bottom: 1px solid rgba(0, 0, 0, 0.05); - position: sticky; - top: 0; - z-index: 1020; - } - - /* Sleek Cards */ - .card-custom { - background: var(--card-bg); - border: 1px solid rgba(0, 0, 0, 0.04); - border-radius: 16px; - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.03); - transition: transform 0.2s ease, box-shadow 0.2s ease; - } - - .kpi-card:hover { - transform: translateY(-3px); - box-shadow: 0 8px 25px rgba(0, 0, 0, 0.06); - } - - /* Modern Tabs */ - .nav-pills { - background: #e5e7eb; - padding: 0.35rem; - border-radius: 12px; - display: inline-flex; - overflow-x: auto; - white-space: nowrap; - flex-wrap: nowrap; - max-width: 100%; - } - - .nav-pills .nav-item { - margin: 0; - } - - .nav-pills .nav-link { - color: var(--text-muted); - font-weight: 500; - border-radius: 8px; - padding: 0.5rem 1.25rem; - transition: all 0.3s ease; - } - - .nav-pills .nav-link:hover { - color: var(--text-main); - } - - .nav-pills .nav-link.active { - background-color: var(--card-bg); - color: var(--primary-accent); - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); - } - - /* Responsive Tables */ - .table-custom { - margin-bottom: 0; - } - - .table-custom th { - font-weight: 600; - text-transform: uppercase; - font-size: 0.75rem; - letter-spacing: 0.5px; - color: var(--text-muted); - border-bottom: 2px solid #e5e7eb; - background-color: transparent; - } - - .table-custom td { - vertical-align: middle; - padding: 1rem 0.75rem; - border-bottom: 1px solid #f3f4f6; - } - - /* Form styling */ - .form-control, .form-select { - border-radius: 10px; - border: 1px solid #d1d5db; - padding: 0.6rem 1rem; - } - - .form-control:focus, .form-select:focus { - border-color: var(--primary-accent); - box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1); - } - - /* Buttons */ - .btn-primary { - background-color: var(--primary-accent); - border-color: var(--primary-accent); - } - .btn-primary:hover { - background-color: var(--primary-hover); - border-color: var(--primary-hover); - } - - /* Mobile Specific Hiding Rules */ - @media (max-width: 768px) { - .hide-on-mobile { - display: none !important; - } - .header-actions { - flex-direction: column; - align-items: stretch !important; - gap: 1rem; - } - .header-actions button { - width: 100%; - } - } \ No newline at end of file +:root { + --bg-color: #f3f4f6; + --card-bg: #ffffff; + --primary-accent: #4f46e5; + --primary-hover: #4338ca; + --text-main: #1f2937; + --text-muted: #6b7280; + } + + body { + font-family: "Inter", sans-serif; + background-color: var(--bg-color); + color: var(--text-main); + padding-bottom: 2rem; + } + + /* Navbar Modernization */ + .navbar-custom { + background-color: rgba(255, 255, 255, 0.9); + backdrop-filter: blur(10px); + border-bottom: 1px solid rgba(0, 0, 0, 0.05); + position: sticky; + top: 0; + z-index: 1020; + } + + /* Sleek Cards */ + .card-custom { + background: var(--card-bg); + border: 1px solid rgba(0, 0, 0, 0.04); + border-radius: 16px; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.03); + transition: transform 0.2s ease, box-shadow 0.2s ease; + } + + .kpi-card:hover { + transform: translateY(-3px); + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.06); + } + + /* Modern Tabs */ + .nav-pills { + background: #e5e7eb; + padding: 0.35rem; + border-radius: 12px; + display: inline-flex; + overflow-x: auto; + white-space: nowrap; + flex-wrap: nowrap; + max-width: 100%; + } + + .nav-pills .nav-item { + margin: 0; + } + + .nav-pills .nav-link { + color: var(--text-muted); + font-weight: 500; + border-radius: 8px; + padding: 0.5rem 1.25rem; + transition: all 0.3s ease; + } + + .nav-pills .nav-link:hover { + color: var(--text-main); + } + + .nav-pills .nav-link.active { + background-color: var(--card-bg); + color: var(--primary-accent); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); + } + + /* Responsive Tables */ + .table-custom { + margin-bottom: 0; + } + + .table-custom th { + font-weight: 600; + text-transform: uppercase; + font-size: 0.75rem; + letter-spacing: 0.5px; + color: var(--text-muted); + border-bottom: 2px solid #e5e7eb; + background-color: transparent; + } + + .table-custom td { + vertical-align: middle; + padding: 1rem 0.75rem; + border-bottom: 1px solid #f3f4f6; + } + + /* Form styling */ + .form-control, .form-select { + border-radius: 10px; + border: 1px solid #d1d5db; + padding: 0.6rem 1rem; + } + + .form-control:focus, .form-select:focus { + border-color: var(--primary-accent); + box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1); + } + + /* Buttons */ + .btn-primary { + background-color: var(--primary-accent); + border-color: var(--primary-accent); + } + .btn-primary:hover { + background-color: var(--primary-hover); + border-color: var(--primary-hover); + } + + /* Mobile Specific Hiding Rules */ + @media (max-width: 768px) { + .hide-on-mobile { + display: none !important; + } + .header-actions { + flex-direction: column; + align-items: stretch !important; + gap: 1rem; + } + .header-actions button { + width: 100%; + } + } + + /* Custom Toasts */ + .toast-custom { + background: rgba(255, 255, 255, 0.98); + backdrop-filter: blur(10px); + border: 1px solid rgba(0, 0, 0, 0.05); + border-radius: 16px; + box-shadow: 0 15px 35px rgba(0, 0, 0, 0.1); + transition: all 0.3s ease; + } + + .toast-header-custom { + background: transparent; + border-bottom: none; + padding: 1rem 1rem 0.5rem; + } + + .toast-body-custom { + padding: 0.5rem 1rem 1rem; + font-weight: 500; + } + + .toast-custom.toast-success { border-left: 5px solid #10b981; } + .toast-custom.toast-danger { border-left: 5px solid #ef4444; } + .toast-custom.toast-warning { border-left: 5px solid #f59e0b; } + .toast-custom.toast-info { border-left: 5px solid #3b82f6; } \ No newline at end of file diff --git a/assets/js/app.js b/assets/js/app.js index 77b0a10..6d2d3da 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -434,7 +434,22 @@ $(document).ready(function () { `; }); $("#lowStockTableBody").html(rows); - setTimeout(() => { $("#lowStockModal").modal("show"); }, 500); + // Replace modal with notification +setTimeout(() => { + if ('Notification' in window) { + Notification.requestPermission().then(permission => { + if (permission === 'granted') { + new Notification('Low Stock Alert!', { + body: 'Items below reorder level detected', + tag: 'lowStockAlert' + }); + } + }); + } else { + // Fallback to alert if notifications not supported + alert('Low Stock Alert! Items below reorder level detected'); + } +}, 500); } } diff --git a/assets/js/inventory.js b/assets/js/inventory.js index 94e3d18..bfdfe0c 100644 --- a/assets/js/inventory.js +++ b/assets/js/inventory.js @@ -245,7 +245,6 @@ $(document).ready(function () { }); }); - // --- 5. Low Stock Alerts --- function checkAndShowLowStockAlert(inventoryData) { let lowStockItems = inventoryData.filter(item => parseInt(item.quantity) <= parseInt(item.reorder_level)); @@ -260,10 +259,23 @@ $(document).ready(function () { `; }); $("#lowStockTableBody").html(rows); - setTimeout(() => { $("#lowStockModal").modal("show"); }, 500); + + // Show premium notification instead of modal + showNotification({ + title: 'Low Stock Alert!', + message: `${lowStockItems.length} items are below reorder level.`, + type: 'danger', + icon: 'bi-exclamation-triangle-fill', + action: { + label: 'View & Restock', + callback: 'viewLowStock()' + } + }); } } + + $(document).on("click", "#manualRestockBtn", function() { $("#lowStockModal").modal("hide"); switchTab('po'); diff --git a/assets/js/main.js b/assets/js/main.js index 34669dc..25d8254 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -24,25 +24,78 @@ let spendChartInstance = null; // ========================================== // 2. GLOBAL HELPER FUNCTIONS // ========================================== -function showAlert(msg, type) { - // Create a unique ID for this alert so the timer doesn't accidentally hide a newer alert - let alertId = 'alert-' + Date.now(); +function showAlert(msg, type = 'info') { + const toastId = 'toast-' + Date.now(); + const iconMap = { + 'success': 'bi-check-circle-fill', + 'danger': 'bi-exclamation-octagon-fill', + 'warning': 'bi-exclamation-triangle-fill', + 'info': 'bi-info-circle-fill' + }; + const icon = iconMap[type] || 'bi-bell-fill'; + const title = type.charAt(0).toUpperCase() + type.slice(1); - $("#alertBox").html(` -
- ${msg} - + const toastHtml = ` + - `); + `; - // Auto-hide the alert after 4 seconds (4000 milliseconds) - setTimeout(function() { - $("#" + alertId).fadeOut(400, function() { - $(this).remove(); // Completely removes it from the screen - }); - }, 4000); + $("#toastContainer").append(toastHtml); + + const toastElement = document.getElementById(toastId); + const toast = new bootstrap.Toast(toastElement, { autohide: false }); + toast.show(); + + toastElement.addEventListener('hidden.bs.toast', function () { + $(this).remove(); + }); } +// Global function for complex notifications (with buttons/links) +function showNotification(options) { + const toastId = 'notif-' + Date.now(); + const type = options.type || 'info'; + const icon = options.icon || 'bi-bell-fill'; + + const toastHtml = ` + + `; + + $("#toastContainer").append(toastHtml); + + const toastElement = document.getElementById(toastId); + const toast = new bootstrap.Toast(toastElement, { autohide: false }); + toast.show(); + + toastElement.addEventListener('hidden.bs.toast', function () { + $(this).remove(); + }); +} + +// Dedicated function for opening low stock modal +window.viewLowStock = function() { + $("#lowStockModal").modal("show"); +}; + + // ========================================== // 3. SPA LAZY LOADING ROUTER // ========================================== diff --git a/index.php b/index.php index 916433c..cbc7406 100644 --- a/index.php +++ b/index.php @@ -36,6 +36,7 @@
+
diff --git a/modals/vendor_modal.php b/modals/vendor_modal.php index 3bfc184..069ad1d 100644 --- a/modals/vendor_modal.php +++ b/modals/vendor_modal.php @@ -154,7 +154,7 @@