1108 lines
39 KiB
PHP
1108 lines
39 KiB
PHP
<?php include('include/headscript.php'); ?>
|
|
|
|
<?php
|
|
/*
|
|
* TRFgo - Brands management page
|
|
* This page manages brands/divisions linked to companies.
|
|
*/
|
|
|
|
function e($value)
|
|
{
|
|
return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
|
|
}
|
|
|
|
function jsonResponse(array $payload): void
|
|
{
|
|
header('Content-Type: application/json');
|
|
echo json_encode($payload);
|
|
exit;
|
|
}
|
|
|
|
/*
|
|
* AJAX actions
|
|
*/
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
|
|
$action = $_POST['action'];
|
|
|
|
try {
|
|
if ($action === 'save_brand') {
|
|
$idbrand = isset($_POST['idbrand']) ? (int) $_POST['idbrand'] : 0;
|
|
$idcompany = isset($_POST['idcompany']) ? (int) $_POST['idcompany'] : 0;
|
|
$brandName = trim($_POST['brand_name'] ?? '');
|
|
$externalBrandCode = trim($_POST['external_brand_code'] ?? '');
|
|
$status = $_POST['status'] ?? 'active';
|
|
|
|
$allowedStatuses = ['active', 'inactive'];
|
|
|
|
if ($idcompany <= 0) {
|
|
jsonResponse([
|
|
'success' => false,
|
|
'message' => 'Company is required.'
|
|
]);
|
|
}
|
|
|
|
if ($brandName === '') {
|
|
jsonResponse([
|
|
'success' => false,
|
|
'message' => 'Brand name is required.'
|
|
]);
|
|
}
|
|
|
|
if (!in_array($status, $allowedStatuses, true)) {
|
|
$status = 'active';
|
|
}
|
|
|
|
/*
|
|
* Check company exists
|
|
*/
|
|
$stmt = $db->prepare("SELECT COUNT(*) FROM companies WHERE idcompany = :idcompany");
|
|
$stmt->execute([':idcompany' => $idcompany]);
|
|
|
|
if ((int) $stmt->fetchColumn() === 0) {
|
|
jsonResponse([
|
|
'success' => false,
|
|
'message' => 'Selected company does not exist.'
|
|
]);
|
|
}
|
|
|
|
if ($idbrand > 0) {
|
|
$sql = "
|
|
UPDATE brands
|
|
SET
|
|
idcompany = :idcompany,
|
|
brand_name = :brand_name,
|
|
external_brand_code = :external_brand_code,
|
|
status = :status,
|
|
updated_at = NOW()
|
|
WHERE idbrand = :idbrand
|
|
";
|
|
|
|
$stmt = $db->prepare($sql);
|
|
$stmt->execute([
|
|
':idcompany' => $idcompany,
|
|
':brand_name' => $brandName,
|
|
':external_brand_code' => $externalBrandCode !== '' ? $externalBrandCode : null,
|
|
':status' => $status,
|
|
':idbrand' => $idbrand,
|
|
]);
|
|
|
|
jsonResponse([
|
|
'success' => true,
|
|
'message' => 'Brand updated successfully.'
|
|
]);
|
|
}
|
|
|
|
$sql = "
|
|
INSERT INTO brands (
|
|
idcompany,
|
|
brand_name,
|
|
external_brand_code,
|
|
status,
|
|
created_at,
|
|
updated_at
|
|
) VALUES (
|
|
:idcompany,
|
|
:brand_name,
|
|
:external_brand_code,
|
|
:status,
|
|
NOW(),
|
|
NOW()
|
|
)
|
|
";
|
|
|
|
$stmt = $db->prepare($sql);
|
|
$stmt->execute([
|
|
':idcompany' => $idcompany,
|
|
':brand_name' => $brandName,
|
|
':external_brand_code' => $externalBrandCode !== '' ? $externalBrandCode : null,
|
|
':status' => $status,
|
|
]);
|
|
|
|
jsonResponse([
|
|
'success' => true,
|
|
'message' => 'Brand created successfully.'
|
|
]);
|
|
}
|
|
|
|
if ($action === 'get_brand') {
|
|
$idbrand = isset($_POST['idbrand']) ? (int) $_POST['idbrand'] : 0;
|
|
|
|
if ($idbrand <= 0) {
|
|
jsonResponse([
|
|
'success' => false,
|
|
'message' => 'Invalid brand id.'
|
|
]);
|
|
}
|
|
|
|
$stmt = $db->prepare("
|
|
SELECT *
|
|
FROM brands
|
|
WHERE idbrand = :idbrand
|
|
LIMIT 1
|
|
");
|
|
$stmt->execute([':idbrand' => $idbrand]);
|
|
$brand = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
if (!$brand) {
|
|
jsonResponse([
|
|
'success' => false,
|
|
'message' => 'Brand not found.'
|
|
]);
|
|
}
|
|
|
|
jsonResponse([
|
|
'success' => true,
|
|
'brand' => $brand
|
|
]);
|
|
}
|
|
|
|
if ($action === 'change_status') {
|
|
$idbrand = isset($_POST['idbrand']) ? (int) $_POST['idbrand'] : 0;
|
|
$status = $_POST['status'] ?? 'inactive';
|
|
|
|
$allowedStatuses = ['active', 'inactive'];
|
|
|
|
if ($idbrand <= 0 || !in_array($status, $allowedStatuses, true)) {
|
|
jsonResponse([
|
|
'success' => false,
|
|
'message' => 'Invalid request.'
|
|
]);
|
|
}
|
|
|
|
$stmt = $db->prepare("
|
|
UPDATE brands
|
|
SET status = :status, updated_at = NOW()
|
|
WHERE idbrand = :idbrand
|
|
");
|
|
$stmt->execute([
|
|
':status' => $status,
|
|
':idbrand' => $idbrand,
|
|
]);
|
|
|
|
jsonResponse([
|
|
'success' => true,
|
|
'message' => 'Brand status updated successfully.'
|
|
]);
|
|
}
|
|
|
|
if ($action === 'delete_brand') {
|
|
$idbrand = isset($_POST['idbrand']) ? (int) $_POST['idbrand'] : 0;
|
|
|
|
if ($idbrand <= 0) {
|
|
jsonResponse([
|
|
'success' => false,
|
|
'message' => 'Invalid brand id.'
|
|
]);
|
|
}
|
|
|
|
/*
|
|
* Safe delete rule:
|
|
* Do not delete a brand if it has linked departments or users.
|
|
*/
|
|
$stmt = $db->prepare("
|
|
SELECT
|
|
(SELECT COUNT(*) FROM departments WHERE idbrand = :idbrand1) AS departments_count,
|
|
(SELECT COUNT(*) FROM company_users WHERE idbrand = :idbrand2) AS users_count
|
|
");
|
|
$stmt->execute([
|
|
':idbrand1' => $idbrand,
|
|
':idbrand2' => $idbrand,
|
|
]);
|
|
|
|
$usage = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
if (((int) $usage['departments_count'] > 0) || ((int) $usage['users_count'] > 0)) {
|
|
jsonResponse([
|
|
'success' => false,
|
|
'message' => 'This brand has linked departments or users. Set it as inactive instead of deleting it.'
|
|
]);
|
|
}
|
|
|
|
$stmt = $db->prepare("
|
|
DELETE FROM brands
|
|
WHERE idbrand = :idbrand
|
|
");
|
|
$stmt->execute([':idbrand' => $idbrand]);
|
|
|
|
jsonResponse([
|
|
'success' => true,
|
|
'message' => 'Brand deleted successfully.'
|
|
]);
|
|
}
|
|
|
|
jsonResponse([
|
|
'success' => false,
|
|
'message' => 'Unknown action.'
|
|
]);
|
|
} catch (Throwable $e) {
|
|
jsonResponse([
|
|
'success' => false,
|
|
'message' => $e->getMessage()
|
|
]);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Page data
|
|
*/
|
|
$companies = [];
|
|
|
|
try {
|
|
$stmt = $db->query("
|
|
SELECT idcompany, company_name, status
|
|
FROM companies
|
|
ORDER BY company_name ASC
|
|
");
|
|
$companies = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
} catch (Throwable $e) {
|
|
$companies = [];
|
|
}
|
|
|
|
$brands = [];
|
|
|
|
try {
|
|
$stmt = $db->query("
|
|
SELECT
|
|
b.idbrand,
|
|
b.idcompany,
|
|
b.brand_name,
|
|
b.external_brand_code,
|
|
b.status,
|
|
b.created_at,
|
|
c.company_name,
|
|
c.status AS company_status,
|
|
COUNT(DISTINCT d.iddepartment) AS department_count,
|
|
COUNT(DISTINCT cu.idcompanyuser) AS user_count
|
|
FROM brands b
|
|
INNER JOIN companies c ON c.idcompany = b.idcompany
|
|
LEFT JOIN departments d ON d.idbrand = b.idbrand
|
|
LEFT JOIN company_users cu ON cu.idbrand = b.idbrand
|
|
GROUP BY
|
|
b.idbrand,
|
|
b.idcompany,
|
|
b.brand_name,
|
|
b.external_brand_code,
|
|
b.status,
|
|
b.created_at,
|
|
c.company_name,
|
|
c.status
|
|
ORDER BY c.company_name ASC, b.brand_name ASC
|
|
");
|
|
$brands = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
} catch (Throwable $e) {
|
|
$brands = [];
|
|
}
|
|
|
|
$pageTitle = 'Brands';
|
|
?>
|
|
|
|
<!doctype html>
|
|
<html lang="en">
|
|
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<link rel="icon" href="assets/images/favicon-32x32.png" type="image/png" />
|
|
|
|
<?php include('cssinclude.php'); ?>
|
|
|
|
<title><?= e($pageTitle); ?> - <?= isset($titlewebsite) ? e($titlewebsite) : 'TRFgo'; ?></title>
|
|
|
|
<style>
|
|
:root {
|
|
--trfgo-primary: #2563eb;
|
|
--trfgo-muted: #64748b;
|
|
--trfgo-border: #e5e7eb;
|
|
--trfgo-soft-blue: #eff6ff;
|
|
--trfgo-soft-green: #ecfdf5;
|
|
--trfgo-soft-orange: #fff7ed;
|
|
}
|
|
|
|
.page-intro-card {
|
|
border: 0;
|
|
border-radius: 20px;
|
|
overflow: hidden;
|
|
background:
|
|
radial-gradient(circle at top right, rgba(59, 130, 246, 0.22), transparent 30%),
|
|
linear-gradient(135deg, #0f172a 0%, #1d4ed8 60%, #38bdf8 100%);
|
|
color: #fff;
|
|
box-shadow: 0 18px 45px rgba(15, 23, 42, 0.18);
|
|
}
|
|
|
|
.page-intro-card .card-body {
|
|
padding: 26px;
|
|
}
|
|
|
|
.page-intro-card h1,
|
|
.page-intro-card h2,
|
|
.page-intro-card h3,
|
|
.page-intro-card h4,
|
|
.page-intro-card h5,
|
|
.page-intro-card h6 {
|
|
color: #ffffff;
|
|
}
|
|
|
|
.intro-eyebrow {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 6px 12px;
|
|
border-radius: 999px;
|
|
background: rgba(255, 255, 255, 0.16);
|
|
color: rgba(255, 255, 255, 0.94);
|
|
font-size: 12px;
|
|
font-weight: 700;
|
|
letter-spacing: 0.04em;
|
|
text-transform: uppercase;
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.intro-title {
|
|
font-size: 28px;
|
|
font-weight: 800;
|
|
letter-spacing: -0.03em;
|
|
margin-bottom: 8px;
|
|
color: #ffffff;
|
|
}
|
|
|
|
.intro-text {
|
|
max-width: 760px;
|
|
color: rgba(255, 255, 255, 0.82);
|
|
margin-bottom: 0;
|
|
line-height: 1.6;
|
|
}
|
|
|
|
.btn-intro {
|
|
border-radius: 12px;
|
|
padding: 10px 16px;
|
|
font-weight: 700;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
border: 0;
|
|
background: #fff;
|
|
color: #1d4ed8;
|
|
box-shadow: 0 12px 28px rgba(15, 23, 42, 0.18);
|
|
}
|
|
|
|
.summary-card {
|
|
border: 0;
|
|
border-radius: 18px;
|
|
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.06);
|
|
}
|
|
|
|
.summary-icon {
|
|
width: 44px;
|
|
height: 44px;
|
|
border-radius: 14px;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 24px;
|
|
}
|
|
|
|
.summary-icon.blue {
|
|
background: var(--trfgo-soft-blue);
|
|
color: #2563eb;
|
|
}
|
|
|
|
.summary-icon.green {
|
|
background: var(--trfgo-soft-green);
|
|
color: #059669;
|
|
}
|
|
|
|
.summary-icon.orange {
|
|
background: var(--trfgo-soft-orange);
|
|
color: #ea580c;
|
|
}
|
|
|
|
.summary-label {
|
|
color: var(--trfgo-muted);
|
|
font-size: 13px;
|
|
font-weight: 700;
|
|
margin-bottom: 3px;
|
|
}
|
|
|
|
.summary-value {
|
|
color: #0f172a;
|
|
font-size: 26px;
|
|
font-weight: 800;
|
|
line-height: 1.1;
|
|
}
|
|
|
|
.content-card {
|
|
border: 0;
|
|
border-radius: 18px;
|
|
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.06);
|
|
}
|
|
|
|
.section-title {
|
|
color: #0f172a;
|
|
font-size: 18px;
|
|
font-weight: 800;
|
|
margin-bottom: 3px;
|
|
}
|
|
|
|
.section-subtitle {
|
|
color: var(--trfgo-muted);
|
|
font-size: 13px;
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.brand-table th {
|
|
color: #64748b;
|
|
font-size: 12px;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.04em;
|
|
border-bottom: 1px solid var(--trfgo-border) !important;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.brand-table td {
|
|
vertical-align: middle;
|
|
border-color: #eef2f7;
|
|
}
|
|
|
|
.brand-name {
|
|
font-weight: 800;
|
|
color: #0f172a;
|
|
}
|
|
|
|
.brand-sub {
|
|
color: var(--trfgo-muted);
|
|
font-size: 12px;
|
|
}
|
|
|
|
.metric-pill {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
background: #f8fafc;
|
|
border: 1px solid #e5e7eb;
|
|
color: #475569;
|
|
border-radius: 999px;
|
|
padding: 5px 9px;
|
|
font-size: 12px;
|
|
font-weight: 700;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.badge-soft-success {
|
|
background: #dcfce7;
|
|
color: #166534;
|
|
border-radius: 999px;
|
|
font-weight: 700;
|
|
padding: 6px 10px;
|
|
}
|
|
|
|
.badge-soft-warning {
|
|
background: #ffedd5;
|
|
color: #9a3412;
|
|
border-radius: 999px;
|
|
font-weight: 700;
|
|
padding: 6px 10px;
|
|
}
|
|
|
|
.badge-soft-muted {
|
|
background: #f1f5f9;
|
|
color: #475569;
|
|
border-radius: 999px;
|
|
font-weight: 700;
|
|
padding: 6px 10px;
|
|
}
|
|
|
|
.btn-action {
|
|
width: 34px;
|
|
height: 34px;
|
|
border-radius: 11px;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border: 1px solid #e5e7eb;
|
|
background: #fff;
|
|
color: #475569;
|
|
transition: all 0.16s ease;
|
|
}
|
|
|
|
.btn-action:hover {
|
|
color: #1d4ed8;
|
|
border-color: rgba(37, 99, 235, 0.35);
|
|
background: #eff6ff;
|
|
}
|
|
|
|
.btn-action.danger:hover {
|
|
color: #dc2626;
|
|
border-color: rgba(220, 38, 38, 0.30);
|
|
background: #fef2f2;
|
|
}
|
|
|
|
.modal-content {
|
|
border: 0;
|
|
border-radius: 20px;
|
|
box-shadow: 0 24px 80px rgba(15, 23, 42, 0.22);
|
|
}
|
|
|
|
.modal-header {
|
|
border-bottom: 1px solid #eef2f7;
|
|
}
|
|
|
|
.modal-title {
|
|
font-weight: 800;
|
|
color: #0f172a;
|
|
}
|
|
|
|
.form-label {
|
|
font-size: 13px;
|
|
font-weight: 700;
|
|
color: #334155;
|
|
}
|
|
|
|
.form-control,
|
|
.form-select {
|
|
border-radius: 12px;
|
|
border-color: #dbe3ef;
|
|
}
|
|
|
|
.form-control:focus,
|
|
.form-select:focus {
|
|
border-color: rgba(37, 99, 235, 0.45);
|
|
box-shadow: 0 0 0 0.20rem rgba(37, 99, 235, 0.12);
|
|
}
|
|
|
|
.required-dot {
|
|
color: #dc2626;
|
|
}
|
|
|
|
@media (max-width: 767px) {
|
|
.intro-title {
|
|
font-size: 24px;
|
|
}
|
|
|
|
.btn-intro {
|
|
width: 100%;
|
|
justify-content: center;
|
|
margin-top: 15px;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
<div class="wrapper">
|
|
<?php include('include/navbar.php'); ?>
|
|
<?php include('include/topbar.php'); ?>
|
|
|
|
<div class="page-wrapper">
|
|
<div class="page-content">
|
|
|
|
<div class="card page-intro-card mb-4">
|
|
<div class="card-body">
|
|
<div class="d-flex align-items-center justify-content-between flex-wrap gap-3">
|
|
<div>
|
|
<div class="intro-eyebrow">
|
|
<i class="bx bx-purchase-tag-alt"></i>
|
|
TRFgo Registry
|
|
</div>
|
|
<h1 class="intro-title">Brands</h1>
|
|
<p class="intro-text">
|
|
Manage brands and divisions linked to customer companies.
|
|
Brands help organize samples, TRF requests, departments and user access.
|
|
</p>
|
|
</div>
|
|
|
|
<div>
|
|
<button type="button" class="btn btn-intro" id="btnAddBrand">
|
|
<i class="bx bx-plus-circle"></i>
|
|
Add Brand
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<?php
|
|
$totalBrands = count($brands);
|
|
$activeBrands = count(array_filter($brands, fn($row) => $row['status'] === 'active'));
|
|
$inactiveBrands = count(array_filter($brands, fn($row) => $row['status'] === 'inactive'));
|
|
?>
|
|
|
|
<div class="row row-cols-1 row-cols-md-3 mb-3">
|
|
<div class="col">
|
|
<div class="card summary-card">
|
|
<div class="card-body">
|
|
<div class="d-flex align-items-center justify-content-between">
|
|
<div>
|
|
<div class="summary-label">Total Brands</div>
|
|
<div class="summary-value"><?= e($totalBrands); ?></div>
|
|
</div>
|
|
<div class="summary-icon blue">
|
|
<i class="bx bx-purchase-tag-alt"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col">
|
|
<div class="card summary-card">
|
|
<div class="card-body">
|
|
<div class="d-flex align-items-center justify-content-between">
|
|
<div>
|
|
<div class="summary-label">Active</div>
|
|
<div class="summary-value"><?= e($activeBrands); ?></div>
|
|
</div>
|
|
<div class="summary-icon green">
|
|
<i class="bx bx-check-circle"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col">
|
|
<div class="card summary-card">
|
|
<div class="card-body">
|
|
<div class="d-flex align-items-center justify-content-between">
|
|
<div>
|
|
<div class="summary-label">Inactive</div>
|
|
<div class="summary-value"><?= e($inactiveBrands); ?></div>
|
|
</div>
|
|
<div class="summary-icon orange">
|
|
<i class="bx bx-pause-circle"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card content-card">
|
|
<div class="card-header bg-transparent">
|
|
<div class="d-flex align-items-center justify-content-between flex-wrap gap-2">
|
|
<div>
|
|
<h6 class="section-title mb-0">Brand List</h6>
|
|
<p class="section-subtitle">Brands and divisions configured for customer companies</p>
|
|
</div>
|
|
|
|
<button type="button" class="btn btn-primary btn-sm" id="btnAddBrandSmall">
|
|
<i class="bx bx-plus-circle"></i>
|
|
Add Brand
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
<?php if (count($companies) === 0): ?>
|
|
<div class="alert alert-warning mb-3">
|
|
<strong>No companies available.</strong>
|
|
Create at least one company before adding brands.
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<div class="table-responsive">
|
|
<table id="brandsTable" class="table table-striped table-hover align-middle brand-table" style="width:100%">
|
|
<thead>
|
|
<tr>
|
|
<th>Brand</th>
|
|
<th>Company</th>
|
|
<th>External Code</th>
|
|
<th class="text-center">Departments</th>
|
|
<th class="text-center">Users</th>
|
|
<th>Status</th>
|
|
<th>Created</th>
|
|
<th class="text-end">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<?php foreach ($brands as $brand): ?>
|
|
<tr>
|
|
<td>
|
|
<div class="brand-name"><?= e($brand['brand_name']); ?></div>
|
|
<div class="brand-sub">ID: <?= e($brand['idbrand']); ?></div>
|
|
</td>
|
|
|
|
<td>
|
|
<div class="brand-name"><?= e($brand['company_name']); ?></div>
|
|
<?php if ($brand['company_status'] !== 'active'): ?>
|
|
<div class="brand-sub">Company status: <?= e($brand['company_status']); ?></div>
|
|
<?php endif; ?>
|
|
</td>
|
|
|
|
<td>
|
|
<?= !empty($brand['external_brand_code']) ? e($brand['external_brand_code']) : '<span class="text-muted">-</span>'; ?>
|
|
</td>
|
|
|
|
<td class="text-center">
|
|
<span class="metric-pill">
|
|
<i class="bx bx-sitemap"></i>
|
|
<?= e($brand['department_count']); ?>
|
|
</span>
|
|
</td>
|
|
|
|
<td class="text-center">
|
|
<span class="metric-pill">
|
|
<i class="bx bx-user"></i>
|
|
<?= e($brand['user_count']); ?>
|
|
</span>
|
|
</td>
|
|
|
|
<td>
|
|
<?php if ($brand['status'] === 'active'): ?>
|
|
<span class="badge-soft-success">Active</span>
|
|
<?php else: ?>
|
|
<span class="badge-soft-muted">Inactive</span>
|
|
<?php endif; ?>
|
|
</td>
|
|
|
|
<td>
|
|
<?= !empty($brand['created_at']) ? e(date('d/m/Y', strtotime($brand['created_at']))) : '-'; ?>
|
|
</td>
|
|
|
|
<td class="text-end">
|
|
<button type="button"
|
|
class="btn-action btnEditBrand"
|
|
data-id="<?= e($brand['idbrand']); ?>"
|
|
title="Edit">
|
|
<i class="bx bx-edit-alt"></i>
|
|
</button>
|
|
|
|
<?php if ($brand['status'] === 'active'): ?>
|
|
<button type="button"
|
|
class="btn-action btnChangeStatus"
|
|
data-id="<?= e($brand['idbrand']); ?>"
|
|
data-status="inactive"
|
|
title="Set inactive">
|
|
<i class="bx bx-toggle-right"></i>
|
|
</button>
|
|
<?php else: ?>
|
|
<button type="button"
|
|
class="btn-action btnChangeStatus"
|
|
data-id="<?= e($brand['idbrand']); ?>"
|
|
data-status="active"
|
|
title="Set active">
|
|
<i class="bx bx-toggle-left"></i>
|
|
</button>
|
|
<?php endif; ?>
|
|
|
|
<button type="button"
|
|
class="btn-action danger btnDeleteBrand"
|
|
data-id="<?= e($brand['idbrand']); ?>"
|
|
title="Delete">
|
|
<i class="bx bx-trash"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<div class="overlay toggle-icon"></div>
|
|
|
|
<a href="javaScript:;" class="back-to-top">
|
|
<i class='bx bxs-up-arrow-alt'></i>
|
|
</a>
|
|
|
|
<?php include('include/footer.php'); ?>
|
|
</div>
|
|
|
|
<div class="modal fade" id="brandModal" tabindex="-1" aria-labelledby="brandModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-lg modal-dialog-centered">
|
|
<form id="brandForm" class="modal-content">
|
|
<input type="hidden" name="action" value="save_brand">
|
|
<input type="hidden" name="idbrand" id="idbrand" value="0">
|
|
|
|
<div class="modal-header">
|
|
<div>
|
|
<h5 class="modal-title" id="brandModalLabel">Add Brand</h5>
|
|
<small class="text-muted">Create or update a brand/division linked to a company.</small>
|
|
</div>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
|
|
<div class="modal-body">
|
|
<div class="row g-3">
|
|
<div class="col-12">
|
|
<label class="form-label">Company <span class="required-dot">*</span></label>
|
|
<select class="form-select" name="idcompany" id="idcompany" required>
|
|
<option value="">Select company</option>
|
|
<?php foreach ($companies as $company): ?>
|
|
<option value="<?= e($company['idcompany']); ?>">
|
|
<?= e($company['company_name']); ?>
|
|
<?= $company['status'] !== 'active' ? ' - ' . e($company['status']) : ''; ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="col-12 col-md-6">
|
|
<label class="form-label">Brand Name <span class="required-dot">*</span></label>
|
|
<input type="text" class="form-control" name="brand_name" id="brand_name" required>
|
|
</div>
|
|
|
|
<div class="col-12 col-md-6">
|
|
<label class="form-label">External Brand Code</label>
|
|
<input type="text" class="form-control" name="external_brand_code" id="external_brand_code">
|
|
</div>
|
|
|
|
<div class="col-12 col-md-4">
|
|
<label class="form-label">Status</label>
|
|
<select class="form-select" name="status" id="status">
|
|
<option value="active">Active</option>
|
|
<option value="inactive">Inactive</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-light" data-bs-dismiss="modal">Cancel</button>
|
|
<button type="submit" class="btn btn-primary" id="btnSaveBrand">
|
|
<i class="bx bx-save"></i>
|
|
Save Brand
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<?php include('jsinclude.php'); ?>
|
|
|
|
<script>
|
|
$(document).ready(function() {
|
|
if ($.fn.DataTable) {
|
|
$('#brandsTable').DataTable({
|
|
pageLength: 25,
|
|
order: [
|
|
[1, 'asc'],
|
|
[0, 'asc']
|
|
],
|
|
responsive: true,
|
|
language: {
|
|
search: "",
|
|
searchPlaceholder: "Search brands..."
|
|
}
|
|
});
|
|
}
|
|
|
|
const brandModalElement = document.getElementById('brandModal');
|
|
const brandModal = new bootstrap.Modal(brandModalElement);
|
|
|
|
function resetBrandForm() {
|
|
$('#brandForm')[0].reset();
|
|
$('#idbrand').val('0');
|
|
$('#brandModalLabel').text('Add Brand');
|
|
$('#status').val('active');
|
|
}
|
|
|
|
function showAlert(type, message) {
|
|
if (typeof Swal !== 'undefined') {
|
|
Swal.fire({
|
|
icon: type,
|
|
title: type === 'success' ? 'Done' : 'Attention',
|
|
text: message,
|
|
confirmButtonColor: '#2563eb'
|
|
});
|
|
return;
|
|
}
|
|
|
|
alert(message);
|
|
}
|
|
|
|
function reloadAfterSuccess(message) {
|
|
if (typeof Swal !== 'undefined') {
|
|
Swal.fire({
|
|
icon: 'success',
|
|
title: 'Done',
|
|
text: message,
|
|
confirmButtonColor: '#2563eb'
|
|
}).then(function() {
|
|
window.location.reload();
|
|
});
|
|
return;
|
|
}
|
|
|
|
alert(message);
|
|
window.location.reload();
|
|
}
|
|
|
|
$('#btnAddBrand, #btnAddBrandSmall').on('click', function() {
|
|
resetBrandForm();
|
|
brandModal.show();
|
|
});
|
|
|
|
$('.btnEditBrand').on('click', function() {
|
|
const idbrand = $(this).data('id');
|
|
|
|
$.ajax({
|
|
url: 'brands.php',
|
|
type: 'POST',
|
|
dataType: 'json',
|
|
data: {
|
|
action: 'get_brand',
|
|
idbrand: idbrand
|
|
},
|
|
success: function(response) {
|
|
if (!response.success) {
|
|
showAlert('error', response.message || 'Unable to load brand.');
|
|
return;
|
|
}
|
|
|
|
const brand = response.brand;
|
|
|
|
$('#brandModalLabel').text('Edit Brand');
|
|
$('#idbrand').val(brand.idbrand);
|
|
$('#idcompany').val(brand.idcompany);
|
|
$('#brand_name').val(brand.brand_name);
|
|
$('#external_brand_code').val(brand.external_brand_code);
|
|
$('#status').val(brand.status);
|
|
|
|
brandModal.show();
|
|
},
|
|
error: function() {
|
|
showAlert('error', 'Server error while loading brand.');
|
|
}
|
|
});
|
|
});
|
|
|
|
$('#brandForm').on('submit', function(e) {
|
|
e.preventDefault();
|
|
|
|
$('#btnSaveBrand').prop('disabled', true).html('<i class="bx bx-loader-alt bx-spin"></i> Saving...');
|
|
|
|
$.ajax({
|
|
url: 'brands.php',
|
|
type: 'POST',
|
|
dataType: 'json',
|
|
data: $(this).serialize(),
|
|
success: function(response) {
|
|
$('#btnSaveBrand').prop('disabled', false).html('<i class="bx bx-save"></i> Save Brand');
|
|
|
|
if (!response.success) {
|
|
showAlert('error', response.message || 'Unable to save brand.');
|
|
return;
|
|
}
|
|
|
|
brandModal.hide();
|
|
reloadAfterSuccess(response.message || 'Brand saved successfully.');
|
|
},
|
|
error: function() {
|
|
$('#btnSaveBrand').prop('disabled', false).html('<i class="bx bx-save"></i> Save Brand');
|
|
showAlert('error', 'Server error while saving brand.');
|
|
}
|
|
});
|
|
});
|
|
|
|
$('.btnChangeStatus').on('click', function() {
|
|
const idbrand = $(this).data('id');
|
|
const status = $(this).data('status');
|
|
|
|
const message = status === 'active' ?
|
|
'Do you want to activate this brand?' :
|
|
'Do you want to set this brand as inactive?';
|
|
|
|
if (typeof Swal !== 'undefined') {
|
|
Swal.fire({
|
|
icon: 'question',
|
|
title: 'Confirm status change',
|
|
text: message,
|
|
showCancelButton: true,
|
|
confirmButtonColor: '#2563eb',
|
|
cancelButtonColor: '#64748b',
|
|
confirmButtonText: 'Yes, continue'
|
|
}).then(function(result) {
|
|
if (result.isConfirmed) {
|
|
changeBrandStatus(idbrand, status);
|
|
}
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (confirm(message)) {
|
|
changeBrandStatus(idbrand, status);
|
|
}
|
|
});
|
|
|
|
function changeBrandStatus(idbrand, status) {
|
|
$.ajax({
|
|
url: 'brands.php',
|
|
type: 'POST',
|
|
dataType: 'json',
|
|
data: {
|
|
action: 'change_status',
|
|
idbrand: idbrand,
|
|
status: status
|
|
},
|
|
success: function(response) {
|
|
if (!response.success) {
|
|
showAlert('error', response.message || 'Unable to update status.');
|
|
return;
|
|
}
|
|
|
|
reloadAfterSuccess(response.message || 'Status updated successfully.');
|
|
},
|
|
error: function() {
|
|
showAlert('error', 'Server error while updating status.');
|
|
}
|
|
});
|
|
}
|
|
|
|
$('.btnDeleteBrand').on('click', function() {
|
|
const idbrand = $(this).data('id');
|
|
|
|
if (typeof Swal !== 'undefined') {
|
|
Swal.fire({
|
|
icon: 'warning',
|
|
title: 'Delete brand?',
|
|
text: 'The brand will be deleted only if it has no linked departments or users.',
|
|
showCancelButton: true,
|
|
confirmButtonColor: '#dc2626',
|
|
cancelButtonColor: '#64748b',
|
|
confirmButtonText: 'Yes, delete'
|
|
}).then(function(result) {
|
|
if (result.isConfirmed) {
|
|
deleteBrand(idbrand);
|
|
}
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (confirm('Delete brand?')) {
|
|
deleteBrand(idbrand);
|
|
}
|
|
});
|
|
|
|
function deleteBrand(idbrand) {
|
|
$.ajax({
|
|
url: 'brands.php',
|
|
type: 'POST',
|
|
dataType: 'json',
|
|
data: {
|
|
action: 'delete_brand',
|
|
idbrand: idbrand
|
|
},
|
|
success: function(response) {
|
|
if (!response.success) {
|
|
showAlert('error', response.message || 'Unable to delete brand.');
|
|
return;
|
|
}
|
|
|
|
reloadAfterSuccess(response.message || 'Brand deleted successfully.');
|
|
},
|
|
error: function() {
|
|
showAlert('error', 'Server error while deleting brand.');
|
|
}
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
|
|
</body>
|
|
|
|
</html>
|