Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c26ea67559 |
32
admin/includes/leaderboard_functions.php
Normal file
32
admin/includes/leaderboard_functions.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
// admin/includes/leaderboard_functions.php
|
||||
|
||||
/**
|
||||
* Fetches leaderboard data by joining quiz_attempts and quiz_categories.
|
||||
*
|
||||
* @param int $limit The maximum number of records to return.
|
||||
* @return array An array of associative arrays, each representing a leaderboard entry.
|
||||
*/
|
||||
function get_leaderboard_data($limit = 100) {
|
||||
$db = db_connect();
|
||||
$sql = "
|
||||
SELECT
|
||||
qa.player_name,
|
||||
qc.name as category_name,
|
||||
qa.score,
|
||||
qa.total_questions,
|
||||
qa.attempt_date
|
||||
FROM
|
||||
quiz_attempts qa
|
||||
JOIN
|
||||
quiz_categories qc ON qa.category_id = qc.id
|
||||
ORDER BY
|
||||
qa.score DESC, qa.attempt_date DESC
|
||||
LIMIT :limit
|
||||
";
|
||||
$stmt = $db->prepare($sql);
|
||||
$stmt->bindParam(':limit', $limit, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
?>
|
||||
44
admin/includes/missions_functions.php
Normal file
44
admin/includes/missions_functions.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
// admin/includes/missions_functions.php
|
||||
|
||||
|
||||
|
||||
function get_all_missions() {
|
||||
$db = db_connect();
|
||||
$stmt = $db->prepare("SELECT * FROM missions ORDER BY id DESC");
|
||||
$stmt->execute();
|
||||
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
function get_mission_by_id($id) {
|
||||
$db = db_connect();
|
||||
$stmt = $db->prepare("SELECT * FROM missions WHERE id = :id");
|
||||
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
return $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
function add_mission($title, $description) {
|
||||
$db = db_connect();
|
||||
$stmt = $db->prepare("INSERT INTO missions (title, description) VALUES (:title, :description)");
|
||||
$stmt->bindParam(':title', $title, PDO::PARAM_STR);
|
||||
$stmt->bindParam(':description', $description, PDO::PARAM_STR);
|
||||
return $stmt->execute();
|
||||
}
|
||||
|
||||
function update_mission($id, $title, $description) {
|
||||
$db = db_connect();
|
||||
$stmt = $db->prepare("UPDATE missions SET title = :title, description = :description WHERE id = :id");
|
||||
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
|
||||
$stmt->bindParam(':title', $title, PDO::PARAM_STR);
|
||||
$stmt->bindParam(':description', $description, PDO::PARAM_STR);
|
||||
return $stmt->execute();
|
||||
}
|
||||
|
||||
function delete_mission($id) {
|
||||
$db = db_connect();
|
||||
$stmt = $db->prepare("DELETE FROM missions WHERE id = :id");
|
||||
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
|
||||
return $stmt->execute();
|
||||
}
|
||||
|
||||
151
admin/includes/questions_functions.php
Normal file
151
admin/includes/questions_functions.php
Normal file
@ -0,0 +1,151 @@
|
||||
<?php
|
||||
// admin/includes/questions_functions.php
|
||||
|
||||
/**
|
||||
* Fetches a single quiz category by its ID to get its name.
|
||||
*
|
||||
* @param int $id The ID of the category.
|
||||
* @return array|false The category data or false if not found.
|
||||
*/
|
||||
function get_quiz_category_name($id) {
|
||||
$db = db_connect();
|
||||
$stmt = $db->prepare("SELECT name FROM quiz_categories WHERE id = :id");
|
||||
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
return $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches all questions for a given quiz ID.
|
||||
*
|
||||
* @param int $quiz_id The ID of the quiz category.
|
||||
* @return array An array of questions.
|
||||
*/
|
||||
function get_questions_by_quiz_id($quiz_id) {
|
||||
$db = db_connect();
|
||||
$stmt = $db->prepare("SELECT * FROM questions WHERE category_id = :quiz_id ORDER BY id ASC");
|
||||
$stmt->bindParam(':quiz_id', $quiz_id, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches all answers for a given question ID.
|
||||
*
|
||||
* @param int $question_id The ID of the question.
|
||||
* @return array An array of answers.
|
||||
*/
|
||||
function get_answers_by_question_id($question_id) {
|
||||
$db = db_connect();
|
||||
$stmt = $db->prepare("SELECT * FROM answers WHERE question_id = :question_id ORDER BY id ASC");
|
||||
$stmt->bindParam(':question_id', $question_id, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a question and its associated answers.
|
||||
*
|
||||
* @param int $id The ID of the question to delete.
|
||||
* @return bool True on success, false on failure.
|
||||
*/
|
||||
function delete_question($id) {
|
||||
$db = db_connect();
|
||||
// The database should handle answer deletion via ON DELETE CASCADE foreign key
|
||||
$stmt = $db->prepare("DELETE FROM questions WHERE id = :id");
|
||||
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
|
||||
return $stmt->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new question and its answers to the database.
|
||||
*
|
||||
* @param int $quiz_id The ID of the quiz category.
|
||||
* @param string $question_text The text of the question.
|
||||
* @param array $answers An array of answers, where each answer is an array with 'text' and 'is_correct' keys.
|
||||
* @return bool True on success, false on failure.
|
||||
*/
|
||||
function add_question($quiz_id, $question_text, $answers) {
|
||||
$db = db_connect();
|
||||
try {
|
||||
$db->beginTransaction();
|
||||
|
||||
// Insert the question
|
||||
$stmt = $db->prepare("INSERT INTO questions (category_id, question_text) VALUES (:quiz_id, :question_text)");
|
||||
$stmt->bindParam(':quiz_id', $quiz_id, PDO::PARAM_INT);
|
||||
$stmt->bindParam(':question_text', $question_text, PDO::PARAM_STR);
|
||||
$stmt->execute();
|
||||
$question_id = $db->lastInsertId();
|
||||
|
||||
// Insert the answers
|
||||
$stmt = $db->prepare("INSERT INTO answers (question_id, answer_text, is_correct) VALUES (:question_id, :answer_text, :is_correct)");
|
||||
foreach ($answers as $answer) {
|
||||
$stmt->bindParam(':question_id', $question_id, PDO::PARAM_INT);
|
||||
$stmt->bindParam(':answer_text', $answer['text'], PDO::PARAM_STR);
|
||||
$stmt->bindParam(':is_correct', $answer['is_correct'], PDO::PARAM_BOOL);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
$db->commit();
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
$db->rollBack();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a single question by its ID for editing.
|
||||
*
|
||||
* @param int $id The ID of the question.
|
||||
* @return array|false The question data or false if not found.
|
||||
*/
|
||||
function get_question($id) {
|
||||
$db = db_connect();
|
||||
$stmt = $db->prepare("SELECT * FROM questions WHERE id = :id");
|
||||
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
return $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a question and its answers.
|
||||
*
|
||||
* @param int $question_id The ID of the question to update.
|
||||
* @param string $question_text The new text of the question.
|
||||
* @param array $answers An array of answers to update/insert.
|
||||
* @return bool
|
||||
*/
|
||||
function update_question($question_id, $question_text, $answers) {
|
||||
$db = db_connect();
|
||||
try {
|
||||
$db->beginTransaction();
|
||||
|
||||
// Update question text
|
||||
$stmt = $db->prepare("UPDATE questions SET question_text = :question_text WHERE id = :id");
|
||||
$stmt->bindParam(':question_text', $question_text, PDO::PARAM_STR);
|
||||
$stmt->bindParam(':id', $question_id, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
|
||||
// Delete old answers
|
||||
$stmt = $db->prepare("DELETE FROM answers WHERE question_id = :question_id");
|
||||
$stmt->bindParam(':question_id', $question_id, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
|
||||
// Insert new answers
|
||||
$stmt = $db->prepare("INSERT INTO answers (question_id, answer_text, is_correct) VALUES (:question_id, :answer_text, :is_correct)");
|
||||
foreach ($answers as $answer) {
|
||||
$stmt->bindParam(':question_id', $question_id, PDO::PARAM_INT);
|
||||
$stmt->bindParam(':answer_text', $answer['text'], PDO::PARAM_STR);
|
||||
$stmt->bindParam(':is_correct', $answer['is_correct'], PDO::PARAM_BOOL);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
$db->commit();
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
$db->rollBack();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
?>
|
||||
75
admin/includes/quizzes_functions.php
Normal file
75
admin/includes/quizzes_functions.php
Normal file
@ -0,0 +1,75 @@
|
||||
<?php
|
||||
// admin/includes/quizzes_functions.php
|
||||
|
||||
/**
|
||||
* Fetches all quiz categories from the database.
|
||||
*
|
||||
* @return array An array of associative arrays, each representing a category.
|
||||
*/
|
||||
function get_all_quiz_categories() {
|
||||
$db = db_connect();
|
||||
$stmt = $db->prepare("SELECT * FROM quiz_categories ORDER BY name ASC");
|
||||
$stmt->execute();
|
||||
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a single quiz category by its ID.
|
||||
*
|
||||
* @param int $id The ID of the category.
|
||||
* @return array|false The category data or false if not found.
|
||||
*/
|
||||
function get_quiz_category_by_id($id) {
|
||||
$db = db_connect();
|
||||
$stmt = $db->prepare("SELECT * FROM quiz_categories WHERE id = :id");
|
||||
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
return $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new quiz category to the database.
|
||||
*
|
||||
* @param string $name The name of the category.
|
||||
* @param string $description The description of the category.
|
||||
* @return bool True on success, false on failure.
|
||||
*/
|
||||
function add_quiz_category($name, $description) {
|
||||
$db = db_connect();
|
||||
$stmt = $db->prepare("INSERT INTO quiz_categories (name, description) VALUES (:name, :description)");
|
||||
$stmt->bindParam(':name', $name, PDO::PARAM_STR);
|
||||
$stmt->bindParam(':description', $description, PDO::PARAM_STR);
|
||||
return $stmt->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an existing quiz category.
|
||||
*
|
||||
* @param int $id The ID of the category to update.
|
||||
* @param string $name The new name.
|
||||
* @param string $description The new description.
|
||||
* @return bool True on success, false on failure.
|
||||
*/
|
||||
function update_quiz_category($id, $name, $description) {
|
||||
$db = db_connect();
|
||||
$stmt = $db->prepare("UPDATE quiz_categories SET name = :name, description = :description WHERE id = :id");
|
||||
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
|
||||
$stmt->bindParam(':name', $name, PDO::PARAM_STR);
|
||||
$stmt->bindParam(':description', $description, PDO::PARAM_STR);
|
||||
return $stmt->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a quiz category from the database.
|
||||
*
|
||||
* @param int $id The ID of the category to delete.
|
||||
* @return bool True on success, false on failure.
|
||||
*/
|
||||
function delete_quiz_category($id) {
|
||||
$db = db_connect();
|
||||
$stmt = $db->prepare("DELETE FROM quiz_categories WHERE id = :id");
|
||||
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
|
||||
return $stmt->execute();
|
||||
}
|
||||
|
||||
?>
|
||||
49
admin/index.php
Normal file
49
admin/index.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
// admin/index.php
|
||||
|
||||
// --- Basic Routing ---
|
||||
$page = $_GET['page'] ?? 'missions';
|
||||
$allowed_pages = ['missions', 'quizzes', 'leaderboard', 'questions'];
|
||||
|
||||
if (!in_array($page, $allowed_pages)) {
|
||||
$page = 'missions'; // Default to missions if page is not allowed
|
||||
}
|
||||
|
||||
// --- Include necessary files ---
|
||||
// General functions that are always needed
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
|
||||
// Page-specific functions
|
||||
if ($page === 'missions') {
|
||||
require_once __DIR__ . '/includes/missions_functions.php';
|
||||
} elseif ($page === 'quizzes') {
|
||||
require_once __DIR__ . '/includes/quizzes_functions.php';
|
||||
} elseif ($page === 'leaderboard') {
|
||||
require_once __DIR__ . '/includes/leaderboard_functions.php';
|
||||
} elseif ($page === 'questions') {
|
||||
require_once __DIR__ . '/includes/questions_functions.php';
|
||||
}
|
||||
|
||||
|
||||
// --- Set Page Title ---
|
||||
$page_title = ucfirst($page) . ' Management';
|
||||
|
||||
|
||||
// --- Include Header ---
|
||||
include __DIR__ . '/partials/header.php';
|
||||
|
||||
|
||||
// --- Include Page Content ---
|
||||
$page_path = __DIR__ . '/pages/' . $page . '.php';
|
||||
if (file_exists($page_path)) {
|
||||
include $page_path;
|
||||
} else {
|
||||
// Fallback for missing page files
|
||||
echo "<div class='alert alert-danger'>Content file not found for this page.</div>";
|
||||
}
|
||||
|
||||
|
||||
// --- Include Footer ---
|
||||
include __DIR__ . '/partials/footer.php';
|
||||
|
||||
?>
|
||||
39
admin/pages/leaderboard.php
Normal file
39
admin/pages/leaderboard.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
// admin/pages/leaderboard.php
|
||||
|
||||
$leaderboard_entries = get_leaderboard_data();
|
||||
|
||||
?>
|
||||
|
||||
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
||||
<h1 class="h2">Leaderboard</h1>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Giocatore</th>
|
||||
<th>Categoria</th>
|
||||
<th>Punteggio</th>
|
||||
<th>Data</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (empty($leaderboard_entries)): ?>
|
||||
<tr>
|
||||
<td colspan="4">Nessun risultato trovato.</td>
|
||||
</tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($leaderboard_entries as $entry): ?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($entry['player_name']); ?></td>
|
||||
<td><?php echo htmlspecialchars($entry['category_name']); ?></td>
|
||||
<td><?php echo htmlspecialchars($entry['score']); ?> / <?php echo htmlspecialchars($entry['total_questions']); ?></td>
|
||||
<td><?php echo htmlspecialchars(date('d/m/Y H:i', strtotime($entry['attempt_date']))); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
116
admin/pages/missions.php
Normal file
116
admin/pages/missions.php
Normal file
@ -0,0 +1,116 @@
|
||||
<?php
|
||||
// admin/pages/missions.php
|
||||
|
||||
$action = $_GET['action'] ?? 'list';
|
||||
$id = $_GET['id'] ?? null;
|
||||
|
||||
// Handle POST requests for add/edit
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$title = $_POST['title'] ?? '';
|
||||
$description = $_POST['description'] ?? '';
|
||||
$id = $_POST['id'] ?? null;
|
||||
|
||||
if ($action === 'add') {
|
||||
add_mission($title, $description);
|
||||
} elseif ($action === 'edit') {
|
||||
update_mission($id, $title, $description);
|
||||
}
|
||||
|
||||
// Redirect to the list view after submission
|
||||
header('Location: index.php?page=missions');
|
||||
exit;
|
||||
}
|
||||
|
||||
// Handle delete action
|
||||
if ($action === 'delete' && $id) {
|
||||
delete_mission($id);
|
||||
header('Location: index.php?page=missions');
|
||||
exit;
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
||||
<h1 class="h2"><?php
|
||||
if ($action === 'add') echo 'Aggiungi Nuova Missione';
|
||||
elseif ($action === 'edit') echo 'Modifica Missione';
|
||||
else echo 'Gestione Missioni';
|
||||
?></h1>
|
||||
<div class="btn-toolbar mb-2 mb-md-0">
|
||||
<a href="index.php?page=missions" class="btn btn-sm btn-outline-secondary">
|
||||
<span data-feather="arrow-left"></span>
|
||||
Torna alla Lista
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ($action === 'add' || $action === 'edit'): ?>
|
||||
<?php
|
||||
$mission = null;
|
||||
if ($action === 'edit' && $id) {
|
||||
$mission = get_mission_by_id($id);
|
||||
}
|
||||
?>
|
||||
<form method="POST" action="index.php?page=missions&action=<?php echo $action; ?>">
|
||||
<?php if ($id): ?>
|
||||
<input type="hidden" name="id" value="<?php echo htmlspecialchars($id); ?>">
|
||||
<?php endif; ?>
|
||||
<div class="mb-3">
|
||||
<label for="title" class="form-label">Titolo Missione</label>
|
||||
<input type="text" class="form-control" id="title" name="title" value="<?php echo htmlspecialchars($mission['title'] ?? ''); ?>" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="description" class="form-label">Descrizione</label>
|
||||
<textarea class="form-control" id="description" name="description" rows="3"><?php echo htmlspecialchars($mission['description'] ?? ''); ?></textarea>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<?php echo $action === 'edit' ? 'Salva Modifiche' : 'Aggiungi Missione'; ?>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<?php else: // 'list' action ?>
|
||||
<div class="d-flex justify-content-end mb-3">
|
||||
<a href="index.php?page=missions&action=add" class="btn btn-sm btn-outline-primary">
|
||||
<span data-feather="plus"></span>
|
||||
Aggiungi Missione
|
||||
</a>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Titolo</th>
|
||||
<th>Descrizione</th>
|
||||
<th>Azioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php $missions = get_all_missions(); ?>
|
||||
<?php if (empty($missions)): ?>
|
||||
<tr>
|
||||
<td colspan="4">Nessuna missione trovata.</td>
|
||||
</tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($missions as $mission): ?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($mission['id']); ?></td>
|
||||
<td><?php echo htmlspecialchars($mission['title']); ?></td>
|
||||
<td><?php echo htmlspecialchars($mission['description']); ?></td>
|
||||
<td>
|
||||
<a href="index.php?page=missions&action=edit&id=<?php echo $mission['id']; ?>" class="btn btn-sm btn-outline-secondary">
|
||||
<span data-feather="edit-2"></span>
|
||||
Modifica
|
||||
</a>
|
||||
<a href="index.php?page=missions&action=delete&id=<?php echo $mission['id']; ?>" class="btn btn-sm btn-outline-danger" onclick="return confirm('Sei sicuro di voler eliminare questa missione?');">
|
||||
<span data-feather="trash-2"></span>
|
||||
Elimina
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
153
admin/pages/questions.php
Normal file
153
admin/pages/questions.php
Normal file
@ -0,0 +1,153 @@
|
||||
<?php
|
||||
// admin/pages/questions.php
|
||||
|
||||
$quiz_id = $_GET['quiz_id'] ?? null;
|
||||
$action = $_GET['action'] ?? 'list';
|
||||
$id = $_GET['id'] ?? null;
|
||||
|
||||
if (!$quiz_id) {
|
||||
echo "<div class='alert alert-danger'>ID Quiz non specificato.</div>";
|
||||
return;
|
||||
}
|
||||
|
||||
$quiz_category = get_quiz_category_name($quiz_id);
|
||||
if (!$quiz_category) {
|
||||
echo "<div class='alert alert-danger'>Categoria Quiz non trovata.</div>";
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle POST requests for add/edit
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$question_text = $_POST['question_text'] ?? '';
|
||||
$answers_post = $_POST['answers'] ?? [];
|
||||
$correct_answer_index = $_POST['correct_answer'] ?? -1;
|
||||
$id = $_POST['id'] ?? null;
|
||||
|
||||
$answers = [];
|
||||
foreach ($answers_post as $index => $text) {
|
||||
if (!empty($text)) {
|
||||
$answers[] = [
|
||||
'text' => $text,
|
||||
'is_correct' => ($index == $correct_answer_index)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if ($action === 'add') {
|
||||
add_question($quiz_id, $question_text, $answers);
|
||||
} elseif ($action === 'edit') {
|
||||
update_question($id, $question_text, $answers);
|
||||
}
|
||||
|
||||
// Redirect to the list view after submission
|
||||
header('Location: index.php?page=questions&quiz_id=' . $quiz_id);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Handle delete action
|
||||
if ($action === 'delete' && $id) {
|
||||
delete_question($id);
|
||||
header('Location: index.php?page=questions&quiz_id=' . $quiz_id);
|
||||
exit;
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
||||
<h1 class="h2">Domande per: <?php echo htmlspecialchars($quiz_category['name']); ?></h1>
|
||||
<div class="btn-toolbar mb-2 mb-md-0">
|
||||
<a href="index.php?page=quizzes" class="btn btn-sm btn-outline-secondary">
|
||||
<span data-feather="arrow-left"></span>
|
||||
Torna alle Categorie
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ($action === 'add' || $action === 'edit'): ?>
|
||||
<?php
|
||||
$question = null;
|
||||
$answers = [['text'=>'', 'is_correct'=>true], ['text'=>'', 'is_correct'=>false], ['text'=>'', 'is_correct'=>false], ['text'=>'', 'is_correct'=>false]];
|
||||
if ($action === 'edit' && $id) {
|
||||
$question = get_question($id);
|
||||
$db_answers = get_answers_by_question_id($id);
|
||||
$answers = [];
|
||||
foreach($db_answers as $ans) {
|
||||
$answers[] = ['text' => $ans['answer_text'], 'is_correct' => $ans['is_correct']];
|
||||
}
|
||||
// ensure we have 4 answers to show in the form
|
||||
while(count($answers) < 4) {
|
||||
$answers[] = ['text' => '', 'is_correct' => false];
|
||||
}
|
||||
}
|
||||
?>
|
||||
<form method="POST" action="index.php?page=questions&quiz_id=<?php echo $quiz_id; ?>&action=<?php echo $action; ?>">
|
||||
<?php if ($id): ?>
|
||||
<input type="hidden" name="id" value="<?php echo htmlspecialchars($id); ?>">
|
||||
<?php endif; ?>
|
||||
<div class="mb-3">
|
||||
<label for="question_text" class="form-label">Testo della Domanda</label>
|
||||
<textarea class="form-control" id="question_text" name="question_text" rows="3" required><?php echo htmlspecialchars($question['question_text'] ?? ''); ?></textarea>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Risposte (la prima selezionata è quella corretta)</label>
|
||||
<?php for ($i = 0; $i < 4; $i++): ?>
|
||||
<div class="input-group mb-2">
|
||||
<div class="input-group-text">
|
||||
<input class="form-check-input mt-0" type="radio" name="correct_answer" value="<?php echo $i; ?>" <?php if($answers[$i]['is_correct']) echo 'checked'; ?>>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="answers[]" value="<?php echo htmlspecialchars($answers[$i]['text'] ?? ''); ?>" required>
|
||||
</div>
|
||||
<?php endfor; ?>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<?php echo $action === 'edit' ? 'Salva Modifiche' : 'Aggiungi Domanda'; ?>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<?php else: // 'list' action ?>
|
||||
<div class="d-flex justify-content-end mb-3">
|
||||
<a href="index.php?page=questions&quiz_id=<?php echo $quiz_id; ?>&action=add" class="btn btn-sm btn-outline-primary">
|
||||
<span data-feather="plus"></span>
|
||||
Aggiungi Domanda
|
||||
</a>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Testo della Domanda</th>
|
||||
<th>Azioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php $questions = get_questions_by_quiz_id($quiz_id); ?>
|
||||
<?php if (empty($questions)):
|
||||
?>
|
||||
<tr>
|
||||
<td colspan="3">Nessuna domanda trovata per questo quiz.</td>
|
||||
</tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($questions as $question): ?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($question['id']); ?></td>
|
||||
<td><?php echo htmlspecialchars($question['question_text']); ?></td>
|
||||
<td>
|
||||
<a href="index.php?page=questions&quiz_id=<?php echo $quiz_id; ?>&action=edit&id=<?php echo $question['id']; ?>" class="btn btn-sm btn-outline-secondary">
|
||||
<span data-feather="edit-2"></span>
|
||||
Modifica
|
||||
</a>
|
||||
<a href="index.php?page=questions&quiz_id=<?php echo $quiz_id; ?>&action=delete&id=<?php echo $question['id']; ?>" class="btn btn-sm btn-outline-danger" onclick="return confirm('Sei sicuro di voler eliminare questa domanda?');">
|
||||
<span data-feather="trash-2"></span>
|
||||
Elimina
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
120
admin/pages/quizzes.php
Normal file
120
admin/pages/quizzes.php
Normal file
@ -0,0 +1,120 @@
|
||||
<?php
|
||||
// admin/pages/quizzes.php
|
||||
|
||||
$action = $_GET['action'] ?? 'list';
|
||||
$id = $_GET['id'] ?? null;
|
||||
|
||||
// Handle POST requests for add/edit
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$name = $_POST['name'] ?? '';
|
||||
$description = $_POST['description'] ?? '';
|
||||
$id = $_POST['id'] ?? null;
|
||||
|
||||
if ($action === 'add') {
|
||||
add_quiz_category($name, $description);
|
||||
} elseif ($action === 'edit') {
|
||||
update_quiz_category($id, $name, $description);
|
||||
}
|
||||
|
||||
// Redirect to the list view after submission
|
||||
header('Location: index.php?page=quizzes');
|
||||
exit;
|
||||
}
|
||||
|
||||
// Handle delete action
|
||||
if ($action === 'delete' && $id) {
|
||||
delete_quiz_category($id);
|
||||
header('Location: index.php?page=quizzes');
|
||||
exit;
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
||||
<h1 class="h2"><?php
|
||||
if ($action === 'add') echo 'Aggiungi Nuova Categoria';
|
||||
elseif ($action === 'edit') echo 'Modifica Categoria';
|
||||
else echo 'Gestione Quiz';
|
||||
?></h1>
|
||||
<div class="btn-toolbar mb-2 mb-md-0">
|
||||
<a href="index.php?page=quizzes" class="btn btn-sm btn-outline-secondary">
|
||||
<span data-feather="arrow-left"></span>
|
||||
Torna alla Lista
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ($action === 'add' || $action === 'edit'): ?>
|
||||
<?php
|
||||
$category = null;
|
||||
if ($action === 'edit' && $id) {
|
||||
$category = get_quiz_category_by_id($id);
|
||||
}
|
||||
?>
|
||||
<form method="POST" action="index.php?page=quizzes&action=<?php echo $action; ?>">
|
||||
<?php if ($id): ?>
|
||||
<input type="hidden" name="id" value="<?php echo htmlspecialchars($id); ?>">
|
||||
<?php endif; ?>
|
||||
<div class="mb-3">
|
||||
<label for="name" class="form-label">Nome Categoria</label>
|
||||
<input type="text" class="form-control" id="name" name="name" value="<?php echo htmlspecialchars($category['name'] ?? ''); ?>" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="description" class="form-label">Descrizione</label>
|
||||
<textarea class="form-control" id="description" name="description" rows="3"><?php echo htmlspecialchars($category['description'] ?? ''); ?></textarea>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<?php echo $action === 'edit' ? 'Salva Modifiche' : 'Aggiungi Categoria'; ?>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<?php else: // 'list' action ?>
|
||||
<div class="d-flex justify-content-end mb-3">
|
||||
<a href="index.php?page=quizzes&action=add" class="btn btn-sm btn-outline-primary">
|
||||
<span data-feather="plus"></span>
|
||||
Aggiungi Categoria
|
||||
</a>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Nome</th>
|
||||
<th>Descrizione</th>
|
||||
<th>Azioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php $categories = get_all_quiz_categories(); ?>
|
||||
<?php if (empty($categories)): ?>
|
||||
<tr>
|
||||
<td colspan="4">Nessuna categoria trovata.</td>
|
||||
</tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($categories as $category): ?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($category['id']); ?></td>
|
||||
<td><?php echo htmlspecialchars($category['name']); ?></td>
|
||||
<td><?php echo htmlspecialchars($category['description']); ?></td>
|
||||
<td>
|
||||
<a href="index.php?page=questions&quiz_id=<?php echo $category['id']; ?>" class="btn btn-sm btn-outline-info">
|
||||
<span data-feather="help-circle"></span>
|
||||
Domande
|
||||
</a>
|
||||
<a href="index.php?page=quizzes&action=edit&id=<?php echo $category['id']; ?>" class="btn btn-sm btn-outline-secondary">
|
||||
<span data-feather="edit-2"></span>
|
||||
Modifica
|
||||
</a>
|
||||
<a href="index.php?page=quizzes&action=delete&id=<?php echo $category['id']; ?>" class="btn btn-sm btn-outline-danger" onclick="return confirm('Sei sicuro di voler eliminare questa categoria?');">
|
||||
<span data-feather="trash-2"></span>
|
||||
Elimina
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
10
admin/partials/footer.php
Normal file
10
admin/partials/footer.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
// admin/partials/footer.php
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
45
admin/partials/header.php
Normal file
45
admin/partials/header.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
// admin/partials/header.php
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>MAVI Admin</title>
|
||||
<link href="../assets/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="../assets/css/custom.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="admin-wrapper">
|
||||
<!-- Sidebar -->
|
||||
<nav id="sidebar">
|
||||
<div class="sidebar-header">
|
||||
<h3>MAVI Admin</h3>
|
||||
</div>
|
||||
|
||||
<ul class="list-unstyled components">
|
||||
<p>Content Management</p>
|
||||
<li class="<?php echo ($page === 'missions') ? 'active' : ''; ?>">
|
||||
<a href="index.php?page=missions">Missions</a>
|
||||
</li>
|
||||
<li class="<?php echo ($page === 'quizzes') ? 'active' : ''; ?>">
|
||||
<a href="index.php?page=quizzes">Quizzes</a>
|
||||
</li>
|
||||
<li class="<?php echo ($page === 'leaderboard') ? 'active' : ''; ?>">
|
||||
<a href="index.php?page=leaderboard">Leaderboard</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="list-unstyled ct-action">
|
||||
<li><a href="/" class="article">Back to Public Site</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<!-- Page Content -->
|
||||
<div id="content">
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-light mb-4">
|
||||
<div class="container-fluid">
|
||||
<h4><?php echo $page_title ?? 'Dashboard'; ?></h4>
|
||||
</div>
|
||||
</nav>
|
||||
6
assets/css/bootstrap.min.css
vendored
Normal file
6
assets/css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
72
assets/css/custom.css
Normal file
72
assets/css/custom.css
Normal file
@ -0,0 +1,72 @@
|
||||
/* assets/css/custom.css */
|
||||
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&display=swap');
|
||||
|
||||
body {
|
||||
font-family: 'Poppins', sans-serif;
|
||||
background-color: #F8F9FA;
|
||||
}
|
||||
|
||||
.admin-wrapper {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#sidebar {
|
||||
min-width: 250px;
|
||||
max-width: 250px;
|
||||
background: #2E7D32;
|
||||
color: #fff;
|
||||
transition: all 0.3s;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
#sidebar .sidebar-header {
|
||||
padding: 20px;
|
||||
background: #256828;
|
||||
}
|
||||
|
||||
#sidebar ul.components {
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
#sidebar ul p {
|
||||
color: #fff;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#sidebar ul li a {
|
||||
padding: 10px;
|
||||
font-size: 1.1em;
|
||||
display: block;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#sidebar ul li a:hover {
|
||||
background: #256828;
|
||||
}
|
||||
|
||||
#sidebar ul li.active > a,
|
||||
a[aria-expanded="true"] {
|
||||
background: #256828;
|
||||
}
|
||||
|
||||
#content {
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 0.5rem;
|
||||
border: none;
|
||||
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: #2E7D32;
|
||||
border-color: #2E7D32;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background-color: #256828;
|
||||
border-color: #256828;
|
||||
}
|
||||
BIN
assets/pasted-20250925-232847-81fff1ea.png
Normal file
BIN
assets/pasted-20250925-232847-81fff1ea.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
BIN
assets/vm-shot-2025-09-25T23-30-09-002Z.jpg
Normal file
BIN
assets/vm-shot-2025-09-25T23-30-09-002Z.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
@ -1,17 +1,48 @@
|
||||
<?php
|
||||
// Generated by setup_mariadb_project.sh — edit as needed.
|
||||
define('DB_HOST', '127.0.0.1');
|
||||
define('DB_NAME', 'app_30903');
|
||||
define('DB_USER', 'app_30903');
|
||||
define('DB_PASS', '7d2d5a2d-6e5e-4580-a9b7-3f8e7288a494');
|
||||
// db/config.php
|
||||
|
||||
function db() {
|
||||
static $pdo;
|
||||
if (!$pdo) {
|
||||
$pdo = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset=utf8mb4', DB_USER, DB_PASS, [
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
||||
]);
|
||||
}
|
||||
return $pdo;
|
||||
function db_connect() {
|
||||
static $pdo;
|
||||
|
||||
if ($pdo) {
|
||||
return $pdo;
|
||||
}
|
||||
|
||||
$host = '127.0.0.1';
|
||||
$db = 'app';
|
||||
$user = 'root';
|
||||
$pass = '';
|
||||
$charset = 'utf8mb4';
|
||||
|
||||
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
|
||||
$options = [
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
||||
PDO::ATTR_EMULATE_PREPARES => false,
|
||||
];
|
||||
|
||||
try {
|
||||
$pdo = new PDO($dsn, $user, $pass, $options);
|
||||
return $pdo;
|
||||
} catch (\PDOException $e) {
|
||||
// In a real app, log this error and show a generic message
|
||||
throw new \PDOException($e->getMessage(), (int)$e->getCode());
|
||||
}
|
||||
}
|
||||
|
||||
function run_migrations() {
|
||||
$pdo = db_connect();
|
||||
$migration_dir = __DIR__ . '/migrations';
|
||||
$files = glob($migration_dir . '/*.sql');
|
||||
sort($files);
|
||||
|
||||
foreach ($files as $file) {
|
||||
try {
|
||||
$sql = file_get_contents($file);
|
||||
$pdo->exec($sql);
|
||||
} catch (\PDOException $e) {
|
||||
// Log error if needed, but continue
|
||||
// This might happen if the table already exists, which is fine for idempotent scripts
|
||||
}
|
||||
}
|
||||
}
|
||||
12
db/migrations/001_initial_schema.sql
Normal file
12
db/migrations/001_initial_schema.sql
Normal file
@ -0,0 +1,12 @@
|
||||
CREATE TABLE IF NOT EXISTS `missions` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`title` VARCHAR(255) NOT NULL,
|
||||
`description` TEXT,
|
||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Insert some dummy data for initial view
|
||||
INSERT INTO `missions` (`title`, `description`) VALUES
|
||||
('The Faces of Lacedonia', 'Explore the portraits of 1957 and learn the stories of the people.'),
|
||||
('A Journey Through Time', 'Compare the Lacedonia of the past with the town of today.'),
|
||||
('Artisans and Crafts', 'Discover the traditional crafts and tools used by the people of Irpinia.');
|
||||
54
db/migrations/002_create_quiz_tables.sql
Normal file
54
db/migrations/002_create_quiz_tables.sql
Normal file
@ -0,0 +1,54 @@
|
||||
-- Create categories table
|
||||
CREATE TABLE IF NOT EXISTS `categories` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`name` VARCHAR(255) NOT NULL UNIQUE
|
||||
);
|
||||
|
||||
-- Create questions table
|
||||
CREATE TABLE IF NOT EXISTS `questions` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`category_id` INT NOT NULL,
|
||||
`question_text` TEXT NOT NULL,
|
||||
FOREIGN KEY (`category_id`) REFERENCES `categories`(`id`) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- Create answers table
|
||||
CREATE TABLE IF NOT EXISTS `answers` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`question_id` INT NOT NULL,
|
||||
`answer_text` VARCHAR(255) NOT NULL,
|
||||
`is_correct` BOOLEAN NOT NULL DEFAULT 0,
|
||||
FOREIGN KEY (`question_id`) REFERENCES `questions`(`id`) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- Insert categories
|
||||
INSERT INTO `categories` (`name`) VALUES ('Cultura'), ('Tradizione')
|
||||
ON DUPLICATE KEY UPDATE `name` = `name`;
|
||||
|
||||
-- Insert questions and answers for "Cultura"
|
||||
-- Question 1
|
||||
INSERT INTO `questions` (`category_id`, `question_text`) SELECT id, 'Quale di questi monumenti si trova a Roma?' FROM `categories` WHERE `name` = 'Cultura';
|
||||
SET @last_question_id = LAST_INSERT_ID();
|
||||
INSERT INTO `answers` (`question_id`, `answer_text`, `is_correct`) VALUES
|
||||
(@last_question_id, 'La Torre di Pisa', 0),
|
||||
(@last_question_id, 'Il Colosseo', 1),
|
||||
(@last_question_id, 'Il Duomo di Milano', 0),
|
||||
(@last_question_id, 'Il Ponte di Rialto', 0);
|
||||
|
||||
-- Question 2
|
||||
INSERT INTO `questions` (`category_id`, `question_text`) SELECT id, 'Chi ha scritto "La Divina Commedia"?' FROM `categories` WHERE `name` = 'Cultura';
|
||||
SET @last_question_id = LAST_INSERT_ID();
|
||||
INSERT INTO `answers` (`question_id`, `answer_text`, `is_correct`) VALUES
|
||||
(@last_question_id, 'Alessandro Manzoni', 0),
|
||||
(@last_question_id, 'Giacomo Leopardi', 0),
|
||||
(@last_question_id, 'Dante Alighieri', 1),
|
||||
(@last_question_id, 'Giovanni Boccaccio', 0);
|
||||
|
||||
-- Question 3
|
||||
INSERT INTO `questions` (`category_id`, `question_text`) SELECT id, 'Qual è la capitale della Francia?' FROM `categories` WHERE `name` = 'Cultura';
|
||||
SET @last_question_id = LAST_INSERT_ID();
|
||||
INSERT INTO `answers` (`question_id`, `answer_text`, `is_correct`) VALUES
|
||||
(@last_question_id, 'Berlino', 0),
|
||||
(@last_question_id, 'Madrid', 0),
|
||||
(@last_question_id, 'Londra', 0),
|
||||
(@last_question_id, 'Parigi', 1);
|
||||
54
db/migrations/003_update_quiz_content.sql
Normal file
54
db/migrations/003_update_quiz_content.sql
Normal file
@ -0,0 +1,54 @@
|
||||
-- Truncate tables to ensure a clean state
|
||||
SET FOREIGN_KEY_CHECKS=0;
|
||||
TRUNCATE TABLE `answers`;
|
||||
TRUNCATE TABLE `questions`;
|
||||
TRUNCATE TABLE `categories`;
|
||||
SET FOREIGN_KEY_CHECKS=1;
|
||||
|
||||
-- Insert the new category
|
||||
INSERT INTO `categories` (`id`, `name`, `description`) VALUES
|
||||
(1, 'MAVI e Lacedonia', 'Domande sul Museo Antropologico Visivo Irpino e sul comune di Lacedonia');
|
||||
|
||||
-- Insert questions for the "MAVI e Lacedonia" category
|
||||
INSERT INTO `questions` (`id`, `category_id`, `question_text`) VALUES
|
||||
(1, 1, 'Dove si trova il MAVI?'),
|
||||
(2, 1, 'Cosa significa l''acronimo MAVI?'),
|
||||
(3, 1, 'In che anno è stato inaugurato il MAVI?'),
|
||||
(4, 1, 'Quale importante fotografo americano ha documentato la vita di Lacedonia nel 1957?'),
|
||||
(5, 1, 'A chi è dedicato il Museo di Lacedonia?');
|
||||
|
||||
-- Insert answers for the questions
|
||||
-- Answers for question 1
|
||||
INSERT INTO `answers` (`id`, `question_id`, `answer_text`, `is_correct`) VALUES
|
||||
(1, 1, 'Lacedonia', 1),
|
||||
(2, 1, 'Avellino', 0),
|
||||
(3, 1, 'Napoli', 0),
|
||||
(4, 1, 'Roma', 0);
|
||||
|
||||
-- Answers for question 2
|
||||
INSERT INTO `answers` (`id`, `question_id`, `answer_text`, `is_correct`) VALUES
|
||||
(5, 2, 'Museo Antropologico Visivo Irpino', 1),
|
||||
(6, 2, 'Museo Archeologico Virtuale Italiano', 0),
|
||||
(7, 2, 'Mostra Artistica Visiva Internazionale', 0),
|
||||
(8, 2, 'Museo d''Arte Visiva Irpino', 0);
|
||||
|
||||
-- Answers for question 3
|
||||
INSERT INTO `answers` (`id`, `question_id`, `answer_text`, `is_correct`) VALUES
|
||||
(9, 3, '2008', 1),
|
||||
(10, 3, '1998', 0),
|
||||
(11, 3, '2018', 0),
|
||||
(12, 3, '1980', 0);
|
||||
|
||||
-- Answers for question 4
|
||||
INSERT INTO `answers` (`id`, `question_id`, `answer_text`, `is_correct`) VALUES
|
||||
(13, 4, 'Frank Cancian', 1),
|
||||
(14, 4, 'Robert Capa', 0),
|
||||
(15, 4, 'Henri Cartier-Bresson', 0),
|
||||
(16, 4, 'Ansel Adams', 0);
|
||||
|
||||
-- Answers for question 5
|
||||
INSERT INTO `answers` (`id`, `question_id`, `answer_text`, `is_correct`) VALUES
|
||||
(17, 5, 'A San Gerardo Maiella', 1),
|
||||
(18, 5, 'A San Francesco d''Assisi', 0),
|
||||
(19, 5, 'A Padre Pio', 0),
|
||||
(20, 5, 'A San Gennaro', 0);
|
||||
65
db/migrations/004_add_tradizioni_questions.sql
Normal file
65
db/migrations/004_add_tradizioni_questions.sql
Normal file
@ -0,0 +1,65 @@
|
||||
-- Inserimento della nuova categoria 'Tradizioni'
|
||||
INSERT INTO `categories` (`name`) VALUES ('Tradizioni');
|
||||
|
||||
-- Inserimento delle domande per la categoria 'Tradizioni'
|
||||
SET @category_id = (SELECT `id` FROM `categories` WHERE `name` = 'Tradizioni');
|
||||
|
||||
-- Domanda 1
|
||||
INSERT INTO `questions` (`category_id`, `question_text`) VALUES
|
||||
(@category_id, 'Come si chiamano i dolci tipici di Carnevale a Lacedonia?');
|
||||
|
||||
SET @question_id = LAST_INSERT_ID();
|
||||
|
||||
INSERT INTO `answers` (`question_id`, `answer_text`, `is_correct`) VALUES
|
||||
(@question_id, 'Chiacchiere', 1),
|
||||
(@question_id, 'Struffoli', 0),
|
||||
(@question_id, 'Cauzuncielli', 0),
|
||||
(@question_id, 'Sfogliatelle', 0);
|
||||
|
||||
-- Domanda 2
|
||||
INSERT INTO `questions` (`category_id`, `question_text`) VALUES
|
||||
(@category_id, 'In che mese si svolge la sagra "cingule ricotta e vrasciol"?');
|
||||
|
||||
SET @question_id = LAST_INSERT_ID();
|
||||
|
||||
INSERT INTO `answers` (`question_id`, `answer_text`, `is_correct`) VALUES
|
||||
(@question_id, 'Agosto', 1),
|
||||
(@question_id, 'Luglio', 0),
|
||||
(@question_id, 'Settembre', 0),
|
||||
(@question_id, 'Giugno', 0);
|
||||
|
||||
-- Domanda 3
|
||||
INSERT INTO `questions` (`category_id`, `question_text`) VALUES
|
||||
(@category_id, 'Quale evento storico viene rievocato a Lacedonia con un corteo in abiti d'epoca?');
|
||||
|
||||
SET @question_id = LAST_INSERT_ID();
|
||||
|
||||
INSERT INTO `answers` (`question_id`, `answer_text`, `is_correct`) VALUES
|
||||
(@question_id, 'La Congiura dei Baroni', 1),
|
||||
(@question_id, 'La Battaglia di Lacedonia', 0),
|
||||
(@question_id, 'L'arrivo di Garibaldi', 0),
|
||||
(@question_id, 'La fondazione della città', 0);
|
||||
|
||||
-- Domanda 4
|
||||
INSERT INTO `questions` (`category_id`, `question_text`) VALUES
|
||||
(@category_id, 'Come si chiamano i ravioli dolci farciti con castagne e cioccolata?');
|
||||
|
||||
SET @question_id = LAST_INSERT_ID();
|
||||
|
||||
INSERT INTO `answers` (`question_id`, `answer_text`, `is_correct`) VALUES
|
||||
(@question_id, 'Cauzuncielli', 1),
|
||||
(@question_id, 'Sfogliatelle', 0),
|
||||
(@question_id, 'Chiacchiere', 0),
|
||||
(@question_id, 'Struffoli', 0);
|
||||
|
||||
-- Domanda 5
|
||||
INSERT INTO `questions` (`category_id`, `question_text`) VALUES
|
||||
(@category_id, 'In onore di quale santo vengono allestiti grandi falò il 18 marzo?');
|
||||
|
||||
SET @question_id = LAST_INSERT_ID();
|
||||
|
||||
INSERT INTO `answers` (`question_id`, `answer_text`, `is_correct`) VALUES
|
||||
(@question_id, 'San Giuseppe', 1),
|
||||
(@question_id, 'San Gerardo', 0),
|
||||
(@question_id, 'San Nicola', 0),
|
||||
(@question_id, 'San Filippo Neri', 0);
|
||||
5
db/migrations/005_add_description_to_categories.sql
Normal file
5
db/migrations/005_add_description_to_categories.sql
Normal file
@ -0,0 +1,5 @@
|
||||
ALTER TABLE `categories` ADD `description` TEXT NULL AFTER `name`;
|
||||
|
||||
UPDATE `categories` SET `description` = 'Domande sul Museo Antropologico Visivo Irpino e sul comune di Lacedonia.' WHERE `name` = 'MAVI e Lacedonia';
|
||||
UPDATE `categories` SET `description` = 'Mettiti alla prova con domande sugli usi, i costumi e le tradizioni popolari.' WHERE `name` = 'Tradizioni';
|
||||
UPDATE `categories` SET `description` = 'Domande sulla storia, l'arte e le curiosità legate al territorio di Lacedonia.' WHERE `name` = 'Cultura';
|
||||
72
games.php
Normal file
72
games.php
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
// games.php
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Games - MAVI Project</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="assets/css/custom.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container py-5">
|
||||
<div class="text-center mb-4">
|
||||
<h1 style="font-family: 'Poppins', sans-serif;">Games Hub</h1>
|
||||
<p class="lead">Select a game to play.</p>
|
||||
</div>
|
||||
|
||||
<div class="row gy-4">
|
||||
<!-- Game 1: Cultural Quiz -->
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="card h-100">
|
||||
<div class="card-body d-flex flex-column text-center">
|
||||
<h5 class="card-title">Quiz Culturale</h5>
|
||||
<p class="card-text">Metti alla prova la tua conoscenza con domande sulla storia e la cultura locale.</p>
|
||||
<a href="quiz.php" class="btn btn-primary mt-auto">Gioca</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Game 2: Memory Game -->
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="card h-100">
|
||||
<div class="card-body d-flex flex-column text-center">
|
||||
<h5 class="card-title">Memory Game</h5>
|
||||
<p class="card-text">Allena la tua memoria trovando le coppie di immagini a tema.</p>
|
||||
<a href="#" class="btn btn-secondary disabled mt-auto">Gioca</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Game 3: Interactive Map -->
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="card h-100">
|
||||
<div class="card-body d-flex flex-column text-center">
|
||||
<h5 class="card-title">Mappa Interattiva di Lacedonia</h5>
|
||||
<p class="card-text">Esplora la Lacedonia del 1957 e scopri foto storiche nascoste.</p>
|
||||
<a href="#" class="btn btn-secondary disabled mt-auto">Gioca</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Game 4: To Be Defined -->
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="card h-100">
|
||||
<div class="card-body d-flex flex-column text-center">
|
||||
<h5 class="card-title">Gioco 4 (Da definire)</h5>
|
||||
<p class="card-text">Un nuovo gioco in arrivo. Le idee sono benvenute!</p>
|
||||
<a href="#" class="btn btn-secondary disabled mt-auto">Gioca</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-center mt-5">
|
||||
<a href="/" class="btn btn-primary">Back to Home</a>
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
137
index.php
137
index.php
@ -1,131 +1,24 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
@ini_set('display_errors', '1');
|
||||
@error_reporting(E_ALL);
|
||||
@date_default_timezone_set('UTC');
|
||||
|
||||
$phpVersion = PHP_VERSION;
|
||||
$now = date('Y-m-d H:i:s');
|
||||
// index.php
|
||||
?>
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>New Style</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--bg-color-start: #6a11cb;
|
||||
--bg-color-end: #2575fc;
|
||||
--text-color: #ffffff;
|
||||
--card-bg-color: rgba(255, 255, 255, 0.01);
|
||||
--card-border-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: 'Inter', sans-serif;
|
||||
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
|
||||
color: var(--text-color);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 100vh;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
body::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path d="M-10 10L110 10M10 -10L10 110" stroke-width="1" stroke="rgba(255,255,255,0.05)"/></svg>');
|
||||
animation: bg-pan 20s linear infinite;
|
||||
z-index: -1;
|
||||
}
|
||||
@keyframes bg-pan {
|
||||
0% { background-position: 0% 0%; }
|
||||
100% { background-position: 100% 100%; }
|
||||
}
|
||||
main {
|
||||
padding: 2rem;
|
||||
}
|
||||
.card {
|
||||
background: var(--card-bg-color);
|
||||
border: 1px solid var(--card-border-color);
|
||||
border-radius: 16px;
|
||||
padding: 2rem;
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.loader {
|
||||
margin: 1.25rem auto 1.25rem;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border: 3px solid rgba(255, 255, 255, 0.25);
|
||||
border-top-color: #fff;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
@keyframes spin {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
.hint {
|
||||
opacity: 0.9;
|
||||
}
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px; height: 1px;
|
||||
padding: 0; margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap; border: 0;
|
||||
}
|
||||
h1 {
|
||||
font-size: 3rem;
|
||||
font-weight: 700;
|
||||
margin: 0 0 1rem;
|
||||
letter-spacing: -1px;
|
||||
}
|
||||
p {
|
||||
margin: 0.5rem 0;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
code {
|
||||
background: rgba(0,0,0,0.2);
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||||
}
|
||||
footer {
|
||||
position: absolute;
|
||||
bottom: 1rem;
|
||||
font-size: 0.8rem;
|
||||
opacity: 0.7;
|
||||
}
|
||||
</style>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>MAVI Landing Page</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="assets/css/custom.css">
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<div class="card">
|
||||
<h1>Analyzing your requirements and generating your website…</h1>
|
||||
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
|
||||
<span class="sr-only">Loading…</span>
|
||||
</div>
|
||||
<p class="hint"><?= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWiZZy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.</p>
|
||||
<p class="hint">This page will update automatically as the plan is implemented.</p>
|
||||
<p>Runtime: PHP <code><?= htmlspecialchars($phpVersion) ?></code> — UTC <code><?= htmlspecialchars($now) ?></code></p>
|
||||
<div class="container d-flex justify-content-center align-items-center vh-100">
|
||||
<div class="text-center">
|
||||
<h1 style="font-family: 'Poppins', sans-serif;">Welcome to the MAVI Project</h1>
|
||||
<p class="lead">The interactive learning platform for the MAVI museum.</p>
|
||||
<a href="/games.php" class="btn btn-success mt-3">Play Games</a>
|
||||
<a href="/admin/" class="btn btn-primary mt-3">Go to Admin Panel</a>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer>
|
||||
Page updated: <?= htmlspecialchars($now) ?> (UTC)
|
||||
</footer>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
44
quiz.php
Normal file
44
quiz.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
require_once 'db/config.php';
|
||||
$pdo = db_connect();
|
||||
$stmt = $pdo->query("SELECT name, description FROM categories ORDER BY name");
|
||||
$categories = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="it">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Quiz MAVI - Scegli una categoria</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="assets/css/custom.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container mt-5">
|
||||
<a href="games.php" class="btn btn-secondary mb-4">Torna a Giochi</a>
|
||||
<h1 class="text-center mb-4">Scegli una categoria</h1>
|
||||
|
||||
<div class="row justify-content-center g-4">
|
||||
<?php foreach ($categories as $category): ?>
|
||||
<div class="col-md-5">
|
||||
<div class="card h-100 text-center">
|
||||
<div class="card-body d-flex flex-column">
|
||||
<h5 class="card-title"><?php echo htmlspecialchars($category['name']); ?></h5>
|
||||
<p class="card-text"><?php echo htmlspecialchars($category['description'] ?? 'Descrizione non disponibile.'); ?></p>
|
||||
<div class="mt-auto">
|
||||
<a href="quiz_play.php?category=<?php echo urlencode($category['name']); ?>&action=start" class="btn btn-primary">Inizia il Quiz</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<div class="text-center mt-5">
|
||||
<a href="games.php" class="btn btn-secondary">← Torna alla lista dei giochi</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
218
quiz_play.php
Normal file
218
quiz_play.php
Normal file
@ -0,0 +1,218 @@
|
||||
<?php
|
||||
require_once 'db/config.php';
|
||||
|
||||
// --- Configuration ---
|
||||
$num_questions_per_quiz = 5;
|
||||
|
||||
// --- Helper Functions ---
|
||||
|
||||
/**
|
||||
* Fetches a single question and its answers from the database.
|
||||
* @param int $question_id
|
||||
* @return array|null
|
||||
*/
|
||||
function get_question(int $question_id): ?array {
|
||||
try {
|
||||
$stmt = db()->prepare("SELECT id, question_text FROM questions WHERE id = :id");
|
||||
$stmt->execute(['id' => $question_id]);
|
||||
$question = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$question) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$stmt = db()->prepare("SELECT id, answer_text FROM answers WHERE question_id = :id ORDER BY RAND()");
|
||||
$stmt->execute(['id' => $question_id]);
|
||||
$question['answers'] = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
return $question;
|
||||
} catch (PDOException $e) {
|
||||
error_log("Error in get_question: " . $e->getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a set of random question IDs for a given category.
|
||||
* @param string $category_name
|
||||
* @param int $limit
|
||||
* @return array
|
||||
*/
|
||||
function get_random_question_ids(string $category_name, int $limit): array {
|
||||
try {
|
||||
// First, get the category ID from the name
|
||||
$cat_stmt = db()->prepare("SELECT id FROM categories WHERE name = :name");
|
||||
$cat_stmt->execute(['name' => $category_name]);
|
||||
$category = $cat_stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$category) {
|
||||
return [];
|
||||
}
|
||||
$category_id = $category['id'];
|
||||
|
||||
// Now, fetch the questions
|
||||
$stmt = db()->prepare("SELECT id FROM questions WHERE category_id = :category_id ORDER BY RAND() LIMIT :limit");
|
||||
$stmt->bindParam('category_id', $category_id, PDO::PARAM_INT);
|
||||
$stmt->bindParam('limit', $limit, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
return $stmt->fetchAll(PDO::FETCH_COLUMN);
|
||||
} catch (PDOException $e) {
|
||||
error_log("Error in get_random_question_ids: " . $e->getMessage());
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the provided answer is correct.
|
||||
* @param int $answer_id
|
||||
* @return bool
|
||||
*/
|
||||
function is_answer_correct(int $answer_id): bool {
|
||||
try {
|
||||
$stmt = db()->prepare("SELECT is_correct FROM answers WHERE id = :id");
|
||||
$stmt->execute(['id' => $answer_id]);
|
||||
$result = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
return $result && $result['is_correct'];
|
||||
} catch (PDOException $e) {
|
||||
error_log("Error in is_answer_correct: " . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// --- State Initialization ---
|
||||
$question_ids_str = '';
|
||||
$current_index = 0;
|
||||
$score = 0;
|
||||
$category_name = '';
|
||||
$is_quiz_finished = false;
|
||||
|
||||
// --- Logic ---
|
||||
|
||||
// Is this a POST request (user answered a question)?
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
// Retrieve state from the form
|
||||
$question_ids_str = $_POST['question_ids'] ?? '';
|
||||
$current_index = isset($_POST['current_index']) ? (int)$_POST['current_index'] : 0;
|
||||
$score = isset($_POST['score']) ? (int)$_POST['score'] : 0;
|
||||
$submitted_answer_id = isset($_POST['answer_id']) ? (int)$_POST['answer_id'] : 0;
|
||||
|
||||
// Check if the answer was correct
|
||||
if ($submitted_answer_id > 0 && is_answer_correct($submitted_answer_id)) {
|
||||
$score++;
|
||||
}
|
||||
|
||||
// Move to the next question
|
||||
$current_index++;
|
||||
|
||||
}
|
||||
// Or is this a GET request (start of the quiz)?
|
||||
else if (isset($_GET['action']) && $_GET['action'] === 'start') {
|
||||
$category_name = $_GET['category'] ?? '';
|
||||
|
||||
if (!empty($category_name)) {
|
||||
$question_ids = get_random_question_ids($category_name, $num_questions_per_quiz);
|
||||
if (count($question_ids) < $num_questions_per_quiz) {
|
||||
$error_message = "Non ci sono abbastanza domande (ne servono {$num_questions_per_quiz}) in questa categoria per iniziare il quiz.";
|
||||
$is_quiz_finished = true; // Stop the quiz
|
||||
} else {
|
||||
$question_ids_str = implode(',', $question_ids);
|
||||
}
|
||||
} else {
|
||||
$error_message = "Nome della categoria non valido.";
|
||||
$is_quiz_finished = true; // Stop the quiz
|
||||
}
|
||||
}
|
||||
|
||||
$question_ids = !empty($question_ids_str) ? explode(',', $question_ids_str) : [];
|
||||
$total_questions = count($question_ids);
|
||||
|
||||
// Check if the quiz is over
|
||||
if ($current_index >= $total_questions && $total_questions > 0) {
|
||||
$is_quiz_finished = true;
|
||||
}
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="it">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Quiz in Corso - MAVI</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="assets/css/custom.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container mt-5">
|
||||
<a href="quiz.php" class="btn btn-secondary mb-4">← Torna alle Categorie</a>
|
||||
|
||||
<?php if ($is_quiz_finished): ?>
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<h1 class="card-title">Quiz Terminato!</h1>
|
||||
<?php if (isset($error_message)): ?>
|
||||
<div class="alert alert-warning"><?php echo $error_message; ?></div>
|
||||
<?php else: ?>
|
||||
<p class="card-text fs-4">Il tuo punteggio finale è:</p>
|
||||
<p class="display-3"><strong><?php echo $score; ?> su <?php echo $total_questions; ?></strong></p>
|
||||
<?php endif; ?>
|
||||
<a href="quiz.php" class="btn btn-primary mt-3">Gioca Ancora</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php elseif (!empty($question_ids)): ?>
|
||||
<?php
|
||||
$question_id = (int)$question_ids[$current_index];
|
||||
$question = get_question($question_id);
|
||||
?>
|
||||
<?php if ($question): ?>
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Domanda <?php echo ($current_index + 1); ?> di <?php echo $total_questions; ?></h5>
|
||||
<p class="card-text fs-4"><?php echo htmlspecialchars($question['question_text']); ?></p>
|
||||
|
||||
<form method="POST" action="quiz_play.php">
|
||||
<?php foreach ($question['answers'] as $answer): ?>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="answer_id" value="<?php echo $answer['id']; ?>" id="answer_<?php echo $answer['id']; ?>" required>
|
||||
<label class="form-check-label" for="answer_<?php echo $answer['id']; ?>">
|
||||
<?php echo htmlspecialchars($answer['answer_text']); ?>
|
||||
</label>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<input type="hidden" name="question_ids" value="<?php echo htmlspecialchars($question_ids_str); ?>">
|
||||
<input type="hidden" name="current_index" value="<?php echo $current_index; ?>">
|
||||
<input type="hidden" name="score" value="<?php echo $score; ?>">
|
||||
|
||||
<button type="submit" class="btn btn-primary mt-4">Rispondi</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- VISIBLE DEBUG INFO -->
|
||||
<div class="card bg-light mt-4">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title">Informazioni di Debug</h6>
|
||||
<pre class="small"><?php echo htmlspecialchars(print_r([
|
||||
'Question IDs' => $question_ids_str,
|
||||
'Current Index' => $current_index,
|
||||
'Score' => $score,
|
||||
'Total Questions' => $total_questions
|
||||
], true)); ?></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php else: ?>
|
||||
<div class="alert alert-danger">Errore: Impossibile caricare la domanda.</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php elseif ($_SERVER['REQUEST_METHOD'] !== 'POST'): ?>
|
||||
<div class="alert alert-info">Seleziona una categoria dalla <a href="quiz.php">pagina dei quiz</a> per iniziare.</div>
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
x
Reference in New Issue
Block a user