Compare commits

...

1 Commits

Author SHA1 Message Date
Flatlogic Bot
c92b13307b Inventory 2025-10-02 00:56:41 +00:00
6 changed files with 805 additions and 158 deletions

250
add_item.php Normal file
View File

@ -0,0 +1,250 @@
<?php
require_once 'db/config.php';
$success_message = '';
$error_message = '';
if ($_SERVER["REQUEST_METHOD"] == "POST") {
try {
$pdo = db_connect();
// Basic validation
$required_fields = [
'acquisition_date', 'item_code', 'company_origin', 'category', 'sub_category',
'po_number', 'item_name', 'acquisition_price', 'item_user_name', 'user_division',
'user_department', 'location_city', 'location_building', 'location_area',
'current_condition', 'condition_at_acquisition', 'asset_status'
];
foreach ($required_fields as $field) {
if (empty($_POST[$field])) {
throw new Exception("Error: Field '{$field}' is required.");
}
}
$sql = "INSERT INTO inventory_items (
acquisition_date, item_code, company_origin, category, sub_category, po_number,
item_name, acquisition_price, item_user_name, user_division, user_department,
location_city, location_building, location_area, current_condition,
condition_at_acquisition, item_information, asset_status, transfer_status
) VALUES (
:acquisition_date, :item_code, :company_origin, :category, :sub_category, :po_number,
:item_name, :acquisition_price, :item_user_name, :user_division, :user_department,
:location_city, :location_building, :location_area, :current_condition,
:condition_at_acquisition, :item_information, :asset_status, :transfer_status
)";
$stmt = $pdo->prepare($sql);
$stmt->execute([
':acquisition_date' => $_POST['acquisition_date'],
':item_code' => $_POST['item_code'],
':company_origin' => $_POST['company_origin'],
':category' => $_POST['category'],
':sub_category' => $_POST['sub_category'],
':po_number' => $_POST['po_number'],
':item_name' => $_POST['item_name'],
':acquisition_price' => $_POST['acquisition_price'],
':item_user_name' => $_POST['item_user_name'],
':user_division' => $_POST['user_division'],
':user_department' => $_POST['user_department'],
':location_city' => $_POST['location_city'],
':location_building' => $_POST['location_building'],
':location_area' => $_POST['location_area'],
':current_condition' => $_POST['current_condition'],
':condition_at_acquisition' => $_POST['condition_at_acquisition'],
':item_information' => $_POST['item_information'] ?? '',
':asset_status' => $_POST['asset_status'],
':transfer_status' => $_POST['transfer_status'] ?? 'N/A',
]);
$success_message = "Inventory item added successfully!";
} catch (Exception $e) {
$error_message = "Error: " . $e->getMessage();
// Check for duplicate item_code
if ($e instanceof PDOException && $e->errorInfo[1] == 1062) {
$error_message = "Error: An item with this Item Code already exists.";
}
}
}
// Static options for dropdowns
$categories = ['Electronics', 'Furniture', 'Software', 'Office Supplies'];
$conditions = ['Good', 'Minor Damage', 'Major Damage', 'Broken'];
$conditions_acq = ['New', 'Used', 'Refurbished'];
$asset_statuses = ['Active', 'In Use', 'In Storage', 'Transferred', 'Disposed'];
$transfer_statuses = ['Pending', 'Approved', 'Rejected', 'Completed', 'N/A'];
$divisions = ['IT', 'HR', 'Finance', 'Operations'];
$departments = ['Help Desk', 'Recruitment', 'Accounting', 'Logistics'];
$cities = ['New York', 'London', 'Tokyo', 'Sydney'];
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Add New Inventory Item</title>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&family=Roboto+Slab:wght@700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
</head>
<body>
<header class="app-header">
<h1>Inventory Management System</h1>
<nav>
<a href="add_item.php" class="active">Add New Item</a>
<a href="inventory_list.php">View Inventory</a>
</nav>
</header>
<main class="container">
<div class="form-container card">
<h2>Add a New Inventory Item</h2>
<p>Fill out the form below to add a new asset to the inventory.</p>
<?php if ($success_message): ?>
<div class="toast success"><?php echo htmlspecialchars($success_message); ?></div>
<?php endif; ?>
<?php if ($error_message): ?>
<div class="toast error"><?php echo htmlspecialchars($error_message); ?></div>
<?php endif; ?>
<form action="add_item.php" method="POST" id="add-item-form">
<div class="form-grid">
<!-- Column 1 -->
<div class="form-column">
<div class="form-group">
<label for="acquisition_date">Acquisition Date</label>
<input type="date" id="acquisition_date" name="acquisition_date" required>
</div>
<div class="form-group">
<label for="item_code">Item Code (Unique)</label>
<input type="text" id="item_code" name="item_code" required>
</div>
<div class="form-group">
<label for="company_origin">Company Origin (PT)</label>
<input type="text" id="company_origin" name="company_origin" required>
</div>
<div class="form-group">
<label for="category">Category</label>
<select id="category" name="category" required>
<?php foreach ($categories as $cat): ?>
<option value="<?php echo htmlspecialchars($cat); ?>"><?php echo htmlspecialchars($cat); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="form-group">
<label for="sub_category">Sub Category</label>
<input type="text" id="sub_category" name="sub_category" required>
</div>
<div class="form-group">
<label for="po_number">Purchase Order Number</label>
<input type="text" id="po_number" name="po_number" required>
</div>
</div>
<!-- Column 2 -->
<div class="form-column">
<div class="form-group">
<label for="item_name">Inventory Item Name</label>
<input type="text" id="item_name" name="item_name" required>
</div>
<div class="form-group">
<label for="acquisition_price">Acquisition Price</label>
<input type="number" step="0.01" id="acquisition_price" name="acquisition_price" required>
</div>
<div class="form-group">
<label for="item_user_name">Item User Name</label>
<input type="text" id="item_user_name" name="item_user_name" required>
</div>
<div class="form-group">
<label for="user_division">User Division</label>
<select id="user_division" name="user_division" required>
<?php foreach ($divisions as $div): ?>
<option value="<?php echo htmlspecialchars($div); ?>"><?php echo htmlspecialchars($div); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="form-group">
<label for="user_department">User Department</label>
<select id="user_department" name="user_department" required>
<?php foreach ($departments as $dep): ?>
<option value="<?php echo htmlspecialchars($dep); ?>"><?php echo htmlspecialchars($dep); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="form-group">
<label for="asset_status">Asset Status</label>
<select id="asset_status" name="asset_status" required>
<?php foreach ($asset_statuses as $status): ?>
<option value="<?php echo htmlspecialchars($status); ?>"><?php echo htmlspecialchars($status); ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<!-- Column 3 -->
<div class="form-column">
<div class="form-group">
<label for="location_city">Location City</label>
<select id="location_city" name="location_city" required>
<?php foreach ($cities as $city): ?>
<option value="<?php echo htmlspecialchars($city); ?>"><?php echo htmlspecialchars($city); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="form-group">
<label for="location_building">Location Building</label>
<input type="text" id="location_building" name="location_building" required>
</div>
<div class="form-group">
<label for="location_area">Location Area / Room</label>
<input type="text" id="location_area" name="location_area" required>
</div>
<div class="form-group">
<label for="current_condition">Current Condition</label>
<select id="current_condition" name="current_condition" required>
<?php foreach ($conditions as $cond): ?>
<option value="<?php echo htmlspecialchars($cond); ?>"><?php echo htmlspecialchars($cond); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="form-group">
<label for="condition_at_acquisition">Condition at Acquisition</label>
<select id="condition_at_acquisition" name="condition_at_acquisition" required>
<?php foreach ($conditions_acq as $cond): ?>
<option value="<?php echo htmlspecialchars($cond); ?>"><?php echo htmlspecialchars($cond); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="form-group">
<label for="transfer_status">Transfer Status</label>
<select id="transfer_status" name="transfer_status" required>
<?php foreach ($transfer_statuses as $status): ?>
<option value="<?php echo htmlspecialchars($status); ?>"><?php echo htmlspecialchars($status); ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
</div>
<div class="form-group form-full-width">
<label for="item_information">Item Information (Notes)</label>
<textarea id="item_information" name="item_information" rows="4"></textarea>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">Add Item</button>
<button type="reset" class="btn btn-secondary">Clear Form</button>
</div>
</form>
</div>
</main>
<footer class="app-footer">
<p>&copy; <?php echo date("Y"); ?> Inventory Management System</p>
</footer>
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
</body>
</html>

