first commit

This commit is contained in:
Emanuele Slusarz
2026-08-22 11:15:29 +02:00
commit ec30fb40b9
38 changed files with 3723 additions and 0 deletions
+26
View File
@@ -0,0 +1,26 @@
<?php
require_once __DIR__ . "/../includes/auth.php";
requireRole("cliente");
$pageTitle = "Dashboard cliente";
$basePath = "..";
require __DIR__ . "/../includes/header.php";
?>
<div class="p-4 mb-4 bg-white rounded shadow-sm">
<h1 class="h3">Ciao, <?= e($_SESSION["nome"]) ?></h1>
<p class="mb-0">Consulta il menu, componi un ordine e controlla le tue consegne.</p>
</div>
<div class="row g-3">
<?php foreach ([
["Menu", "Prodotti disponibili e caratteristiche", "menu.php"],
["Nuovo ordine", "Componi e conferma un ordine", "ordine.php"],
["I miei ordini", "Stato e storico degli ordini", "miei_ordini.php"],
["Preferiti", "I prodotti ordinati più spesso", "preferiti.php"],
["Indirizzi", "Gestisci le destinazioni", "indirizzi.php"],
] as [$titolo, $testo, $url]): ?>
<div class="col-md-6 col-lg-4"><div class="card h-100 shadow-sm"><div class="card-body">
<h2 class="h5"><?= e($titolo) ?></h2><p><?= e($testo) ?></p>
<a class="btn btn-primary" href="<?= e($url) ?>">Apri</a>
</div></div></div>
<?php endforeach; ?>
</div>
<?php require __DIR__ . "/../includes/footer.php"; ?>
+224
View File
@@ -0,0 +1,224 @@
<?php
require_once __DIR__ . "/../includes/auth.php";
requireRole("cliente");
require_once __DIR__ . "/../config/database.php";
$idCliente = (int) $_SESSION["idUtente"];
$azione = $_POST["azione"] ?? null;
$idIndirizzo = filter_input(INPUT_POST, "idIndirizzo", FILTER_VALIDATE_INT);
$via = trim($_POST["via"] ?? "");
$numeroCivico = trim($_POST["numeroCivico"] ?? "");
$idComune = filter_input(INPUT_POST, "idComune", FILTER_VALIDATE_INT);
$indirizzi = [];
$messaggio = null;
$comuni = [];
$stmt = $pdo->prepare("
SELECT
comune.idComune,
comune.nome AS nomeComune,
provincia.nome AS nomeProvincia,
provincia.sigla
FROM comune JOIN provincia ON comune.idProvincia = provincia.idProvincia
");
$stmt->execute();
$comuni = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (postMethod()) {
try {
switch($azione) {
case "predefinito": {
if (!$idIndirizzo) {
$messaggio = "Id indirizzo non valido";
die("Id indirizzo non valido");
}
$pdo->beginTransaction();
// Rimozione dei precedenti indirizzi predefiniti
$stmt = $pdo->prepare("
UPDATE indirizzo
SET predefinito = 0
WHERE idCliente = :idCliente
");
$stmt->execute([
"idCliente" => $idCliente
]);
// Settando indirizzo corrente come predefinito
$stmt = $pdo->prepare("
UPDATE indirizzo
SET predefinito = 1
WHERE
idCliente = :idCliente AND idIndirizzo = :idIndirizzo
");
$stmt->execute([
"idCliente" => $idCliente,
"idIndirizzo" => $idIndirizzo
]);
$pdo->commit();
break;
}
case "inserisci": {
if (
$via === "" ||
$numeroCivico === "" ||
$idComune === ""
) {
$messaggio = "Compila i campi correttamente";
die("Compila i campi correttamente");
}
$stmt = $pdo->prepare("
SELECT EXISTS (
SELECT 1
FROM indirizzo
WHERE idCliente = :idCliente
) AS esiste
");
$stmt->execute([
"idCliente" => $idCliente
]);
$predefinito = $stmt->fetchColumn();
if ($predefinito) {
// Sono presenti record di indirizzi
$predefinito = 0;
} else {
// Non sono presenti record di indirizzi
$predefinito = 1;
}
$pdo->beginTransaction();
$stmt = $pdo->prepare("
INSERT INTO indirizzo (via, numeroCivico, predefinito, idComune, idCliente)
VALUES (:via, :numeroCivico, :predefinito, :idComune, :idCliente)
");
$stmt->execute([
"via" => $via,
"numeroCivico" => $numeroCivico,
"predefinito" => $predefinito,
"idComune" => $idComune,
"idCliente" => $idCliente
]);
$pdo->commit();
break;
}
case "elimina": {
if (!$idIndirizzo) {
$messaggio = "Id indirizzo non valido";
die("Id indirizzo non valido");
}
$pdo->beginTransaction();
$stmt = $pdo->prepare("
DELETE FROM indirizzo
WHERE
idIndirizzo = :idIndirizzo AND idCliente = :idCliente
");
$stmt->execute([
"idIndirizzo" => $idIndirizzo,
"idCliente" => $idCliente
]);
$pdo->commit();
$messaggio = "Indirizzo eliminato con successo";
break;
}
default:
$messaggio = "Azione non valida";
break;
}
} catch (PDOException $e) {
if ($pdo->inTransaction()) {
$pdo->rollBack();
}
die(
"Errore durante l'aggiunta dell'indirizzo di consegna: "
. $e->getMessage()
);
}
}
$stmt = $pdo->prepare("
SELECT
indirizzo.idIndirizzo,
indirizzo.via,
indirizzo.numeroCivico,
indirizzo.predefinito,
comune.nome AS nomeComune,
provincia.sigla AS siglaProvincia
FROM (indirizzo JOIN comune ON indirizzo.idComune = comune.idComune)
JOIN provincia ON comune.idProvincia = provincia.idProvincia
WHERE idCliente = :idCliente
");
$stmt->execute([
"idCliente" => $idCliente
]);
$indirizzi = $stmt->fetchAll(PDO::FETCH_ASSOC);
$pageTitle = "Indirizzi"; $basePath = "..";
require __DIR__ . "/../includes/header.php";
?>
<h1 class="h3">Indirizzi di consegna</h1>
<?php if ($messaggio): ?><div class="alert alert-warning"><?= e($messaggio) ?></div><?php endif; ?>
<div class="row g-4"><div class="col-lg-7">
<?php foreach ($indirizzi as $i): ?>
<div class="card mb-2">
<div class="card-body d-flex justify-content-between">
<div>
<strong><?= e($i["via"] . " " . $i["numeroCivico"]) ?></strong>
<br>
<?= e(($i["nomeComune"] ?? "") . " " . ($i["siglaProvincia"] ?? "")) ?>
<?php if (!empty($i["predefinito"])): ?>
<span class="badge bg-success">Predefinito</span>
<?php endif; ?>
</div>
<form method="post">
<input type="hidden" name="idIndirizzo" value="<?= e($i["idIndirizzo"]) ?>">
<button class="btn btn-sm btn-outline-primary" name="azione" value="predefinito">Predefinito</button>
<button class="btn btn-sm btn-outline-danger" name="azione" value="elimina">Elimina</button>
</form>
</div>
</div>
<?php endforeach; ?>
</div>
<div class="col-lg-5">
<form method="post" class="card card-body shadow-sm">
<h2 class="h5">Nuovo indirizzo</h2>
<input type="hidden" name="azione" value="inserisci">
<div class="mb-3">
<label class="form-label" for="via">Via</label>
<input class="form-control" id="via" name="via" required></div>
<div class="mb-3"><label class="form-label" for="numeroCivico">Numero civico</label>
<input class="form-control" id="numeroCivico" name="numeroCivico" required></div>
<div class="mb-3"><label class="form-label" for="idComune">Comune</label>
<select class="form-select" id="idComune" name="idComune" required>
<option value="">
Seleziona un comune
</option>
<?php foreach ($comuni as $comune):?>
<option value="<?= $comune["idComune"] ?>">
<?=
htmlspecialchars($comune["nomeComune"] . " - " . $comune["nomeProvincia"] . " - " . $comune["sigla"])
?>
</option>
<?php endforeach; ?>
</select>
<br>
<button class="btn btn-primary">Salva</button>
</form>
</div>
</div>
<?php require __DIR__ . "/../includes/footer.php"; ?>
+46
View File
@@ -0,0 +1,46 @@
<?php
require_once __DIR__ . "/../includes/auth.php";
requireRole("cliente");
require_once __DIR__ . "/../config/database.php";
$idCliente = (int) $_SESSION["idUtente"];
$prodotti = [];
$stmt = $pdo->prepare("
SELECT
prodotto.idProdotto,
prodotto.nome,
prodotto.descrizione,
prodotto.prezzoBase,
caratteristica.nome AS nomeCaratteristica,
caratteristica.differenzaPrezzo
FROM prodotto JOIN caratteristica ON prodotto.idProdotto = caratteristica.idProdotto
");
$stmt->execute();
$prodotti = $stmt->fetchAll(PDO::FETCH_ASSOC);
$pageTitle = "Menu"; $basePath = "..";
require __DIR__ . "/../includes/header.php";
?>
<div class="d-flex justify-content-between align-items-center mb-3">
<div><h1 class="h3 mb-1">Menu</h1><p class="text-muted mb-0">Prodotti disponibili e personalizzazioni.</p></div>
<a class="btn btn-primary" href="ordine.php">Componi ordine</a>
</div>
<?php if (!$prodotti): ?>
<div class="alert alert-info">Il menu sarà visualizzato dopo l'implementazione della Query 1.</div>
<?php endif; ?>
<div class="row g-3">
<?php foreach ($prodotti as $prodotto): ?>
<div class="col-md-6"><div class="card h-100 shadow-sm"><div class="card-body">
<h2 class="h5"><?= e($prodotto["nome"] ?? "") ?></h2>
<p><?= e($prodotto["descrizione"] ?? "") ?></p>
<span class="badge bg-primary">€ <?= e(number_format((float) ($prodotto["prezzoBase"] ?? 0), 2, ",", ".")) ?></span>
<?php if (!empty($prodotto["nomeCaratteristica"])): ?>
<hr><strong>Caratteristica:</strong> <?= e($prodotto["nomeCaratteristica"]) ?>
(+ € <?= e($prodotto["differenzaPrezzo"] ?? 0) ?>)
<?php endif; ?>
</div></div></div>
<?php endforeach; ?>
</div>
<?php require __DIR__ . "/../includes/footer.php"; ?>
+88
View File
@@ -0,0 +1,88 @@
<?php
require_once __DIR__ . "/../includes/auth.php";
requireRole("cliente");
require_once __DIR__ . "/../config/database.php";
$idCliente = (int) $_SESSION["idUtente"];
$ordini = [];
$stmt = $pdo->prepare("
SELECT
o1.idOrdine,
o1.dataOraCreazione,
o1.statoConferma,
o1.orarioConsegna,
o1.totale,
o1.tempoStimatoConsegna,
so1.nomeStato
FROM
ordine AS o1
JOIN storicoStato AS ss1
ON o1.idOrdine = ss1.idOrdine
JOIN statoOrdine AS so1
ON ss1.idStatoOrdine = so1.idStatoOrdine
WHERE
o1.idCliente = :idCliente
AND so1.posizione = (
SELECT
MAX(so2.posizione)
FROM
storicoStato AS ss2
JOIN statoOrdine AS so2
ON ss2.idStatoOrdine = so2.idStatoOrdine
WHERE
ss2.idOrdine = o1.idOrdine
)
");
$stmt->execute([
"idCliente" => $idCliente
]);
$ordini = $stmt->fetchAll(PDO::FETCH_ASSOC);
/* TODO SQL DI SUPPORTO - Elenco e stato degli ordini del cliente.
* Input: $idCliente. Output: idOrdine, dataOraCreazione, statoConferma,
* orarioConsegna, totale, tempoStimatoConsegna, nomeStato. */
$pageTitle = "I miei ordini"; $basePath = "..";
require __DIR__ . "/../includes/header.php";
?>
<h1 class="h3">I miei ordini</h1>
<?php if (!$ordini): ?>
<div class="alert alert-info">Nessun ordine da mostrare.</div>
<?php endif; ?>
<div class="table-responsive">
<table class="table table-striped align-middle">
<thead>
<tr>
<th>ID</th>
<th>Creato</th>
<th>Conferma</th>
<th>Avanzamento</th>
<th>Consegna</th>
<th>Totale</th>
</tr>
</thead>
<tbody>
<?php foreach ($ordini as $o): ?>
<tr>
<td><?= e($o["idOrdine"]) ?>
</td><td><?= e($o["dataOraCreazione"]) ?>
</td><td>
<span class="badge bg-secondary"><?= e($o["statoConferma"]) ?>
</span>
</td><td><?= e($o["nomeStato"] ?? "—") ?>
</td><td><?= e($o["orarioConsegna"]) ?>
</td><td>€ <?= e($o["totale"]) ?>
</td></tr><?php endforeach; ?>
</tbody></table></div>
<?php require __DIR__ . "/../includes/footer.php"; ?>
+972
View File
@@ -0,0 +1,972 @@
<?php
require_once __DIR__ . "/../includes/auth.php";
requireRole("cliente");
require_once __DIR__ . "/../config/database.php";
$idCliente = (int) $_SESSION["idUtente"];
$idProdotto = filter_input(INPUT_POST, "idProdotto", FILTER_VALIDATE_INT);
$quantita = filter_input(INPUT_POST, "quantita", FILTER_VALIDATE_INT);
$caratteristiche = array_values(
array_unique(
array_filter(
array_map("intval", (array) ($_POST["caratteristiche"] ?? []))
)
)
);
$azione = $_POST["azione"] ?? null;
$orarioConsegna = $_POST["orarioConsegna"] ?? null;
$idIndirizzo = filter_input(INPUT_POST, "idIndirizzo", FILTER_VALIDATE_INT);
$idOrdine = null; // CARICATO
$prodotti = []; // CARICATO
$caratteristicheDisponibili = []; // CARICATO
$indirizzi = []; // CARICATO
$righeOrdine = []; // CARICATO
$riepilogo = null; // CARICATO
$messaggio = $_SESSION["messaggio"] ?? null; // CARICATO
unset($_SESSION["messaggio"]);
/* ============================================================
* INDIRIZZI DEL CLIENTE
* ============================================================
*/
$stmt = $pdo->prepare("
SELECT indirizzo.idIndirizzo, indirizzo.via, indirizzo.numeroCivico,
indirizzo.predefinito, indirizzo.idComune
FROM indirizzo
WHERE indirizzo.idCliente = :idCliente
");
$stmt->execute([
"idCliente" => $idCliente
]);
$indirizzi = $stmt->fetchAll(PDO::FETCH_ASSOC);
/* ============================================================
* EVENTUALE ORDINE IN BOZZA
* ============================================================
*/
$stmt = $pdo->prepare("
SELECT ordine.idOrdine
FROM ordine
WHERE ordine.idCliente = :idCliente
AND ordine.statoConferma = 'bozza'
ORDER BY ordine.dataOraCreazione DESC
LIMIT 1
");
$stmt->execute([
"idCliente" => $idCliente
]);
$idOrdine = $stmt->fetchColumn();
if ($idOrdine === false) {
$idOrdine = null;
}
/* ============================================================
* PRODOTTI DISPONIBILI
* ============================================================
*/
$stmt = $pdo->prepare("
SELECT prodotto.idProdotto, prodotto.nome, prodotto.descrizione,
prodotto.prezzoBase, prodotto.tempoPreparazione,
prodotto.proceduraPreparazione, prodotto.disponibile
FROM prodotto
WHERE prodotto.disponibile = 1
ORDER BY prodotto.nome
");
$stmt->execute();
$prodotti = $stmt->fetchAll(PDO::FETCH_ASSOC);
/* ============================================================
* CARATTERISTICHE DISPONIBILI
* ============================================================
*/
$stmt = $pdo->prepare("
SELECT caratteristica.idCaratteristica, caratteristica.nome,
caratteristica.descrizione, caratteristica.differenzaPrezzo,
caratteristica.predefinita, caratteristica.disponibile,
caratteristica.idProdotto, caratteristica.idGruppoEsclusione,
gruppoEsclusione.nome AS nomeGruppo
FROM caratteristica
LEFT JOIN gruppoEsclusione
ON caratteristica.idGruppoEsclusione = gruppoEsclusione.idGruppoEsclusione
WHERE caratteristica.disponibile = 1
ORDER BY caratteristica.idProdotto,
caratteristica.idGruppoEsclusione,
caratteristica.idCaratteristica
");
$stmt->execute();
$caratteristicheDisponibili = $stmt->fetchAll(PDO::FETCH_ASSOC);
/* ============================================================
* QUERY 3
*
* Inserimento di un prodotto in un ordine
* con le caratteristiche selezionate.
* ============================================================
*/
if (postMethod() && $azione === "aggiungi") {
if (
$idCliente <= 0 ||
!$idProdotto ||
!$quantita ||
$quantita < 1 ||
$quantita > 255
) {
$messaggio = "Dati in input non validi";
} else {
try {
/* Verifico che il prodotto esista e sia disponibile. */
$stmt = $pdo->prepare("
SELECT prodotto.prezzoBase
FROM prodotto
WHERE prodotto.idProdotto = :idProdotto
AND prodotto.disponibile = 1
LIMIT 1
");
$stmt->execute([
"idProdotto" => $idProdotto
]);
$prezzoBaseApplicato = $stmt->fetchColumn();
if ($prezzoBaseApplicato === false) {
$messaggio = "Prodotto inesistente o non disponibile";
} else {
/* Se non esiste una bozza recupero l'indirizzo predefinito. */
if (!$idOrdine) {
$stmt = $pdo->prepare("
SELECT indirizzo.idIndirizzo
FROM indirizzo
WHERE indirizzo.idCliente = :idCliente
AND indirizzo.predefinito = 1
LIMIT 1
");
$stmt->execute([
"idCliente" => $idCliente
]);
$idIndirizzo = $stmt->fetchColumn();
if ($idIndirizzo === false) {
$messaggio = "Prima di creare un ordine devi impostare un indirizzo predefinito.";
}
}
if ($idOrdine || $idIndirizzo) {
$pdo->beginTransaction();
/* ========================================================
* CREAZIONE EVENTUALE BOZZA
* ========================================================
*/
if (!$idOrdine) {
$stmt = $pdo->prepare("
INSERT INTO ordine (
dataOraCreazione,
dataOraConferma,
dataOraAnnullamento,
statoConferma,
orarioConsegna,
totale,
tempoStimatoConsegna,
idCliente,
idIndirizzo
)
VALUES (
NOW(),
NULL,
NULL,
'bozza',
NULL,
0.00,
NULL,
:idCliente,
:idIndirizzo
)
");
$stmt->execute([
"idCliente" => $idCliente,
"idIndirizzo" => $idIndirizzo
]);
$idOrdine = (int) $pdo->lastInsertId();
}
/* ========================================================
* INSERIMENTO RIGA ORDINE
* ========================================================
*/
$stmt = $pdo->prepare("
INSERT INTO rigaOrdine (
quantita,
prezzoBaseApplicato,
idOrdine,
idProdotto
)
VALUES (
:quantita,
:prezzoBaseApplicato,
:idOrdine,
:idProdotto
)
");
$stmt->execute([
"quantita" => $quantita,
"prezzoBaseApplicato" => $prezzoBaseApplicato,
"idOrdine" => $idOrdine,
"idProdotto" => $idProdotto
]);
$idRigaOrdine = (int) $pdo->lastInsertId();
/* ========================================================
* CARATTERISTICHE DELLA RIGA
* ========================================================
*/
$stmtCaratteristica = $pdo->prepare("
SELECT caratteristica.idCaratteristica,
caratteristica.differenzaPrezzo,
caratteristica.idGruppoEsclusione
FROM caratteristica
WHERE caratteristica.idCaratteristica = :idCaratteristica
AND caratteristica.idProdotto = :idProdotto
AND caratteristica.disponibile = 1
LIMIT 1
");
$stmtInserisciCaratteristica = $pdo->prepare("
INSERT INTO rigaOrdineSelezionaCaratteristica (
idCaratteristica,
idRigaOrdine,
differenzaPrezzoApplicata
)
VALUES (
:idCaratteristica,
:idRigaOrdine,
:differenzaPrezzoApplicata
)
");
$gruppiSelezionati = [];
foreach ($caratteristiche as $idCaratteristica) {
$stmtCaratteristica->execute([
"idCaratteristica" => $idCaratteristica,
"idProdotto" => $idProdotto
]);
$caratteristica = $stmtCaratteristica->fetch(PDO::FETCH_ASSOC);
if (!$caratteristica) {
throw new RuntimeException(
"Caratteristica non valida per il prodotto selezionato."
);
}
$idGruppoEsclusione = $caratteristica["idGruppoEsclusione"];
if ($idGruppoEsclusione !== null) {
$idGruppoEsclusione = (int) $idGruppoEsclusione;
if (isset($gruppiSelezionati[$idGruppoEsclusione])) {
throw new RuntimeException(
"Sono state selezionate due caratteristiche incompatibili."
);
}
$gruppiSelezionati[$idGruppoEsclusione] = true;
}
$stmtInserisciCaratteristica->execute([
"idCaratteristica" => $idCaratteristica,
"idRigaOrdine" => $idRigaOrdine,
"differenzaPrezzoApplicata" => $caratteristica["differenzaPrezzo"]
]);
}
/* ========================================================
* FINE QUERY 3
* ========================================================
*/
$pdo->commit();
// POST -> REDIRECT -> GET
header("Location: ordine.php");
exit;
}
}
} catch (Throwable $e) {
if ($pdo->inTransaction()) {
$pdo->rollBack();
}
die(
"Errore durante l'aggiunta del prodotto all'ordine: "
. $e->getMessage()
);
}
}
}
/* ============================================================
* RIGHE DELLA BOZZA
* ============================================================
*/
if ($idOrdine) {
$stmt = $pdo->prepare("
SELECT rigaOrdine.idRigaOrdine,
rigaOrdine.quantita,
rigaOrdine.prezzoBaseApplicato,
rigaOrdine.idOrdine,
rigaOrdine.idProdotto,
prodotto.nome AS nomeProdotto,
(
rigaOrdine.quantita *
(
rigaOrdine.prezzoBaseApplicato +
COALESCE(
(
SELECT SUM(
rigaOrdineSelezionaCaratteristica.differenzaPrezzoApplicata
)
FROM rigaOrdineSelezionaCaratteristica
WHERE rigaOrdineSelezionaCaratteristica.idRigaOrdine =
rigaOrdine.idRigaOrdine
),
0
)
)
) AS subtotale
FROM rigaOrdine
JOIN prodotto
ON rigaOrdine.idProdotto = prodotto.idProdotto
WHERE rigaOrdine.idOrdine = :idOrdine
ORDER BY rigaOrdine.idRigaOrdine
");
$stmt->execute([
"idOrdine" => $idOrdine
]);
$righeOrdine = $stmt->fetchAll(PDO::FETCH_ASSOC);
}
/* ============================================================
* QUERY 4
*
* Calcolo totale e tempo stimato di consegna
* ============================================================
*/
if ($idOrdine) {
$stmt = $pdo->prepare("
SELECT
SUM(
(
rigaOrdine.prezzoBaseApplicato +
COALESCE(
(
SELECT SUM(
rigaOrdineSelezionaCaratteristica.differenzaPrezzoApplicata
)
FROM rigaOrdineSelezionaCaratteristica
WHERE
rigaOrdineSelezionaCaratteristica.idRigaOrdine =
rigaOrdine.idRigaOrdine
),
0
)
) * rigaOrdine.quantita
) AS totale,
SUM(
prodotto.tempoPreparazione * rigaOrdine.quantita
) AS tempoStimatoConsegna
FROM rigaOrdine JOIN prodotto ON prodotto.idProdotto = rigaOrdine.idProdotto
WHERE rigaOrdine.idOrdine = :idOrdine
");
$stmt->execute([
"idOrdine" => $idOrdine
]);
$riepilogo = $stmt->fetch(PDO::FETCH_ASSOC);
}
/* ============================================================
* CONFERMA / ANNULLA
* ============================================================
*/
if (postMethod() && in_array($azione, ["conferma", "annulla"], true)) {
// Annullamento ordine
if ($azione === "annulla") {
// Registrazione dell'annullamento dell'ordine
$stmt = $pdo->prepare("
UPDATE
ordine
SET
ordine.dataOraAnnullamento = NOW(),
ordine.statoConferma = 'annullato',
ordine.orarioConsegna = NULL,
ordine.tempoStimatoConsegna = NULL
WHERE
ordine.idOrdine = :idOrdine
AND ordine.idCliente = :idCliente
AND ordine.statoConferma = 'bozza'
");
$stmt->execute([
"idOrdine" => $idOrdine,
"idCliente" => $idCliente
]);
// Pulizia del riepilogo
header("Location: ordine.php");
// Messaggio
$_SESSION["messaggio"] = "Ordine annullato con successo";
exit;
}
// Conferma ordine
if ($azione === "conferma") {
// Calcolo del tempo di preparazione
$stmt = $pdo->prepare("
SELECT
COALESCE(
SUM(rigaOrdine.quantita * prodotto.tempoPreparazione),
0
) AS tempoPreparazione
FROM
ordine
JOIN rigaOrdine
ON rigaOrdine.idOrdine = ordine.idOrdine
JOIN prodotto
ON rigaOrdine.idProdotto = prodotto.idProdotto
WHERE
ordine.idOrdine = :idOrdine
");
$stmt->execute([
"idOrdine" => $idOrdine
]);
$tempoPreparazione = $stmt->fetchColumn();
// Calcolo del totale
$stmt = $pdo->prepare("
SELECT
COALESCE(
SUM(totali.totaleRigaOrdine),
0
)
FROM
rigaOrdine AS ro1
LEFT JOIN (
SELECT
ro2.idRigaOrdine AS idRigaOrdine,
ro2.quantita * (
ro2.prezzoBaseApplicato
+
COALESCE(
SUM(rosc2.differenzaPrezzoApplicata),
0
)
) AS totaleRigaOrdine
FROM
rigaOrdine AS ro2
LEFT JOIN rigaOrdineSelezionaCaratteristica AS rosc2
ON ro2.idRigaOrdine = rosc2.idRigaOrdine
WHERE
ro2.idOrdine = :idOrdine
GROUP BY
ro2.idRigaOrdine
) AS totali
ON ro1.idRigaOrdine = totali.idRigaOrdine
WHERE
ro1.idOrdine = :idOrdine
");
$stmt->execute([
"idOrdine" => $idOrdine
]);
$totale = $stmt->fetchColumn();
// Registrazione della conferma dell'ordine
$stmt = $pdo->prepare("
UPDATE
ordine
SET
ordine.dataOraConferma = NOW(),
ordine.statoConferma = 'confermato',
ordine.totale = :totale,
ordine.tempoStimatoConsegna = :tempoPreparazione
WHERE
ordine.idOrdine = :idOrdine
AND ordine.idCliente = :idCliente
AND ordine.statoConferma = 'bozza'
");
$stmt->execute([
"idOrdine" => $idOrdine,
"idCliente" => $idCliente,
"totale" => $totale,
"tempoPreparazione" => $tempoPreparazione
]);
// Creazione dello storicoStato e statoOrdine
$stmt = $pdo->prepare("
INSERT
INTO statoOrdine
(
nomeStato,
posizione
)
VALUES (
'IN LAVORAZIONE',
1
)
");
$stmt->execute();
$idStatoOrdine = $pdo->lastInsertId();
$stmt = $pdo->prepare("
INSERT
INTO storicoStato
(
timestamp,
idOrdine,
idStatoOrdine
)
VALUES (
NOW(),
:idOrdine,
:idStatoOrdine
)
");
$stmt->execute([
"idOrdine" => $idOrdine,
"idStatoOrdine" => $idStatoOrdine
]);
// Pulizia del riepilogo
header("Location: ordine.php");
// Messaggio
$_SESSION["messaggio"] = "Ordine confermato con successo";
exit;
}
}
/* ============================================================
* PAGINA
* ============================================================
*/
$pageTitle = "Componi ordine";
$basePath = "..";
require __DIR__ . "/../includes/header.php";
?>
<h1 class="h3">Componi ordine</h1>
<?php if ($messaggio): ?>
<div class="alert alert-warning">
<?= e($messaggio) ?>
</div>
<?php endif; ?>
<div class="row g-4">
<!-- ======================================================
AGGIUNTA PRODOTTO
====================================================== -->
<div class="col-lg-7">
<div class="card shadow-sm">
<div class="card-body">
<h2 class="h5">Aggiungi un prodotto</h2>
<form method="post">
<input type="hidden" name="azione" value="aggiungi">
<!-- PRODOTTO -->
<div class="mb-3">
<label class="form-label" for="idProdotto">Prodotto</label>
<select class="form-select" id="idProdotto" name="idProdotto" required>
<option value="">Seleziona...</option>
<?php foreach ($prodotti as $p): ?>
<option value="<?= e($p["idProdotto"]) ?>">
<?= e($p["nome"]) ?> — € <?= e($p["prezzoBase"]) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<!-- QUANTITA -->
<div class="mb-3">
<label class="form-label" for="quantita">Quantità</label>
<input
class="form-control"
type="number"
min="1"
max="255"
value="1"
id="quantita"
name="quantita"
required
>
</div>
<!-- CARATTERISTICHE -->
<fieldset class="mb-3">
<legend class="h6">Caratteristiche</legend>
<p id="messaggioCaratteristiche" class="text-muted">
Seleziona prima un prodotto.
</p>
<?php foreach ($caratteristicheDisponibili as $c): ?>
<div
class="caratteristica-item align-items-center gap-2"
style="display: none; width: 100%;"
data-id-prodotto="<?= e($c["idProdotto"]) ?>"
>
<input
class="form-check-input caratteristica-checkbox mt-0"
style="float: none; margin-left: 0;"
type="checkbox"
name="caratteristiche[]"
value="<?= e($c["idCaratteristica"]) ?>"
id="c<?= e($c["idCaratteristica"]) ?>"
data-gruppo-esclusione="<?= e($c["idGruppoEsclusione"] ?? "") ?>"
<?= !empty($c["predefinita"]) ? "checked" : "" ?>
disabled
>
<label
class="form-check-label"
for="c<?= e($c["idCaratteristica"]) ?>"
>
<?= e($c["nome"]) ?>
<?php if ($c["idGruppoEsclusione"] !== null): ?>
<small class="text-muted">
(<?= e($c["nomeGruppo"]) ?>)
</small>
<?php endif; ?>
<?= $c["differenzaPrezzo"] >= 0 ? "+" : "" ?>
€ <?= e($c["differenzaPrezzo"]) ?>
</label>
</div>
<?php endforeach; ?>
</fieldset>
<button class="btn btn-primary" type="submit">
Aggiungi all'ordine
</button>
</form>
</div>
</div>
</div>
<!-- ======================================================
RIEPILOGO
====================================================== -->
<div class="col-lg-5">
<div class="card shadow-sm mb-3">
<div class="card-body">
<h2 class="h5">Riepilogo</h2>
<?php if (!$righeOrdine): ?>
<p class="text-muted">La bozza è vuota.</p>
<?php endif; ?>
<?php foreach ($righeOrdine as $r): ?>
<div class="d-flex justify-content-between">
<span>
<?= e($r["quantita"]) ?> × <?= e($r["nomeProdotto"]) ?>
</span>
<span>
€ <?= e($r["subtotale"]) ?>
</span>
</div>
<?php endforeach; ?>
<hr>
<!-- QUERY 4 non ancora implementata. -->
<p>
<strong>Totale:</strong> €
<?= e($riepilogo["totale"] ?? "-")?>
<br>
<strong>Tempo stimato:</strong>
<?= e($riepilogo["tempoStimatoConsegna"] ?? "—") ?> min
</p>
</div>
</div>
<!-- ==================================================
CONFERMA / ANNULLA
================================================== -->
<div class="card shadow-sm">
<div class="card-body">
<h2 class="h5">Conferma o annulla</h2>
<form method="post">
<input type="hidden" name="idOrdine" value="<?= e($idOrdine) ?>">
<!-- INDIRIZZO -->
<div class="mb-3">
<label class="form-label" for="idIndirizzo">
Indirizzo
</label>
<select
class="form-select"
id="idIndirizzo"
name="idIndirizzo"
required
>
<option value="">Seleziona...</option>
<?php foreach ($indirizzi as $i): ?>
<option value="<?= e($i["idIndirizzo"]) ?>">
<?= e($i["via"] . " " . $i["numeroCivico"]) ?>
<?= !empty($i["predefinito"]) ? "(predefinito)" : "" ?>
</option>
<?php endforeach; ?>
</select>
</div>
<!-- ORARIO -->
<div class="mb-3">
<label class="form-label" for="orarioConsegna">
Orario di consegna
</label>
<input
class="form-control"
type="datetime-local"
id="orarioConsegna"
name="orarioConsegna"
required
>
</div>
<button
class="btn btn-success"
name="azione"
value="conferma"
>
Conferma
</button>
<button
class="btn btn-outline-danger"
name="azione"
value="annulla"
formnovalidate
>
Annulla
</button>
</form>
</div>
</div>
</div>
</div>
<!-- ==========================================================
JAVASCRIPT CARATTERISTICHE
========================================================== -->
<script>
document.addEventListener("DOMContentLoaded", function () {
const selectProdotto = document.getElementById("idProdotto");
const caratteristiche = document.querySelectorAll(".caratteristica-item");
const messaggio = document.getElementById("messaggioCaratteristiche");
function aggiornaCaratteristiche() {
const idProdotto = selectProdotto.value;
let trovata = false;
caratteristiche.forEach(function (elemento) {
const appartiene = elemento.dataset.idProdotto === idProdotto;
elemento.style.display = appartiene ? "flex" : "none";
const input = elemento.querySelector("input");
input.disabled = !appartiene;
if (appartiene) {
trovata = true;
}
});
if (!idProdotto) {
messaggio.textContent = "Seleziona prima un prodotto.";
messaggio.classList.remove("d-none");
} else if (!trovata) {
messaggio.textContent = "Questo prodotto non ha caratteristiche disponibili.";
messaggio.classList.remove("d-none");
} else {
messaggio.classList.add("d-none");
}
}
/*
* Se seleziono una caratteristica appartenente ad un gruppo
* deseleziono le altre dello stesso gruppo.
*/
document.querySelectorAll(".caratteristica-checkbox").forEach(function (checkbox) {
checkbox.addEventListener("change", function () {
const gruppo = this.dataset.gruppoEsclusione;
if (!this.checked || !gruppo) {
return;
}
document.querySelectorAll(".caratteristica-checkbox").forEach(function (altra) {
if (altra === checkbox) {
return;
}
if (altra.dataset.gruppoEsclusione === gruppo) {
altra.checked = false;
}
});
});
});
selectProdotto.addEventListener("change", aggiornaCaratteristiche);
aggiornaCaratteristiche();
});
</script>
<?php require __DIR__ . "/../includes/footer.php"; ?>
+22
View File
@@ -0,0 +1,22 @@
<?php
require_once __DIR__ . "/../includes/auth.php";
requireRole("cliente");
require_once __DIR__ . "/../config/database.php";
$idCliente = (int) $_SESSION["idUtente"];
$sogliaMinima = filter_input(INPUT_GET, "sogliaMinima", FILTER_VALIDATE_INT) ?: 3;
$prodotti = [];
/*
* QUERY 10 - Estrazione dei prodotti preferiti da un cliente
* Prodotti più ordinati dal cliente, con soglia minima configurabile.
* Input: $idCliente, $sogliaMinima
* Output atteso: idProdotto, nome, numeroOrdini, quantitaTotale
* TODO SQL: implementare manualmente la Query 10.
*/
$pageTitle = "Prodotti preferiti"; $basePath = "..";
require __DIR__ . "/../includes/header.php";
?>
<h1 class="h3">Prodotti preferiti</h1>
<form method="get" class="card card-body shadow-sm mb-3"><div class="row align-items-end g-3"><div class="col-md-4"><label class="form-label" for="sogliaMinima">Numero minimo di ordini</label><input class="form-control" type="number" min="1" id="sogliaMinima" name="sogliaMinima" value="<?= e($sogliaMinima) ?>" required></div><div class="col-md-3"><button class="btn btn-primary">Calcola</button></div></div></form>
<?php if (!$prodotti): ?><div class="alert alert-info">I preferiti saranno mostrati dopo l'implementazione della Query 10.</div><?php endif; ?>
<table class="table table-striped"><thead><tr><th>Posizione</th><th>Prodotto</th><th>Ordini</th><th>Quantità totale</th></tr></thead><tbody><?php foreach ($prodotti as $n => $p): ?><tr><td><?= e($n + 1) ?></td><td><?= e($p["nome"]) ?></td><td><?= e($p["numeroOrdini"]) ?></td><td><?= e($p["quantitaTotale"]) ?></td></tr><?php endforeach; ?></tbody></table>
<?php require __DIR__ . "/../includes/footer.php"; ?>