Réalisation du tp3, tp4, tp5 et tp6 avec documentation.

This commit is contained in:
2026-10-07 00:48:56 +02:00
parent fc4c55546f
commit 4a84a17cbf
40 changed files with 1584 additions and 120 deletions
@@ -0,0 +1,41 @@
@extends('layouts.app')
@section('content')
<h2>Ajouter un client</h2>
{{-- TP5 : résumé des erreurs de validation renvoyées par Laravel. --}}
@if ($errors->any())
<div role="alert">
<strong>Des erreurs sont présentes :</strong>
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form method="POST" action="{{ route('clients.store') }}">
{{-- TP4 : protection CSRF du formulaire de création. --}}
@csrf
{{-- TP5 : old() conserve la saisie ; @error affiche le problème sous chaque champ. --}}
<label for="name">Nom</label>
<input id="name" type="text" name="name" value="{{ old('name') }}" required>
@error('name') <div role="alert">{{ $message }}</div> @enderror
<label for="email">Email</label>
<input id="email" type="email" name="email" value="{{ old('email') }}" required>
@error('email') <div role="alert">{{ $message }}</div> @enderror
<label for="phone">Téléphone (facultatif)</label>
<input id="phone" type="text" name="phone" value="{{ old('phone') }}">
@error('phone') <div role="alert">{{ $message }}</div> @enderror
<label for="city">Ville (facultative)</label>
<input id="city" type="text" name="city" value="{{ old('city') }}">
@error('city') <div role="alert">{{ $message }}</div> @enderror
<button type="submit">Enregistrer</button>
</form>
@endsection
@@ -0,0 +1,42 @@
@extends('layouts.app')
@section('content')
<h2>Modifier {{ $client->name }}</h2>
{{-- TP5 : messages de validation visibles aussi lors d'une modification. --}}
@if ($errors->any())
<div role="alert">
<strong>Des erreurs sont présentes :</strong>
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form method="POST" action="{{ route('clients.update', $client) }}">
{{-- TP4 : un formulaire HTML POST représente ici une mise à jour PUT. --}}
@csrf
@method('PUT')
{{-- TP5 : old() reprend la saisie refusée ou, sinon, la valeur du client. --}}
<label for="name">Nom</label>
<input id="name" type="text" name="name" value="{{ old('name', $client->name) }}" required>
@error('name') <div role="alert">{{ $message }}</div> @enderror
<label for="email">Email</label>
<input id="email" type="email" name="email" value="{{ old('email', $client->email) }}" required>
@error('email') <div role="alert">{{ $message }}</div> @enderror
<label for="phone">Téléphone (facultatif)</label>
<input id="phone" type="text" name="phone" value="{{ old('phone', $client->phone) }}">
@error('phone') <div role="alert">{{ $message }}</div> @enderror
<label for="city">Ville (facultative)</label>
<input id="city" type="text" name="city" value="{{ old('city', $client->city) }}">
@error('city') <div role="alert">{{ $message }}</div> @enderror
<button type="submit">Mettre à jour</button>
</form>
@endsection
@@ -1,19 +1,45 @@
@extends('layouts.app')
@section('content')
<h2> Liste des clients : </h2>
<h2>Liste des clients</h2>
{{-- TP4 : total, date et actions ; TP6 : total de tous les résultats, même sur plusieurs pages. --}}
<p>Nombre total de clients : {{ $clients->total() }}</p>
<p><a href="{{ route('clients.create') }}">Ajouter un client</a></p>
{{-- TP6 : GET rend la recherche visible dans l'URL sans modifier la base. --}}
<form method="GET" action="{{ route('clients.index') }}">
<label for="client-search">Rechercher par nom, email ou ville</label>
<input id="client-search" type="search" name="search" value="{{ $search }}" placeholder="Rechercher un client">
<button type="submit">Rechercher</button>
<a href="{{ route('clients.index') }}">Effacer</a>
</form>
<table>
<tr>
<th>Nom</th>
<!-- <th>Email</th>
<th>Ville</th> -->
<th>Email</th>
<th>Téléphone</th>
<th>Ville</th>
<th>Client créé le</th>
<th>Actions</th>
</tr>
<!-- @foreach($clients as $client) -->
@foreach($clients as $client)
<tr>
<td>{{ $clients->name }}</td>
<td>{{ $client->name }}</td>
<td>{{ $client->email }}</td>
<td>{{ $client->phone ?? '—' }}</td>
<td>{{ $client->city ?? '—' }}</td>
<td>{{ $client->created_at->format('d/m/Y') }}</td>
<td>
<a href="{{ route('clients.show', $client) }}">Voir</a>
<a href="{{ route('clients.edit', $client) }}">Modifier</a>
<form method="POST" action="{{ route('clients.destroy', $client) }}" style="display: inline">
@csrf
@method('DELETE')
<button type="submit">Supprimer</button>
</form>
</td>
</tr>
<!-- @endforeach -->
@endforeach
</table>
{{-- TP6 : liens générés pour les dix résultats de chaque page. --}}
{{ $clients->links() }}
@endsection
@@ -0,0 +1,10 @@
@extends('layouts.app')
@section('content')
<h2>{{ $client->name }}</h2>
<p>Email : {{ $client->email }}</p>
<p>Téléphone : {{ $client->phone ?? '—' }}</p>
<p>Ville : {{ $client->city ?? '—' }}</p>
<p>Client créé le : {{ $client->created_at->format('d/m/Y') }}</p>
<a href="{{ route('clients.index') }}">Retour</a>
@endsection
@@ -3,14 +3,20 @@
<head>
<meta charset="UTF-8">
<title>Mini-CRM</title>
{{-- TP6 : taille lisible des flèches SVG utilisées par la pagination Laravel. --}}
<style>
main nav[role="navigation"] svg { width: 1rem; height: 1rem; }
main nav[role="navigation"] a, main nav[role="navigation"] span { margin-right: .35rem; }
</style>
</head>
<body>
<header>
<h1>Mini-CRM</h1>
<nav>
<a href="/">Accueil</a>
<a href="/clients">Clients</a>
<a href="/products">Produits</a>
<a href="{{ route('clients.index') }}">Clients</a>
<a href="{{ route('clients.create') }}">Ajouter un client</a>
<a href="{{ route('products.index') }}">Produits</a>
<a href="/contacts">Contacts</a>
@@ -23,4 +29,4 @@
Mini-CRM
</footer>
</body>
</html>
</html>
@@ -0,0 +1,37 @@
@extends('layouts.app')
@section('content')
<h2>Ajouter un produit</h2>
{{-- TP5 : liste générale des erreurs de validation. --}}
@if ($errors->any())
<div role="alert">
<strong>Des erreurs sont présentes :</strong>
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form method="POST" action="{{ route('products.store') }}">
{{-- TP4 : formulaire de création protégé par un jeton CSRF. --}}
@csrf
{{-- TP5 : anciennes valeurs et erreurs propres à chaque champ. --}}
<label for="name">Nom</label>
<input id="name" type="text" name="name" value="{{ old('name') }}" required>
@error('name') <div role="alert">{{ $message }}</div> @enderror
<label for="price">Prix (EUR)</label>
<input id="price" type="number" name="price" min="0" step="0.01" value="{{ old('price') }}" required>
@error('price') <div role="alert">{{ $message }}</div> @enderror
<label for="stock">Stock</label>
<input id="stock" type="number" name="stock" min="0" value="{{ old('stock') }}" required>
@error('stock') <div role="alert">{{ $message }}</div> @enderror
<button type="submit">Enregistrer</button>
</form>
@endsection
@@ -0,0 +1,38 @@
@extends('layouts.app')
@section('content')
<h2>Modifier {{ $product->name }}</h2>
{{-- TP5 : erreurs de validation de la modification. --}}
@if ($errors->any())
<div role="alert">
<strong>Des erreurs sont présentes :</strong>
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form method="POST" action="{{ route('products.update', $product) }}">
{{-- TP4 : @method('PUT') permet la route products.update. --}}
@csrf
@method('PUT')
{{-- TP5 : old() conserve la saisie après une erreur. --}}
<label for="name">Nom</label>
<input id="name" type="text" name="name" value="{{ old('name', $product->name) }}" required>
@error('name') <div role="alert">{{ $message }}</div> @enderror
<label for="price">Prix (EUR)</label>
<input id="price" type="number" name="price" min="0" step="0.01" value="{{ old('price', $product->price) }}" required>
@error('price') <div role="alert">{{ $message }}</div> @enderror
<label for="stock">Stock</label>
<input id="stock" type="number" name="stock" min="0" value="{{ old('stock', $product->stock) }}" required>
@error('stock') <div role="alert">{{ $message }}</div> @enderror
<button type="submit">Mettre à jour</button>
</form>
@endsection
@@ -1,26 +1,48 @@
@extends('layouts.app')
@section('content')
<h3> Liste des produtis : </h3>
<h2>Liste des produits</h2>
{{-- TP3 : affichage des produits ; TP4 : actions CRUD et indication de stock faible. --}}
<p>Nombre total de produits : {{ $products->total() }}</p>
<p><a href="{{ route('products.create') }}">Ajouter un produit</a></p>
{{-- TP6 : recherche par nom ; le prix est inclus pour le bonus. --}}
<form method="GET" action="{{ route('products.index') }}">
<label for="product-search">Rechercher par nom ou prix</label>
<input id="product-search" type="search" name="search" value="{{ $search }}" placeholder="Rechercher un produit">
<button type="submit">Rechercher</button>
<a href="{{ route('products.index') }}">Effacer</a>
</form>
<table>
<tr>
<th>Produit</th>
<th>Prix</th>
<th>Stock</th>
<th>Disponibilité</th>
<th>Actions</th>
</tr>
@foreach($products as $produit)
<tr>
<td>{{ $produit['name'] }}</td>
<td>{{ $produit['price'] }}</td>
<td>{{ $produit['stock'] }}</td>
<td>@if($produit['stock'] < 5 && $produit['stock'] != 0)
Stock faible
@else
Stock disponible
<td>{{ $produit->name }}</td>
<td>{{ $produit->price }} €</td>
<td>{{ $produit->stock }}</td>
<td>
@if($produit->stock < 5)
⚠ Stock faible
@else
Stock disponible
@endif
</td>
<td>
<a href="{{ route('products.show', $produit) }}">Voir</a>
<a href="{{ route('products.edit', $produit) }}">Modifier</a>
<form method="POST" action="{{ route('products.destroy', $produit) }}" style="display: inline">
@csrf
@method('DELETE')
<button type="submit">Supprimer</button>
</form>
</td>
@endif
</tr>
@endforeach
</table>
@endsection
{{-- TP6 : la recherche est conservée dans les liens grâce à withQueryString(). --}}
{{ $products->links() }}
@endsection
@@ -0,0 +1,9 @@
@extends('layouts.app')
@section('content')
<h2>{{ $product->name }}</h2>
<p>Prix : {{ $product->price }} EUR</p>
<p>Stock : {{ $product->stock }}</p>
<p>Disponibilité : {{ $product->stock < 5 ? '⚠ Stock faible' : 'Disponible' }}</p>
<a href="{{ route('products.index') }}">Retour</a>
@endsection