You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
613 lines
24 KiB
613 lines
24 KiB
<!-- Content Wrapper. Contains page content -->
|
|
<div class="content-wrapper">
|
|
<!-- Content Header (Page header) -->
|
|
<section class="content-header">
|
|
<h1>
|
|
Gérer les
|
|
<small>Motos</small>
|
|
</h1>
|
|
<ol class="breadcrumb">
|
|
<li><a href="#"><i class="fa fa-dashboard"></i> Accueil</a></li>
|
|
<li class="active">Motos</li>
|
|
</ol>
|
|
</section>
|
|
|
|
<!-- Main content -->
|
|
<section class="content">
|
|
<!-- Small boxes (Stat box) -->
|
|
<div class="row">
|
|
<div class="col-md-12 col-xs-12">
|
|
|
|
<div id="messages"></div>
|
|
|
|
<?php if (session()->getFlashdata('success')): ?>
|
|
<div class="alert alert-success alert-dismissible" role="alert">
|
|
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
|
<?php echo session()->getFlashdata('success'); ?>
|
|
</div>
|
|
<?php elseif (session()->getFlashdata('error')): ?>
|
|
<div class="alert alert-error alert-dismissible" role="alert">
|
|
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
|
<?php echo session()->getFlashdata('error'); ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if (in_array('createProduct', $user_permission)): ?>
|
|
<div class="d-flex gap-2 mb-3 align-items-center">
|
|
<a href="<?= base_url('products/create') ?>" class="btn btn-primary">
|
|
<i class="fa fa-plus"></i> Ajouter une moto
|
|
</a>
|
|
|
|
<button class="btn btn-secondary" id="openModalBtn">
|
|
<i class="fa fa-qrcode"></i>
|
|
</button>
|
|
|
|
<button
|
|
type="button"
|
|
class="btn btn-success"
|
|
id="importExcelBtn"
|
|
onclick="document.getElementById('excel_product').click()"
|
|
>
|
|
<i class="far fa-file-excel"></i> Importer un fichier
|
|
</button>
|
|
|
|
<form
|
|
action="<?= base_url('products/importExcel') ?>"
|
|
method="post"
|
|
enctype="multipart/form-data"
|
|
class="d-inline-flex align-items-center"
|
|
>
|
|
<input
|
|
type="file"
|
|
name="excel_product"
|
|
id="excel_product"
|
|
accept=".xls,.xlsx"
|
|
hidden
|
|
required
|
|
style="display: none;"
|
|
/>
|
|
</form>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
const inputFile = document.getElementById('excel_product');
|
|
const form = inputFile ? inputFile.form : null;
|
|
|
|
if (inputFile && form) {
|
|
inputFile.addEventListener('change', function () {
|
|
if (this.files.length) {
|
|
const formData = new FormData(form);
|
|
|
|
$.ajax({
|
|
url: "<?= base_url('products/createByExcel') ?>",
|
|
type: 'post',
|
|
data: formData,
|
|
contentType: false,
|
|
processData: false,
|
|
dataType: 'json',
|
|
success: function(response) {
|
|
if (typeof manageTable !== 'undefined') {
|
|
manageTable.ajax.reload(null, false);
|
|
}
|
|
|
|
if (response.success === true) {
|
|
$("#messages").html(
|
|
'<div class="alert alert-success alert-dismissible" role="alert">' +
|
|
'<button type="button" class="close" data-dismiss="alert" aria-label="Close">' +
|
|
'<span aria-hidden="true">×</span>' +
|
|
'</button>' +
|
|
'<strong><span class="glyphicon glyphicon-ok-sign"></span></strong> ' +
|
|
response.messages +
|
|
'</div>'
|
|
);
|
|
} else {
|
|
if (response.messages instanceof Object) {
|
|
$.each(response.messages, function(index, value) {
|
|
var id = $("#" + index);
|
|
|
|
id.closest('.form-group')
|
|
.removeClass('has-error has-success')
|
|
.addClass(value.length > 0 ? 'has-error' : 'has-success');
|
|
|
|
id.after(value);
|
|
});
|
|
} else {
|
|
$("#messages").html(
|
|
'<div class="alert alert-danger alert-dismissible" role="alert">' +
|
|
'<button type="button" class="close" data-dismiss="alert" aria-label="Close">' +
|
|
'<span aria-hidden="true">×</span>' +
|
|
'</button>' +
|
|
'<strong><span class="glyphicon glyphicon-exclamation-sign"></span></strong> ' +
|
|
response.messages +
|
|
'</div>'
|
|
);
|
|
}
|
|
}
|
|
},
|
|
error: function(xhr, status, error) {
|
|
console.error("Erreur AJAX : ", error);
|
|
$("#messages").html(
|
|
'<div class="alert alert-danger alert-dismissible" role="alert">' +
|
|
'<button type="button" class="close" data-dismiss="alert" aria-label="Close">' +
|
|
'<span aria-hidden="true">×</span>' +
|
|
'</button>' +
|
|
'<strong><span class="glyphicon glyphicon-exclamation-sign"></span></strong> ' +
|
|
'Erreur lors de l\'upload du fichier' +
|
|
'</div>'
|
|
);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<div class="box">
|
|
<div class="box-header">
|
|
<h3 class="box-title">Gérer les produits</h3>
|
|
</div>
|
|
<!-- /.box-header -->
|
|
<div class="box-body">
|
|
<table id="manageTable" class="table table-bordered table-striped">
|
|
<thead>
|
|
<tr>
|
|
<th>Image</th>
|
|
<th>UGS</th>
|
|
<th>Nom de produit</th>
|
|
<th>Prix</th>
|
|
<th>Magasin</th>
|
|
<th>Disponibilité</th>
|
|
<!-- ✅ MODIFICATION PRINCIPALE : Toujours afficher la colonne Action -->
|
|
<th>Action</th>
|
|
</tr>
|
|
</thead>
|
|
</table>
|
|
</div>
|
|
<!-- /.box-body -->
|
|
</div>
|
|
<!-- /.box -->
|
|
</div>
|
|
<!-- col-md-12 -->
|
|
</div>
|
|
<!-- /.row -->
|
|
|
|
</section>
|
|
<!-- /.content -->
|
|
</div>
|
|
<!-- /.content-wrapper -->
|
|
|
|
<?php if (in_array('deleteProduct', $user_permission)): ?>
|
|
<!-- remove brand modal -->
|
|
<div class="modal fade" tabindex="-1" role="dialog" id="removeModal">
|
|
<div class="modal-dialog" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
|
<h4 class="modal-title">Supprimer le produit</h4>
|
|
</div>
|
|
<form role="form" action="<?php echo base_url('products/remove') ?>" method="post" id="removeForm">
|
|
<div class="modal-body">
|
|
<p>Voulez-vous vraiment supprimer ce produit ?</p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">Fermer</button>
|
|
<button type="submit" class="btn btn-primary">Oui</button>
|
|
</div>
|
|
</form>
|
|
</div><!-- /.modal-content -->
|
|
</div><!-- /.modal-dialog -->
|
|
</div><!-- /.modal -->
|
|
<?php endif; ?>
|
|
|
|
<div class="modal fade" id="assignStoreModal" tabindex="-1" role="dialog" aria-labelledby="assignStoreModalLabel">
|
|
<div class="modal-dialog" role="document">
|
|
<div class="modal-content">
|
|
<!-- Modal Header -->
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
<h4 class="modal-title" id="assignStoreModalLabel">Assigner une moto à un Point de vente</h4>
|
|
</div>
|
|
|
|
<!-- Modal Body -->
|
|
<div class="modal-body">
|
|
<p>Point de vente actuel : <span class="badge badge-primary" id="current_magasin"></span></p>
|
|
<p>Veuillez sélectionner un magasin dans la liste ci-dessous :</p>
|
|
<!-- Store List -->
|
|
<div class="list-group">
|
|
<?php foreach ($stores as $store): ?>
|
|
<div class="list-group-item d-flex justify-content-between align-items-center">
|
|
<!-- Store Name -->
|
|
<span><?php echo $store['name']; ?></span>
|
|
<!-- Action Button -->
|
|
<button class="btn btn-primary btn-sm assign-store-btn"
|
|
style="border-radius: 15px;"
|
|
data-products-id=""
|
|
data-store-id="<?php echo $store['id']; ?>">
|
|
Assigner
|
|
</button>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal Footer -->
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">Fermer</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- QR Code Multiple Modal -->
|
|
<div class="modal fade" tabindex="-1" role="dialog" id="qrMultipleModal">
|
|
<div class="modal-dialog" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
|
<h4 class="modal-title">Ajouter plusieur code QR</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="form-group">
|
|
<label for="moto">Motos</label>
|
|
<select class="form-control select_group" id="moto" name="moto[]" multiple="multiple" style="display: block;width: 100%;">
|
|
<?php foreach ($motos as $k => $v): ?>
|
|
<option value="<?php echo $v['id'] ?>"><?php echo $v['name'] ?></option>
|
|
<?php endforeach ?>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">Fermer</button>
|
|
<button type="button" class="btn btn-primary" id="prints">Imprimer</button>
|
|
</div>
|
|
</div><!-- /.modal-content -->
|
|
</div><!-- /.modal-dialog -->
|
|
</div><!-- /.modal -->
|
|
|
|
<div id="qrcode" style="display: none;"></div>
|
|
<div id="qrContainer" style="display: none;"></div>
|
|
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
|
|
|
|
<script type="text/javascript">
|
|
var manageTable;
|
|
var base_url = "<?php echo base_url(); ?>";
|
|
$(".select_group").select2();
|
|
|
|
$(document).ready(function() {
|
|
$("#mainProductNav").addClass('active');
|
|
$("#manageProductNav").addClass('active');
|
|
|
|
// Configuration DataTables en français
|
|
$.extend(true, $.fn.dataTable.defaults, {
|
|
language: {
|
|
sProcessing: "Traitement en cours...",
|
|
sSearch: "Rechercher :",
|
|
sLengthMenu: "Afficher _MENU_ éléments",
|
|
sInfo: "Affichage de l'élement _START_ à _END_ sur _TOTAL_ éléments",
|
|
sInfoEmpty: "Affichage de l'élement 0 à 0 sur 0 élément",
|
|
sInfoFiltered: "(filtré de _MAX_ éléments au total)",
|
|
sLoadingRecords: "Chargement en cours...",
|
|
sZeroRecords: "Aucun élément à afficher",
|
|
sEmptyTable: "Aucune donnée disponible dans le tableau",
|
|
oPaginate: {
|
|
sFirst: "Premier",
|
|
sPrevious: "Précédent",
|
|
sNext: "Suivant",
|
|
sLast: "Dernier"
|
|
},
|
|
oAria: {
|
|
sSortAscending: ": activer pour trier la colonne par ordre croissant",
|
|
sSortDescending: ": activer pour trier la colonne par ordre décroissant"
|
|
}
|
|
}
|
|
});
|
|
|
|
// Initialisation DataTable
|
|
manageTable = $('#manageTable').DataTable({
|
|
'ajax': base_url + 'products/fetchProductData',
|
|
'order': [],
|
|
'columns': [
|
|
{
|
|
data: 0, // Colonne Image
|
|
render: function(data) {
|
|
return data; // Affiche le HTML brut (déjà formaté en PHP)
|
|
},
|
|
orderable: false // Désactive le tri sur cette colonne
|
|
},
|
|
{ data: 1 }, // SKU
|
|
{ data: 2 }, // Nom
|
|
{
|
|
data: 3, // Prix
|
|
render: function(data, type, row) {
|
|
if (type === 'display') {
|
|
// Format: "1 900 000 Ar"
|
|
return new Intl.NumberFormat('fr-FR').format(data) + ' Ar';
|
|
}
|
|
return data; // Valeur non formatée pour le tri/filtre
|
|
}
|
|
},
|
|
{ data: 4 }, // Magasin
|
|
{ data: 5 }, // Disponibilité
|
|
{ data: 6 } // Actions - ✅ Toujours présent maintenant
|
|
],
|
|
'columnDefs': [{
|
|
targets: 3,
|
|
className: 'text-right'
|
|
}]
|
|
});
|
|
|
|
// CORRECTION: Utilisation de la délégation d'événements pour les boutons
|
|
// Boutons d'assignation de magasin
|
|
$(document).on('click', '.assign-store-btn', function() {
|
|
const productId = $(this).data('products-id');
|
|
const storeId = $(this).data('store-id');
|
|
|
|
console.log('Product ID:', productId, 'Store ID:', storeId); // Debug
|
|
|
|
if (confirm('Êtes-vous sûr de vouloir assigner cette moto à ce magasin ?')) {
|
|
$.ajax({
|
|
url: base_url + 'products/assign_store',
|
|
type: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-Requested-With': 'XMLHttpRequest',
|
|
},
|
|
data: JSON.stringify({
|
|
product_id: productId,
|
|
store_id: storeId
|
|
}),
|
|
dataType: 'json',
|
|
success: function(data) {
|
|
$("#assignStoreModal").modal("hide");
|
|
|
|
if (data.success) {
|
|
$("#messages").html(
|
|
'<div class="alert alert-success alert-dismissible" role="alert">' +
|
|
'<button type="button" class="close" data-dismiss="alert" aria-label="Close">' +
|
|
'<span aria-hidden="true">×</span>' +
|
|
'</button>' +
|
|
'<strong><span class="glyphicon glyphicon-ok-sign"></span></strong> ' +
|
|
(data.message || 'Moto assignée avec succès !') +
|
|
'</div>'
|
|
);
|
|
|
|
// Recharger seulement le DataTable au lieu de la page
|
|
manageTable.ajax.reload(null, false);
|
|
} else {
|
|
$("#messages").html(
|
|
'<div class="alert alert-danger alert-dismissible" role="alert">' +
|
|
'<button type="button" class="close" data-dismiss="alert" aria-label="Close">' +
|
|
'<span aria-hidden="true">×</span>' +
|
|
'</button>' +
|
|
'<strong><span class="glyphicon glyphicon-exclamation-sign"></span></strong> ' +
|
|
(data.message || 'Une erreur est survenue.') +
|
|
'</div>'
|
|
);
|
|
}
|
|
},
|
|
error: function(xhr, status, error) {
|
|
console.error('Error assigning store:', error);
|
|
$("#assignStoreModal").modal("hide");
|
|
$("#messages").html(
|
|
'<div class="alert alert-danger alert-dismissible" role="alert">' +
|
|
'<button type="button" class="close" data-dismiss="alert" aria-label="Close">' +
|
|
'<span aria-hidden="true">×</span>' +
|
|
'</button>' +
|
|
'<strong><span class="glyphicon glyphicon-exclamation-sign"></span></strong> ' +
|
|
'Erreur de connexion lors de l\'assignation.' +
|
|
'</div>'
|
|
);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
// Boutons d'ouverture du modal d'assignation
|
|
$(document).on('click', '.assignbtn', function() {
|
|
const storeName = $(this).data('magasin');
|
|
const productId = $(this).data('products-id');
|
|
|
|
console.log('Opening modal for product:', productId, 'Current store:', storeName); // Debug
|
|
|
|
$('#current_magasin').text(storeName);
|
|
$('.assign-store-btn').attr('data-products-id', productId);
|
|
});
|
|
|
|
});
|
|
|
|
// Fonction QR Code PDF pour un seul produit
|
|
async function generateQrPdf(productId) {
|
|
const productUrl = `https://motorbike.c4m.mg/ventes/show/${productId}`;
|
|
|
|
// Generate QR Code
|
|
const qrDiv = document.getElementById("qrcode");
|
|
qrDiv.innerHTML = ""; // Clear previous QR code
|
|
new QRCode(qrDiv, {
|
|
text: productUrl,
|
|
width: 300, // Increased size for better resolution
|
|
height: 300
|
|
});
|
|
|
|
// Wait for QR code to render (small delay)
|
|
await new Promise(resolve => setTimeout(resolve, 500));
|
|
|
|
// Convert QR Code to Image
|
|
const qrCanvas = qrDiv.querySelector("canvas");
|
|
const qrImage = qrCanvas.toDataURL("image/png", 1.0); // Max quality
|
|
|
|
// Create PDF
|
|
const { jsPDF } = window.jspdf;
|
|
const pdf = new jsPDF({
|
|
orientation: "portrait",
|
|
unit: "mm",
|
|
format: "a6" // Set to A6 size
|
|
});
|
|
|
|
pdf.addImage(qrImage, "PNG", 25, 40, 55, 55); // Adjust size & position
|
|
|
|
// Download PDF
|
|
pdf.save(`QRCode_Product_${productId}.pdf`);
|
|
}
|
|
|
|
// Function to show the QR multiple modal
|
|
function showQrMultipleModal() {
|
|
$('#qrMultipleModal').modal('show');
|
|
}
|
|
|
|
// Event listener pour le bouton d'ouverture du modal QR
|
|
document.addEventListener("DOMContentLoaded", function() {
|
|
const openModalBtn = document.getElementById("openModalBtn");
|
|
if (openModalBtn) {
|
|
openModalBtn.addEventListener("click", function() {
|
|
showQrMultipleModal();
|
|
});
|
|
}
|
|
});
|
|
|
|
// Génération PDF pour multiples QR codes
|
|
const moto = document.getElementById('moto');
|
|
const buttontest = document.getElementById('prints')
|
|
|
|
let arrayvalue = [];
|
|
if (buttontest) {
|
|
buttontest.addEventListener('click', async function() {
|
|
arrayvalue = Array.from(moto.selectedOptions).map(option => ({
|
|
id: option.value, // Value from <option value="...">
|
|
name: option.text // Label from <option>...</option>
|
|
}));
|
|
|
|
console.log(arrayvalue); // Debugging: Check selected values in console
|
|
|
|
const { jsPDF } = window.jspdf;
|
|
const doc = new jsPDF();
|
|
|
|
const qrSize = 50; // QR Code size
|
|
const marginX = 20; // Left margin
|
|
const marginY = 20; // Top margin
|
|
const spacingX = 65; // Space between QR codes horizontally
|
|
const spacingY = 80; // Space between QR codes vertically
|
|
|
|
let x = marginX;
|
|
let y = marginY;
|
|
let count = 0;
|
|
|
|
for (let i = 0; i < arrayvalue.length; i++) {
|
|
let moto = arrayvalue[i];
|
|
|
|
// Create a hidden div for the QR Code
|
|
let qrDiv = document.createElement("div");
|
|
document.getElementById("qrContainer").appendChild(qrDiv);
|
|
|
|
// Generate QR Code
|
|
let qrCode = new QRCode(qrDiv, {
|
|
text: `https://motorbike.c4m.mg/ventes/show/${moto.id}`,
|
|
width: qrSize,
|
|
height: qrSize
|
|
});
|
|
|
|
// Wait for QR code to render
|
|
await new Promise(resolve => setTimeout(resolve, 500));
|
|
|
|
// Convert QR code to Base64 Image
|
|
let canvas = qrDiv.querySelector("canvas");
|
|
if (!canvas) {
|
|
alert("Error: QR Code not generated!");
|
|
return;
|
|
}
|
|
let qrDataUrl = canvas.toDataURL("image/png");
|
|
|
|
// Draw text (Moto Name)
|
|
doc.text(moto.name, x + 5, y - 5);
|
|
|
|
// Draw QR Code
|
|
doc.addImage(qrDataUrl, "PNG", x, y, qrSize, qrSize);
|
|
|
|
// Remove QR code from the DOM
|
|
qrDiv.remove();
|
|
|
|
// Update position for next QR code
|
|
x += spacingX;
|
|
count++;
|
|
|
|
// If 3 QR codes in a row, move to the next row
|
|
if (count % 3 === 0) {
|
|
x = marginX; // Reset X position
|
|
y += spacingY; // Move to next row
|
|
}
|
|
|
|
// If 9 QR codes per page, add a new page
|
|
if (count % 9 === 0 && i !== arrayvalue.length - 1) {
|
|
doc.addPage();
|
|
x = marginX; // Reset X position
|
|
y = marginY; // Reset Y position
|
|
}
|
|
}
|
|
|
|
// Save PDF
|
|
doc.save(`QRCode_Motos.pdf`);
|
|
$("#qrMultipleModal").modal('hide');
|
|
});
|
|
}
|
|
|
|
// Remove functions avec délégation d'événements
|
|
function removeFunc(id) {
|
|
if (id) {
|
|
$("#removeForm").off('submit').on('submit', function(e) {
|
|
e.preventDefault();
|
|
|
|
var form = $(this);
|
|
$(".text-danger").remove();
|
|
|
|
$.ajax({
|
|
url: form.attr('action'),
|
|
type: form.attr('method'),
|
|
data: { product_id: id },
|
|
dataType: 'json',
|
|
success: function(response) {
|
|
manageTable.ajax.reload(null, false);
|
|
|
|
if (response.success === true) {
|
|
$("#messages").html(
|
|
'<div class="alert alert-success alert-dismissible" role="alert">' +
|
|
'<button type="button" class="close" data-dismiss="alert" aria-label="Close">' +
|
|
'<span aria-hidden="true">×</span>' +
|
|
'</button>' +
|
|
'<strong><span class="glyphicon glyphicon-ok-sign"></span></strong> ' + response.messages +
|
|
'</div>'
|
|
);
|
|
$("#removeModal").modal('hide');
|
|
} else {
|
|
$("#messages").html(
|
|
'<div class="alert alert-warning alert-dismissible" role="alert">' +
|
|
'<button type="button" class="close" data-dismiss="alert" aria-label="Close">' +
|
|
'<span aria-hidden="true">×</span>' +
|
|
'</button>' +
|
|
'<strong><span class="glyphicon glyphicon-exclamation-sign"></span></strong> ' + response.messages +
|
|
'</div>'
|
|
);
|
|
}
|
|
},
|
|
error: function(xhr, status, error) {
|
|
console.error('Error removing product:', error);
|
|
$("#messages").html(
|
|
'<div class="alert alert-danger alert-dismissible" role="alert">' +
|
|
'<button type="button" class="close" data-dismiss="alert" aria-label="Close">' +
|
|
'<span aria-hidden="true">×</span>' +
|
|
'</button>' +
|
|
'<strong><span class="glyphicon glyphicon-exclamation-sign"></span></strong> ' +
|
|
'Erreur lors de la suppression.' +
|
|
'</div>'
|
|
);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
}
|
|
</script>
|