283
assets/css/custom.css Normal file
View File

@ -0,0 +1,283 @@
/* General Body Styles */
body {
font-family: 'Roboto', sans-serif;
background-color: #ECF0F1;
color: #333;
line-height: 1.6;
margin: 0;
}
/* App Header */
.app-header {
background: linear-gradient(135deg, #2A3F54 0%, #3E5771 100%);
color: #FFFFFF;
padding: 1rem 2rem;
display: flex;
justify-content: space-between;
align-items: center;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.app-header h1 {
font-family: 'Roboto Slab', serif;
margin: 0;
font-size: 1.5rem;
color: #FFFFFF;
}
.app-header nav a {
color: #FFFFFF;
text-decoration: none;
margin-left: 1.5rem;
font-weight: 500;
padding-bottom: 0.25rem;
border-bottom: 2px solid transparent;
transition: border-color 0.3s ease;
}
.app-header nav a.active,
.app-header nav a:hover {
border-color: #2ECC71;
}
/* Main Container */
.container {
max-width: 1200px;
margin: 2rem auto;
padding: 0 2rem;
}
/* Card Style */
.card {
background-color: #FFFFFF;
border-radius: 0.5rem;
box-shadow: 0 4px 6px rgba(0,0,0,0.05);
padding: 2rem;
margin-bottom: 2rem;
}
/* Form Styles */
.form-container h2 {
font-family: 'Roboto Slab', serif;
color: #2A3F54;
margin-top: 0;
margin-bottom: 0.5rem;
}
.form-container p {
margin-top: 0;
margin-bottom: 2rem;
color: #555;
}
.form-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
}
.form-column {
display: flex;
flex-direction: column;
gap: 1.5rem;
}
.form-group {
display: flex;
flex-direction: column;
}
.form-group label {
font-weight: 700;
margin-bottom: 0.5rem;
color: #3E5771;
}
.form-group input,
.form-group select,
.form-group textarea {
width: 100%;
padding: 0.75rem;
border: 1px solid #ccc;
border-radius: 0.25rem;
font-size: 1rem;
transition: border-color 0.3s ease, box-shadow 0.3s ease;
}
.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
outline: none;
border-color: #2A3F54;
box-shadow: 0 0 0 2px rgba(42, 63, 84, 0.2);
}
.form-full-width {
grid-column: 1 / -1;
}
.form-actions {
grid-column: 1 / -1;
display: flex;
justify-content: flex-end;
gap: 1rem;
margin-top: 2rem;
}
/* Buttons */
.btn {
padding: 0.75rem 1.5rem;
border-radius: 0.25rem;
text-decoration: none;
color: #fff;
font-weight: bold;
transition: background-color 0.3s ease, transform 0.2s ease;
border: none;
cursor: pointer;
}
.btn:hover {
transform: translateY(-2px);
}
.btn-primary {
background-color: #2ECC71;
}
.btn-primary:hover {
background-color: #25a25a;
}
.btn-secondary {
background-color: #95a5a6;
}
.btn-secondary:hover {
background-color: #7f8c8d;
}
/* Toast Notifications */
.toast {
padding: 1rem;
margin-bottom: 1.5rem;
border-radius: 0.25rem;
color: #fff;
font-weight: 500;
}
.toast.success {
background-color: #2ECC71;
}
.toast.error {
background-color: #E74C3C;
}
/* Inventory List Specific */
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 2rem;
border-bottom: 1px solid #ddd;
padding-bottom: 1rem;
}
.search-and-filter-section {
margin-bottom: 2rem;
}
.search-bar input {
width: 100%;
padding: 0.75rem;
border: 1px solid #ccc;
border-radius: 0.25rem;
margin-bottom: 1rem;
}
.filter-form {
margin-bottom: 2rem;
}
.filter-controls {
display: flex;
gap: 1rem;
align-items: center;
}
.filter-controls select {
padding: 0.75rem;
border: 1px solid #ccc;
border-radius: 0.25rem;
flex-grow: 1;
}
.filter-controls .btn {
padding: 0.75rem 1.5rem;
}
.inventory-table-container {
overflow-x: auto;
}
.inventory-table {
width: 100%;
border-collapse: collapse;
}
.inventory-table th, .inventory-table td {
padding: 1rem;
text-align: left;
border-bottom: 1px solid #ddd;
}
.inventory-table th {
font-family: 'Roboto Slab', serif;
}
.inventory-table th a {
text-decoration: none;
color: #2A3F54;
}
.inventory-table tbody tr:hover {
background-color: #f9f9f9;
}
.status {
padding: 0.25rem 0.5rem;
border-radius: 1rem;
color: #fff;
font-size: 0.8rem;
font-weight: bold;
text-transform: uppercase;
}
.status-active, .status-in-use {
background-color: #2ECC71;
}
.status-in-storage {
background-color: #3498DB;
}
.status-transferred {
background-color: #F1C40F;
}
.status-disposed {
background-color: #E74C3C;
}
/* App Footer */
.app-footer {
text-align: center;
padding: 2rem 0;
margin-top: 2rem;
color: #777;
font-size: 0.9rem;
}

