Files
yogibook_aury_new/public/orderbooklist.php
T
2026-08-09 07:01:23 +02:00

507 lines
23 KiB
PHP

<?php
require_once('include/headscript.php');
/**
* Gestione ordini in stato "pending": elenco, propagazione (con calcolo
* scadenza), cancellazione e inserimento manuale di un nuovo ordine.
* orderbook contiene già first_name, last_name, cod, ecc.
*/
$pdo = DBHandlerSelect::getInstance()->getConnection();
function e($value): string
{
return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
}
function initials(string $first, string $last): string
{
$ini = strtoupper(mb_substr(trim($first), 0, 1) . mb_substr(trim($last), 0, 1));
return $ini !== '' ? $ini : '?';
}
function avatarColor(string $seed): string
{
$palette = ['#1ebf73', '#2980b9', '#8e44ad', '#e67e22', '#16a085', '#c0392b', '#2c3e50', '#d35400'];
return $palette[abs(crc32($seed)) % count($palette)];
}
// Ordini pending
$orders = $pdo->query("SELECT * FROM orderbook WHERE status = 'pending' ORDER BY order_date_created DESC")->fetchAll();
// Servizi per il dropdown del nuovo ordine
$services = $pdo->query("SELECT idservice, servicename, day, time FROM service ORDER BY servicename")->fetchAll();
?>
<!doctype html>
<html lang="it">
<head>
<meta charset="utf-8" />
<title>YogiBook - Ordini in attesa</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta content="YogiBook - Prenotazione facile YogaSoul" name="description" />
<meta content="Advanced Creative Solutions" name="author" />
<link rel="shortcut icon" href="assets/images/favicon.ico">
<link href="assets/css/bootstrap.min.css" id="bootstrap-style" rel="stylesheet" type="text/css" />
<link href="assets/css/icons.min.css" rel="stylesheet" type="text/css" />
<link href="assets/css/app.min.css" id="app-style" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<style>
.admin-card {
border: none;
border-radius: 14px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.06);
}
.admin-card .card-body {
padding: 26px 30px;
}
.section-title {
font-size: 15px;
font-weight: 700;
letter-spacing: 0.04em;
text-transform: uppercase;
color: #6b7280;
margin-bottom: 4px;
}
.section-lead {
color: #9ca3af;
font-size: 14px;
margin-bottom: 22px;
}
.order-table thead th {
font-size: 12px;
text-transform: uppercase;
letter-spacing: 0.03em;
color: #6b7280;
border-bottom: 2px solid #eef0f3;
white-space: nowrap;
}
.order-table td {
vertical-align: middle;
}
.user-cell {
display: flex;
align-items: center;
gap: 10px;
}
.avatar {
width: 36px;
height: 36px;
border-radius: 50%;
color: #fff;
font-weight: 700;
font-size: 13px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.user-name {
font-weight: 600;
color: #1f2937;
}
.qty-pill {
display: inline-block;
background: #eef6f1;
color: #1a7f52;
font-weight: 700;
font-size: 13px;
padding: 2px 10px;
border-radius: 20px;
}
.btn-propagate,
.btn-cancel {
border: none;
border-radius: 8px;
padding: 7px 14px;
font-size: 13px;
font-weight: 600;
color: #fff;
cursor: pointer;
transition: filter 0.15s;
white-space: nowrap;
}
.btn-propagate {
background: #27ae60;
}
.btn-cancel {
background: #e74c3c;
}
.btn-propagate:hover,
.btn-cancel:hover {
filter: brightness(0.93);
}
.form-label {
font-weight: 600;
font-size: 14px;
color: #374151;
}
.form-control,
.form-select {
border-radius: 8px;
border: 1px solid #e2e4e9;
padding: 10px 12px;
}
.form-control:focus,
.form-select:focus {
border-color: #1ebf73;
box-shadow: 0 0 0 3px rgba(30, 191, 115, 0.12);
}
.btn-save {
border-radius: 8px;
padding: 10px 26px;
font-weight: 600;
}
.search-results {
border: 1px solid #e2e4e9;
border-radius: 8px;
margin-top: 6px;
max-height: 220px;
overflow-y: auto;
display: none;
background: #fff;
}
.search-results.show {
display: block;
}
.user-result {
padding: 10px 12px;
cursor: pointer;
font-size: 13px;
border-bottom: 1px solid #f0f2f5;
display: flex;
align-items: center;
gap: 10px;
}
.user-result:last-child {
border-bottom: none;
}
.user-result:hover {
background: #eef6f1;
}
.empty-state {
text-align: center;
padding: 40px 10px;
color: #9ca3af;
}
.empty-state i {
font-size: 34px;
margin-bottom: 10px;
display: block;
color: #d5d9e0;
}
</style>
</head>
<body>
<div id="layout-wrapper">
<header id="page-topbar" class="isvertical-topbar">
<div class="navbar-header">
<div class="d-flex">
<?php include('include/logoarea.php'); ?>
<button type="button" class="btn btn-sm px-3 font-size-24 header-item waves-effect vertical-menu-btn">
<i class="bx bx-menu align-middle"></i>
</button>
<div class="page-title-box align-self-center d-none d-md-block">
<h4 class="page-title mb-0">Ordini in attesa</h4>
</div>
</div>
<div class="d-flex">
<?php include('include/languageselection.php'); ?>
<?php include('include/profiletopbar.php'); ?>
</div>
</div>
</header>
<?php include('include/sidebar.php'); ?>
<header class="ishorizontal-topbar">
<div class="navbar-header">
<div class="d-flex"></div>
</div>
<div class="topnav">
<div class="container-fluid">
<nav class="navbar navbar-light navbar-expand-lg topnav-menu"></nav>
</div>
</div>
</header>
<div class="main-content">
<div class="page-content">
<div class="container-fluid">
<!-- Elenco ordini pending -->
<div class="row">
<div class="col-12">
<div class="card admin-card mb-4">
<div class="card-body">
<div class="section-title">Ordini in attesa</div>
<p class="section-lead">Ciao <?php echo e($firstname); ?>, questi ordini sono in stato pending: propagali o cancellali.</p>
<div class="table-responsive">
<table class="table order-table align-middle">
<thead>
<tr>
<th>ID Ordine</th>
<th>Data</th>
<th>Utente</th>
<th>Classe</th>
<th>Quantità</th>
<th class="text-end">Azioni</th>
</tr>
</thead>
<tbody>
<?php if (empty($orders)) : ?>
<tr>
<td colspan="6">
<div class="empty-state">
<i class="fas fa-receipt"></i>
Nessun ordine in attesa al momento.
</div>
</td>
</tr>
<?php else : ?>
<?php foreach ($orders as $o) :
$fullName = trim($o['first_name'] . ' ' . $o['last_name']);
$idorder = (int) $o['idorderbook'];
?>
<tr>
<td><strong><?php echo e($o['order_id']); ?></strong></td>
<td><?php echo e($o['order_date_created'] ? date('d-m-Y', strtotime($o['order_date_created'])) : '-'); ?></td>
<td>
<div class="user-cell">
<div class="avatar" style="background: <?php echo avatarColor($fullName); ?>;">
<?php echo e(initials($o['first_name'] ?? '', $o['last_name'] ?? '')); ?>
</div>
<span class="user-name"><?php echo e($fullName); ?></span>
</div>
</td>
<td><?php echo e($o['cod']); ?></td>
<td><span class="qty-pill"><?php echo e($o['quantityclass']); ?></span></td>
<td class="text-end">
<button type="button" class="btn-propagate propagate-btn" data-idorder="<?php echo $idorder; ?>">
<i class="bx bx-check-double"></i> Propaga
</button>
<a href="cancelsingleorder.php?idorder=<?php echo $idorder; ?>">
<button type="button" class="btn-cancel"><i class="bx bx-block"></i> Cancella</button>
</a>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<!-- Nuovo ordine -->
<div class="row">
<div class="col-12">
<div class="card admin-card">
<div class="card-body">
<div class="section-title">Inserisci nuovo ordine</div>
<p class="section-lead">Cerca un utente esistente digitando il cognome, oppure inserisci i dati manualmente.</p>
<form action="inserisci_ordine.php" method="post" id="new-order-form">
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label">Nome</label>
<input type="text" class="form-control name" placeholder="Nome" name="formrow-firstname-input">
</div>
<div class="col-md-6 mb-3">
<label class="form-label">Cognome</label>
<input type="text" class="form-control surname" placeholder="Cognome" name="surname-input" autocomplete="off">
<div class="search-results"></div>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label">Email</label>
<input type="email" class="form-control email" placeholder="Email" name="formrow-email-input">
</div>
<div class="col-md-6 mb-3">
<label class="form-label">Data ordine</label>
<input class="form-control" type="date" name="example-date-input">
</div>
</div>
<div class="row">
<div class="col-md-4 mb-3">
<label class="form-label">Data prima lezione</label>
<input class="form-control" type="date" name="first-lesson-date">
</div>
<div class="col-md-4 mb-3">
<label class="form-label">N. Ticket</label>
<input type="text" class="form-control" placeholder="Ticket" name="ticket">
</div>
<div class="col-md-4 mb-3">
<label class="form-label">Classe</label>
<select id="service-select" name="formrow-inputState" class="form-select">
<option value="">Scegli...</option>
<?php foreach ($services as $svc) :
$label = trim($svc['servicename'] . ' - ' . $svc['day'] . ' - ' . $svc['time'], ' -');
?>
<option value="<?php echo (int) $svc['idservice']; ?>"><?php echo e($label); ?></option>
<?php endforeach; ?>
</select>
<input type="hidden" name="cod" id="hiddenCod">
</div>
</div>
<input type="hidden" class="userid" name="userid" id="userid">
<button type="submit" class="btn btn-primary btn-save">Inserisci ordine</button>
</form>
</div>
</div>
</div>
</div>
</div>
<?php include('include/footer.php'); ?>
</div>
</div>
</div>
<script src="assets/libs/bootstrap/js/bootstrap.bundle.min.js"></script>
<script src="assets/libs/metismenujs/metismenujs.min.js"></script>
<script src="assets/libs/simplebar/simplebar.min.js"></script>
<script src="assets/libs/eva-icons/eva.min.js"></script>
<script src="assets/js/app.js"></script>
<script>
// Salva il testo della classe scelta nel campo hidden 'cod'
const selectElem = document.getElementById('service-select');
const hiddenElem = document.getElementById('hiddenCod');
selectElem.addEventListener('change', function() {
hiddenElem.value = selectElem.options[selectElem.selectedIndex].text;
});
$(document).ready(function() {
// Ricerca utenti per cognome (e nome)
let searchTimeout;
$('.surname, .name').on('input', function() {
clearTimeout(searchTimeout);
var form = $(this).closest('form');
var results = form.find('.search-results');
var firstName = form.find('.name').val().trim();
var lastName = form.find('.surname').val().trim();
if (firstName.length < 2 && lastName.length < 2) {
results.removeClass('show').empty();
return;
}
searchTimeout = setTimeout(function() {
$.ajax({
url: 'search_users.php',
method: 'POST',
data: {
firstName: firstName,
lastName: lastName,
searchTerm: lastName
},
dataType: 'json',
cache: false,
success: function(data) {
results.empty();
if (data.results && data.results.length > 0) {
data.results.forEach(function(u) {
var uid = u.userid || u.id;
var ini = ((u.first_name || '').charAt(0) + (u.last_name || '').charAt(0)).toUpperCase();
results.append(
'<div class="user-result" data-email="' + u.email + '" data-userid="' + uid +
'" data-firstname="' + u.first_name + '" data-lastname="' + u.last_name + '">' +
'<span class="avatar" style="width:32px;height:32px;font-size:12px;background:#2980b9;">' + ini + '</span>' +
'<span><strong>' + u.first_name + ' ' + u.last_name + '</strong><br>' +
'<small style="color:#6b7280;">' + u.email + '</small></span></div>'
);
});
results.addClass('show');
results.find('.user-result').on('click', function() {
form.find('.email').val($(this).data('email'));
form.find('.userid').val($(this).data('userid'));
form.find('.name').val($(this).data('firstname'));
form.find('.surname').val($(this).data('lastname'));
results.removeClass('show').empty();
});
} else {
results.append('<div class="user-result" style="color:#9ca3af;">Nessun utente trovato.</div>').addClass('show');
}
},
error: function() {
results.html('<div class="user-result" style="color:#c0392b;">Errore durante la ricerca.</div>').addClass('show');
}
});
}, 300);
});
// Propagazione ordine con calcolo scadenza
$('.propagate-btn').on('click', function() {
var idorder = $(this).data('idorder');
$.ajax({
url: 'calculate_expiry.php',
method: 'GET',
data: {
idorder: idorder
},
dataType: 'json',
success: function(data) {
if (data.error) {
Swal.fire('Errore', data.error, 'error');
return;
}
var calculatedExpiry = data.expiry_date;
Swal.fire({
title: 'Conferma Scadenza',
html: '<p>Data di scadenza calcolata: <strong>' + calculatedExpiry + '</strong></p>' +
'<label for="expiry-date">Modifica scadenza (se necessario):</label>' +
'<input type="date" id="expiry-date" class="swal2-input" value="' + calculatedExpiry + '">',
showCancelButton: true,
confirmButtonText: 'Conferma e Propaga',
cancelButtonText: 'Annulla',
preConfirm: () => document.getElementById('expiry-date').value
}).then((result) => {
if (result.isConfirmed) {
var expiryDate = result.value || calculatedExpiry;
window.location.href = 'propagatesingleorder.php?idorder=' + idorder + '&expiry_date=' + expiryDate;
}
});
},
error: function() {
Swal.fire('Errore', 'Impossibile calcolare la scadenza', 'error');
}
});
});
});
</script>
</body>
</html>