added gitignore

This commit is contained in:
2026-07-27 10:15:23 +02:00
parent 2392a267d1
commit d4b6a51b7f
5 changed files with 284 additions and 3 deletions
+35
View File
@@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
ini_set('display_errors', 1);
error_reporting(E_ALL);
header('Content-Type: application/json');
// ==============================
// PATH BASE
// ==============================
$BASE_PATH = dirname(__DIR__) . '/userarea';
// ==============================
// DB
// ==============================
require_once $BASE_PATH . '/class/db-functions.php';
$db = DBHandlerSelect::getInstance()->getConnection();
// ==============================
// AUTH VANGUARD
// ==============================
require_once $BASE_PATH . '/../../extra/auth.php';
// ==============================
// AUTH API (TOKEN)
// ==============================
$user = Auth::guard('api')->user();
if (!$user) {
http_response_code(401);
echo json_encode(['error' => 'Unauthorized']);
exit;
}
+224
View File
@@ -0,0 +1,224 @@
<?php
/**
* my_lessons.php
* --------------------------------------------------------------------------
* Endpoint API delle lezioni per l'app Flutter (scuola YogaSoul).
*
* Posizione prevista sul server: public/api/my_lessons.php
* (accanto a _bootstrap.php)
*
* Autenticazione: gestita da _bootstrap.php (Vanguard, token Bearer).
* Dopo il require sono già disponibili:
* - $user -> utente autenticato ($user->id == bookingclass.iduser)
* - $db -> connessione PDO (da DBHandlerSelect)
*
* Parametri GET:
* - month=YYYY-MM (opzionale, default = mese corrente)
*
* Logica ricalcata su userpanel.php:
* - summary: conteggi utente-globali (acquistate/praticate/prenotate/
* da confermare/da programmare/perse)
* - lessons: lezioni "booked" del mese selezionato, con regole
* can_reschedule / can_delete identiche alla webapp.
* --------------------------------------------------------------------------
*/
require_once __DIR__ . '/_bootstrap.php';
// A questo punto $user e $db esistono già (altrimenti _bootstrap ha fatto exit 401).
$userId = (int) $user->id;
// Location fissa, come nella webapp (userpanel.php la stampa hardcoded).
const LESSON_LOCATION = 'via Valassina 62/B Seregno - Sala Contesto Yoga';
// ==========================================================================
// PARAMETRI: mese
// ==========================================================================
$month = $_GET['month'] ?? date('Y-m');
// Validazione: deve essere YYYY-MM, altrimenti fallback al mese corrente.
$monthDate = DateTime::createFromFormat('Y-m-d', $month . '-01');
if ($monthDate === false) {
$month = date('Y-m');
$monthDate = new DateTime(date('Y-m') . '-01');
}
// Finestra del mese. Replichiamo la logica di userpanel.php:
// se il mese richiesto è quello corrente, si parte da OGGI (non dal giorno 1),
// così non si mostrano lezioni già passate del mese in corso.
$monthStart = $monthDate->format('Y-m-01');
$today = date('Y-m-d');
if ($today > $monthStart && date('Y-m') === $month) {
$monthStart = $today;
}
// Fine mese + 1 giorno (bound superiore esclusivo), come nella webapp.
$monthEndPlus1 = (clone $monthDate)->modify('first day of next month')->format('Y-m-d');
// ==========================================================================
// SUMMARY: conteggi utente-globali
// (tradotti 1:1 dalle query mysqli di userpanel.php in PDO)
// ==========================================================================
// -- Totale biglietti acquistati (SUM nticket sugli ordini dell'utente) -----
$stmt = $db->prepare("
SELECT COALESCE(SUM(nticket), 0) AS total_tickets
FROM orderbook
WHERE iduser = :uid
");
$stmt->execute([':uid' => $userId]);
$purchased = (int) $stmt->fetchColumn();
// -- Stato prenotazioni (passate/future/perse/pending) ----------------------
$now = date('Y-m-d H:i:s');
$stmt = $db->prepare("
SELECT
SUM(CASE WHEN ss.dateschedule <= :now1
AND bc.status = 'booked'
AND bc.lostlesson = 'N' THEN 1 ELSE 0 END) AS passed,
SUM(CASE WHEN ss.dateschedule > :now2
AND bc.status = 'booked'
AND bc.lostlesson = 'N' THEN 1 ELSE 0 END) AS future,
SUM(CASE WHEN bc.lostlesson = 'Y'
AND bc.status != 'cancelled' THEN 1 ELSE 0 END) AS lost,
SUM(CASE WHEN bc.status = 'pending' THEN 1 ELSE 0 END) AS pending
FROM bookingclass bc
LEFT JOIN serviceschedule ss
ON bc.idserviceschedule = ss.idserviceschedule
WHERE bc.iduser = :uid
AND bc.status != 'cancelled'
");
$stmt->execute([
':now1' => $now,
':now2' => $now,
':uid' => $userId,
]);
$counts = $stmt->fetch() ?: [];
$practiced = (int) ($counts['passed'] ?? 0);
$booked = (int) ($counts['future'] ?? 0);
$lost = (int) ($counts['lost'] ?? 0);
$pending = (int) ($counts['pending'] ?? 0);
// "Da programmare" = acquistate - praticate - prenotate - da confermare - perse
// (identico al calcolo $toprogram di userpanel.php)
$toSchedule = $purchased - $practiced - $booked - $pending - $lost;
if ($toSchedule < 0) {
$toSchedule = 0;
}
$summary = [
'purchased' => $purchased,
'practiced' => $practiced,
'booked' => $booked,
'pending' => $pending,
'to_schedule' => $toSchedule,
'lost' => $lost,
];
// ==========================================================================
// LESSONS: lezioni "booked" del mese selezionato
// (query principale di userpanel.php, tradotta in PDO)
// ==========================================================================
$stmt = $db->prepare("
SELECT
bc.idbookingclass,
bc.status,
bc.idservice,
bc.idorder,
bc.lostlesson,
ss.dateschedule,
s.servicename,
s.colorclass,
ob.expireon,
ob.maxreschedule,
ob.reprogrammed
FROM bookingclass bc
LEFT JOIN service s ON bc.idservice = s.idservice
LEFT JOIN serviceschedule ss ON bc.idserviceschedule = ss.idserviceschedule
LEFT JOIN orderbook ob ON bc.idorder = ob.idorderbook
WHERE bc.iduser = :uid
AND bc.status = 'booked'
AND ss.dateschedule >= :start
AND ss.dateschedule < :end
ORDER BY ss.dateschedule ASC
");
$stmt->execute([
':uid' => $userId,
':start' => $monthStart . ' 00:00:00',
':end' => $monthEndPlus1 . ' 00:00:00',
]);
$rows = $stmt->fetchAll();
$lessons = [];
$nowDt = new DateTime();
foreach ($rows as $r) {
$dateschedule = $r['dateschedule'] ?? null;
if ($dateschedule === null) {
continue; // riga orfana senza schedule, la saltiamo
}
$classDt = new DateTime($dateschedule);
// ------------------------------------------------------------------
// Regola oraria can_delete (identica a userpanel.php)
// ------------------------------------------------------------------
$isSameDay = $classDt->format('Y-m-d') === $nowDt->format('Y-m-d');
$classHour = (int) $classDt->format('H');
$classMinute = (int) $classDt->format('i');
// "prima delle 17:00" = ora < 17, oppure esattamente 17:00
$isBefore1700 = ($classHour < 17) || ($classHour === 17 && $classMinute === 0);
if ($isSameDay) {
if ($isBefore1700) {
// lezioni prima delle 17: valido fino alle 00:01 dello stesso giorno
$deadline = new DateTime($classDt->format('Y-m-d 00:01:00'));
} else {
// lezioni dalle 17 in poi: valido fino alle 12:00 dello stesso giorno
$deadline = new DateTime($classDt->format('Y-m-d 12:00:00'));
}
$canByTime = $nowDt <= $deadline;
} else {
// giorni futuri: sempre consentito
$canByTime = true;
}
// ------------------------------------------------------------------
// Limite riprogrammazioni dell'ordine (identico a userpanel.php)
// ------------------------------------------------------------------
$maxreschedule = (int) ($r['maxreschedule'] ?? 0);
$reprogrammed = (int) ($r['reprogrammed'] ?? 0);
$canReprogram = $reprogrammed < $maxreschedule;
// Nella webapp i bottoni "Riprogramma" e "Cancella" compaiono entrambi
// solo se ($canByTime && $canReprogram). Riproduciamo la stessa condizione.
$canReschedule = $canByTime && $canReprogram;
$canDelete = $canByTime && $canReprogram;
$lessons[] = [
'booking_id' => (int) $r['idbookingclass'],
'status' => (string) $r['status'],
'datetime' => $classDt->format('Y-m-d H:i:s'),
'date' => $classDt->format('Y-m-d'),
'time' => $classDt->format('H:i'),
'class_name' => (string) ($r['servicename'] ?? ''),
'color' => (string) ($r['colorclass'] ?? '#1ebf73'),
'location' => LESSON_LOCATION,
'expire_on' => $r['expireon'] ?? null,
'lost_lesson' => ($r['lostlesson'] ?? 'N') === 'Y',
'can_reschedule' => $canReschedule,
'can_delete' => $canDelete,
];
}
// ==========================================================================
// OUTPUT
// ==========================================================================
echo json_encode([
'success' => true,
'month' => $month,
'summary' => $summary,
'lessons' => $lessons,
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
+10 -3
View File
@@ -29,16 +29,23 @@ if (isset($_POST['idserviceordered'])) {
$idserviceordered = $_POST['idserviceordered'];
}
// Recupera la data di scadenza dell'ordine
$expiryQuery = "SELECT expireon FROM orderbook WHERE order_id = ?";
// Recover the expiry date of the order linked to the booking being rescheduled
$expiryQuery = "SELECT ob.expireon
FROM bookingclass bc
INNER JOIN orderbook ob ON bc.idorder = ob.idorderbook
WHERE bc.idbookingclass = ?";
$stmt = $conn->prepare($expiryQuery);
$stmt->bind_param("i", $idpreviousbooking);
$stmt->execute();
$expiryResult = $stmt->get_result();
$expiryDate = null;
if ($expiryResult->num_rows > 0) {
$row = $expiryResult->fetch_assoc();
$expiryDate = new DateTime($row['expireon']);
if (!empty($row['expireon'])) {
$expiryDate = new DateTime($row['expireon']);
}
}
$stmt->close();