36
assets/js/main.js Normal file
View File

@ -0,0 +1,36 @@
document.addEventListener('DOMContentLoaded', function() {
const addItemForm = document.getElementById('add-item-form');
if (addItemForm) {
addItemForm.addEventListener('submit', function(e) {
const requiredInputs = addItemForm.querySelectorAll('[required]');
let firstError = null;
requiredInputs.forEach(input => {
if (!input.value.trim()) {
input.style.borderColor = '#E74C3C';
if (!firstError) {
firstError = input;
}
} else {
input.style.borderColor = '#ccc';
}
});
if (firstError) {
e.preventDefault();
alert('Please fill out all required fields.');
firstError.focus();
}
});
}
// Auto-hide toast messages
const toastMessages = document.querySelectorAll('.toast');
toastMessages.forEach(toast => {
setTimeout(() => {
toast.style.display = 'none';
}, 5000); // Hide after 5 seconds
});
});

View File

@ -1,17 +1,64 @@
<?php
// Generated by setup_mariadb_project.sh — edit as needed.
define('DB_HOST', '127.0.0.1');
define('DB_NAME', 'app_30908');
define('DB_USER', 'app_30908');
define('DB_PASS', '98b730aa-be6c-479d-a47d-e5e7abc49229');
function db_connect() {
$host = '127.0.0.1';
$db = 'inventory_management';
$user = 'inventory_user';
$pass = 'password';
$charset = 'utf8mb4';
function db() {
static $pdo;
if (!$pdo) {
$pdo = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset=utf8mb4', DB_USER, DB_PASS, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
}
return $pdo;
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
$pdo = new PDO($dsn, $user, $pass, $options);
} catch (PDOException $e) {
throw new PDOException($e->getMessage(), (int)$e->getCode());
}
return $pdo;
}
function create_schema($pdo) {
$queries = [
'CREATE TABLE IF NOT EXISTS `inventory_items` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`acquisition_date` DATE NOT NULL,
`item_code` VARCHAR(255) UNIQUE NOT NULL,
`company_origin` VARCHAR(255) NOT NULL,
`category` VARCHAR(255) NOT NULL,
`sub_category` VARCHAR(255) NOT NULL,
`po_number` VARCHAR(255) NOT NULL,
`item_name` VARCHAR(255) NOT NULL,
`acquisition_price` DECIMAL(10, 2) NOT NULL,
`item_user_name` VARCHAR(255) NOT NULL,
`user_division` VARCHAR(255) NOT NULL,
`user_department` VARCHAR(255) NOT NULL,
`location_city` VARCHAR(255) NOT NULL,
`location_building` VARCHAR(255) NOT NULL,
`location_area` VARCHAR(255) NOT NULL,
`current_condition` VARCHAR(255) NOT NULL,
`condition_at_acquisition` VARCHAR(255) NOT NULL,
`item_information` TEXT,
`asset_status` VARCHAR(255) NOT NULL,
`transfer_status` VARCHAR(255) NOT NULL,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);'
];
foreach ($queries as $query) {
$pdo->exec($query);
}
}
try {
$pdo = db_connect();
create_schema($pdo);
} catch (PDOException $e) {
// In a real app, you'd log this error
error_log($e->getMessage());
// You could also show a generic error page
// die("Database setup failed. Please check the logs.");
}
?>

