premières bases du projet
This commit is contained in:
parent
9f919674de
commit
303194437c
55
admin/index.php
Normal file
55
admin/index.php
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
require_once '../includes/config.php';
|
||||||
|
require_once '../includes/auth.php';
|
||||||
|
require_once '../includes/stories.php';
|
||||||
|
|
||||||
|
// Vérification de l'authentification
|
||||||
|
if (!Auth::check()) {
|
||||||
|
header('Location: login.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$stories = Stories::getAll();
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Administration</title>
|
||||||
|
<link rel="stylesheet" href="../assets/css/admin.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<nav class="admin-nav">
|
||||||
|
<div class="nav-brand">Administration</div>
|
||||||
|
<div class="nav-menu">
|
||||||
|
<a href="story-edit.php" class="button">Nouveau roman</a>
|
||||||
|
<form method="POST" action="logout.php" class="logout-form">
|
||||||
|
<button type="submit">Déconnexion</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main class="admin-main">
|
||||||
|
<h1>Gestion des romans</h1>
|
||||||
|
|
||||||
|
<div class="stories-list">
|
||||||
|
<?php foreach ($stories as $story): ?>
|
||||||
|
<div class="story-item">
|
||||||
|
<img src="<?= htmlspecialchars($story['cover']) ?>" alt="" class="story-cover">
|
||||||
|
<div class="story-info">
|
||||||
|
<h2><?= htmlspecialchars($story['title']) ?></h2>
|
||||||
|
<p>Dernière modification : <?= htmlspecialchars($story['updated']) ?></p>
|
||||||
|
</div>
|
||||||
|
<div class="story-actions">
|
||||||
|
<a href="story-edit.php?id=<?= htmlspecialchars($story['id']) ?>" class="button">Modifier</a>
|
||||||
|
<button type="button" class="button delete-story" data-id="<?= htmlspecialchars($story['id']) ?>">Supprimer</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script src="../assets/js/admin.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
50
admin/login.php
Normal file
50
admin/login.php
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
require_once '../includes/config.php';
|
||||||
|
require_once '../includes/auth.php';
|
||||||
|
|
||||||
|
$error = '';
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$username = $_POST['username'] ?? '';
|
||||||
|
$password = $_POST['password'] ?? '';
|
||||||
|
|
||||||
|
if (Auth::login($username, $password)) {
|
||||||
|
header('Location: index.php');
|
||||||
|
exit;
|
||||||
|
} else {
|
||||||
|
$error = 'Identifiants incorrects';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Connexion - Administration</title>
|
||||||
|
<link rel="stylesheet" href="../assets/css/admin.css">
|
||||||
|
</head>
|
||||||
|
<body class="login-page">
|
||||||
|
<div class="login-container">
|
||||||
|
<h1>Connexion</h1>
|
||||||
|
|
||||||
|
<?php if ($error): ?>
|
||||||
|
<div class="error-message"><?= htmlspecialchars($error) ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<form method="POST" class="login-form">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="username">Identifiant</label>
|
||||||
|
<input type="text" id="username" name="username" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="password">Mot de passe</label>
|
||||||
|
<input type="password" id="password" name="password" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit">Se connecter</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
6
admin/logout.php
Normal file
6
admin/logout.php
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?php
|
||||||
|
require_once '../includes/auth.php';
|
||||||
|
|
||||||
|
Auth::logout();
|
||||||
|
header('Location: login.php');
|
||||||
|
exit;
|
140
assets/css/admin.css
Normal file
140
assets/css/admin.css
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Login Page */
|
||||||
|
.login-page {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-height: 100vh;
|
||||||
|
background-color: #2c1810;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-container {
|
||||||
|
background: white;
|
||||||
|
padding: 2rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||||
|
width: 100%;
|
||||||
|
max-width: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form .form-group {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.5rem;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form button {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.75rem;
|
||||||
|
background-color: #8b4513;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form button:hover {
|
||||||
|
background-color: #703610;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-message {
|
||||||
|
background-color: #ffebee;
|
||||||
|
color: #c62828;
|
||||||
|
padding: 0.75rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Admin Dashboard */
|
||||||
|
.admin-nav {
|
||||||
|
background-color: #2c1810;
|
||||||
|
color: white;
|
||||||
|
padding: 1rem 2rem;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-brand {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-menu {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
background-color: #8b4513;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button:hover {
|
||||||
|
background-color: #703610;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-main {
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stories-list {
|
||||||
|
display: grid;
|
||||||
|
gap: 1rem;
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.story-item {
|
||||||
|
background: white;
|
||||||
|
padding: 1rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.story-cover {
|
||||||
|
width: 100px;
|
||||||
|
height: 150px;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.story-info {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.story-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-story {
|
||||||
|
background-color: #c62828;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-story:hover {
|
||||||
|
background-color: #b71c1c;
|
||||||
|
}
|
BIN
assets/images/favicon.ico
Normal file
BIN
assets/images/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
13
config.json
Normal file
13
config.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"site": {
|
||||||
|
"name": "Nom du Site",
|
||||||
|
"description": "Description du site"
|
||||||
|
},
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"id": "admin",
|
||||||
|
"password": "$2y$10$pfYTH9z.ZvdgTJTj779X7.wL6m8S4.vSznQEiPdy6coaz.MeJkT76",
|
||||||
|
"comment": "Mot de passe par défaut « admin ». À changer dès la première connexion."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
26
includes/auth.php
Normal file
26
includes/auth.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
require_once 'config.php';
|
||||||
|
|
||||||
|
class Auth {
|
||||||
|
public static function check() {
|
||||||
|
return isset($_SESSION['user_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function login($username, $password) {
|
||||||
|
$config = Config::load();
|
||||||
|
$users = $config['users'];
|
||||||
|
|
||||||
|
foreach ($users as $user) {
|
||||||
|
if ($user['id'] === $username && password_verify($password, $user['password'])) {
|
||||||
|
$_SESSION['user_id'] = $user['id'];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function logout() {
|
||||||
|
unset($_SESSION['user_id']);
|
||||||
|
session_destroy();
|
||||||
|
}
|
||||||
|
}
|
22
includes/config.php
Normal file
22
includes/config.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
class Config {
|
||||||
|
private static $config = null;
|
||||||
|
|
||||||
|
public static function load() {
|
||||||
|
if (self::$config === null) {
|
||||||
|
$configFile = __DIR__ . '/../config.json';
|
||||||
|
if (!file_exists($configFile)) {
|
||||||
|
throw new Exception('Configuration file not found');
|
||||||
|
}
|
||||||
|
self::$config = json_decode(file_get_contents($configFile), true);
|
||||||
|
}
|
||||||
|
return self::$config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function get($key, $default = null) {
|
||||||
|
$config = self::load();
|
||||||
|
return $config[$key] ?? $default;
|
||||||
|
}
|
||||||
|
}
|
26
includes/stories.php
Normal file
26
includes/stories.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
class Stories {
|
||||||
|
private static $storiesDir = __DIR__ . '/../stories/';
|
||||||
|
|
||||||
|
public static function getAll() {
|
||||||
|
$stories = [];
|
||||||
|
foreach (glob(self::$storiesDir . '*.json') as $file) {
|
||||||
|
$story = json_decode(file_get_contents($file), true);
|
||||||
|
$stories[] = $story;
|
||||||
|
}
|
||||||
|
return $stories;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function get($id) {
|
||||||
|
$file = self::$storiesDir . $id . '.json';
|
||||||
|
if (!file_exists($file)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return json_decode(file_get_contents($file), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function save($story) {
|
||||||
|
$file = self::$storiesDir . $story['id'] . '.json';
|
||||||
|
return file_put_contents($file, json_encode($story, JSON_PRETTY_PRINT));
|
||||||
|
}
|
||||||
|
}
|
35
index.php
Normal file
35
index.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
require_once 'includes/config.php';
|
||||||
|
require_once 'includes/stories.php';
|
||||||
|
|
||||||
|
$config = Config::load();
|
||||||
|
$stories = Stories::getAll();
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title><?= htmlspecialchars($config['site']['name']) ?></title>
|
||||||
|
<link rel="stylesheet" href="assets/css/style.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<h1><?= htmlspecialchars($config['site']['name']) ?></h1>
|
||||||
|
<p><?= htmlspecialchars($config['site']['description']) ?></p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<div class="stories-grid">
|
||||||
|
<?php foreach ($stories as $story): ?>
|
||||||
|
<article class="story-card">
|
||||||
|
<img src="<?= htmlspecialchars($story['cover']) ?>" alt="">
|
||||||
|
<h2><?= htmlspecialchars($story['title']) ?></h2>
|
||||||
|
<p><?= htmlspecialchars($story['description']) ?></p>
|
||||||
|
<a href="story.php?id=<?= htmlspecialchars($story['id']) ?>">Lire</a>
|
||||||
|
</article>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
x
Reference in New Issue
Block a user