713 lines
23 KiB
PHP
713 lines
23 KiB
PHP
<?php
|
||
ini_set('display_errors', 1);
|
||
error_reporting(E_ALL);
|
||
session_start();
|
||
|
||
$db = new PDO('sqlite:db.sqlite');
|
||
|
||
$CATEGORIES = [
|
||
"Bricolage",
|
||
"Jardinage",
|
||
"Cuisine",
|
||
"Outils lourds",
|
||
"Matériel événementiel",
|
||
"Transport",
|
||
"Sport",
|
||
"Voyage",
|
||
"Autre"
|
||
];
|
||
|
||
$action = $_GET['action'] ?? 'home';
|
||
|
||
function redirect($a) {
|
||
header("Location: index.php?action=$a");
|
||
exit;
|
||
}
|
||
|
||
function is_logged() {
|
||
return isset($_SESSION['owner_id']);
|
||
}
|
||
|
||
/* ============================================================
|
||
TRAITEMENT DES FORMULAIRES
|
||
============================================================ */
|
||
|
||
/* ---------- INSCRIPTION ---------- */
|
||
if ($action === 'do_register' && $_SERVER['REQUEST_METHOD'] === 'POST') {
|
||
try {
|
||
$stmt = $db->prepare("
|
||
INSERT INTO owners (name, address, phone, email, username, password_hash)
|
||
VALUES (?, ?, ?, ?, ?, ?)
|
||
");
|
||
$stmt->execute([
|
||
$_POST['name'],
|
||
$_POST['address'],
|
||
$_POST['phone'],
|
||
$_POST['email'],
|
||
$_POST['username'],
|
||
password_hash($_POST['password'], PASSWORD_DEFAULT)
|
||
]);
|
||
|
||
$_SESSION['owner_id'] = $db->lastInsertId();
|
||
redirect('edit');
|
||
|
||
} catch (PDOException $e) {
|
||
$error = "Nom d'utilisateur déjà pris.";
|
||
$action = 'register';
|
||
}
|
||
}
|
||
|
||
/* ---------- CONNEXION ---------- */
|
||
if ($action === 'do_login' && $_SERVER['REQUEST_METHOD'] === 'POST') {
|
||
$stmt = $db->prepare("SELECT * FROM owners WHERE username=?");
|
||
$stmt->execute([$_POST['username']]);
|
||
$owner = $stmt->fetch(PDO::FETCH_ASSOC);
|
||
|
||
if ($owner && password_verify($_POST['password'], $owner['password_hash'])) {
|
||
$_SESSION['owner_id'] = $owner['id'];
|
||
redirect('edit');
|
||
} else {
|
||
$error = "Identifiants incorrects.";
|
||
$action = 'login';
|
||
}
|
||
}
|
||
|
||
/* ---------- DÉCONNEXION ---------- */
|
||
if ($action === 'logout') {
|
||
session_destroy();
|
||
redirect('home');
|
||
}
|
||
|
||
/* ---------- SAUVEGARDE MATERIEL (prix numérique + prix libre) ---------- */
|
||
if ($action === 'save_item' && $_SERVER['REQUEST_METHOD'] === 'POST' && is_logged()) {
|
||
|
||
// Prix numérique obligatoire
|
||
$price = floatval($_POST['price']);
|
||
if ($price <= 0) {
|
||
$error = "Le prix doit être un nombre positif.";
|
||
$action = 'edit';
|
||
}
|
||
|
||
// Prix libre ?
|
||
$price_free = isset($_POST['price_free']) ? "free" : "";
|
||
$price_value = $price_free ? "$price|free" : "$price";
|
||
|
||
// Upload photo
|
||
$photo = null;
|
||
if (!empty($_FILES['photo']['name'])) {
|
||
$photo = time() . "_" . basename($_FILES['photo']['name']);
|
||
move_uploaded_file($_FILES['photo']['tmp_name'], "uploads/" . $photo);
|
||
}
|
||
|
||
// UPDATE
|
||
if (!empty($_POST['id'])) {
|
||
if ($photo) {
|
||
$stmt = $db->prepare("UPDATE items SET name=?, price=?, description=?, photo=?, category=? WHERE id=? AND owner_id=?");
|
||
$stmt->execute([
|
||
$_POST['name'],
|
||
$price_value,
|
||
$_POST['description'],
|
||
$photo,
|
||
$_POST['category'],
|
||
$_POST['id'],
|
||
$_SESSION['owner_id']
|
||
]);
|
||
} else {
|
||
$stmt = $db->prepare("UPDATE items SET name=?, price=?, description=?, category=? WHERE id=? AND owner_id=?");
|
||
$stmt->execute([
|
||
$_POST['name'],
|
||
$price_value,
|
||
$_POST['description'],
|
||
$_POST['category'],
|
||
$_POST['id'],
|
||
$_SESSION['owner_id']
|
||
]);
|
||
}
|
||
|
||
// INSERT
|
||
} else {
|
||
$stmt = $db->prepare("INSERT INTO items (name, price, description, photo, owner_id, category)
|
||
VALUES (?, ?, ?, ?, ?, ?)");
|
||
$stmt->execute([
|
||
$_POST['name'],
|
||
$price_value,
|
||
$_POST['description'],
|
||
$photo,
|
||
$_SESSION['owner_id'],
|
||
$_POST['category']
|
||
]);
|
||
}
|
||
|
||
redirect('edit');
|
||
}
|
||
|
||
/* ---------- SUPPRESSION MATERIEL ---------- */
|
||
if ($action === 'delete_item' && is_logged()) {
|
||
$stmt = $db->prepare("DELETE FROM items WHERE id=? AND owner_id=?");
|
||
$stmt->execute([$_GET['id'], $_SESSION['owner_id']]);
|
||
redirect('edit');
|
||
}
|
||
|
||
/* ---------- SUPPRESSION PHOTO MATERIEL ---------- */
|
||
if ($action === 'delete_photo' && is_logged()) {
|
||
|
||
// Récupérer le matériel
|
||
$stmt = $db->prepare("SELECT photo FROM items WHERE id=? AND owner_id=?");
|
||
$stmt->execute([$_GET['id'], $_SESSION['owner_id']]);
|
||
$item = $stmt->fetch(PDO::FETCH_ASSOC);
|
||
|
||
if ($item && !empty($item['photo'])) {
|
||
$file = "uploads/" . $item['photo'];
|
||
if (file_exists($file)) {
|
||
unlink($file);
|
||
}
|
||
|
||
// Mettre la colonne photo à NULL
|
||
$stmt = $db->prepare("UPDATE items SET photo=NULL WHERE id=? AND owner_id=?");
|
||
$stmt->execute([$_GET['id'], $_SESSION['owner_id']]);
|
||
}
|
||
|
||
redirect('edit_item&id=' . $_GET['id']);
|
||
}
|
||
|
||
/* ---------- MODIFICATION PROFIL ---------- */
|
||
if ($action === 'save_profile' && $_SERVER['REQUEST_METHOD'] === 'POST' && is_logged()) {
|
||
|
||
$params = [
|
||
$_POST['name'],
|
||
$_POST['address'],
|
||
$_POST['phone'],
|
||
$_POST['email'],
|
||
$_POST['username']
|
||
];
|
||
|
||
$sql = "UPDATE owners SET name=?, address=?, phone=?, email=?, username=?";
|
||
|
||
if (!empty($_POST['password'])) {
|
||
$sql .= ", password_hash=?";
|
||
$params[] = password_hash($_POST['password'], PASSWORD_DEFAULT);
|
||
}
|
||
|
||
$sql .= " WHERE id=?";
|
||
$params[] = $_SESSION['owner_id'];
|
||
|
||
$stmt = $db->prepare($sql);
|
||
$stmt->execute($params);
|
||
|
||
$success = "Profil mis à jour.";
|
||
$action = 'profile';
|
||
}
|
||
?>
|
||
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<title>Location de matériel</title>
|
||
<link rel="stylesheet" href="pico.css">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<style>
|
||
body { max-width: 900px; margin: 40px auto; }
|
||
.item { padding: 1rem; border: 1px solid #ddd; border-radius: 8px; margin-bottom: 1.5rem; }
|
||
.tool-row { display: flex; gap: 1.5rem; align-items: flex-start; }
|
||
.tool-row img { width: 180px; border-radius: 8px; object-fit: cover; }
|
||
.tool-info { flex: 1; }
|
||
.owner-block { margin-top: .5rem; font-size: .9rem; color: #555; }
|
||
</style>
|
||
</head>
|
||
<body style="padding: 0 10px">
|
||
|
||
<h1 style="display:flex; align-items:center; justify-content:space-between;">
|
||
<span>Matériel partagé à Durban-sur-Arize</span>
|
||
<img src="uploads/blason-durban.png" alt="Blason de Durban-sur-Arize"
|
||
style="height:48px; width:auto; margin-left:1rem;">
|
||
</h1>
|
||
|
||
<nav>
|
||
<a href="index.php">Accueil</a>
|
||
<?php if (is_logged()): ?>
|
||
<a href="index.php?action=edit">Mon matériel</a>
|
||
<a href="index.php?action=profile">Mon profil</a>
|
||
<a href="index.php?action=logout">Déconnexion</a>
|
||
<?php else: ?>
|
||
<a href="index.php?action=login">Connexion</a>
|
||
<a href="index.php?action=register">Inscription</a>
|
||
<?php endif; ?>
|
||
</nav>
|
||
|
||
<hr>
|
||
|
||
<?php
|
||
/* ============================================================
|
||
VUE : ACCUEIL (liste publique)
|
||
============================================================ */
|
||
if ($action === 'home') {
|
||
?>
|
||
|
||
<div id="price-customizer" style="
|
||
margin-bottom: 1.2rem;
|
||
padding: .6rem .8rem;
|
||
border: 1px solid var(--pico-muted-border-color);
|
||
border-radius: .5rem;
|
||
font-size: .9rem;
|
||
">
|
||
<form id="income-form" style="
|
||
display: flex;
|
||
align-items: center;
|
||
gap: .4rem;
|
||
flex-wrap: wrap;
|
||
margin: 0;
|
||
">
|
||
<strong>Personnaliser les indications de prix libre</strong>
|
||
<span>selon mon revenu mensuel :</span>
|
||
<input
|
||
type="number"
|
||
id="income"
|
||
value="1900"
|
||
min="0"
|
||
step="1"
|
||
style="width: 110px; margin: 0;">
|
||
<span>€/mois</span>
|
||
</form>
|
||
</div>
|
||
|
||
<div id="search-tools" style="
|
||
margin-bottom: 1.2rem;
|
||
padding: .6rem .8rem;
|
||
border: 1px solid var(--pico-muted-border-color);
|
||
border-radius: .5rem;
|
||
font-size: .9rem;
|
||
">
|
||
<form style="display:flex; align-items:center; gap:.6rem; flex-wrap:wrap; margin:0;">
|
||
<strong style="font-size:.95rem;">Rechercher un matériel :</strong>
|
||
<input
|
||
type="text"
|
||
id="search"
|
||
placeholder="Nom ou description…"
|
||
style="flex:1; min-width:200px; margin:0;"
|
||
>
|
||
</form>
|
||
</div>
|
||
|
||
|
||
<?php
|
||
$items = $db->query("
|
||
SELECT items.*, owners.name AS owner_name, owners.phone, owners.address, owners.email
|
||
FROM items
|
||
JOIN owners ON owners.id = items.owner_id
|
||
ORDER BY items.category COLLATE NOCASE ASC,
|
||
items.name COLLATE NOCASE ASC
|
||
")->fetchAll(PDO::FETCH_ASSOC);
|
||
|
||
foreach ($items as $item) {
|
||
|
||
// Décodage du prix
|
||
$price_raw = $item['price'] ?? '';
|
||
$price_parts = explode('|', $price_raw);
|
||
$price_value = floatval($price_parts[0]);
|
||
$price_free = isset($price_parts[1]) && $price_parts[1] === 'free';
|
||
|
||
$search_text = strtolower(
|
||
($item['name'] ?? '') . ' ' . ($item['description'] ?? '')
|
||
);
|
||
|
||
echo "<article class='item' data-search='" . htmlspecialchars($search_text, ENT_QUOTES) . "'>";
|
||
echo "<div class='tool-row'>";
|
||
|
||
// Photo
|
||
if (!empty($item['photo'])) {
|
||
echo "<img src='uploads/{$item['photo']}' alt='Photo'>";
|
||
} else {
|
||
echo "<div style='
|
||
width:180px;
|
||
height:120px;
|
||
display:flex;
|
||
align-items:center;
|
||
justify-content:center;
|
||
font-size:60px;
|
||
'>🛠️</div>";
|
||
}
|
||
|
||
echo "<div class='tool-info'>";
|
||
|
||
echo "<h2 style='margin: 0;'>" . htmlspecialchars($item['name'] ?? '') . "</h2>";
|
||
|
||
echo "<p style='opacity:.7; font-size:.85rem;'>Catégorie : " . htmlspecialchars($item['category']) . "</p>";
|
||
|
||
// Prix
|
||
echo "<p class='price-block' data-base-price='{$price_value}' data-free='{$price_free}'>";
|
||
echo "<strong>Prix :</strong> {$price_value} € / jour";
|
||
if ($price_free) echo " <em>(prix libre)</em>";
|
||
echo "</p>";
|
||
|
||
// Description
|
||
echo "<p>" . nl2br(htmlspecialchars($item['description'] ?? '')) . "</p>";
|
||
|
||
// Propriétaire
|
||
echo "<div class='owner-block'>";
|
||
echo "<strong>Propriétaire :</strong> " . htmlspecialchars($item['owner_name'] ?? '') . "<br>";
|
||
|
||
// Adresse
|
||
$addr = urlencode($item['address'] ?? '');
|
||
echo htmlspecialchars($item['address'] ?? '')."<br>";
|
||
|
||
// Téléphone → tel:
|
||
echo "<a href='tel:" . htmlspecialchars($item['phone'] ?? '') . "'>"
|
||
. htmlspecialchars($item['phone'] ?? '')
|
||
. "</a><br>";
|
||
|
||
// Email → mailto:
|
||
echo "<a href='mailto:" . htmlspecialchars($item['email'] ?? '') . "'>"
|
||
. htmlspecialchars($item['email'] ?? '')
|
||
. "</a>";
|
||
|
||
echo "</div>"; // owner-block
|
||
|
||
echo "</div>"; // tool-info
|
||
echo "</div>"; // tool-row
|
||
echo "</article>";
|
||
}
|
||
}
|
||
|
||
/* ============================================================
|
||
VUE : CONNEXION
|
||
============================================================ */
|
||
if ($action === 'login') {
|
||
echo "<h2>Connexion</h2>";
|
||
if (!empty($error)) echo "<p style='color:red'>$error</p>";
|
||
?>
|
||
<form method="post" action="index.php?action=do_login">
|
||
<input name="username" placeholder="Nom d'utilisateur" required>
|
||
<input name="password" type="password" placeholder="Mot de passe" required>
|
||
<button>Connexion</button>
|
||
</form>
|
||
<?php
|
||
}
|
||
|
||
/* ============================================================
|
||
VUE : INSCRIPTION
|
||
============================================================ */
|
||
if ($action === 'register') {
|
||
echo "<h2>Inscription</h2>";
|
||
if (!empty($error)) echo "<p style='color:red'>$error</p>";
|
||
?>
|
||
<form method="post" action="index.php?action=do_register">
|
||
<input name="name" placeholder="Nom complet" required>
|
||
<input name="address" placeholder="Code postal">
|
||
<input name="phone" placeholder="Téléphone">
|
||
<input name="email" placeholder="Email">
|
||
<input name="username" placeholder="Nom d'utilisateur" required>
|
||
<input name="password" type="password" placeholder="Mot de passe" required>
|
||
<button>Créer mon compte</button>
|
||
</form>
|
||
<?php
|
||
}
|
||
|
||
/* ============================================================
|
||
VUE : PROFIL
|
||
============================================================ */
|
||
if ($action === 'profile' && is_logged()) {
|
||
|
||
$stmt = $db->prepare("SELECT * FROM owners WHERE id=?");
|
||
$stmt->execute([$_SESSION['owner_id']]);
|
||
$owner = $stmt->fetch(PDO::FETCH_ASSOC);
|
||
|
||
echo "<h2>Mon profil</h2>";
|
||
|
||
if (!empty($success)) echo "<p style='color:green'>$success</p>";
|
||
|
||
?>
|
||
<form method="post" action="index.php?action=save_profile">
|
||
<input name="name" value="<?= htmlspecialchars($owner['name'] ?? '') ?>" placeholder="Nom complet" required>
|
||
<input name="address" value="<?= htmlspecialchars($owner['address'] ?? '') ?>" placeholder="Code postal">
|
||
<input name="phone" value="<?= htmlspecialchars($owner['phone'] ?? '') ?>" placeholder="Téléphone">
|
||
<input name="email" value="<?= htmlspecialchars($owner['email'] ?? '') ?>" placeholder="Email">
|
||
<input name="username" value="<?= htmlspecialchars($owner['username'] ?? '') ?>" placeholder="Nom d'utilisateur" required>
|
||
<input name="password" type="password" placeholder="Nouveau mot de passe (laisser vide)">
|
||
<button>Mettre à jour</button>
|
||
</form>
|
||
<?php
|
||
}
|
||
|
||
/* ============================================================
|
||
VUE : ÉDITION D’UN MATERIEL
|
||
============================================================ */
|
||
if ($action === 'edit_item' && is_logged()) {
|
||
|
||
$stmt = $db->prepare("SELECT * FROM items WHERE id=? AND owner_id=?");
|
||
$stmt->execute([$_GET['id'], $_SESSION['owner_id']]);
|
||
$item = $stmt->fetch(PDO::FETCH_ASSOC);
|
||
|
||
if (!$item) {
|
||
echo "<p>Matériel introuvable.</p>";
|
||
} else {
|
||
|
||
// Décodage du prix
|
||
$price_raw = $item['price'] ?? '';
|
||
$price_parts = explode('|', $price_raw);
|
||
$price_value = floatval($price_parts[0]);
|
||
$price_free = isset($price_parts[1]) && $price_parts[1] === 'free';
|
||
|
||
echo "<h2>Modifier le matériel</h2>";
|
||
?>
|
||
|
||
<form method="post" enctype="multipart/form-data" action="index.php?action=save_item">
|
||
<input type="hidden" name="id" value="<?= $item['id'] ?>">
|
||
|
||
<label>Nom du matériel</label>
|
||
<input name="name" value="<?= htmlspecialchars($item['name']) ?>" required>
|
||
|
||
<label>Prix par jour (€)</label>
|
||
<input name="price" type="number" step="0.01" min="0"
|
||
value="<?= $price_value ?>" required>
|
||
|
||
<p style="font-size:.85rem; opacity:.8;">
|
||
Le prix libre conseillé sera automatiquement ajusté selon le revenu de l’utilisateur.
|
||
</p>
|
||
|
||
<label>
|
||
<input type="checkbox" name="price_free" <?= $price_free ? 'checked' : '' ?>>
|
||
Prix libre (le prix devient indicatif)
|
||
</label>
|
||
|
||
<label>Catégorie</label>
|
||
<select name="category" required>
|
||
<option value="">Choisir…</option>
|
||
<?php foreach ($CATEGORIES as $cat): ?>
|
||
<option value="<?= htmlspecialchars($cat) ?>"
|
||
<?= ($item['category'] === $cat ? 'selected' : '') ?>>
|
||
<?= htmlspecialchars($cat) ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
|
||
<label>Description</label>
|
||
<textarea name="description"><?= htmlspecialchars($item['description']) ?></textarea>
|
||
|
||
<label>Photo actuelle</label><br>
|
||
<?php if ($item['photo']): ?>
|
||
<img src="uploads/<?= $item['photo'] ?>" style="max-width:150px;border-radius:6px;">
|
||
|
||
<br>
|
||
|
||
<a href="index.php?action=delete_photo&id=<?= $item['id'] ?>"
|
||
onclick="return confirm('Supprimer cette photo ?')"
|
||
style="font-size:.85rem; color:var(--pico-del-color);">
|
||
Supprimer la photo
|
||
</a>
|
||
<?php else: ?>
|
||
<div style='
|
||
width:150px;
|
||
height:100px;
|
||
display:flex;
|
||
align-items:center;
|
||
justify-content:center;
|
||
font-size:50px;
|
||
'>🛠️</div>
|
||
<?php endif; ?>
|
||
<br><br>
|
||
|
||
<label>Nouvelle photo (optionnel)</label>
|
||
<input type="file" name="photo">
|
||
|
||
<button>Mettre à jour</button>
|
||
</form>
|
||
|
||
<?php
|
||
}
|
||
}
|
||
|
||
/* ============================================================
|
||
VUE : GESTION DES MATERIELS
|
||
============================================================ */
|
||
if ($action === 'edit' && is_logged()) {
|
||
|
||
echo "<h2>Mes matériels</h2>";
|
||
|
||
?>
|
||
<h3 style="cursor:pointer;" id="toggle-form">➕ Ajouter un matériel</h3>
|
||
<div id="tool-form" style="display:none; margin-bottom:2rem;">
|
||
<form method="post" enctype="multipart/form-data" action="index.php?action=save_item">
|
||
<input type="hidden" name="id">
|
||
|
||
<label>Nom du matériel</label>
|
||
<input name="name" placeholder="Nom" required>
|
||
|
||
<label>Prix par jour (€)</label>
|
||
<input name="price" type="number" step="0.01" min="0" placeholder="Prix" required>
|
||
|
||
<p style="font-size:.85rem; opacity:.8;">
|
||
Le prix libre conseillé sera automatiquement ajusté selon le revenu de l’utilisateur.
|
||
</p>
|
||
|
||
<label>
|
||
<input type="checkbox" name="price_free">
|
||
Prix libre (le prix devient indicatif)
|
||
</label>
|
||
|
||
<label>Catégorie</label>
|
||
<select name="category" required>
|
||
<option value="">Choisir…</option>
|
||
<?php foreach ($CATEGORIES as $cat): ?>
|
||
<option value="<?= htmlspecialchars($cat) ?>"><?= htmlspecialchars($cat) ?></option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
|
||
<label>Description</label>
|
||
<textarea name="description" placeholder="Description"></textarea>
|
||
|
||
<label>Photo</label>
|
||
<input type="file" name="photo">
|
||
|
||
<button>Enregistrer</button>
|
||
</form>
|
||
</div>
|
||
<?php
|
||
|
||
/* Liste des matériels existants */
|
||
$stmt = $db->prepare("SELECT * FROM items WHERE owner_id=? ORDER BY category COLLATE NOCASE ASC,
|
||
name COLLATE NOCASE ASC
|
||
");
|
||
$stmt->execute([$_SESSION['owner_id']]);
|
||
$items = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||
|
||
echo "<h3>Mes matériels existants</h3>";
|
||
|
||
foreach ($items as $item) {
|
||
|
||
// Décodage du prix
|
||
$price_raw = $item['price'] ?? '';
|
||
$price_parts = explode('|', $price_raw);
|
||
$price_value = floatval($price_parts[0]);
|
||
$price_free = isset($price_parts[1]) && $price_parts[1] === 'free';
|
||
|
||
echo "<article class='item'>";
|
||
echo "<div class='tool-row'>";
|
||
|
||
// Photo
|
||
if (!empty($item['photo'])) {
|
||
echo "<img src='uploads/{$item['photo']}' alt='Photo'>";
|
||
} else {
|
||
echo "<div style='
|
||
width:180px;
|
||
height:120px;
|
||
display:flex;
|
||
align-items:center;
|
||
justify-content:center;
|
||
font-size:60px;
|
||
'>🛠️</div>";
|
||
}
|
||
|
||
echo "<div class='tool-info'>";
|
||
echo "<h3 style='margin: 0;'>" . htmlspecialchars($item['name'] ?? '') . "</h3>";
|
||
|
||
echo "<p style='opacity:.7; font-size:.85rem;'>Catégorie : " . htmlspecialchars($item['category']) . "</p>";
|
||
|
||
echo "<p><strong>Prix :</strong> {$price_value} € / jour";
|
||
if ($price_free) echo " <em>(prix libre)</em>";
|
||
echo "</p>";
|
||
|
||
echo "<p>" . nl2br(htmlspecialchars($item['description'] ?? '')) . "</p>";
|
||
|
||
echo "<footer>";
|
||
echo "<a href='index.php?action=edit_item&id={$item['id']}'>Modifier</a> | ";
|
||
echo "<a href='index.php?action=delete_item&id={$item['id']}' onclick='return confirm(\"Supprimer ce matériel ?\")'>Supprimer</a>";
|
||
echo "</footer>";
|
||
|
||
|
||
echo "</div>"; // tool-info
|
||
echo "</div>"; // tool-row
|
||
echo "</article>";
|
||
}
|
||
}
|
||
?>
|
||
|
||
<script>
|
||
// -----------------------------
|
||
// Recalcul des prix libres
|
||
// -----------------------------
|
||
function updateFreePrices() {
|
||
const incomeInput = document.getElementById('income');
|
||
if (!incomeInput) return; // Pas de champ -> rien à faire
|
||
|
||
const income = parseFloat(incomeInput.value) || 1900;
|
||
const ratio = income / 1900;
|
||
|
||
document.querySelectorAll('.price-block').forEach(block => {
|
||
const base = parseFloat(block.dataset.basePrice);
|
||
const isFree = block.dataset.free === "1" || block.dataset.free === "true";
|
||
|
||
if (!isFree) return;
|
||
|
||
const newPrice = (base * ratio).toFixed(2);
|
||
block.innerHTML = `<strong>Prix :</strong> ${newPrice} € / jour <em>(prix libre)</em>`;
|
||
});
|
||
}
|
||
|
||
// Mise à jour en direct si le champ existe
|
||
const incomeInput = document.getElementById('income');
|
||
if (incomeInput) {
|
||
incomeInput.addEventListener('input', updateFreePrices);
|
||
updateFreePrices(); // Mise à jour initiale
|
||
}
|
||
|
||
// Empêcher Enter dans le formulaire income
|
||
const incomeForm = document.getElementById('income-form');
|
||
if (incomeForm) {
|
||
incomeForm.addEventListener('keydown', function (e) {
|
||
if (e.key === "Enter") e.preventDefault();
|
||
});
|
||
}
|
||
|
||
|
||
// -----------------------------
|
||
// Recherche dynamique
|
||
// -----------------------------
|
||
function updateSearch() {
|
||
const searchInput = document.getElementById('search');
|
||
if (!searchInput) return;
|
||
|
||
const query = searchInput.value.toLowerCase().trim();
|
||
const words = query.split(/\s+/).filter(w => w.length > 0);
|
||
|
||
document.querySelectorAll('article.item').forEach(item => {
|
||
const text = item.dataset.search || "";
|
||
const match = words.every(w => text.includes(w));
|
||
item.style.display = match ? "" : "none";
|
||
});
|
||
}
|
||
|
||
const searchInput = document.getElementById('search');
|
||
if (searchInput) {
|
||
searchInput.addEventListener('input', updateSearch);
|
||
|
||
searchInput.addEventListener('keydown', function (e) {
|
||
if (e.key === "Enter") e.preventDefault();
|
||
});
|
||
}
|
||
|
||
|
||
// -----------------------------
|
||
// Dépliage du formulaire matériel
|
||
// -----------------------------
|
||
const toggleForm = document.getElementById('toggle-form');
|
||
const toolForm = document.getElementById('tool-form');
|
||
|
||
if (toggleForm && toolForm) {
|
||
toggleForm.addEventListener('click', function () {
|
||
toolForm.style.display =
|
||
(toolForm.style.display === "none" || toolForm.style.display === "")
|
||
? "block"
|
||
: "none";
|
||
});
|
||
}
|
||
|
||
</script>
|
||
|
||
<footer style="margin-top:2rem; text-align:center; opacity:.7; font-size:.85rem;">
|
||
Problème ou question :
|
||
<a href="mailto:leo@kabano.org">Léo / leo@kabano.org</a>
|
||
</footer>
|
||
|
||
</body>
|
||
</html>
|