161
index.php
View File

@ -1,150 +1,23 @@
<?php
declare(strict_types=1);
@ini_set('display_errors', '1');
@error_reporting(E_ALL);
@date_default_timezone_set('UTC');
$phpVersion = PHP_VERSION;
$now = date('Y-m-d H:i:s');
?>
<!doctype html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>New Style</title>
<?php
// Read project preview data from environment
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? '';
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
?>
<?php if ($projectDescription): ?>
<!-- Meta description -->
<meta name="description" content='<?= htmlspecialchars($projectDescription) ?>' />
<!-- Open Graph meta tags -->
<meta property="og:description" content="<?= htmlspecialchars($projectDescription) ?>" />
<!-- Twitter meta tags -->
<meta property="twitter:description" content="<?= htmlspecialchars($projectDescription) ?>" />
<?php endif; ?>
<?php if ($projectImageUrl): ?>
<!-- Open Graph image -->
<meta property="og:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
<!-- Twitter image -->
<meta property="twitter:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
<?php endif; ?>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
<style>
:root {
--bg-color-start: #6a11cb;
--bg-color-end: #2575fc;
--text-color: #ffffff;
--card-bg-color: rgba(255, 255, 255, 0.01);
--card-border-color: rgba(255, 255, 255, 0.1);
}
body {
margin: 0;
font-family: 'Inter', sans-serif;
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
color: var(--text-color);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
text-align: center;
overflow: hidden;
position: relative;
}
body::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path d="M-10 10L110 10M10 -10L10 110" stroke-width="1" stroke="rgba(255,255,255,0.05)"/></svg>');
animation: bg-pan 20s linear infinite;
z-index: -1;
}
@keyframes bg-pan {
0% { background-position: 0% 0%; }
100% { background-position: 100% 100%; }
}
main {
padding: 2rem;
}
.card {
background: var(--card-bg-color);
border: 1px solid var(--card-border-color);
border-radius: 16px;
padding: 2rem;
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.1);
}
.loader {
margin: 1.25rem auto 1.25rem;
width: 48px;
height: 48px;
border: 3px solid rgba(255, 255, 255, 0.25);
border-top-color: #fff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.hint {
opacity: 0.9;
}
.sr-only {
position: absolute;
width: 1px; height: 1px;
padding: 0; margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap; border: 0;
}
h1 {
font-size: 3rem;
font-weight: 700;
margin: 0 0 1rem;
letter-spacing: -1px;
}
p {
margin: 0.5rem 0;
font-size: 1.1rem;
}
code {
background: rgba(0,0,0,0.2);
padding: 2px 6px;
border-radius: 4px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
footer {
position: absolute;
bottom: 1rem;
font-size: 0.8rem;
opacity: 0.7;
}
</style>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Inventory Management System</title>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&family=Roboto+Slab:wght@700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="assets/css/custom.css">
</head>
<body>
<main>
<div class="card">
<h1>Analyzing your requirements and generating your website…</h1>
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
<span class="sr-only">Loading…</span>
</div>
<p class="hint"><?= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWizzy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.</p>
<p class="hint">This page will update automatically as the plan is implemented.</p>
<p>Runtime: PHP <code><?= htmlspecialchars($phpVersion) ?></code> — UTC <code><?= htmlspecialchars($now) ?></code></p>
<div class="container">
<header class="header">
<h1>Inventory Management System</h1>
</header>
<div style="text-align:center; padding: 4rem 0;">
<h2>Welcome!</h2>
<p>You can start by viewing the inventory or adding a new item.</p>
<a href="inventory_list.php" class="btn btn-primary">View Inventory</a>
<a href="add_item.php" class="btn" style="background-color: #3498DB;">Add New Item</a>
</div>
</div>
</main>
<footer>
Page updated: <?= htmlspecialchars($now) ?> (UTC)
</footer>
</body>
</html>
</html>

158
inventory_list.php Normal file
View File

@ -0,0 +1,158 @@
<?php
require_once 'db/config.php';
$pdo = db_connect();
// Get distinct values for filters
$categories = $pdo->query("SELECT DISTINCT category FROM inventory_items ORDER BY category")->fetchAll(PDO::FETCH_COLUMN);
$statuses = $pdo->query("SELECT DISTINCT asset_status FROM inventory_items ORDER BY asset_status")->fetchAll(PDO::FETCH_COLUMN);
$locations = $pdo->query("SELECT DISTINCT location_city FROM inventory_items ORDER BY location_city")->fetchAll(PDO::FETCH_COLUMN);
// Base query
$sql = "SELECT id, item_name, item_code, category, asset_status, location_city, acquisition_price, acquisition_date FROM inventory_items";
$params = [];
$where_clauses = [];
// Search
$search = $_GET['search'] ?? '';
if ($search) {
$search_term = "%{$search}%";
$where_clauses[] = "(item_name LIKE :search OR item_code LIKE :search OR po_number LIKE :search OR item_user_name LIKE :search OR user_department LIKE :search OR location_city LIKE :search OR company_origin LIKE :search)";
$params[':search'] = $search_term;
}
// Filters
$filter_category = $_GET['category'] ?? '';
if ($filter_category) {
$where_clauses[] = "category = :category";
$params[':category'] = $filter_category;
}
$filter_status = $_GET['status'] ?? '';
if ($filter_status) {
$where_clauses[] = "asset_status = :status";
$params[':status'] = $filter_status;
}
$filter_location = $_GET['location'] ?? '';
if ($filter_location) {
$where_clauses[] = "location_city = :location";
$params[':location'] = $filter_location;
}
if (!empty($where_clauses)) {
$sql .= " WHERE " . implode(' AND ', $where_clauses);
}
// Sorting
$sort_columns = ['item_name', 'item_code', 'category', 'asset_status', 'location_city', 'acquisition_price', 'acquisition_date'];
$sort_column = $_GET['sort'] ?? 'acquisition_date';
$sort_direction = $_GET['dir'] ?? 'desc';
if (!in_array($sort_column, $sort_columns)) {
$sort_column = 'acquisition_date';
}
$sort_direction = strtolower($sort_direction) === 'asc' ? 'asc' : 'desc';
$sql .= " ORDER BY `$sort_column` $sort_direction";
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$items = $stmt->fetchAll();
function get_sort_link($column, $current_sort, $current_dir) {
$dir = ($current_sort === $column && $current_dir === 'asc') ? 'desc' : 'asc';
$query_params = http_build_query(array_merge($_GET, ['sort' => $column, 'dir' => $dir]));
return '?' . $query_params;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Inventory List</title>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&family=Roboto+Slab:wght@700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="assets/css/custom.css">
</head>
<body>
<div class="container">
<header class="header">
<h1>Inventory List</h1>
<a href="add_item.php" class="btn btn-primary">Add New Item</a>
</header>
<form method="get" action="inventory_list.php" class="filter-form">
<div class="search-and-filter-section">
<div class="search-bar">
<input type="text" id="search" name="search" placeholder="Search by keyword..." value="<?= htmlspecialchars($search) ?>">
</div>
<div class="filter-controls">
<select name="category">
<option value="">All Categories</option>
<?php foreach ($categories as $category): ?>
<option value="<?= htmlspecialchars($category) ?>" <?= $filter_category === $category ? 'selected' : '' ?>><?= htmlspecialchars($category) ?></option>
<?php endforeach; ?>
</select>
<select name="status">
<option value="">All Statuses</option>
<?php foreach ($statuses as $status): ?>
<option value="<?= htmlspecialchars($status) ?>" <?= $filter_status === $status ? 'selected' : '' ?>><?= htmlspecialchars($status) ?></option>
<?php endforeach; ?>
</select>
<select name="location">
<option value="">All Locations</option>
<?php foreach ($locations as $location): ?>
<option value="<?= htmlspecialchars($location) ?>" <?= $filter_location === $location ? 'selected' : '' ?>><?= htmlspecialchars($location) ?></option>
<?php endforeach; ?>
</select>
<button type="submit" class="btn">Filter</button>
<a href="/inventory_list.php" class="btn btn-sm" style="background-color: #95a5a6;">Reset</a>
</div>
</div>
</form>
<div class="inventory-table-container">
<table class="inventory-table">
<thead>
<tr>
<th><a href="<?= get_sort_link('item_name', $sort_column, $sort_direction) ?>">Item Name</a></th>
<th><a href="<?= get_sort_link('item_code', $sort_column, $sort_direction) ?>">Item Code</a></th>
<th><a href="<?= get_sort_link('category', $sort_column, $sort_direction) ?>">Category</a></th>
<th><a href="<?= get_sort_link('asset_status', $sort_column, $sort_direction) ?>">Status</a></th>
<th><a href="<?= get_sort_link('location_city', $sort_column, $sort_direction) ?>">Location</a></th>
<th><a href="<?= get_sort_link('acquisition_price', $sort_column, $sort_direction) ?>">Price</a></th>
<th><a href="<?= get_sort_link('acquisition_date', $sort_column, $sort_direction) ?>">Acquisition Date</a></th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php if (empty($items)): ?>
<tr>
<td colspan="8" style="text-align:center;">No inventory items found matching your criteria.</td>
</tr>
<?php else: ?>
<?php foreach ($items as $item): ?>
<tr>
<td><?= htmlspecialchars($item['item_name']) ?></td>
<td><?= htmlspecialchars($item['item_code']) ?></td>
<td><?= htmlspecialchars($item['category']) ?></td>
<td><span class="status status-<?= strtolower(str_replace(' ', '-', $item['asset_status'])) ?>"><?= htmlspecialchars($item['asset_status']) ?></span></td>
<td><?= htmlspecialchars($item['location_city']) ?></td>
<td>$<?= number_format($item['acquisition_price'], 2) ?></td>
<td><?= htmlspecialchars($item['acquisition_date']) ?></td>
<td>
<a href="edit_item.php?id=<?= $item['id'] ?>" class="btn btn-sm">Edit</a>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
<script src="assets/js/main.js"></script>
</body>
</html>