From 6972ed7543e5d706fecfc0d7b404a75bf70ed6a6 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sun, 28 Sep 2025 23:26:12 +0000 Subject: [PATCH] + Grafica --- admin.php | 268 +++++++++++++++-------------------- assets/css/custom.css | 231 ++++++++++++++++++++---------- includes/footer.php | 15 ++ includes/header.php | 55 ++++++++ index.php | 246 +++++++++++++++----------------- leaderboard.php | 97 +++++-------- login.php | 98 ++++++------- puzzle.php | 319 +++++++++++++++++++++--------------------- register.php | 104 ++++++-------- 9 files changed, 736 insertions(+), 697 deletions(-) create mode 100644 includes/footer.php create mode 100644 includes/header.php diff --git a/admin.php b/admin.php index 9b8afb55..e48371a6 100644 --- a/admin.php +++ b/admin.php @@ -47,9 +47,9 @@ function create_puzzle_pieces($source_image_path, $puzzle_id, $pieces_count) { // Grid dimensions $cols = 0; $rows = 0; - if ($pieces_count == 16) { $cols = 4; $rows = 4; } - elseif ($pieces_count == 32) { $cols = 8; $rows = 4; } - elseif ($pieces_count == 64) { $cols = 8; $rows = 8; } + if ($pieces_count == 16) { $cols = 4; $rows = 4; } + elseif ($pieces_count == 32) { $cols = 8; $rows = 4; } + elseif ($pieces_count == 64) { $cols = 8; $rows = 8; } else { error_log("Invalid pieces count: " . $pieces_count); return false; @@ -104,8 +104,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_puzzle'])) { $upload_path = $upload_dir . $safe_filename; if (move_uploaded_file($image_file['tmp_name'], $upload_path)) { - $stmt = $pdo->prepare('INSERT INTO puzzles (name, original_image, file_name, pieces, is_public, created_at) VALUES (?, ?, ?, ?, ?, NOW())'); - $stmt->execute([$puzzle_name, $safe_filename, $safe_filename, $pieces, $is_public]); + $stmt = $pdo->prepare('INSERT INTO puzzles (name, file_name, pieces, is_public, is_admin_upload) VALUES (?, ?, ?, ?, 1)'); + $stmt->execute([$puzzle_name, $safe_filename, $pieces, $is_public]); $puzzle_id = $pdo->lastInsertId(); create_puzzle_pieces($upload_path, $puzzle_id, $pieces); @@ -123,12 +123,12 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_puzzle'])) { if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_puzzle'])) { $puzzle_id_to_delete = $_POST['puzzle_id']; - $stmt = $pdo->prepare('SELECT original_image FROM puzzles WHERE id = ?'); + $stmt = $pdo->prepare('SELECT file_name FROM puzzles WHERE id = ?'); $stmt->execute([$puzzle_id_to_delete]); $puzzle = $stmt->fetch(PDO::FETCH_ASSOC); if ($puzzle) { - $original_image_path = __DIR__ . '/uploads/' . $puzzle['original_image']; + $original_image_path = __DIR__ . '/uploads/' . $puzzle['file_name']; if (file_exists($original_image_path)) { unlink($original_image_path); } @@ -155,168 +155,132 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_puzzle'])) { } -$puzzles = $pdo->query('SELECT id, name, original_image, pieces, is_public, created_at FROM puzzles ORDER BY created_at DESC')->fetchAll(PDO::FETCH_ASSOC); +$puzzles = $pdo->query('SELECT id, name, file_name, pieces, is_public, created_at FROM puzzles ORDER BY created_at DESC')->fetchAll(PDO::FETCH_ASSOC); // Fetch users $users = $pdo->query('SELECT id, username, email, created_at FROM users ORDER BY created_at DESC')->fetchAll(PDO::FETCH_ASSOC); +$page_title = 'Pannello di Amministrazione'; +require_once 'includes/header.php'; ?> - - - - - - Pannello di Amministrazione - - - - - -
- - -
Puzzle aggiunto con successo!
- - -
Puzzle eliminato con successo.
- - -
Errore durante l'upload. Controlla i dati e riprova.
- +
+ +
Puzzle aggiunto con successo!
+ +
Puzzle eliminato con successo.
+ +
Errore durante l\'upload. Controlla i dati e riprova.
+ - -
-

Aggiungi Nuovo Puzzle

-
-
- - -
-
- - -
-
- - -
-
- - -
- -
-
+ +
+

Aggiungi Nuovo Puzzle

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+
-

Gestione Puzzle

-
- - +

Gestione Puzzle

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
IDNomeImmaginePezziPubblicoCreato ilAzioni
Nessun puzzle trovato.
Puzzle +
+ + +
+
+
+ + +
+

Gestione Utenti

+
+ + - - - - - - + + + - - - - - - - - - - - - - - + + + + + + - - +
IDNomeImmaginePezziPubblicoCreato ilAzioniUsernameEmailRegistrato il
Nessun puzzle trovato.
Puzzle -
- - -
-
Nessun utente trovato.
- - -
-

Gestione Utenti

-
- - - - - - - - - - - - - - - - - - - - - - - - - -
IDUsernameEmailRegistrato il
Nessun utente trovato.
-
-
-
-
-

© Puzzle Game

-
- - \ No newline at end of file +
+ + diff --git a/assets/css/custom.css b/assets/css/custom.css index 95e9a820..b3c1721a 100644 --- a/assets/css/custom.css +++ b/assets/css/custom.css @@ -1,114 +1,193 @@ +/* IMPORT TYPOGRAPHY */ +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Orbitron:wght@400;600;700;900&display=swap'); + +/* PALETTE */ :root { - --bg-slate-900: #0F172A; - --bg-slate-800: #1E293B; - --text-cyan-400: #22D3EE; - --bg-cyan-500: #06B6D4; - --border-slate-700: #334155; - --text-slate-200: #E2E8F0; - --text-slate-400: #94A3B8; + --bg-primary: #0F172A; /* slate-900 - Deep space background */ + --bg-secondary: #1E293B; /* slate-800 - Card backgrounds */ + --accent-primary: #06B6D4; /* cyan-500 - CTAs and highlights */ + --accent-glow: #22D3EE; /* cyan-400 - Hover states */ + --text-primary: #F8FAFC; /* slate-50 - Primary text */ + --text-secondary: #94A3B8; /* slate-400 - Secondary text */ } +/* GENERAL STYLES */ body { - background-color: var(--bg-slate-900); - color: var(--text-slate-200); - font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; + background: var(--bg-primary); + color: var(--text-primary); + font-family: 'Inter', sans-serif; + margin: 0; + padding: 0; } -.navbar { - background-color: rgba(30, 41, 59, 0.8); /* bg-slate-800 with opacity */ - backdrop-filter: blur(10px); - -webkit-backdrop-filter: blur(10px); - border-bottom: 1px solid var(--border-slate-700); +h1, h2, h3, h4, h5, h6 { + font-family: 'Orbitron', sans-serif; + color: var(--accent-primary); + font-weight: 700; } -.puzzle-board { - background-color: var(--bg-slate-900); - border: 2px dashed var(--border-slate-700); - aspect-ratio: 4 / 3; - transition: background-color 0.3s; +a { + color: var(--accent-primary); + text-decoration: none; + transition: color 0.3s ease; } -.pieces-tray { - background-color: var(--bg-slate-800); - border-radius: 0.75rem; - max-height: 80vh; - overflow-y: auto; - border: 1px solid var(--border-slate-700); +a:hover { + color: var(--accent-glow); } -.btn-cyan { - background-color: var(--bg-cyan-500); - color: var(--bg-slate-900); - font-weight: bold; - border: none; - transition: background-color 0.2s; +.btn-primary { + background-color: var(--accent-primary); + border-color: var(--accent-primary); + color: var(--bg-primary) !important; + font-weight: 600; + transition: background-color 0.3s ease, border-color 0.3s ease, transform 0.2s ease; } -.btn-cyan:hover { - background-color: var(--text-cyan-400); - color: var(--bg-slate-900); +.btn-primary:hover { + background-color: var(--accent-glow); + border-color: var(--accent-glow); + transform: translateY(-2px); } -.form-select { - background-color: var(--bg-slate-800); - color: var(--text-slate-200); - border-color: var(--border-slate-700); - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%2394a3b8' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"); -} -.form-select:focus { - background-color: var(--bg-slate-800); - color: var(--text-slate-200); - border-color: var(--text-cyan-400); - box-shadow: 0 0 0 0.25rem rgba(34, 211, 238, 0.25); +.form-control { + background-color: var(--bg-secondary); + border: 1px solid rgba(6, 182, 212, 0.15); + color: var(--text-primary); } -.text-cyan { - color: var(--text-cyan-400); +.form-control:focus { + background-color: var(--bg-secondary); + border-color: var(--accent-primary); + color: var(--text-primary); + box-shadow: 0 0 0 0.2rem rgba(6, 182, 212, 0.25); } -.text-slate-400 { - color: var(--text-slate-400); +/* HEADER */ +header.navbar { + background: rgba(15, 23, 42, 0.95) !important; + backdrop-filter: blur(12px); + border-bottom: 1px solid rgba(6, 182, 212, 0.1); + height: 64px; + position: sticky; + top: 0; + z-index: 1000; } -.rounded-xl { - border-radius: 0.75rem; +.navbar-brand, .nav-link { + color: var(--text-primary) !important; + font-family: 'Orbitron', sans-serif; } -/* --- Gallery --- */ -.gallery-scroll-container { - overflow-x: auto; - scrollbar-width: thin; - scrollbar-color: var(--border-slate-700) var(--bg-slate-900); +.navbar-brand:hover, .nav-link:hover { + color: var(--accent-glow) !important; } -.gallery-scroll-container::-webkit-scrollbar { - height: 8px; +/* MAIN CONTENT */ +main { + background: linear-gradient(135deg, var(--bg-primary) 0%, #131c31 100%); + padding: 40px 24px; + min-height: calc(100vh - 64px); } -.gallery-scroll-container::-webkit-scrollbar-track { - background: var(--bg-slate-900); +/* PUZZLE CARDS */ +.puzzle-gallery .card { + background: rgba(30, 41, 59, 0.7); + backdrop-filter: blur(8px); + border: 1px solid rgba(6, 182, 212, 0.15); + border-radius: 16px; + transition: transform 0.3s ease, box-shadow 0.3s ease; + overflow: hidden; } -.gallery-scroll-container::-webkit-scrollbar-thumb { - background-color: var(--border-slate-700); - border-radius: 10px; - border: 2px solid var(--bg-slate-900); +.puzzle-gallery .card:hover { + transform: translateY(-4px) scale(1.02); + box-shadow: 0 12px 32px rgba(6, 182, 212, 0.25); } -.gallery-item { - display: block; - flex: 0 0 auto; /* Prevent shrinking */ - width: 150px; /* Fixed width for items */ - height: 112px; /* Fixed height for items (4:3 ratio) */ - transition: transform 0.2s ease-in-out; +.card-title { + color: var(--accent-primary); } -.gallery-item:hover { - transform: scale(1.05); +.card-text { + color: var(--text-secondary); } -.gallery-item img { +.card-body{ + background: var(--bg-secondary); +} + +/* LEADERBOARD */ +.leaderboard-sidebar { + background: rgba(30, 41, 59, 0.7); + backdrop-filter: blur(8px); + border: 1px solid rgba(6, 182, 212, 0.15); + border-radius: 16px; + padding: 20px; +} + +.leaderboard-sidebar h3 { + color: var(--accent-primary); + font-family: 'Orbitron', sans-serif; +} + +.leaderboard-sidebar table { width: 100%; - height: 100%; - object-fit: cover; /* Ensure images fill the container */ + color: var(--text-primary); +} + +.leaderboard-sidebar th { + color: var(--accent-primary); + border-bottom: 1px solid rgba(6, 182, 212, 0.15); +} + +.leaderboard-sidebar td { + padding: 8px 4px; + border-bottom: 1px solid rgba(30, 41, 59, 0.5); +} + +/* PUZZLE PAGE */ +#puzzle-container { + border: 2px solid var(--accent-primary); + border-radius: 16px; + overflow: hidden; + box-shadow: 0 8px 24px rgba(6, 182, 212, 0.2); +} + +#piece-container { + border: 2px dashed var(--text-secondary); + border-radius: 16px; + padding: 1rem; + background: rgba(30, 41, 59, 0.5); +} + +.puzzle-piece { + cursor: grab; + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.puzzle-piece:active { + cursor: grabbing; +} + +.puzzle-piece:hover { + transform: scale(1.1); + box-shadow: 0 0 15px var(--accent-glow); +} + +.bg-dark { + background-color: var(--bg-secondary) !important; +} + +.text-white { + color: var(--text-primary) !important; +} + +.border-dark{ + border-color: #06b6d4 !important; +} + +.table-dark { + --bs-table-bg: var(--bg-secondary); + --bs-table-border-color: var(--accent-primary); } \ No newline at end of file diff --git a/includes/footer.php b/includes/footer.php new file mode 100644 index 00000000..78443fcc --- /dev/null +++ b/includes/footer.php @@ -0,0 +1,15 @@ + + +
+ © Photo Puzzle. Creato con ❤️. + + Admin Panel + +
+ + + + + + + diff --git a/includes/header.php b/includes/header.php new file mode 100644 index 00000000..2173c77d --- /dev/null +++ b/includes/header.php @@ -0,0 +1,55 @@ + + + + + + + <?php echo isset($page_title) ? htmlspecialchars($page_title) : 'Photo Puzzle'; ?> + + + + + + + + + + + + diff --git a/index.php b/index.php index facc7e67..53bd590a 100644 --- a/index.php +++ b/index.php @@ -35,10 +35,23 @@ $gallery_images = []; // --- DATA FETCHING --- try { $pdo = db(); + // Fetch puzzles $stmt = $pdo->query("SELECT id, file_name, name FROM puzzles WHERE is_public = 1 OR is_admin_upload = 1 ORDER BY created_at DESC"); $gallery_images = $stmt->fetchAll(PDO::FETCH_ASSOC); + + // Fetch leaderboard + $leaderboard_stmt = $pdo->query(" + SELECT u.username, s.score + FROM scores s + JOIN users u ON s.user_id = u.id + ORDER BY s.score DESC + LIMIT 10 + "); + $leaderboard_scores = $leaderboard_stmt->fetchAll(PDO::FETCH_ASSOC); + } catch (PDOException $e) { - $error_message = "Impossibile caricare la galleria."; + $error_message = "Impossibile caricare i dati della pagina."; + // Optionally log the error: error_log($e->getMessage()); } @@ -108,144 +121,109 @@ if (isset($_SESSION['selected_puzzle'])) { } ?> - - - - - - Photo Puzzle - - - - - - - - - - - - - - - - - - - + -
+
+
+
+ +
+ + - - -
- - -
- -
- -
-
-
-

Tavola del Puzzle

- - -
- - - - Immagine del puzzle caricata - -

Crea un nuovo Puzzle

-

Carica un'immagine per iniziare.

- -
-
- - -
- -
- - -
- -
- - -
- -
- -
-
- + +
+
-
- - - + +
-
+
+ - - - - - - - - - + diff --git a/leaderboard.php b/leaderboard.php index 5bdc32ad..a6af24b6 100644 --- a/leaderboard.php +++ b/leaderboard.php @@ -25,73 +25,46 @@ $stmt = $pdo->query(" "); $scores = $stmt->fetchAll(PDO::FETCH_ASSOC); +$page_title = 'Classifica'; +require_once 'includes/header.php'; ?> - - - - - - Classifica - - - - -
-

Classifica Generale

-
- - +
+

Classifica Generale

+
+
+ + + + + + + + + + + + + - - - - - - - + - - - + + $score): ?> - + + + + + + + - - $score): ?> - - - - - - - - - - - - -
#UtentePuzzlePunteggioTempoMosseData
#UtentePuzzlePunteggioTempoMosseDataNessun punteggio registrato.
Nessun punteggio registrato.s
s
-
+ + + +
+ - - - + \ No newline at end of file diff --git a/login.php b/login.php index 1ee1902b..3e3a85f7 100644 --- a/login.php +++ b/login.php @@ -1,3 +1,4 @@ + - - - - - - Login - - - - -
-

