Lot, Serial, ExpiryDate
This commit is contained in:
+185
-130
@@ -2,7 +2,6 @@
|
||||
session_start();
|
||||
require '../config.php';
|
||||
require '../include_header.php';
|
||||
|
||||
?>
|
||||
|
||||
<body>
|
||||
@@ -13,96 +12,87 @@
|
||||
<!-- MAIN CONTENT -->
|
||||
<main id="content" class="content py-15">
|
||||
<div class="container-fluid">
|
||||
|
||||
<!-- Page header -->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="d-flex flex-column flex-md-row justify-content-between align-items-md-center mb-5 gap-3">
|
||||
<div class="">
|
||||
<div>
|
||||
<h1 class="fs-3 mb-1">Contact</h1>
|
||||
<p class="mb-0">Manage your contact</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Summary stats -->
|
||||
<div class="row g-5 mb-5">
|
||||
<div class="col-xl-3 col-md-6 col-12">
|
||||
<div class="card">
|
||||
<div class="card-body p-6">
|
||||
<div class="d-flex align-items-start gap-3">
|
||||
<div class="icon-shape icon-lg bg-primary bg-opacity-10 text-primary rounded-2">
|
||||
<i class="ti ti-category fs-4 "></i>
|
||||
<i class="ti ti-category fs-4"></i>
|
||||
</div>
|
||||
<div class="">
|
||||
<div>
|
||||
<span>Total Categories</span>
|
||||
<h2 class="fw-bold mb-0">6</h2>
|
||||
<h2 class="fw-bold mb-0" id="stat_total_category">—</h2>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-xl-3 col-md-6 col-12">
|
||||
<div class="card">
|
||||
<div class="card-body p-6">
|
||||
<div class="d-flex align-items-start gap-3">
|
||||
<div class="icon-shape icon-lg bg-info bg-opacity-10 text-info rounded-2">
|
||||
<i class="ti ti-check fs-4 "></i>
|
||||
<i class="ti ti-check fs-4"></i>
|
||||
</div>
|
||||
<div class="">
|
||||
<div>
|
||||
<span>Active</span>
|
||||
<h2 class="fw-bold mb-0">5</h2>
|
||||
<h2 class="fw-bold mb-0" id="stat_active_category">—</h2>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-xl-3 col-md-6 col-12">
|
||||
<div class="card">
|
||||
<div class="card-body p-6">
|
||||
<div class="d-flex align-items-start gap-3">
|
||||
<div class="icon-shape icon-lg bg-warning bg-opacity-10 text-warning rounded-2">
|
||||
<i class="ti ti-x fs-4 "></i>
|
||||
<i class="ti ti-x fs-4"></i>
|
||||
</div>
|
||||
<div class="">
|
||||
<div>
|
||||
<span>Inactive</span>
|
||||
<h2 class="fw-bold mb-0">1</h2>
|
||||
<h2 class="fw-bold mb-0" id="stat_inactive_category">—</h2>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-xl-3 col-md-6 col-12">
|
||||
<div class="card">
|
||||
<div class="card-body p-6">
|
||||
<div class="d-flex align-items-start gap-3">
|
||||
<div class="icon-shape icon-lg bg-warning bg-opacity-10 text-warning rounded-2">
|
||||
<i class="ti ti-box-seam fs-4 "></i>
|
||||
<i class="ti ti-box-seam fs-4"></i>
|
||||
</div>
|
||||
<div class="">
|
||||
<div>
|
||||
<span>Total Contact</span>
|
||||
<h2 class="fw-bold mb-0">356</h2>
|
||||
<h2 class="fw-bold mb-0" id="stat_total_contact">—</h2>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Tabs -->
|
||||
<ul class="nav nav-pills mb-3 bg-light p-2 rounded-2 d-inline-flex" id="pills-tab" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link active" id="pills-contact_type-tab" data-bs-toggle="pill"
|
||||
@@ -115,6 +105,7 @@
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Contact Type tab -->
|
||||
<div class="row g-5 mb-5 tab-pane fade show active" id="pills-contact_type" role="tabpanel"
|
||||
aria-labelledby="pills-contact_type-tab">
|
||||
<div class="col-12">
|
||||
@@ -129,20 +120,23 @@
|
||||
<div>
|
||||
<a href="<?php echo $server_url?>contact/manage_contact_type.php" class="btn btn-primary">
|
||||
<span class="me-1"><i class="ti ti-plus"></i></span>
|
||||
<span>Add Contact Type</span></a>
|
||||
<span>Add Contact Type</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Search bar -->
|
||||
<div class="col-lg-12 mb-5">
|
||||
<div class="position-relative">
|
||||
<input type="search" class="form-control ps-9" placeholder="Search by contact name">
|
||||
<input type="search" id="search_contact_type" class="form-control ps-9"
|
||||
placeholder="Search by contact type or description…">
|
||||
<span class="position-absolute top-25 ms-4">
|
||||
<i class="ti ti-search text-muted"></i>
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Table -->
|
||||
<div class="table-responsive">
|
||||
<table class="table mb-0 text-nowrap table-hover table-centered" id="contact_type">
|
||||
<thead class="table-primary border-light">
|
||||
@@ -153,26 +147,23 @@
|
||||
<th>Status</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
<tbody>
|
||||
|
||||
</tbody>
|
||||
<tfoot class="">
|
||||
|
||||
</tfoot>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
<tfoot></tfoot>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Contacts tab -->
|
||||
<div class="row g-5 mb-5 tab-pane fade" id="pills-contact" role="tabpanel" aria-labelledby="pills-contact-tab">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body p-5">
|
||||
|
||||
<div class="mb-6 d-flex align-items-center justify-content-between">
|
||||
<div>
|
||||
<h3 class="mb-1 fs-4">Contacts</h3>
|
||||
@@ -181,10 +172,23 @@
|
||||
<div>
|
||||
<a href="<?php echo $server_url?>contact/manage_contact.php" class="btn btn-secondary">
|
||||
<span class="me-1"><i class="ti ti-plus"></i></span>
|
||||
<span>Add Contact</span></a>
|
||||
<span>Add Contact</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Search bar -->
|
||||
<div class="col-lg-12 mb-5">
|
||||
<div class="position-relative">
|
||||
<input type="search" id="search_contact" class="form-control ps-9"
|
||||
placeholder="Search by name, tax ID, organization, or branch…">
|
||||
<span class="position-absolute top-25 ms-4">
|
||||
<i class="ti ti-search text-muted"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Table -->
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover mb-0 table-centered" id="contact">
|
||||
<thead class="table-secondary border-light">
|
||||
@@ -200,24 +204,27 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
<tfoot class="">
|
||||
|
||||
</tfoot>
|
||||
<tfoot></tfoot>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php require "../include_ending.php";?>
|
||||
|
||||
<script>
|
||||
// ── Current search terms ─────────────────────────────────────────────
|
||||
var search_term_contact_type = '';
|
||||
var search_term_contact = '';
|
||||
|
||||
|
||||
// ── Contact Type: fetch + render ─────────────────────────────────────
|
||||
function retrieve_contact_type() {
|
||||
|
||||
return ajax_request({
|
||||
@@ -228,57 +235,59 @@
|
||||
action: 'read',
|
||||
onSuccess: function(res) {
|
||||
|
||||
// Register the array as a table name
|
||||
alasql('CREATE TABLE IF NOT EXISTS contact_type');
|
||||
alasql.tables.contact_type.data = res.output || [];
|
||||
|
||||
var total_records = alasql.tables.contact_type.data.length;
|
||||
|
||||
var table_id = 'contact_type';
|
||||
|
||||
var page = generate_pagination(table_id,total_records);
|
||||
$(`table#${table_id} tfoot`).html(page);
|
||||
|
||||
// dynamic function name
|
||||
if (typeof window[`change_page_${table_id}`] === "function") {
|
||||
window[`change_page_${table_id}`](1);
|
||||
} else {
|
||||
console.error(`Function change_page_${table_id} does not exist.`);
|
||||
}
|
||||
change_page_contact_type(1);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
function change_page_contact_type(page_num) {
|
||||
|
||||
var offset = (page_num - 1) * prop_limit;
|
||||
var kw = search_term_contact_type.toLowerCase();
|
||||
|
||||
var page_data = alasql(`SELECT * FROM contact_type LIMIT ${prop_limit} OFFSET ${offset}`);
|
||||
|
||||
var body = ``;
|
||||
var filtered = kw ?
|
||||
alasql(`SELECT * FROM contact_type
|
||||
WHERE LOWER(contact_type) LIKE '%${kw}%'
|
||||
OR LOWER(description) LIKE '%${kw}%'`) :
|
||||
alasql(`SELECT * FROM contact_type`);
|
||||
|
||||
var page = generate_pagination('contact_type', filtered.length);
|
||||
$(`table#contact_type tfoot`).html(page);
|
||||
|
||||
if (filtered.length === 0) {
|
||||
$("table#contact_type > tbody").html(
|
||||
'<tr><td colspan="5" class="text-center py-5 text-muted">No contact types match your search.</td></tr>'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
var page_data = filtered.slice(offset, offset + prop_limit);
|
||||
|
||||
var body = '';
|
||||
$.each(page_data, function(key, item) {
|
||||
body += `<tr>
|
||||
<td class="py-3">${item['contact_type']}</td>
|
||||
<td class="py-3">${item['description']}</td>
|
||||
<td class="py-3">${item['status']}</td>
|
||||
<td class="py-3">
|
||||
${(item['status'])?'<span class="badge bg-success">Active</span>':'<span class="badge bg-secondary">Inactive</span>'}
|
||||
</td>
|
||||
<td class="py-3">
|
||||
<a href="<?php echo $server_url?>contact/manage_contact_type.php?id=${item['id']}" class=""><i class="ti ti-eye fs-5"></i></a>
|
||||
<a href="javascript:;" class="link-danger" onclick="remove_contact_type(${item['id']},$(this))"><i class="ti ti-trash ms-2 fs-5"></i></a>
|
||||
</td>
|
||||
</tr>`;
|
||||
})
|
||||
<td class="py-3">${item['contact_type']}</td>
|
||||
<td class="py-3">${item['description']}</td>
|
||||
<td class="py-3">${item['contact_count'] ?? 0}</td>
|
||||
<td class="py-3">
|
||||
${(item['status'])?'<span class="badge bg-success">Active</span>':'<span class="badge bg-secondary">Inactive</span>'}
|
||||
</td>
|
||||
<td class="py-3">
|
||||
<a href="<?php echo $server_url?>contact/manage_contact_type.php?id=${item['id']}" class=""><i class="ti ti-eye fs-5"></i></a>
|
||||
<a href="javascript:;" class="link-danger" onclick="remove_contact_type(${item['id']},$(this))"><i class="ti ti-trash ms-2 fs-5"></i></a>
|
||||
</td>
|
||||
</tr>`;
|
||||
});
|
||||
|
||||
$("table#contact_type > tbody").html(body);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ── Contacts: fetch + render ─────────────────────────────────────────
|
||||
function retrieve_contact() {
|
||||
|
||||
return ajax_request({
|
||||
@@ -288,60 +297,86 @@
|
||||
action: 'read',
|
||||
onSuccess: function(res) {
|
||||
|
||||
// Register the array as a table name
|
||||
alasql('CREATE TABLE IF NOT EXISTS contact');
|
||||
alasql.tables.contact.data = res.output || [];
|
||||
|
||||
var total_records = alasql.tables.contact.data.length;
|
||||
|
||||
var table_id = 'contact';
|
||||
|
||||
var page = generate_pagination(table_id,total_records);
|
||||
$(`table#${table_id} tfoot`).html(page);
|
||||
|
||||
// dynamic function name
|
||||
if (typeof window[`change_page_${table_id}`] === "function") {
|
||||
window[`change_page_${table_id}`](1);
|
||||
} else {
|
||||
console.error(`Function change_page_${table_id} does not exist.`);
|
||||
}
|
||||
change_page_contact(1);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
function change_page_contact(page_num) {
|
||||
|
||||
var offset = (page_num - 1) * prop_limit;
|
||||
var kw = search_term_contact.toLowerCase();
|
||||
|
||||
var page_data = alasql(`SELECT * FROM contact LIMIT ${prop_limit} OFFSET ${offset}`);
|
||||
var filtered = kw ?
|
||||
alasql(`SELECT * FROM contact
|
||||
WHERE LOWER(contact_name) LIKE '%${kw}%'
|
||||
OR LOWER(tax_id) LIKE '%${kw}%'
|
||||
OR LOWER(organization) LIKE '%${kw}%'
|
||||
OR LOWER(branch) LIKE '%${kw}%'
|
||||
OR LOWER(billing_address) LIKE '%${kw}%'
|
||||
OR LOWER(shipping_address) LIKE '%${kw}%'`) :
|
||||
alasql(`SELECT * FROM contact`);
|
||||
|
||||
var body = ``;
|
||||
var page = generate_pagination('contact', filtered.length);
|
||||
$(`table#contact tfoot`).html(page);
|
||||
|
||||
if (filtered.length === 0) {
|
||||
$("table#contact > tbody").html(
|
||||
'<tr><td colspan="8" class="text-center py-5 text-muted">No contacts match your search.</td></tr>'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
var page_data = filtered.slice(offset, offset + prop_limit);
|
||||
|
||||
var body = '';
|
||||
$.each(page_data, function(key, item) {
|
||||
body += `<tr>
|
||||
<td class="py-3">${item['tax_id']}</td>
|
||||
<td class="py-3">${item['contact_name']}</td>
|
||||
<td class="py-3">${item['organization']}</td>
|
||||
<td class="py-3">${item['branch']}</td>
|
||||
<td class="py-3">${item['billing_address']}</td>
|
||||
<td class="py-3">${item['shipping_address']}</td>
|
||||
<td class="py-3">
|
||||
${(item['status'])?'<span class="badge bg-success">Active</span>':'<span class="badge bg-secondary">Inactive</span>'}
|
||||
</td>
|
||||
<td class="py-3">
|
||||
<a href="<?php echo $server_url?>contact/manage_contact.php?id=${item['id']}" class=""><i class="ti ti-eye fs-5"></i></a>
|
||||
<a href="javascript:;" class="link-danger" onclick="remove_contact(${item['id']},$(this))"><i class="ti ti-trash ms-2 fs-5"></i></a>
|
||||
</td>
|
||||
</tr>`;
|
||||
})
|
||||
<td class="py-3">${item['tax_id']}</td>
|
||||
<td class="py-3">${item['contact_name']}</td>
|
||||
<td class="py-3">${item['organization']}</td>
|
||||
<td class="py-3">${item['branch']}</td>
|
||||
<td class="py-3">${item['billing_address']}</td>
|
||||
<td class="py-3">${item['shipping_address']}</td>
|
||||
<td class="py-3">
|
||||
${(item['status'])?'<span class="badge bg-success">Active</span>':'<span class="badge bg-secondary">Inactive</span>'}
|
||||
</td>
|
||||
<td class="py-3">
|
||||
<a href="<?php echo $server_url?>contact/manage_contact.php?id=${item['id']}" class=""><i class="ti ti-eye fs-5"></i></a>
|
||||
<a href="javascript:;" class="link-danger" onclick="remove_contact(${item['id']},$(this))"><i class="ti ti-trash ms-2 fs-5"></i></a>
|
||||
</td>
|
||||
</tr>`;
|
||||
});
|
||||
|
||||
$("table#contact > tbody").html(body);
|
||||
|
||||
}
|
||||
|
||||
|
||||
function remove_contact_type(id,element) {
|
||||
// ── Stats ────────────────────────────────────────────────────────────
|
||||
function retrieve_stats() {
|
||||
|
||||
return ajax_request({
|
||||
url: "<?php echo $server_url?>contact/api/engine/contact_stats.php",
|
||||
autoPrepare: true,
|
||||
checkRequired: 0,
|
||||
action: 'read',
|
||||
debugMode: 0,
|
||||
onSuccess: function(res) {
|
||||
$("#stat_total_category").text(res.total_category);
|
||||
$("#stat_active_category").text(res.active_category);
|
||||
$("#stat_inactive_category").text(res.inactive_category);
|
||||
$("#stat_total_contact").text(res.total_contact);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// ── Remove handlers ──────────────────────────────────────────────────
|
||||
function remove_contact_type(id, element) {
|
||||
|
||||
return ajax_request({
|
||||
url: "<?php echo $server_url?>contact/api/engine/remove_contact_type.php",
|
||||
@@ -353,16 +388,13 @@
|
||||
},
|
||||
action: 'delete',
|
||||
onSuccess: function(res) {
|
||||
|
||||
element.parent().parent().remove();
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
function remove_contact(id,element) {
|
||||
function remove_contact(id, element) {
|
||||
|
||||
return ajax_request({
|
||||
url: "<?php echo $server_url?>contact/api/engine/remove_contact.php",
|
||||
@@ -374,16 +406,40 @@
|
||||
},
|
||||
action: 'delete',
|
||||
onSuccess: function(res) {
|
||||
|
||||
element.parent().parent().remove();
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
// ── Search: debounce + re-render ─────────────────────────────────────
|
||||
function debounce(fn, ms) {
|
||||
var t;
|
||||
return function() {
|
||||
var args = arguments,
|
||||
ctx = this;
|
||||
clearTimeout(t);
|
||||
t = setTimeout(function() {
|
||||
fn.apply(ctx, args);
|
||||
}, ms);
|
||||
};
|
||||
}
|
||||
|
||||
$('#search_contact_type').on('input', debounce(function() {
|
||||
search_term_contact_type = $(this).val().trim();
|
||||
change_page_contact_type(1); // reset to page 1 on new search
|
||||
}, 200));
|
||||
|
||||
$('#search_contact').on('input', debounce(function() {
|
||||
search_term_contact = $(this).val().trim();
|
||||
change_page_contact(1);
|
||||
}, 200));
|
||||
|
||||
|
||||
// ── Boot ─────────────────────────────────────────────────────────────
|
||||
$(async function() {
|
||||
try {
|
||||
await retrieve_stats();
|
||||
await retrieve_contact_type();
|
||||
await retrieve_contact();
|
||||
} catch (e) {
|
||||
@@ -391,20 +447,19 @@
|
||||
}
|
||||
});
|
||||
|
||||
// Remember last active tab across page reloads
|
||||
$(document).ready(function() {
|
||||
// switching to nav-link from last leave
|
||||
$('button.nav-link').on('click', function() {
|
||||
nav_id = $(this).attr('id');
|
||||
var nav_id = $(this).attr('id');
|
||||
sessionStorage.setItem("contact_nav_id", nav_id);
|
||||
})
|
||||
let nav_id = sessionStorage.getItem("contact_nav_id");
|
||||
if(nav_id){
|
||||
});
|
||||
var nav_id = sessionStorage.getItem("contact_nav_id");
|
||||
if (nav_id) {
|
||||
$(`button#${nav_id}`).trigger('click');
|
||||
}
|
||||
})
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user