Cistell: diferència entre les revisions

De Wiki personal d'en Guillem Serrat
Línia 21: Línia 21:
// Si processa.php no realitza correctament l'operació, catàleg.php veuria el següent:
// Si processa.php no realitza correctament l'operació, catàleg.php veuria el següent:
$_SESSION['missatge_error'] = "X" // Depenent de l'error es mostrarà un missatge o un altre  
$_SESSION['missatge_error'] = "X" // Depenent de l'error es mostrarà un missatge o un altre  
</pre>Per tant, dins del cistell hem de comprovar si hem rebut aquest missatge (ja sigui el d'error o èxit), i en cas afirmatiu, mostrar-lo<pre>
</pre>Per tant, dins del cistell hem de comprovar si hem rebut aquest missatge (ja sigui el d'error o èxit), i en cas afirmatiu, mostrar-lo. Just després de mostrar-lo l'eliminem, per que així únicament es mostri una sola vegada.<pre>
<!-- Missatge de confirmació d'accions -->
<!-- Missatge de confirmació d'accions -->
             <center>
             <center>

Revisió del 22:42, 30 des 2025

Inicialització de la sessió i connexió a la BD

Sempre que es treballa amb sessions, el primer que hem de fer és iniciar-la abans d'escriure el codi HTML

session_start();

A partir d'aquí, l'element principal d'aquesta aplicació és el cistell, el qual està present a la sessió i requerit per la majoria de codis. Per això, hem de comprovar que estigui creat, i en cas que no ho estigui, que es creï.

// Inicialitzar cistell if (!isset($_SESSION['cistell'])) {

   $_SESSION['cistell'] = array();

}

A més d'incloure la connexió a la BD i requerir el fitxer funcions.php, on es troba la funció calcularPreus

require_once "funcions.php"; require_once "./connexioBD/connexioR.php";

Per últim, sempre inicialitzarem una variable que indicarà el total de compra. La inicialitzem aquí perquè s’utilitza dins d’un bucle i no hi ha cap altre lloc per declarar-la. Com que és un bucle, si la declaréssim dins, el valor del total es reiniciaria a 0 a cada iteració, i volem que el total s’acumuli al llarg de totes les iteracions

$total = 0; // Inicialitzem la variable del preu total

Mostra de missatges d'error o èxit

Quan s'afageix, es retira o s'elimina un producte del cistell des del propi cistell, el procés el realitza el codi processa.php, que depenent del resultat de l'operació, ens pot enviar un missatge d'èxit o d'error mitjançant la sessió

// Si processa.php realitza correctament l'operació, catàleg.php veuria el següent:
$_SESSION['missatge_ok'] = "S'ha retirat 1 unitat(s) de Teclat mecànic del cistell.";

// Si processa.php no realitza correctament l'operació, catàleg.php veuria el següent:
$_SESSION['missatge_error'] = "X" // Depenent de l'error es mostrarà un missatge o un altre 

Per tant, dins del cistell hem de comprovar si hem rebut aquest missatge (ja sigui el d'error o èxit), i en cas afirmatiu, mostrar-lo. Just després de mostrar-lo l'eliminem, per que així únicament es mostri una sola vegada.

<!-- Missatge de confirmació d'accions -->

           <center>
           <?php if (isset($_SESSION['missatge_ok'])): // Quan s'enviï un missatge de confirmació?>
               <p style="color: green; font-weight: bold;">
                   <?php
                       echo htmlspecialchars($_SESSION['missatge_ok']); // Mostrem el missatge
                       unset($_SESSION['missatge_ok']); // Eliminem el missatge, així al recarregar la pàgina no tornarà a sortir, únicament mostrant-se un sol cop
                   ?>
               </p>
           <?php endif; ?>
           </center>
           <!-- Missatge d'error -->
           <center>
           <?php if (isset($_SESSION['missatge_error'])): // Quan s'enviï un missatge d'error?>
               <p style="color: red; font-weight: bold;">
                   <?php
                       echo htmlspecialchars($_SESSION['missatge_error']); // Mostrem el missatge
                       unset($_SESSION['missatge_error']); // Eliminem el missatge, així al recarregar la pàgina no tornarà a sortir, únicament mostrant-se un sol cop
                   ?>
               </p>
           <?php endif; ?>
           </center>

Un exemple d'un missatge seria el següent:

Mostra de productes

La mostra de productes és bàsicament una taula amb les següents columnes:

  • Imatge
  • Nom del producte
  • Preu unitari
  • Quantitat
  • Subtotal
  • Accions

Mitjançant un foreach, per cada producte es crearà una fila on es definiràn els aspectes abans comentats, a més de realitzar un càlcul de preu i descompte

Càlcul de totals, subtotals i descomptes

Primerament, calcularem el subtotal de cada producte mitjançant la funció calcularPreus, la qual ens retorna:

  • Preu original (Quantitat * Preu unitari)
  • Preu descomptat, si és el cas
  • % descomptat
$preusProducte = calcularPreus($prod['preu'], $prod['quantitat']); // Calculem el seu preu segons la quantitat i els possibles descomptes (també retorna el preu sense descopmpte)

Seguidament, afagarem el preu descomptat (ja que si no hi ha cap descompte, té el mateix valor que el preu original) i el sumem a la variable $total declarada a l'inici del codi, que indica el total de la compra

$total += $preusProducte['total_final']; //Sumem el preu final del producte al total de la compra

Gestió de l'stock

Més endavant veurem com s'implementa una funcionalitat que permet afegir més untiats d'un producte des del propi cistell. Això significa que hem de fer el mateix que al catàleg i mantenir un control de l'stock per evitar poder afegir més unitats al cistell de les que realment hi ha.

Per això, farem una consulta SQL per recuperar l'stock de la BD del producte

// Obtenim el seu stock
$stmt = $pdo->prepare("SELECT estoc FROM productes WHERE id = :id");
$stmt->bindParam(":id", $id);
$stmt->execute();
$stockBD = (int)$stmt->fetchColumn();

Per a continuació, definir el nombre màxim d'unitats que es poden afegir al cistell restant a l'stock de la BD les unitats del cistell

$maxAfegir = $stockBD - $prod['quantitat']; // Stock real (BD - Cistell) if ($maxAfegir < 0) {

       $maxAfegir = 0;

}

Mostra de característiques bàsiques del producte

A continuació, començarem a imprimir files HTML i inserint els valors del producte. Aquests valors s'agafan directament del cistell (es pot consultar l'Exemple de model de dades de l'array $SESSION[cistell] amb productes per entendre el model de dades del cistell).

<!-- Mostrem tots els detalls dels productes -->
                        <tr> <!-- Una fila per cada producte --> 
                            <!-- Imatge -->
                            <td><img src="imatges/<?php echo htmlspecialchars($prod['imatge']); ?>" width="80"></td>
                            <!-- Nom -->
                            <td><?php echo htmlspecialchars($prod['nom']); ?></td>
                            <!-- Preu -->
                            <td><?php echo number_format($prod['preu'],2); ?> €</td>
                            <!-- Quantitat -->
                            <td><?php echo $prod['quantitat']; ?></td>

Mostra del preu

La següent cel·la és el subtotal del producte. En aquesta cel·la es poden donar dues casuístiques:

  1. Que al producte se li hagi aplicat un descompte
  2. Que no s'hagi aplicat cap descompte

En cas de que s'apliqui el descompte, mostrarem el preu original tatxat i al costat el preu descomptat més el % descomptat. En cas que no hi hagi descompte únicament es mostrarà el preu original.

És per això que hem de comprovar, del retornat per la funcio calcularPreus, el "descompte_percent" i verificar si és major a 0 (i per tant hi ha descompte). En cas afirmatiu, es mostrarà l'anteriorment comentat

<?php if($preusProducte['descompte_percent'] > 0): ?> <!-- Si el percentatge de descompte és major a 0 (s'aplica un descompte) -->
                                    <span style="text-decoration: line-through;"><?php echo number_format($preusProducte['total_original'],2); ?> €</span> <!-- Mostrem el total original sense descompte tatxat -->
                                    →<!-- És el símbol "→" --> <?php echo number_format($preusProducte['total_final'],2); ?> € <!-- Imprimim "→" i el preu amb el descompte aplicat -->
                                    (<?php echo $preusProducte['descompte_percent']; ?>% desc.) <!-- Mostrem el % de descompte aplicat -->

Que es veuria de la següent manera

En cas que no hi hagi descompte, únicament s'imprimirà el preu original.

<?php else: ?>
<?php echo number_format($preusProducte['total_original'],2); ?> € <!-- En cas que no tingui descompte, únicament mostrem el total original (sense cap descompte calculat)-->
<?php endif; ?>

Que es veuria de la següent forma

Botons d'acció

Afegir productes

En el cistell donem la possibilitat d'afegir més unitats d'un producte.

El botó d'afegir productes únicament es mostrarà en cas que la variable $maxAfegir (que era l'stock real: stock BD - Cistell) sigui superior a 0. Si no ho és vol dir que no hi ha estoc i per tant s'informarà així.

A l'hora d'afegir productes, es defineix una entrada numèrica i un botó per realitzar l'acció. L'operació la realitza el codi processa.php, i mitjançant l'acció del formulari, definim el valor "afegir" a la variable "accio" i que el codi processa.php sap com tractar aquesta informació. Com a part del formulari enviem la ID del producte i la quantitat a afegir.

Retirar productes

En el cistell donem la possibilitat de retirar unitats d'un producte.

A l'hora de retirar productes, es defineix una entrada numèrica i un botó per realitzar l'acció. L'operació la realitza el codi processa.php, i mitjançant l'acció del formulari, definim el valor "retirar" a la variable "accio" i que el codi processa.php sap com tractar aquesta informació. Com a part del formulari enviem la ID del producte i la quantitat a retirar.

<!-- Retirar productes -->
<form action="processa.php?accio=retirar" method="post">
    <input type="hidden" name="id" value="<?php echo $id; ?>">
    <input 
        type="number"
        name="quantitat"
        value="1"
        min="1"
        max="<?php echo $prod['quantitat']; ?>"
    >
    <input type="submit" value="Retira">
</form>

Eliminar un producte del cistell

En el cistell donem la possibilitat d'eliminar per complet un producte.

A l'hora d'eliminar un producte únicament es defineix un botó per realitzar l'acció. L'operació la realitza el codi processa.php, i mitjançant l'acció del formulari, definim el valor "eliminar" a la variable "accio" i que el codi processa.php sap com tractar aquesta informació. Com a part del formulari enviem la ID del producte a eliminar.

<!-- Eliminar un producte del cistell -->
<br>
<form action="processa.php?accio=eliminar" method="post">
    <input type="hidden" name="id" value="<?php echo $id; ?>">
    <input type="submit" value="Eliminar producte">
</form>

Visualització dels botons d'acció

Aquesta seria la visualització dels tres botons d'acció

Mostra del total de compra

Per últim, afegim una última fila on es mostra el total de la compra calculat durant les iteracions dels productes

<tr> <!-- Mostrem el total de la compra -->
                        <td colspan="4"><strong>Total</strong></td>
                        <td colspan="2"><strong><?php echo number_format($total,2); ?> €</strong></td>
                    </tr>

Botons d'acció i navegació

Botó de compra

En cas que hi hagi productes dins del cistell, a la part inferior de la taula es trobarà un botó per realitzar la compra, el qual redirigeix al codi compra.php

Botó per buidar el cistell

En cas que hi hagi productes dins del cistell, a la part inferior de la taula es trobarà un botó per buidar el cistell, el qual redirigeix al processa.php, i mitjançant l'acció del formulari, definim el valor "buidar" a la variable "accio"

<a href="processa.php?accio=buidar">Buida el cistell</a>

Botó per tornar al catàleg

Per últim, tinguem o no productes dins del cistell, trobarem un botó de navegació que ens redirigirà al catàleg