Login

- -
- - - - - Accedi con Google - -
-
- oppure -
-
-
-
- - + +
+
+
+
+

Login

+ +
+ + + + + + Accedi con Google + + +
+
+ oppure +
+
+ + +
+ + +
+
+ + +
+ + + +
+

Non hai un account? Registrati

+
-
- - -
- - -
-

Non hai un account? Registrati

- - \ No newline at end of file +
+ + diff --git a/puzzle.php b/puzzle.php index 5a5042cf..8ebf0152 100644 --- a/puzzle.php +++ b/puzzle.php @@ -120,187 +120,184 @@ if ($puzzle_id > 0) { } else { $error_message = "ID del puzzle non valido."; } + +$page_title = 'Risolvi: ' . ($puzzle ? htmlspecialchars($puzzle['name']) : 'Puzzle'); +require_once 'includes/header.php'; ?> - - - - - - Risolvi: <?php echo $puzzle ? htmlspecialchars($puzzle['name']) : 'Puzzle'; ?> - - - - - -
-

Complimenti!

-

Hai risolto il puzzle!

-

Punteggio: 0

- Classifica - Gioca Ancora + + + +
+

Complimenti!

+

Hai risolto il puzzle!

+

Punteggio: 0

+ Classifica + Gioca Ancora +
+ +
+
+

