fix grafica
This commit is contained in:
72
README.md
72
README.md
@@ -116,8 +116,11 @@ define('PAYPAL_SECRET', 'il-tuo-secret-sandbox');
|
||||
|
||||
### Passo 4: Configura i Permessi (Linux/Mac)
|
||||
```bash
|
||||
# Rendi scrivibile la cartella uploads
|
||||
chmod 755 uploads/
|
||||
# Rendi scrivibile la cartella uploads e sottocartelle
|
||||
chmod -R 755 uploads/
|
||||
chmod -R 755 uploads/lessons/demo/
|
||||
chmod -R 755 uploads/lessons/pay/
|
||||
chmod -R 755 uploads/images/
|
||||
```
|
||||
|
||||
### Passo 5: Avvia il Server
|
||||
@@ -245,11 +248,20 @@ Apri `assets/css/style.css` e modifica le variabili CSS:
|
||||
}
|
||||
```
|
||||
|
||||
### Logo
|
||||
Sostituisci il testo "Pilates Studio" in `index.php` e negli altri file con:
|
||||
```html
|
||||
<img src="assets/images/logo.png" alt="Logo" class="logo">
|
||||
```
|
||||
### Logo e Foto Istruttrice ⭐ **AGGIORNATO**
|
||||
1. **Logo**: Carica `logo.png` in `uploads/images/`
|
||||
- Dimensioni consigliate: 200x60px
|
||||
- Formato: PNG con sfondo trasparente
|
||||
- Il logo viene mostrato automaticamente nell'header se presente
|
||||
|
||||
2. **Foto Istruttrice**: Carica `instructor.jpg` in `uploads/images/`
|
||||
- Dimensioni consigliate: 400x400px
|
||||
- Formato: JPG o PNG
|
||||
- Viene mostrata nella sezione "Chi Sono" della homepage
|
||||
|
||||
3. **Hero Image**: Carica `hero-bg.jpg` in `uploads/images/`
|
||||
- Dimensioni: 1920x600px
|
||||
- Immagine di sfondo homepage
|
||||
|
||||
### Email
|
||||
Per usare SMTP invece di `mail()` PHP, decomenta in `includes/config.php`:
|
||||
@@ -265,23 +277,36 @@ define('SMTP_ENCRYPTION', 'tls');
|
||||
|
||||
## 🎥 Hosting Video
|
||||
|
||||
### Opzione 1: YouTube (Consigliato per Iniziare)
|
||||
### Opzione 1: File Locali (Upload Diretto) ⭐ **NUOVO**
|
||||
1. Nella creazione/modifica lezione, seleziona **File Locale**
|
||||
2. Clicca su "Scegli file" e seleziona il video dal tuo PC
|
||||
3. Il sistema carica automaticamente il file in:
|
||||
- `uploads/lessons/demo/` per lezioni gratuite
|
||||
- `uploads/lessons/pay/` per lezioni a pagamento
|
||||
4. Formati supportati: MP4, WebM, OGG, MOV
|
||||
5. ✅ **Vantaggi**: Upload automatico, nessun inserimento manuale del path
|
||||
6. ⚠️ Limiti: Dimensione massima upload dipende da `php.ini` (default ~2MB)
|
||||
|
||||
**Per aumentare il limite di upload:**
|
||||
Modifica `php.ini`:
|
||||
```ini
|
||||
upload_max_filesize = 500M
|
||||
post_max_size = 500M
|
||||
max_execution_time = 300
|
||||
```
|
||||
|
||||
### Opzione 2: YouTube (Consigliato per Video Grandi)
|
||||
1. Carica video su YouTube come **Non in elenco**
|
||||
2. Copia l'URL (es: `https://youtube.com/watch?v=ABC123`)
|
||||
3. Quando crei la lezione:
|
||||
- Piattaforma: YouTube
|
||||
- URL: Incolla il link
|
||||
|
||||
### Opzione 2: Vimeo
|
||||
### Opzione 3: Vimeo
|
||||
1. Carica su Vimeo
|
||||
2. Imposta privacy su "Nascosto"
|
||||
3. Copia URL e usa come YouTube
|
||||
|
||||
### Opzione 3: File Locali
|
||||
1. Carica il file in `uploads/videos/`
|
||||
2. URL Video: `/uploads/videos/nome-file.mp4`
|
||||
3. ⚠️ Non consigliato per file grandi (limiti server)
|
||||
|
||||
### Opzione 4: AWS S3 (Professionale)
|
||||
Per grandi quantità di video, usa Amazon S3:
|
||||
1. Crea un bucket S3
|
||||
@@ -360,7 +385,14 @@ Crea `.htaccess` nella cartella `includes/`:
|
||||
### I video non si vedono
|
||||
- Verifica che l'URL sia corretto
|
||||
- Per YouTube/Vimeo: usa URL diretti al video
|
||||
- Per file locali: controlla i permessi della cartella
|
||||
- Per file locali caricati: controlla che esistano in `uploads/lessons/demo/` o `pay/`
|
||||
- Verifica permessi cartella uploads (755)
|
||||
- Per video grandi, verifica limiti upload in `php.ini`
|
||||
|
||||
### Errore durante upload video
|
||||
- Controlla `upload_max_filesize` e `post_max_size` in `php.ini`
|
||||
- Verifica che la cartella `uploads/lessons/` sia scrivibile
|
||||
- Assicurati che il formato sia supportato (MP4, WebM, OGG, MOV)
|
||||
|
||||
### PayPal non funziona
|
||||
- Verifica Client ID e Secret
|
||||
@@ -414,9 +446,13 @@ pilates-platform/
|
||||
│ ├── functions.php # Funzioni comuni
|
||||
│ └── logout.php # Script logout
|
||||
│
|
||||
├── uploads/ # File caricati (da creare)
|
||||
│ ├── thumbnails/ # Anteprime lezioni
|
||||
│ └── videos/ # Video locali
|
||||
├── uploads/ # File caricati
|
||||
│ ├── lessons/ # Video lezioni
|
||||
│ │ ├── demo/ # Video lezioni gratuite
|
||||
│ │ ├── pay/ # Video lezioni a pagamento
|
||||
│ │ └── .htaccess # Protezione accesso diretto
|
||||
│ ├── images/ # Logo e foto istruttrice
|
||||
│ └── thumbnails/ # Anteprime lezioni (future)
|
||||
│
|
||||
├── user/ # Area utente
|
||||
│ ├── dashboard.php # Dashboard utente
|
||||
|
||||
@@ -68,7 +68,14 @@ $top_lessons = $stmt->fetchAll();
|
||||
<header class="header">
|
||||
<div class="container">
|
||||
<div class="header-content">
|
||||
<h1 class="logo">Pilates Studio - Admin</h1>
|
||||
<?php if (file_exists('../uploads/images/logo.png')): ?>
|
||||
<div class="logo">
|
||||
<img src="../uploads/images/logo.png" alt="Pilates Studio" class="logo-image">
|
||||
<span style="margin-left: 10px; color: var(--primary-color); font-weight: 600;">Admin</span>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<h1 class="logo">Pilates Studio - Admin</h1>
|
||||
<?php endif; ?>
|
||||
<nav class="nav">
|
||||
<a href="../index.php" class="btn btn-outline">Vedi Sito</a>
|
||||
<a href="../includes/logout.php" class="btn btn-secondary">Logout</a>
|
||||
|
||||
@@ -32,6 +32,29 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$is_demo = isset($_POST['is_demo']) ? 1 : 0;
|
||||
$is_active = isset($_POST['is_active']) ? 1 : 0;
|
||||
|
||||
// Gestione upload file locale
|
||||
if ($type === 'video' && $video_platform === 'local' && isset($_FILES['video_file']) && $_FILES['video_file']['error'] === UPLOAD_ERR_OK) {
|
||||
$upload_dir = $is_demo ? '../uploads/lessons/demo/' : '../uploads/lessons/pay/';
|
||||
|
||||
// Crea nome file sicuro
|
||||
$file_extension = strtolower(pathinfo($_FILES['video_file']['name'], PATHINFO_EXTENSION));
|
||||
$allowed_extensions = ['mp4', 'webm', 'ogg', 'mov'];
|
||||
|
||||
if (!in_array($file_extension, $allowed_extensions)) {
|
||||
$error = 'Formato video non supportato. Usa: mp4, webm, ogg, mov';
|
||||
} else {
|
||||
$file_name = uniqid('video_') . '_' . time() . '.' . $file_extension;
|
||||
$upload_path = $upload_dir . $file_name;
|
||||
|
||||
if (move_uploaded_file($_FILES['video_file']['tmp_name'], $upload_path)) {
|
||||
// Imposta il percorso relativo per il database
|
||||
$video_url = '/uploads/lessons/' . ($is_demo ? 'demo' : 'pay') . '/' . $file_name;
|
||||
} else {
|
||||
$error = 'Errore durante il caricamento del file';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validazione
|
||||
if (empty($title)) {
|
||||
$error = 'Il titolo è obbligatorio';
|
||||
@@ -39,7 +62,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$error = 'La descrizione è obbligatoria';
|
||||
} elseif ($type === 'live' && empty($live_date)) {
|
||||
$error = 'Per le lezioni live, la data è obbligatoria';
|
||||
} else {
|
||||
} elseif ($type === 'video' && $video_platform === 'local' && empty($video_url)) {
|
||||
$error = 'Devi caricare un file video per le lezioni locali';
|
||||
} elseif (!$error) {
|
||||
$pdo = get_db_connection();
|
||||
|
||||
try {
|
||||
@@ -94,7 +119,14 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
<header class="header">
|
||||
<div class="container">
|
||||
<div class="header-content">
|
||||
<h1 class="logo">Pilates Studio - Admin</h1>
|
||||
<?php if (file_exists('../uploads/images/logo.png')): ?>
|
||||
<div class="logo">
|
||||
<img src="../uploads/images/logo.png" alt="Pilates Studio" class="logo-image">
|
||||
<span style="margin-left: 10px; color: var(--primary-color); font-weight: 600;">Admin</span>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<h1 class="logo">Pilates Studio - Admin</h1>
|
||||
<?php endif; ?>
|
||||
<nav class="nav">
|
||||
<a href="lessons.php" class="btn btn-outline">← Torna alle Lezioni</a>
|
||||
<a href="../includes/logout.php" class="btn btn-secondary">Logout</a>
|
||||
@@ -122,7 +154,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="card">
|
||||
<form method="POST" action="">
|
||||
<form method="POST" action="" enctype="multipart/form-data">
|
||||
<!-- Informazioni Base -->
|
||||
<h3 style="margin-bottom: 1rem; color: var(--primary-color);">Informazioni Base</h3>
|
||||
|
||||
@@ -156,20 +188,29 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
|
||||
<div class="form-group">
|
||||
<label for="video_platform" class="form-label">Piattaforma Video</label>
|
||||
<select id="video_platform" name="video_platform" class="form-control">
|
||||
<option value="local">File Locale</option>
|
||||
<select id="video_platform" name="video_platform" class="form-control" onchange="toggleVideoInput()">
|
||||
<option value="local">File Locale (Carica dal PC)</option>
|
||||
<option value="youtube">YouTube</option>
|
||||
<option value="vimeo">Vimeo</option>
|
||||
<option value="s3">AWS S3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="video_url" class="form-label">URL/Percorso Video</label>
|
||||
<!-- Upload file locale -->
|
||||
<div id="local-upload" class="form-group">
|
||||
<label for="video_file" class="form-label">Carica Video *</label>
|
||||
<input type="file" id="video_file" name="video_file" class="form-control"
|
||||
accept="video/mp4,video/webm,video/ogg,video/quicktime">
|
||||
<small class="text-muted">Formati supportati: MP4, WebM, OGG, MOV. Il file verrà salvato automaticamente nella cartella demo/pay.</small>
|
||||
</div>
|
||||
|
||||
<!-- URL esterno -->
|
||||
<div id="external-url" class="form-group" style="display: none;">
|
||||
<label for="video_url" class="form-label">URL Video</label>
|
||||
<input type="text" id="video_url" name="video_url" class="form-control"
|
||||
placeholder="es: https://youtube.com/watch?v=..."
|
||||
value="<?php echo htmlspecialchars($_POST['video_url'] ?? ''); ?>">
|
||||
<small class="text-muted">Lascia vuoto se caricherai il video successivamente</small>
|
||||
<small class="text-muted">Inserisci l'URL del video sulla piattaforma esterna</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
@@ -280,6 +321,29 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
liveFields.style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
// Mostra/nascondi campi upload/URL in base alla piattaforma
|
||||
function toggleVideoInput() {
|
||||
const platform = document.getElementById('video_platform').value;
|
||||
const localUpload = document.getElementById('local-upload');
|
||||
const externalUrl = document.getElementById('external-url');
|
||||
const videoFileInput = document.getElementById('video_file');
|
||||
|
||||
if (platform === 'local') {
|
||||
localUpload.style.display = 'block';
|
||||
externalUrl.style.display = 'none';
|
||||
videoFileInput.required = true;
|
||||
} else {
|
||||
localUpload.style.display = 'none';
|
||||
externalUrl.style.display = 'block';
|
||||
videoFileInput.required = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Inizializza lo stato al caricamento
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
toggleVideoInput();
|
||||
});
|
||||
</script>
|
||||
<script src="../assets/js/main.js"></script>
|
||||
</body>
|
||||
|
||||
@@ -53,7 +53,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$category = sanitize_input($_POST['category'] ?? '');
|
||||
$price = floatval($_POST['price'] ?? 0);
|
||||
$duration = !empty($_POST['duration']) ? intval($_POST['duration']) : null;
|
||||
$video_url = sanitize_input($_POST['video_url'] ?? '');
|
||||
$video_url = sanitize_input($_POST['video_url'] ?? '') ?: $lesson['video_url']; // Mantieni il vecchio se non specificato
|
||||
$video_platform = $_POST['video_platform'] ?? 'local';
|
||||
$live_url = sanitize_input($_POST['live_url'] ?? '');
|
||||
$live_platform = sanitize_input($_POST['live_platform'] ?? '');
|
||||
@@ -61,6 +61,33 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$is_demo = isset($_POST['is_demo']) ? 1 : 0;
|
||||
$is_active = isset($_POST['is_active']) ? 1 : 0;
|
||||
|
||||
// Gestione upload nuovo file locale (opzionale)
|
||||
if ($type === 'video' && $video_platform === 'local' && isset($_FILES['video_file']) && $_FILES['video_file']['error'] === UPLOAD_ERR_OK) {
|
||||
$upload_dir = $is_demo ? '../uploads/lessons/demo/' : '../uploads/lessons/pay/';
|
||||
|
||||
// Crea nome file sicuro
|
||||
$file_extension = strtolower(pathinfo($_FILES['video_file']['name'], PATHINFO_EXTENSION));
|
||||
$allowed_extensions = ['mp4', 'webm', 'ogg', 'mov'];
|
||||
|
||||
if (!in_array($file_extension, $allowed_extensions)) {
|
||||
$error = 'Formato video non supportato. Usa: mp4, webm, ogg, mov';
|
||||
} else {
|
||||
$file_name = uniqid('video_') . '_' . time() . '.' . $file_extension;
|
||||
$upload_path = $upload_dir . $file_name;
|
||||
|
||||
if (move_uploaded_file($_FILES['video_file']['tmp_name'], $upload_path)) {
|
||||
// Elimina il vecchio file se esisteva
|
||||
if (!empty($lesson['video_url']) && file_exists('../' . $lesson['video_url'])) {
|
||||
@unlink('../' . $lesson['video_url']);
|
||||
}
|
||||
// Imposta il nuovo percorso
|
||||
$video_url = '/uploads/lessons/' . ($is_demo ? 'demo' : 'pay') . '/' . $file_name;
|
||||
} else {
|
||||
$error = 'Errore durante il caricamento del file';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validazione
|
||||
if (empty($title)) {
|
||||
$error = 'Il titolo è obbligatorio';
|
||||
@@ -68,7 +95,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$error = 'La descrizione è obbligatoria';
|
||||
} elseif ($type === 'live' && empty($live_date)) {
|
||||
$error = 'Per le lezioni live, la data è obbligatoria';
|
||||
} else {
|
||||
} elseif (!$error) {
|
||||
try {
|
||||
$stmt = $pdo->prepare("
|
||||
UPDATE lessons SET
|
||||
@@ -130,7 +157,14 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
<header class="header">
|
||||
<div class="container">
|
||||
<div class="header-content">
|
||||
<h1 class="logo">Pilates Studio - Admin</h1>
|
||||
<?php if (file_exists('../uploads/images/logo.png')): ?>
|
||||
<div class="logo">
|
||||
<img src="../uploads/images/logo.png" alt="Pilates Studio" class="logo-image">
|
||||
<span style="margin-left: 10px; color: var(--primary-color); font-weight: 600;">Admin</span>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<h1 class="logo">Pilates Studio - Admin</h1>
|
||||
<?php endif; ?>
|
||||
<nav class="nav">
|
||||
<a href="lessons.php" class="btn btn-outline">← Torna alle Lezioni</a>
|
||||
<a href="../includes/logout.php" class="btn btn-secondary">Logout</a>
|
||||
@@ -158,7 +192,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="card">
|
||||
<form method="POST" action="">
|
||||
<form method="POST" action="" enctype="multipart/form-data">
|
||||
<!-- Informazioni Base -->
|
||||
<h3 style="margin-bottom: 1rem; color: var(--primary-color);">Informazioni Base</h3>
|
||||
|
||||
@@ -192,20 +226,34 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
|
||||
<div class="form-group">
|
||||
<label for="video_platform" class="form-label">Piattaforma Video</label>
|
||||
<select id="video_platform" name="video_platform" class="form-control">
|
||||
<option value="local" <?php echo ($_POST['video_platform'] ?? $lesson['video_platform']) === 'local' ? 'selected' : ''; ?>>File Locale</option>
|
||||
<select id="video_platform" name="video_platform" class="form-control" onchange="toggleVideoInput()">
|
||||
<option value="local" <?php echo ($_POST['video_platform'] ?? $lesson['video_platform']) === 'local' ? 'selected' : ''; ?>>File Locale (Carica dal PC)</option>
|
||||
<option value="youtube" <?php echo ($_POST['video_platform'] ?? $lesson['video_platform']) === 'youtube' ? 'selected' : ''; ?>>YouTube</option>
|
||||
<option value="vimeo" <?php echo ($_POST['video_platform'] ?? $lesson['video_platform']) === 'vimeo' ? 'selected' : ''; ?>>Vimeo</option>
|
||||
<option value="s3" <?php echo ($_POST['video_platform'] ?? $lesson['video_platform']) === 's3' ? 'selected' : ''; ?>>AWS S3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="video_url" class="form-label">URL/Percorso Video</label>
|
||||
<!-- Upload file locale -->
|
||||
<div id="local-upload" class="form-group" style="display: <?php echo ($_POST['video_platform'] ?? $lesson['video_platform']) === 'local' ? 'block' : 'none'; ?>;">
|
||||
<?php if (!empty($lesson['video_url'])): ?>
|
||||
<div style="margin-bottom: 0.5rem; padding: 0.5rem; background: #e8f4f8; border-radius: 4px;">
|
||||
<strong>File attuale:</strong> <?php echo htmlspecialchars(basename($lesson['video_url'])); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<label for="video_file" class="form-label">Carica Nuovo Video (opzionale)</label>
|
||||
<input type="file" id="video_file" name="video_file" class="form-control"
|
||||
accept="video/mp4,video/webm,video/ogg,video/quicktime">
|
||||
<small class="text-muted">Formati supportati: MP4, WebM, OGG, MOV. Lascia vuoto per mantenere il file attuale.</small>
|
||||
</div>
|
||||
|
||||
<!-- URL esterno -->
|
||||
<div id="external-url" class="form-group" style="display: <?php echo ($_POST['video_platform'] ?? $lesson['video_platform']) === 'local' ? 'none' : 'block'; ?>;">
|
||||
<label for="video_url" class="form-label">URL Video</label>
|
||||
<input type="text" id="video_url" name="video_url" class="form-control"
|
||||
placeholder="es: https://youtube.com/watch?v=..."
|
||||
value="<?php echo htmlspecialchars($_POST['video_url'] ?? $lesson['video_url'] ?? ''); ?>">
|
||||
<small class="text-muted">Lascia vuoto se caricherai il video successivamente</small>
|
||||
<small class="text-muted">Inserisci l'URL del video sulla piattaforma esterna</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
@@ -323,6 +371,26 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
liveFields.style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
// Mostra/nascondi campi upload/URL in base alla piattaforma
|
||||
function toggleVideoInput() {
|
||||
const platform = document.getElementById('video_platform').value;
|
||||
const localUpload = document.getElementById('local-upload');
|
||||
const externalUrl = document.getElementById('external-url');
|
||||
|
||||
if (platform === 'local') {
|
||||
localUpload.style.display = 'block';
|
||||
externalUrl.style.display = 'none';
|
||||
} else {
|
||||
localUpload.style.display = 'none';
|
||||
externalUrl.style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
// Inizializza lo stato al caricamento
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
toggleVideoInput();
|
||||
});
|
||||
</script>
|
||||
<script src="../assets/js/main.js"></script>
|
||||
</body>
|
||||
|
||||
@@ -58,7 +58,14 @@ $lessons = $stmt->fetchAll();
|
||||
<header class="header">
|
||||
<div class="container">
|
||||
<div class="header-content">
|
||||
<h1 class="logo">Pilates Studio - Admin</h1>
|
||||
<?php if (file_exists('../uploads/images/logo.png')): ?>
|
||||
<div class="logo">
|
||||
<img src="../uploads/images/logo.png" alt="Pilates Studio" class="logo-image">
|
||||
<span style="margin-left: 10px; color: var(--primary-color); font-weight: 600;">Admin</span>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<h1 class="logo">Pilates Studio - Admin</h1>
|
||||
<?php endif; ?>
|
||||
<nav class="nav">
|
||||
<a href="../index.php" class="btn btn-outline">Vedi Sito</a>
|
||||
<a href="../includes/logout.php" class="btn btn-secondary">Logout</a>
|
||||
@@ -90,6 +97,7 @@ $lessons = $stmt->fetchAll();
|
||||
|
||||
<div class="card">
|
||||
<?php if (!empty($lessons)): ?>
|
||||
<div class="table-container">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -135,6 +143,7 @@ $lessons = $stmt->fetchAll();
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<p class="text-muted text-center">Nessuna lezione disponibile. <a href="lesson_create.php">Creane una!</a></p>
|
||||
<?php endif; ?>
|
||||
|
||||
@@ -49,7 +49,14 @@ $stats = $stmt->fetch();
|
||||
<header class="header">
|
||||
<div class="container">
|
||||
<div class="header-content">
|
||||
<h1 class="logo">Pilates Studio - Admin</h1>
|
||||
<?php if (file_exists('../uploads/images/logo.png')): ?>
|
||||
<div class="logo">
|
||||
<img src="../uploads/images/logo.png" alt="Pilates Studio" class="logo-image">
|
||||
<span style="margin-left: 10px; color: var(--primary-color); font-weight: 600;">Admin</span>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<h1 class="logo">Pilates Studio - Admin</h1>
|
||||
<?php endif; ?>
|
||||
<nav class="nav">
|
||||
<a href="../index.php" class="btn btn-outline">Vedi Sito</a>
|
||||
<a href="../includes/logout.php" class="btn btn-secondary">Logout</a>
|
||||
@@ -99,6 +106,7 @@ $stats = $stmt->fetch();
|
||||
|
||||
<div class="card">
|
||||
<?php if (!empty($purchases)): ?>
|
||||
<div class="table-container">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
@@ -56,7 +56,14 @@ $users = $stmt->fetchAll();
|
||||
<header class="header">
|
||||
<div class="container">
|
||||
<div class="header-content">
|
||||
<h1 class="logo">Pilates Studio - Admin</h1>
|
||||
<?php if (file_exists('../uploads/images/logo.png')): ?>
|
||||
<div class="logo">
|
||||
<img src="../uploads/images/logo.png" alt="Pilates Studio" class="logo-image">
|
||||
<span style="margin-left: 10px; color: var(--primary-color); font-weight: 600;">Admin</span>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<h1 class="logo">Pilates Studio - Admin</h1>
|
||||
<?php endif; ?>
|
||||
<nav class="nav">
|
||||
<a href="../index.php" class="btn btn-outline">Vedi Sito</a>
|
||||
<a href="../includes/logout.php" class="btn btn-secondary">Logout</a>
|
||||
@@ -87,6 +94,7 @@ $users = $stmt->fetchAll();
|
||||
<p class="text-muted mb-2">Totale utenti registrati: <strong><?php echo count($users); ?></strong></p>
|
||||
|
||||
<?php if (!empty($users)): ?>
|
||||
<div class="table-container">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -132,6 +140,7 @@ $users = $stmt->fetchAll();
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<p class="text-muted text-center">Nessun utente registrato ancora.</p>
|
||||
<?php endif; ?>
|
||||
|
||||
@@ -134,6 +134,14 @@ a:hover {
|
||||
font-weight: 700;
|
||||
color: var(--primary-color);
|
||||
margin: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.logo-image {
|
||||
max-height: 60px;
|
||||
width: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.nav {
|
||||
@@ -630,11 +638,55 @@ select.form-control {
|
||||
.align-center { align-items: center; }
|
||||
.gap-1 { gap: var(--spacing-md); }
|
||||
|
||||
/* ============================================
|
||||
SEZIONE ISTRUTTRICE
|
||||
============================================ */
|
||||
|
||||
.instructor-section {
|
||||
padding: var(--spacing-2xl) 0;
|
||||
background: var(--gray-100);
|
||||
}
|
||||
|
||||
.instructor-content {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: var(--spacing-2xl);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.instructor-image img {
|
||||
border-radius: var(--radius-lg);
|
||||
box-shadow: var(--shadow-lg);
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.instructor-text h2 {
|
||||
margin-bottom: var(--spacing-lg);
|
||||
}
|
||||
|
||||
.instructor-text p {
|
||||
margin-bottom: var(--spacing-md);
|
||||
color: var(--gray-700);
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.instructor-text .btn {
|
||||
margin-top: var(--spacing-md);
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
RESPONSIVE
|
||||
============================================ */
|
||||
|
||||
@media (max-width: 768px) {
|
||||
/* Container più stretto su mobile */
|
||||
.container {
|
||||
padding: 0 var(--spacing-md);
|
||||
}
|
||||
|
||||
/* Hero section */
|
||||
.hero-title {
|
||||
font-size: 2rem;
|
||||
}
|
||||
@@ -643,41 +695,155 @@ select.form-control {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
/* Header */
|
||||
.header {
|
||||
padding: var(--spacing-md) 0;
|
||||
}
|
||||
|
||||
.header-content {
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-md);
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.logo-image {
|
||||
max-height: 50px;
|
||||
}
|
||||
|
||||
.nav {
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Dashboard */
|
||||
.dashboard {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
order: 2;
|
||||
margin-top: var(--spacing-lg);
|
||||
}
|
||||
|
||||
/* Griglie */
|
||||
.lessons-grid,
|
||||
.features-grid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: var(--spacing-lg);
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
/* Sezione istruttrice */
|
||||
.instructor-content {
|
||||
grid-template-columns: 1fr;
|
||||
gap: var(--spacing-lg);
|
||||
}
|
||||
|
||||
.instructor-image img {
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
/* Tabelle responsive */
|
||||
.table-container {
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
table {
|
||||
min-width: 600px;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
/* Form */
|
||||
.form-group {
|
||||
margin-bottom: var(--spacing-md);
|
||||
}
|
||||
|
||||
.form-control {
|
||||
font-size: 16px; /* Previene zoom su iOS */
|
||||
}
|
||||
|
||||
/* Card */
|
||||
.card {
|
||||
padding: var(--spacing-lg);
|
||||
}
|
||||
|
||||
/* Bottoni in flex */
|
||||
.d-flex {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.d-flex .btn {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
/* Typography più piccola */
|
||||
.hero-title {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
|
||||
/* Bottoni full width */
|
||||
.btn {
|
||||
width: 100%;
|
||||
display: block;
|
||||
padding: 0.75rem 1rem;
|
||||
}
|
||||
|
||||
.btn + .btn {
|
||||
margin-top: var(--spacing-sm);
|
||||
}
|
||||
|
||||
.btn-small {
|
||||
padding: 0.5rem 0.75rem;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
/* Nav stack verticale */
|
||||
.nav {
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.nav .btn {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Stats cards */
|
||||
.stat-card {
|
||||
padding: var(--spacing-md);
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
|
||||
/* Sidebar menu */
|
||||
.sidebar-menu {
|
||||
padding: var(--spacing-md);
|
||||
}
|
||||
|
||||
/* Alert responsive */
|
||||
.alert {
|
||||
padding: var(--spacing-md);
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
.footer {
|
||||
padding: var(--spacing-lg) 0;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,13 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
<div class="container-sm" style="padding-top: 3rem;">
|
||||
<div class="card">
|
||||
<div class="text-center mb-3">
|
||||
<h1 class="logo">Pilates Studio</h1>
|
||||
<?php if (file_exists('uploads/images/logo.png')): ?>
|
||||
<div class="logo">
|
||||
<img src="uploads/images/logo.png" alt="Pilates Studio" class="logo-image">
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<h1 class="logo">Pilates Studio</h1>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<h2 class="card-header text-center">Recupero Password</h2>
|
||||
|
||||
29
index.php
29
index.php
@@ -30,7 +30,13 @@ $demo_lessons = get_demo_lessons();
|
||||
<header class="header">
|
||||
<div class="container">
|
||||
<div class="header-content">
|
||||
<h1 class="logo">Pilates Studio</h1>
|
||||
<?php if (file_exists('uploads/images/logo.png')): ?>
|
||||
<div class="logo">
|
||||
<img src="uploads/images/logo.png" alt="Pilates Studio" class="logo-image">
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<h1 class="logo">Pilates Studio</h1>
|
||||
<?php endif; ?>
|
||||
<nav class="nav">
|
||||
<?php if (is_logged_in()): ?>
|
||||
<?php if (is_admin()): ?>
|
||||
@@ -103,6 +109,27 @@ $demo_lessons = get_demo_lessons();
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Sezione Chi Sono -->
|
||||
<?php if (file_exists('uploads/images/instructor.jpg')): ?>
|
||||
<section class="instructor-section">
|
||||
<div class="container">
|
||||
<div class="instructor-content">
|
||||
<div class="instructor-image">
|
||||
<img src="uploads/images/instructor.jpg" alt="La tua Istruttrice">
|
||||
</div>
|
||||
<div class="instructor-text">
|
||||
<h2 class="section-title">Chi Sono</h2>
|
||||
<p>Benvenuto nel mio studio di Pilates! Sono un'istruttrice certificata con anni di esperienza nell'insegnamento del Pilates a tutti i livelli.</p>
|
||||
<p>La mia missione è aiutarti a raggiungere i tuoi obiettivi di fitness attraverso lezioni personalizzate e di alta qualità.</p>
|
||||
<?php if (!is_logged_in()): ?>
|
||||
<a href="register.php" class="btn btn-primary">Unisciti a Noi</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Sezione Vantaggi -->
|
||||
<section class="features-section">
|
||||
<div class="container">
|
||||
|
||||
@@ -55,7 +55,13 @@ $can_view = $lesson['is_demo'] || $user_owns;
|
||||
<header class="header">
|
||||
<div class="container">
|
||||
<div class="header-content">
|
||||
<h1 class="logo">Pilates Studio</h1>
|
||||
<?php if (file_exists('uploads/images/logo.png')): ?>
|
||||
<div class="logo">
|
||||
<img src="uploads/images/logo.png" alt="Pilates Studio" class="logo-image">
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<h1 class="logo">Pilates Studio</h1>
|
||||
<?php endif; ?>
|
||||
<nav class="nav">
|
||||
<a href="index.php" class="btn btn-outline">Home</a>
|
||||
<?php if ($is_logged_in): ?>
|
||||
|
||||
@@ -90,7 +90,13 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
<div class="container-sm" style="padding-top: 3rem;">
|
||||
<div class="card">
|
||||
<div class="text-center mb-3">
|
||||
<h1 class="logo">Pilates Studio</h1>
|
||||
<?php if (file_exists('uploads/images/logo.png')): ?>
|
||||
<div class="logo">
|
||||
<img src="uploads/images/logo.png" alt="Pilates Studio" class="logo-image">
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<h1 class="logo">Pilates Studio</h1>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<h2 class="card-header text-center">Accedi al tuo account</h2>
|
||||
|
||||
@@ -87,7 +87,13 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
<div class="container-sm" style="padding-top: 3rem; padding-bottom: 3rem;">
|
||||
<div class="card">
|
||||
<div class="text-center mb-3">
|
||||
<h1 class="logo">Pilates Studio</h1>
|
||||
<?php if (file_exists('uploads/images/logo.png')): ?>
|
||||
<div class="logo">
|
||||
<img src="uploads/images/logo.png" alt="Pilates Studio" class="logo-image">
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<h1 class="logo">Pilates Studio</h1>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<h2 class="card-header text-center">Crea un nuovo account</h2>
|
||||
|
||||
@@ -80,7 +80,13 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && $user_id) {
|
||||
<div class="container-sm" style="padding-top: 3rem;">
|
||||
<div class="card">
|
||||
<div class="text-center mb-3">
|
||||
<h1 class="logo">Pilates Studio</h1>
|
||||
<?php if (file_exists('uploads/images/logo.png')): ?>
|
||||
<div class="logo">
|
||||
<img src="uploads/images/logo.png" alt="Pilates Studio" class="logo-image">
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<h1 class="logo">Pilates Studio</h1>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<h2 class="card-header text-center">Reimposta Password</h2>
|
||||
|
||||
11
uploads/lessons/.htaccess
Normal file
11
uploads/lessons/.htaccess
Normal file
@@ -0,0 +1,11 @@
|
||||
# Proteggi i video a pagamento
|
||||
# Permetti solo l'accesso tramite PHP
|
||||
|
||||
<FilesMatch "\.(mp4|webm|ogg|mov)$">
|
||||
# Permetti l'accesso solo se proveniente da script PHP
|
||||
Order Deny,Allow
|
||||
Deny from all
|
||||
</FilesMatch>
|
||||
|
||||
# Opzionale: previeni il listing delle directory
|
||||
Options -Indexes
|
||||
@@ -39,7 +39,13 @@ $owned_lesson_ids = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
||||
<header class="header">
|
||||
<div class="container">
|
||||
<div class="header-content">
|
||||
<h1 class="logo">Pilates Studio</h1>
|
||||
<?php if (file_exists('../uploads/images/logo.png')): ?>
|
||||
<div class="logo">
|
||||
<img src="../uploads/images/logo.png" alt="Pilates Studio" class="logo-image">
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<h1 class="logo">Pilates Studio</h1>
|
||||
<?php endif; ?>
|
||||
<nav class="nav">
|
||||
<a href="../index.php" class="btn btn-outline">Home</a>
|
||||
<a href="dashboard.php" class="btn btn-secondary">Le Mie Lezioni</a>
|
||||
|
||||
@@ -33,7 +33,13 @@ $user = get_user_by_id($user_id);
|
||||
<header class="header">
|
||||
<div class="container">
|
||||
<div class="header-content">
|
||||
<h1 class="logo">Pilates Studio</h1>
|
||||
<?php if (file_exists('../uploads/images/logo.png')): ?>
|
||||
<div class="logo">
|
||||
<img src="../uploads/images/logo.png" alt="Pilates Studio" class="logo-image">
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<h1 class="logo">Pilates Studio</h1>
|
||||
<?php endif; ?>
|
||||
<nav class="nav">
|
||||
<a href="../index.php" class="btn btn-outline">Home</a>
|
||||
<a href="catalog.php" class="btn btn-secondary">Catalogo Lezioni</a>
|
||||
|
||||
@@ -99,7 +99,13 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['change_password'])) {
|
||||
<header class="header">
|
||||
<div class="container">
|
||||
<div class="header-content">
|
||||
<h1 class="logo">Pilates Studio</h1>
|
||||
<?php if (file_exists('../uploads/images/logo.png')): ?>
|
||||
<div class="logo">
|
||||
<img src="../uploads/images/logo.png" alt="Pilates Studio" class="logo-image">
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<h1 class="logo">Pilates Studio</h1>
|
||||
<?php endif; ?>
|
||||
<nav class="nav">
|
||||
<a href="../index.php" class="btn btn-outline">Home</a>
|
||||
<a href="dashboard.php" class="btn btn-secondary">Le Mie Lezioni</a>
|
||||
|
||||
Reference in New Issue
Block a user