367 lines
13 KiB
PHP
367 lines
13 KiB
PHP
<?php
|
|
// Forza la visualizzazione degli errori (solo dev)
|
|
ini_set('display_errors', 1);
|
|
ini_set('display_startup_errors', 1);
|
|
error_reporting(E_ALL);
|
|
|
|
if (session_status() === PHP_SESSION_NONE) {
|
|
session_start();
|
|
}
|
|
|
|
include('include/headscript.php');
|
|
|
|
// Connessione DB
|
|
$dbHandler = DBHandlerSelect::getInstance();
|
|
$pdo = $dbHandler->getConnection();
|
|
|
|
// Verifica utente loggato
|
|
if (!isset($iduserlogin)) {
|
|
header("Location: login.php");
|
|
exit;
|
|
}
|
|
|
|
// Controlla se esiste almeno un salone
|
|
$stmt = $pdo->prepare("SELECT COUNT(*) FROM shops WHERE owner_id = ?");
|
|
$stmt->execute([$iduserlogin]);
|
|
if ((int)$stmt->fetchColumn() === 0) {
|
|
header("Location: onboarding_salon.php");
|
|
exit;
|
|
}
|
|
|
|
// Prendi il primo salone
|
|
$stmt = $pdo->prepare("
|
|
SELECT id, name
|
|
FROM shops
|
|
WHERE owner_id = ?
|
|
ORDER BY created_at ASC
|
|
LIMIT 1
|
|
");
|
|
$stmt->execute([$iduserlogin]);
|
|
$shop = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
if (!$shop) {
|
|
die("Errore: salone non trovato.");
|
|
}
|
|
|
|
$shop_id = (int)$shop['id'];
|
|
$shop_name = $shop['name'];
|
|
|
|
// Helpers flash
|
|
function setFlash(string $type, string $text): void
|
|
{
|
|
$_SESSION['flash'] = ['type' => $type, 'text' => $text];
|
|
}
|
|
|
|
function getFlash(): ?array
|
|
{
|
|
if (!isset($_SESSION['flash'])) return null;
|
|
$f = $_SESSION['flash'];
|
|
unset($_SESSION['flash']);
|
|
return $f;
|
|
}
|
|
|
|
// POST - Salva impostazioni
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
try {
|
|
$show_prices_online = isset($_POST['show_prices_online']) ? 1 : 0;
|
|
$restrict_start_minutes = trim($_POST['restrict_start_minutes'] ?? '00,30');
|
|
$min_booking_notice_hours = (int)($_POST['min_booking_notice_hours'] ?? 2);
|
|
$max_booking_days_ahead = (int)($_POST['max_booking_days_ahead'] ?? 90);
|
|
|
|
// Validazione restrict_start_minutes
|
|
$valid_options = ['any', '00', '00,30', '00,15,30,45'];
|
|
if (!in_array($restrict_start_minutes, $valid_options)) {
|
|
$restrict_start_minutes = '00,30';
|
|
}
|
|
|
|
// Controlla esistenza
|
|
$stmt = $pdo->prepare("SELECT id FROM shop_settings WHERE shop_id = ?");
|
|
$stmt->execute([$shop_id]);
|
|
$exists = $stmt->fetchColumn() !== false;
|
|
|
|
if ($exists) {
|
|
$stmt = $pdo->prepare("
|
|
UPDATE shop_settings SET
|
|
show_prices_online = ?,
|
|
allowed_start_minutes = ?,
|
|
min_booking_notice_hours = ?,
|
|
max_booking_days_ahead = ?,
|
|
updated_at = NOW()
|
|
WHERE shop_id = ?
|
|
");
|
|
$ok = $stmt->execute([
|
|
$show_prices_online,
|
|
$restrict_start_minutes,
|
|
$min_booking_notice_hours,
|
|
$max_booking_days_ahead,
|
|
$shop_id
|
|
]);
|
|
} else {
|
|
$stmt = $pdo->prepare("
|
|
INSERT INTO shop_settings (
|
|
shop_id, show_prices_online, allowed_start_minutes,
|
|
min_booking_notice_hours, max_booking_days_ahead
|
|
) VALUES (?, ?, ?, ?, ?)
|
|
");
|
|
$ok = $stmt->execute([
|
|
$shop_id,
|
|
$show_prices_online,
|
|
$restrict_start_minutes,
|
|
$min_booking_notice_hours,
|
|
$max_booking_days_ahead
|
|
]);
|
|
}
|
|
|
|
setFlash($ok ? 'success' : 'danger', $ok ? "Impostazioni salvate con successo!" : "Errore durante il salvataggio.");
|
|
header("Location: salon_settings.php");
|
|
exit;
|
|
} catch (Throwable $e) {
|
|
setFlash('danger', "Errore: " . $e->getMessage());
|
|
header("Location: salon_settings.php");
|
|
exit;
|
|
}
|
|
}
|
|
|
|
// Fetch impostazioni
|
|
$stmt = $pdo->prepare("SELECT * FROM shop_settings WHERE shop_id = ?");
|
|
$stmt->execute([$shop_id]);
|
|
$settings = $stmt->fetch(PDO::FETCH_ASSOC) ?: [
|
|
'show_prices_online' => 1,
|
|
'allowed_start_minutes' => '00,30',
|
|
'min_booking_notice_hours' => 2,
|
|
'max_booking_days_ahead' => 90
|
|
];
|
|
|
|
$flash = getFlash();
|
|
?>
|
|
|
|
<!doctype html>
|
|
<html lang="it">
|
|
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<link rel="icon" href="assets/images/favicon-32x32.png" type="image/png" />
|
|
<?php include('cssinclude.php'); ?>
|
|
<?php include('siteinfo.php'); ?>
|
|
<title>Impostazioni Salone - <?= htmlspecialchars($shop_name) ?></title>
|
|
<style>
|
|
.settings-card {
|
|
border: none;
|
|
border-radius: 16px;
|
|
overflow: hidden;
|
|
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.08);
|
|
}
|
|
|
|
.settings-header {
|
|
background: linear-gradient(135deg, #6366f1 0%, #4f46e5 100%);
|
|
color: white;
|
|
padding: 1.8rem 2rem;
|
|
}
|
|
|
|
.form-section {
|
|
background: #ffffff;
|
|
padding: 2.5rem;
|
|
}
|
|
|
|
.form-group {
|
|
margin-bottom: 2rem;
|
|
}
|
|
|
|
.form-label {
|
|
font-weight: 600;
|
|
color: #1f2937;
|
|
margin-bottom: 0.75rem;
|
|
display: block;
|
|
}
|
|
|
|
.form-text {
|
|
font-size: 0.9rem;
|
|
color: #6b7280;
|
|
margin-top: 0.5rem;
|
|
}
|
|
|
|
.preview-box {
|
|
background: #f9fafb;
|
|
border: 1px solid #e5e7eb;
|
|
border-radius: 10px;
|
|
padding: 1.25rem;
|
|
margin-top: 1rem;
|
|
}
|
|
|
|
.preview-slots {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 10px;
|
|
margin-top: 10px;
|
|
}
|
|
|
|
.preview-slot {
|
|
background: #e5e7eb;
|
|
color: #374151;
|
|
padding: 6px 14px;
|
|
border-radius: 9999px;
|
|
font-size: 0.9rem;
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.preview-slot.allowed {
|
|
background: #d1fae5;
|
|
color: #065f46;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.btn-save {
|
|
background: linear-gradient(135deg, #10b981 0%, #059669 100%);
|
|
border: none;
|
|
padding: 1rem 2.5rem;
|
|
font-size: 1.15rem;
|
|
font-weight: 600;
|
|
border-radius: 12px;
|
|
transition: all 0.3s;
|
|
}
|
|
|
|
.btn-save:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 8px 20px rgba(16, 185, 129, 0.3);
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
<div class="wrapper">
|
|
<?php include('include/navbar.php'); ?>
|
|
<?php include('include/topbar.php'); ?>
|
|
|
|
<div class="page-wrapper">
|
|
<div class="page-content">
|
|
<div class="card settings-card">
|
|
<div class="settings-header d-flex justify-content-between align-items-center">
|
|
<h5 class="mb-0">Impostazioni Salone</h5>
|
|
<a href="salon_dashboard.php" class="btn btn-light btn-sm px-4">
|
|
<i class="bx bx-arrow-back me-2"></i> Dashboard
|
|
</a>
|
|
</div>
|
|
|
|
<div class="form-section">
|
|
<?php if ($flash): ?>
|
|
<div class="alert alert-<?= $flash['type'] ?> alert-dismissible fade show mb-4" role="alert">
|
|
<?= htmlspecialchars($flash['text']) ?>
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<form action="" method="POST">
|
|
<!-- Visibilità prezzi -->
|
|
<div class="form-group">
|
|
<div class="d-flex align-items-center justify-content-between">
|
|
<label class="form-label mb-0" for="showPrices">Mostra i prezzi online ai clienti</label>
|
|
<div class="form-check form-switch form-switch-lg">
|
|
<input class="form-check-input" type="checkbox" name="show_prices_online" id="showPrices" <?= $settings['show_prices_online'] ? 'checked' : '' ?>>
|
|
</div>
|
|
</div>
|
|
<div class="form-text">
|
|
I clienti vedranno i prezzi durante la prenotazione online.
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Orari inizio -->
|
|
<div class="form-group">
|
|
<label class="form-label" for="restrictSelect">Orari di inizio appuntamenti permessi</label>
|
|
<select class="form-select form-select-lg" name="restrict_start_minutes" id="restrictSelect">
|
|
<option value="any" <?= $settings['allowed_start_minutes'] === 'any' ? 'selected' : '' ?>>
|
|
Qualsiasi minuto (libero)
|
|
</option>
|
|
<option value="00" <?= $settings['allowed_start_minutes'] === '00' ? 'selected' : '' ?>>
|
|
Solo ore piene (:00)
|
|
</option>
|
|
<option value="00,30" <?= $settings['allowed_start_minutes'] === '00,30' ? 'selected' : '' ?>>
|
|
Solo :00 e :30 (ogni mezz'ora piena)
|
|
</option>
|
|
<option value="00,15,30,45" <?= $settings['allowed_start_minutes'] === '00,15,30,45' ? 'selected' : '' ?>>
|
|
Ogni 15 minuti (:00, :15, :30, :45)
|
|
</option>
|
|
</select>
|
|
<div class="preview-box">
|
|
<strong>Anteprima slot (es. dalle 9:00):</strong>
|
|
<div class="preview-slots" id="previewSlots"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Limiti temporali -->
|
|
<div class="row g-4">
|
|
<div class="col-md-6 form-group">
|
|
<label class="form-label" for="minNotice">Preavviso minimo prenotazione (ore)</label>
|
|
<input type="number" class="form-control form-control-lg" name="min_booking_notice_hours" id="minNotice" min="0" max="72"
|
|
value="<?= (int)$settings['min_booking_notice_hours'] ?>">
|
|
<div class="form-text">Es: 2 = non prenotabile per oggi se mancano meno di 2 ore.</div>
|
|
</div>
|
|
|
|
<div class="col-md-6 form-group">
|
|
<label class="form-label" for="maxDays">Giorni massimi in anticipo</label>
|
|
<input type="number" class="form-control form-control-lg" name="max_booking_days_ahead" id="maxDays" min="7" max="365"
|
|
value="<?= (int)$settings['max_booking_days_ahead'] ?>">
|
|
<div class="form-text">Es: 90 = massimo 90 giorni da oggi.</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="d-grid mt-5">
|
|
<button type="submit" class="btn btn-save">
|
|
<i class="bx bx-save me-2"></i> Salva Impostazioni
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<?php include('include/footer.php'); ?>
|
|
</div>
|
|
|
|
<?php include('jsinclude.php'); ?>
|
|
|
|
<script>
|
|
$(document).ready(function() {
|
|
const restrictSelect = document.getElementById('restrictSelect');
|
|
const previewSlots = document.getElementById('previewSlots');
|
|
|
|
function updatePreview() {
|
|
const value = restrictSelect.value;
|
|
previewSlots.innerHTML = '';
|
|
|
|
const examples = [{
|
|
val: 'any',
|
|
slots: ['9:00', '9:05', '9:10', '9:15', '9:20', '...']
|
|
},
|
|
{
|
|
val: '00',
|
|
slots: ['9:00', '10:00', '11:00', '12:00']
|
|
},
|
|
{
|
|
val: '00,30',
|
|
slots: ['9:00', '9:30', '10:00', '10:30', '11:00']
|
|
},
|
|
{
|
|
val: '00,15,30,45',
|
|
slots: ['9:00', '9:15', '9:30', '9:45', '10:00']
|
|
}
|
|
];
|
|
|
|
const selected = examples.find(e => e.val === value) || examples[2];
|
|
|
|
selected.slots.forEach(slot => {
|
|
const span = document.createElement('span');
|
|
span.className = 'preview-slot' + (value !== 'any' ? ' allowed' : '');
|
|
span.textContent = slot;
|
|
previewSlots.appendChild(span);
|
|
});
|
|
}
|
|
|
|
restrictSelect.addEventListener('change', updatePreview);
|
|
updatePreview(); // init
|
|
});
|
|
</script>
|
|
</body>
|
|
|
|
</html>
|