In the pasted code is my Product menu code. The problem is that, whenever i edit a product, even though there is akready a "Expiration Date" data under that product, it still require to input a espiration dta when im editing. Here is the code: <?php
session_start();
?>
<?php
/**
* Plugin Name: Product Menu Snippet
* Description: Adds a Product menu with add, edit, and delete functionality, including server-side search with a clear button.
*/
global $wpdb;
// --- Configuration ---
$product_table_name = 'products'; // Adjust if you use prefixes: $wpdb->prefix . 'products';
$category_table_name = 'categories'; // Adjust if you use prefixes: $wpdb->prefix . 'categories';
$inventory_history_table_name = 'inventory_history';
// Ensure upload directory exists
$upload_dir_info = wp_upload_dir();
$upload_dir = $upload_dir_info['basedir'] . '/product_images/';
$upload_url = $upload_dir_info['baseurl'] . '/product_images/'; // Base URL for displaying images
if (!file_exists($upload_dir)) {
wp_mkdir_p($upload_dir); // Use wp_mkdir_p for recursive creation
}
$editing_product = null; // Initialize editing product variable
$message = ''; // For success/error messages
$message_type = ''; // 'success' or 'error'
// Function to log inventory actions
function log_inventory_action($action_type, $item_type, $item_name, $description) {
global $wpdb;
$history_table_name = 'inventory_history';
$username = wp_get_current_user()->user_login;
$result = $wpdb->insert(
$history_table_name,
array(
'username' => $username,
'action_type' => $action_type,
'item_type' => $item_type,
'item_name' => $item_name,
'description' => $description,
'timestamp' => current_time('mysql')
),
array('%s', '%s', '%s', '%s', '%s', '%s')
);
return $result;
}
// --- Handle Delete Product Action ---
if (isset($_GET['action']) && $_GET['action'] === 'delete_product' && isset($_GET['id']) && isset($_GET['_wpnonce']) && wp_verify_nonce($_GET['_wpnonce'], 'delete_product_' . absint($_GET['id']))) {
$product_id_to_delete = absint($_GET['id']);
if ($product_id_to_delete) {
// Get product info before deletion for logging
$product_to_delete = $wpdb->get_row(
$wpdb->prepare("SELECT name FROM $product_table_name WHERE id = %d", $product_id_to_delete),
ARRAY_A
);
// Optional: Delete image file first
$image_url_to_delete = $wpdb->get_var($wpdb->prepare("SELECT image_url FROM $product_table_name WHERE id = %d", $product_id_to_delete));
if ($image_url_to_delete) {
$image_path = str_replace($upload_url, $upload_dir, $image_url_to_delete);
if (file_exists($image_path)) {
@unlink($image_path);
}
}
// Delete product record
$deleted = $wpdb->delete(
$product_table_name,
array('id' => $product_id_to_delete),
array('%d')
);
if ($deleted) {
$message = 'Product deleted successfully!';
$message_type = 'success';
// Log the deletion action
log_inventory_action(
'delete',
'product',
$product_to_delete['name'],
"Product {$product_to_delete['name']} was deleted from the system"
);
// Redirect after delete to clear URL parameters
wp_redirect(remove_query_arg(array('action', 'id', '_wpnonce')));
exit;
} else {
$message = 'Error deleting product.';
$message_type = 'error';
}
}
}
// --- Handle Edit Product Action (Prepare form) ---
if (isset($_GET['action']) && $_GET['action'] === 'edit_product' && isset($_GET['id'])) {
$product_id_to_edit = absint($_GET['id']);
if ($product_id_to_edit) {
$editing_product = $wpdb->get_row(
$wpdb->prepare("SELECT * FROM $product_table_name WHERE id = %d", $product_id_to_edit),
ARRAY_A
);
if (!$editing_product) {
$message = 'Product not found for editing.';
$message_type = 'error';
}
}
}
// --- Handle Add/Update Product Form Submission ---
if (isset($_POST['save_product']) && isset($_POST['_wpnonce_product_form']) && wp_verify_nonce($_POST['_wpnonce_product_form'], 'save_product_action')) {
// Sanitize and validate input data
$product_name = isset($_POST['product_name']) ? sanitize_text_field($_POST['product_name']) : '';
$product_category = isset($_POST['product_category']) ? sanitize_text_field($_POST['product_category']) : '';
$unit = isset($_POST['unit']) ? sanitize_text_field($_POST['unit']) : '';
$buying_price = isset($_POST['buying_price']) ? preg_replace('/[^0-9.]/', '', $_POST['buying_price']) : '0';
$selling_price = isset($_POST['selling_price']) ? preg_replace('/[^0-9.]/', '', $_POST['selling_price']) : '0';
$quantity_submitted = isset($_POST['quantity_input']) ? absint($_POST['quantity_input']) : 0;
$expiration_date = sanitize_text_field($_POST['expiration_date']);
$edit_product_id = isset($_POST['edit_product_id']) ? absint($_POST['edit_product_id']) : 0;
$product_image_url = isset($_POST['old_image_url']) ? esc_url_raw($_POST['old_image_url']) : '';
// --- Image Upload Handling ---
if (isset($_FILES['product_image']) && $_FILES['product_image']['error'] === UPLOAD_ERR_OK) {
$file = $_FILES['product_image'];
if (!function_exists('wp_handle_upload')) {
require_once(ABSPATH . 'wp-admin/includes/file.php');
}
$upload_overrides = array('test_form' => false);
$movefile = wp_handle_upload($file, $upload_overrides, current_time('mysql'));
if ($movefile && !isset($movefile['error'])) {
$product_image_url = $movefile['url'];
if ($edit_product_id && isset($_POST['old_image_url']) && $_POST['old_image_url'] !== $product_image_url) {
$old_image_path = str_replace($upload_url, $upload_dir, esc_url_raw($_POST['old_image_url']));
if (file_exists($old_image_path)) {
@unlink($old_image_path);
}
}
} else {
$message = 'Image upload error: ' . esc_html($movefile['error']);
$message_type = 'error';
}
} elseif (isset($_FILES['product_image']) && $_FILES['product_image']['error'] !== UPLOAD_ERR_NO_FILE) {
$message = 'Image upload error code: ' . $_FILES['product_image']['error'];
$message_type = 'error';
}
// Proceed only if no upload error occurred or no file was uploaded
if ($message_type !== 'error') {
if (!empty($product_name) && !empty($product_category) && is_numeric($buying_price) && is_numeric($selling_price)) {
$product_data = array(
'image_url' => $product_image_url,
'name' => $product_name,
'category' => $product_category,
'unit' => $unit,
'buying_price' => (float)$buying_price,
'selling_price' => (float)$selling_price,
'expiration_date' => $expiration_date,
);
$data_format = array('%s', '%s', '%s', '%s', '%f', '%f', '%s');
if ($edit_product_id) {
// --- UPDATE existing product ---
$current_stock = $wpdb->get_var(
$wpdb->prepare("SELECT in_stock FROM $product_table_name WHERE id = %d", $edit_product_id)
);
if ($current_stock === null) {
$message = 'Error: Could not find product to update stock.';
$message_type = 'error';
} else {
$new_stock_value = absint($current_stock) + $quantity_submitted;
$product_data['in_stock'] = $new_stock_value;
$data_format[] = '%d';
$updated = $wpdb->update(
$product_table_name,
$product_data,
array('id' => $edit_product_id),
$data_format,
array('%d')
);
if ($updated !== false) {
$message = 'Product updated successfully!';
$message_type = 'success';
// Log the update action
log_inventory_action(
'update',
'product',
$product_name,
"Product {$product_name} was updated. Stock changed by {$quantity_submitted} (new total: {$new_stock_value})"
);
$editing_product = null;
} else {
$message = 'Error updating product. ' . $wpdb->last_error;
$message_type = 'error';
}
}
} else {
// --- INSERT new product ---
$product_data['in_stock'] = $quantity_submitted;
$product_data['created_at'] = current_time('mysql');
$data_format[] = '%d';
$data_format[] = '%s';
$inserted = $wpdb->insert(
$product_table_name,
$product_data,
$data_format
);
if ($inserted) {
$message = 'Product added successfully!';
$message_type = 'success';
// Log the add action
log_inventory_action(
'add',
'product',
$product_name,
"Product {$product_name} was added with initial stock of {$quantity_submitted}"
);
} else {
$message = 'Error adding product. ' . $wpdb->last_error;
$message_type = 'error';
}
}
} else {
$message = 'Please fill in all required fields with valid data.';
$message_type = 'error';
}
}
} elseif (isset($_POST['save_product'])) {
$message = 'Security check failed. Please try again.';
$message_type = 'error';
}
// --- Fetch Products and Categories for Display ---
$sql = "SELECT id, image_url, name, category, unit, in_stock, buying_price, selling_price, expiration_date,created_at, updated_at FROM $product_table_name";
$where = '';
$search_term = isset($_GET['product_search']) ? sanitize_text_field(wp_unslash($_GET['product_search'])) : '';
if (!empty($search_term)) {
$search_like = '%' . $wpdb->esc_like($search_term) . '%';
$where = $wpdb->prepare(
" WHERE name LIKE %s OR category LIKE %s OR unit LIKE %s",
$search_like,
$search_like,
$search_like
);
}
$order_by = " ORDER BY name ASC";
$products_sql = $sql . $where . $order_by;
$products = $wpdb->get_results($products_sql, ARRAY_A);
$categories = $wpdb->get_results("SELECT name FROM $category_table_name ORDER BY name ASC", ARRAY_A);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Product Management</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 0;
padding: 0;
background-color: #f4f7f9;
color: #333;
}
.dashboard-container {
display: flex;
}
.sidebar {
width: 240px;
background-color: #D1B48C;
color: #000000;
height: 100vh;
position: fixed;
left: 0;
top: 0;
overflow-y: auto;
box-shadow: 2px 0 5px rgba(0, 0, 0, 0.1);
z-index: 1000;
}
.sidebar-header {
padding: 20px;
text-align: center;
}
.sidebar-header .inventory-name {
font-size: 17px;
font-weight: bold;
color: #000;
}
.sidebar-menu {
padding: 20px 0;
}
.sidebar-menu ul {
list-style: none;
padding: 0;
margin: 0;
}
.sidebar-menu li a {
display: flex;
align-items: center;
padding: 12px 20px;
text-decoration: none;
color: #000000;
transition: background-color 0.3s ease, color 0.3s ease;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: 16px;
}
.sidebar-menu li a i {
margin-right: 12px;
width: 20px;
text-align: center;
flex-shrink: 0;
}
.sidebar-menu li a:hover {
background-color: #ffffff;
color: #000000;
}
.main-content {
margin-left: 240px;
padding: 20px;
flex-grow: 1;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #fff;
padding: 15px 30px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
border-bottom: 1px solid #eee;
margin-bottom: 20px;
}
.header-left .date-time {
font-size: 15px;
color: #555;
font-weight: 500;
}
.header-right {
display: flex;
align-items: center;
font-size: 16px;
color: #333;
}
.header-right .user-info {
display: flex;
align-items: center;
gap: 1px;
}
.header-right i {
color: #6c757d;
font-size: 40px;
}
.header-right span {
font-size: 15px;
color: #333;
}
.product-content {
display: flex;
flex-direction: column;
gap: 20px;
}
.product-form-container,
.product-list-container {
background-color: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
border: 1px solid #eee;
width: 100%;
}
.product-form-container h2,
.product-list-container h2 {
margin-top: 0;
color: #2f4050;
}
.product-form-container .form-row {
display: flex 1;
justify-content: space-between;
gap: 10px;
margin-bottom: 15px;
}
.product-form-container input[type="text"],
.product-form-container input[type="number"],
.product-form-container input[type="date"],
.product-form-container select {
flex: 1;
padding: 8px;
border: 1px solid #ced4da;
border-radius: 4px;
font-size: 1em;
}
.product-form-container input#quantity_input {
max-width: 150px;
}
.product-form-container input[type="date"] {
max-width: 180px;
}
.product-form-container input[type="file"] {
padding: 8px;
border: 1px solid #ced4da;
border-radius: 4px;
font-size: 1em;
background-color: #fff;
width: auto;
}
.form-row {
display: flex;
justify-content: space-between;
margin-bottom: 10px; /* Space between rows */
}
.product-form-container label {
font-weight: bold; /* Make label text bold */
font-size: 14px; /* Slightly increase the font size */
margin-bottom: 5px; /* Space between the label and input */
}
.product-form-container .form-actions {
display: flex;
gap: 10px;
margin-top: 10px;
}
.product-form-container button[type="submit"],
.product-form-container .cancel-button {
background-color: #000;
color: #fff;
border: none;
padding: 10px 20px;
cursor: pointer;
border-radius: 4px;
}
.product-form-container .cancel-button {
background-color: #e0e0e0;
color: #000;}
.product-list-container table {
width: 100%;
border-collapse: collapse;
}
.product-list-container th, .product-list-container td {
padding: 5px;
border-bottom: 1px solid #eee;
text-align: left;
}
/* --- Improved Styles for Search Bar --- */
.product-list-container form {
display: flex;
align-items: center;
margin-bottom: 15px;
width: auto;
gap: 8px; /* Add gap between wrapper and button */
}
.search-wrapper {
position: relative;
display: flex; /* Use flex for better control */
flex-grow: 0; /* Allow wrapper to take available space */
align-items: center; /* Vertically align items */
width: auto;
}
.product-search-bar {
padding: 8px 30px 8px 10px; /* Adjust padding: top/bottom, right (for clear), left */
border: 5px solid #000000; /* Slightly darker border */
border-radius: 4px;
font-size: 15px;
font-family: inherit;
width: 50%;
box-sizing: border-box;
line-height: 1.5; /* Adjust line height for better vertical centering */
transition: border-color 0.5s ease-in-out;
}
.product-search-bar:focus {
border-color: #0073aa; /* Highlight border on focus */
outline: none; /* Remove default outline */
box-shadow: 0 0 0 1px #0073aa; /* Optional: Add subtle focus shadow */
}
.clear-search-button {
position: absolute;
top: 50%;
right: 8px; /* Adjust position */
transform: translateY(-50%);
background: none;
border: none;
font-size: 1.5em; /* Slightly larger 'x' */
color: #aaa; /* Lighter color */
cursor: pointer;
padding: 0 4px;
line-height: 1;
display: none; /* Hide initially - JS will show it */
transition: color 0.2s ease-in-out;
}
.clear-search-button:hover {
color: #555; /* Darker on hover */
}
.search-submit-button {
padding: 8px 12px; /* Adjust padding */
background-color: #0073aa;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 1em;
line-height: 1.5; /* Match input line height */
transition: background-color 0.3s ease;
flex-shrink: 0;
display: inline-flex; /* Align icon nicely */
align-items: center;
justify-content: center;
}
.search-submit-button i {
font-size: 1pxem; /* Adjust icon size if needed */
}
.search-submit-button:hover {
background-color: #005a87;
}
/* --- End Search Bar Styles --- */
/* Add this to your existing CSS */
.product-list-container table th {
font-size: 16px; /* Increased from previous size */
font-weight: 700; /* Bolder */
padding: 12px 15px; /* Slightly more padding */
}
.product-list-container table td {
font-size: 15px; /* Increased from 0.95em */
padding: 5px 10px; /* Consistent padding with headers */
}
/* Make the "Expiring" items stand out more */
.product-list-container table td.expiring {
font-size: 15px;
font-weight: 600;
}
/* Make the "No Image" text slightly larger */
.product-list-container table td span[style*="color: #999"] {
font-size: 14px;
}
.product-list-container table { width: 100%; border-collapse: collapse; }
.product-list-container th, .product-list-container td { padding: 10px 12px; text-align: left; border-bottom: 1px solid #eee; font-size: 15pxem; vertical-align: middle; }
.product-list-container th { background-color: #f9f9f9; font-weight: 600; color: #555; white-space: nowrap; }
.product-list-container tbody tr:last-child td { border-bottom: none; }
.product-list-container tbody tr:hover { background-color: #f5f5f5; }
.product-list-container table img { max-width: 45px; max-height: 45px; display: block; border-radius: 3px; }
.product-actions a { margin-right: 5px; text-decoration: none; padding: 4px 8px; border-radius: 4px; color: #000000; font-size: 16px; white-space: nowrap; }
.product-actions a i { margin-right: 3px; }
/* Message Styles */
.notice-wrap { margin-bottom: 15px; }
.notice { padding: 10px 15px; border-radius: 4px; border-left: 4px solid; }
.notice-success { background-color: #d4edda; border-color: #28a745; color: #155724; }
.notice-error { background-color: #f8d7da; border-color: #dc3545; color: #721c24; }
.expiring {
color: red;
font-weight: bold;
}
.search-container {
margin-bottom: 20px; /* Space before the search input */
}
</style>
</head>
<body>
<div class="dashboard-container">
<aside class="sidebar">
<div class="sidebar-header">
<div class="inventory-name">ArKi Inventory</div>
</div>
<div class="sidebar-menu">
<ul>
<li><a href="http://localhost/inventory/index.php/admin-page/"><i class="fas fa-tachometer-alt"></i> Dashboard</a></li>
<?php
$current_username = isset($_SESSION['username']) ? $_SESSION['username'] : '';
if ($current_username === 'admin'):
?>
<li><a href="http://localhost/inventory/index.php/usersmanagement/"><i class="fas fa-users-cog"></i> User Management</a></li>
<li><a href="http://localhost/inventory/index.php/category-page/"><i class="fas fa-list"></i> Categories</a></li>
<li class="active"><a href="http://localhost/inventory/index.php/products/"><i class="fas fa-boxes"></i> Products</a></li>
<li><a href="http://localhost/inventory/index.php/order/"><i class="fas fa-shopping-cart"></i> Orders</a></li>
<li><a href="http://localhost/inventory/index.php/view-order/"><i class="fas fa-eye"></i> View Orders</a></li>
<li><a href="http://localhost/inventory/index.php/sales/"><i class="fas fa-chart-line"></i> Sales Report</a></li>
<li><a href="http://localhost/inventory/index.php/report/"><i class="fas fa-file-alt"></i> Inventory Report</a></li>
<li><a href="http://localhost/inventory/index.php/history/"><i class="fas fa-history"></i> History</a></li>
<?php else: ?>
<li><a href="http://localhost/inventory/index.php/category-page/"><i class="fas fa-list"></i> Categories</a></li>
<li class="active"><a href="http://localhost/inventory/index.php/products/"><i class="fas fa-boxes"></i> Products</a></li>
<li><a href="http://localhost/inventory/index.php/order/"><i class="fas fa-shopping-cart"></i> Orders</a></li>
<?php endif; ?>
<li><a href="http://localhost/inventory/index.php/sign-in2/" onclick="return confirm('Are you sure you want to log out?');"><i class="fas fa-sign-out-alt"></i> Logout</a></li>
</ul>
</div>
</aside>
<main class="main-content">
<header class="header">
<div class="header-left">
<span class="date-time" id="current-date-time"></span>
</div>
<div class="header-right">
<div class="user-info">
<i class="fas fa-user-circle"></i>
<span id="current-username-header"><?php echo esc_html($current_username); ?></span>
</div>
</div>
</header>
<h1>Products Management</h1>
<hr/>
</header>
<?php if ($message): ?>
<div class="notice-wrap">
<div class="notice notice-<?php echo esc_attr($message_type); ?>">
<p><?php echo esc_html($message); ?></p>
</div>
</div>
<?php endif; ?>
<section class="product-content">
<div class="product-form-container">
<h2><?php echo $editing_product ? 'Edit Product' : 'Add New Product'; ?></h2>
<form method="post" enctype="multipart/form-data">
<!-- Add nonce field for security -->
<?php wp_nonce_field('save_product_action', '_wpnonce_product_form'); ?>
<input type="hidden" name="edit_product_id" value="<?php echo esc_attr($editing_product['id'] ?? ''); ?>">
<input type="hidden" name="old_image_url" value="<?php echo esc_attr($editing_product['image_url'] ?? ''); ?>">
<div class="form-row">
<label for="product_name">Product Name:</label>
<input type="text" id="product_name" name="product_name" placeholder="Enter product name" value="<?php echo esc_attr($editing_product['name'] ?? ''); ?>" required>
<label for="product_category">Category:</label>
<select id="product_category" name="product_category" required>
<option value="">Select Category</option>
<?php if (!empty($categories)): ?>
<?php foreach ($categories as $category): ?>
<option value="<?php echo esc_attr($category['name']); ?>" <?php selected($editing_product['category'] ?? '', $category['name']); ?>>
<?php echo esc_html($category['name']); ?>
</option>
<?php endforeach; ?>
<?php else: ?>
<option value="" disabled>No categories found</option>
<?php endif; ?>
</select>
<!-- Changed Volume Unit to Unit -->
<label for="unit">Unit:</label>
<input type="text" id="unit" name="unit" placeholder="e.g., kg, l, ml, pcs" value="<?php echo esc_attr($editing_product['unit'] ?? ''); ?>">
</div>
<div class="form-row">
<label for="product_image">Product Image:
<?php if (!empty($editing_product['image_url'])): ?>
<img src="<?php echo esc_url($editing_product['image_url']); ?>" style="max-width: 30px; max-height: 30px; vertical-align: middle; margin-left: 5px;">
<?php endif; ?>
</label>
<input type="file" id="product_image" name="product_image" accept="image/jpeg,image/png,image/gif">
<?php if (!empty($editing_product['image_url'])): ?>
<small>Current image shown. Upload a new file to replace it.</small>
<?php endif; ?>
<label for="buying_price">Buying Price:</label>
<input type="number" step="0.01" min="0" id="buying_price" name="buying_price" placeholder="0.00" value="<?php echo esc_attr($editing_product['buying_price'] ?? '0.00'); ?>" required>
<label for="selling_price">Selling Price:</label>
<input type="number" step="0.01" min="0" id="selling_price" name="selling_price" placeholder="0.00" value="<?php echo esc_attr($editing_product['selling_price'] ?? '0.00'); ?>" required>
</div>
<div class="form-row">
<label for="quantity_input">
<?php echo $editing_product ? 'Quantity to Add:' : 'Quantity:'; ?>
</label>
<input type="number" min="0" id="quantity_input" name="quantity_input" placeholder="Quantity" value="0" required>
<?php if ($editing_product): ?>
<small>Current Stock: <?php echo esc_html($editing_product['in_stock']); ?>. Enter amount to add.</small>
<?php endif; ?>
<label for="expiration_date">Expiration Date:</label>
<input type="date" id="expiration_date" name="expiration_date" required>
</div>
<div class="form-buttons">
<button type="submit" name="save_product"><?php echo $editing_product ? 'Update Product' : 'Add Product'; ?></button>
<?php if ($editing_product): ?>
<a href="<?php echo add_query_arg(['action' => 'cancel_edit']); ?>" class="button-cancel">Cancel Edit</a>
<?php endif; ?>
</div>
</form>
</div>
<div class="product-list-container">
<h2>Product List</h2>
<form method="GET">
<div class="product-search-wrapper">
<input type="text" id="product-search" class="product-search-bar" name="product_search"
placeholder="Search products..." value="<?php echo esc_attr($search_term); ?>">
<?php if (!empty($search_term)): ?>
<button type="submit" class="product-search-clear"
onclick="this.form.product_search.value = ''; this.form.submit(); return false;">
×
</button>
<?php endif; ?>
</div>
</form>
<table id="product-table">
<thead>
<tr>
<th>No.</th>
<th>Image</th>
<th>Product Name</th>
<th>Category</th>
<th>Unit</th>
<th>In-Stock</th>
<th>Buying Price</th>
<th>Selling Price</th>
<th>Expiration Date</th>
<th>Date Created</th>
<th>Date Updated</th>
<th>Action</th>
</tr>
</thead>
<tbody id="product-table-body">
<?php if (empty($products)): ?>
<tr><td colspan="11" style="text-align: center;">
<?php echo !empty($search_term) ? 'No products match your search.' : 'No products added yet.'; ?>
</td></tr>
<?php else: ?>
<?php $i = 1; foreach ($products as $product):
$edit_url = add_query_arg(['action' => 'edit_product', 'id' => $product['id']], get_permalink());
$delete_url = add_query_arg([
'action' => 'delete_product',
'id' => $product['id'],
'_wpnonce' => wp_create_nonce('delete_product_' . $product['id'])
], get_permalink());
?>
<tr>
<td><?php echo $i++; ?></td>
<td>
<?php if ($product['image_url']): ?>
<img src="<?php echo esc_url($product['image_url']); ?>" alt="<?php echo esc_attr($product['name']); ?>" />
<?php else: ?>
<span style="color: #999; font-size: 0.9em;">No Image</span>
<?php endif; ?>
</td>
<td><?php echo esc_html($product['name']); ?></td>
<td><?php echo esc_html($product['category']); ?></td>
<td><?php echo esc_html($product['unit']); ?></td>
<td><?php echo esc_html($product['in_stock']); ?></td>
<td><?php echo number_format_i18n((float)$product['buying_price'], 2); ?></td>
<td><?php echo number_format_i18n((float)$product['selling_price'], 2); ?></td>
<td class="<?php echo (new DateTime($product['expiration_date']) < (new DateTime())->modify('+2 months')) ? 'expiring' : ''; ?>">
<?php echo esc_html($product['expiration_date']); ?>
</td>
<td><?php echo esc_html(mysql2date(get_option('date_format'), $product['created_at'])); ?></td>
<td><?php echo esc_html(mysql2date(get_option('date_format'), $product['updated_at'])); ?></td>
<td class="product-actions">
<a href="<?php echo esc_url($edit_url); ?>" class="edit"><i class="fas fa-edit"></i> Edit</a>
<a href="<?php echo esc_url($delete_url); ?>" class="delete" onclick="return confirm('Are you sure you want to delete this product: <?php echo esc_js($product['name']); ?>?')"><i class="fas fa-trash-alt"></i> Delete</a>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</section>
</main>
</div>
<!-- JavaScript for Clear Button (No changes needed here from previous version) -->
<script>
document.addEventListener('DOMContentLoaded', function() {
console.log("Clear Button Script: DOM Loaded");
// --- Clear Search Button Logic ---
const searchInput = document.getElementById('product-search');
const clearButton = document.getElementById('clear-search-btn');
if (searchInput && clearButton) {
console.log("Clear Button Script: Elements found.");
// Function to show/hide clear button
const toggleClearButton = () => {
// Use 'inline-block' to show it next to text
clearButton.style.display = searchInput.value.trim() !== '' ? 'inline-block' : 'none';
};
// Show/hide button based on input changes
searchInput.addEventListener('input', toggleClearButton);
console.log("Clear Button Script: 'input' listener attached.");
// Handle clear button click
clearButton.addEventListener('click', function(event) {
console.log("Clear Button Script: Click event triggered on button.");
event.preventDefault(); // Prevent any default button behavior
searchInput.value = ''; // Clear the input field visually
clearButton.style.display = 'none'; // Hide the button immediately
console.log("Clear Button Script: Input cleared and button hidden.");
try {
const currentHref = window.location.href;
console.log("Clear Button Script: Current href:", currentHref);
const currentUrl = new URL(currentHref);
console.log("Clear Button Script: Original URL object created:", currentUrl.toString());
currentUrl.searchParams.delete('product_search'); // Remove the specific parameter
const newUrlString = currentUrl.toString();
console.log("Clear Button Script: New URL string:", newUrlString);
// Redirect to the cleaned URL
window.location.href = newUrlString;
console.log("Clear Button Script: Redirect initiated to:", newUrlString);
} catch (error) {
console.error("Clear Button Script: Error during URL manipulation or redirect:", error);
// Provide feedback if redirect fails
alert("An error occurred while trying to clear the search. Please check the console (F12) and reload the page manually.");
}
});
console.log("Clear Button Script: 'click' listener attached.");
// Initial check in case the page loaded with a search term
toggleClearButton();
console.log("Clear Button Script: Initial button state set.");
} else {
if (!searchInput) console.error("Clear Button Script: Could not find search input #product-search.");
if (!clearButton) console.error("Clear Button Script: Could not find clear button #clear-search-btn.");
}
// --- End Clear Search Button Logic ---
console.log("Clear Button Script: Setup Complete.");
});
</script>
<script>
function updateDateTime() {
const now = new Date();
const options = {weekday: 'short', year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit'};
document.getElementById("current-date-time").textContent = now.toLocaleDateString('en-US', options);
}
setInterval(updateDateTime, 1000);
updateDateTime();
</script>
</body>
</html>