+
+ Torna alla Galleria + Tempo: 0s + Mosse: 0 +
-
-
-

-
- Torna alla Galleria - Tempo: 0s - Mosse: 0 -
+ +
+ +
+
+ + + +
- -
- -
-
- - - -
+
+
+
- -
-
-
-
-
-

I Tuoi Pezzi

-
+
+
+

I Tuoi Pezzi

+
Pezzo del puzzle
- -
+
+ +
- - - + + pieces.forEach(piece => { + const match = piece.src.match(/piece_(\d+)_(\d+)\.jpg$/); + if (match) { piece.dataset.position = `${match[1]}-${match[2]}`; } + + piece.addEventListener('dragstart', e => { + draggedPiece = e.target; + setTimeout(() => { e.target.style.opacity = '0.5'; }, 0); + }); + + piece.addEventListener('dragend', e => { + draggedPiece = null; + e.target.style.opacity = '1'; + }); + }); + + function checkWin() { + const dropZones = board.querySelectorAll('.drop-zone'); + if ([...dropZones].every(zone => + zone.children.length > 0 && + zone.children[0].dataset.position === zone.dataset.position + )) { + clearInterval(timerInterval); + const timeTaken = Math.floor((Date.now() - startTime) / 1000); + + const formData = new FormData(); + formData.append('action', 'save_score'); + formData.append('puzzle_id', puzzleId); + formData.append('time_taken', timeTaken); + formData.append('moves', moves); + + fetch('puzzle.php', { + method: 'POST', + body: formData + }) + .then(response => response.json()) + .then(data => { + if (data.success) { + document.getElementById('final-score').textContent = data.score; + document.getElementById('win-message').style.display = 'block'; + board.style.borderColor = 'var(--mavi-orange)'; + } else { + console.error('Failed to save score:', data.error); + alert('Si è verificato un errore durante il salvataggio del punteggio.'); + } + }); + } + } +}); + + + \ No newline at end of file diff --git a/register.php b/register.php index 697bdbb1..a22e729c 100644 --- a/register.php +++ b/register.php @@ -38,67 +38,55 @@ if ($_SERVER['REQUEST_METHOD'] == 'POST') { } } } + +$page_title = 'Registrazione'; +require_once 'includes/header.php'; ?> - - - - - - Registrazione - - - - -
-
-

Registrazione

- -
- - -
- - - - - Registrati con Google - -
-
- oppure -
-
-
-
- - + +
+
+
+
+

Registrazione

+ +
+ + +
+ + + + + + Registrati con Google + +
+
+ oppure +
-
- - + + +
+ + +
+
+ + +
+
+ + +
+ + +
+

Hai già un account? Accedi

-
- - -
- - -
-

Hai già un account? Accedi

- - +
+ + \ No newline at end of file