2 Commits

Author SHA1 Message Date
Clément
a5a03737a9 finished api no auth 2025-06-03 14:46:58 +02:00
Clément
2c4aeb4704 to squeeze 2025-06-03 14:10:35 +02:00
112 changed files with 1617 additions and 6762 deletions

View File

@@ -10,31 +10,3 @@
- `storage` => logs, cache - `storage` => logs, cache
- `tests` => tests de l'app (automatisés) - `tests` => tests de l'app (automatisés)
- `vendor` => le dossier de composer (on n'y touche pas) - `vendor` => le dossier de composer (on n'y touche pas)
# Commandes PHP Artisan (Docker)
- Créer une migration => `php artisan make:migration create_nom_table`
- migration => `php artisan migrate:fresh`
- seeder => `php artisan db:seed --class=NomSeeder`
php artisan make:model Categorie --migration -a
php artisan make:model billet_categorie -m
```sql
use laravel_db;
INSERT INTO billet_categorie (id, billet_id, categorie_id, created_at, updated_at)
VALUES
(1, 1, 1, NULL, NULL),
(2, 1, 2, NULL, NULL),
(3, 1, 10, NULL, NULL),
(4, 2, 3, NULL, NULL),
(5, 3, 9, NULL, NULL),
(6, 4, 1, NULL, NULL),
(7, 4, 4, NULL, NULL),
(8, 5, 5, NULL, NULL),
(9, 6, 7, NULL, NULL),
(10, 7, 1, NULL, NULL),
(11, 8, 10, NULL, NULL),
(12, 9, 6, NULL, NULL),
(13, 10, 8, NULL, NULL);
```

View File

@@ -12,12 +12,9 @@ services:
- laravel_db_volume:/var/lib/mysql - laravel_db_volume:/var/lib/mysql
laravel: laravel:
build: image: bitnami/laravel
context: images
dockerfile: Laravel_Dockerfile
ports: ports:
- "8080:8000" - "8080:8000"
- "8001:8001"
environment: environment:
LARAVEL_DATABASE_USER: laravel_user LARAVEL_DATABASE_USER: laravel_user
LARAVEL_DATABASE_PASSWORD: super_strong_password LARAVEL_DATABASE_PASSWORD: super_strong_password

View File

@@ -1,7 +0,0 @@
FROM bitnami/laravel
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/master/install.sh | bash
RUN . ~/.nvm/nvm.sh && nvm install --lts
RUN composer require laravel/breeze --dev

View File

@@ -1,3 +0,0 @@
composer require laravel/breeze --dev
php artisan breeze:install blade
php artisan migrate

View File

@@ -1,47 +0,0 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Http\Requests\Auth\LoginRequest;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;
class AuthenticatedSessionController extends Controller
{
/**
* Display the login view.
*/
public function create(): View
{
return view('auth.login');
}
/**
* Handle an incoming authentication request.
*/
public function store(LoginRequest $request): RedirectResponse
{
$request->authenticate();
$request->session()->regenerate();
return redirect()->intended(route('dashboard', absolute: false));
}
/**
* Destroy an authenticated session.
*/
public function destroy(Request $request): RedirectResponse
{
Auth::guard('web')->logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect('/');
}
}

View File

@@ -1,40 +0,0 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\ValidationException;
use Illuminate\View\View;
class ConfirmablePasswordController extends Controller
{
/**
* Show the confirm password view.
*/
public function show(): View
{
return view('auth.confirm-password');
}
/**
* Confirm the user's password.
*/
public function store(Request $request): RedirectResponse
{
if (! Auth::guard('web')->validate([
'email' => $request->user()->email,
'password' => $request->password,
])) {
throw ValidationException::withMessages([
'password' => __('auth.password'),
]);
}
$request->session()->put('auth.password_confirmed_at', time());
return redirect()->intended(route('dashboard', absolute: false));
}
}

View File

@@ -1,24 +0,0 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
class EmailVerificationNotificationController extends Controller
{
/**
* Send a new email verification notification.
*/
public function store(Request $request): RedirectResponse
{
if ($request->user()->hasVerifiedEmail()) {
return redirect()->intended(route('dashboard', absolute: false));
}
$request->user()->sendEmailVerificationNotification();
return back()->with('status', 'verification-link-sent');
}
}

View File

@@ -1,21 +0,0 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
class EmailVerificationPromptController extends Controller
{
/**
* Display the email verification prompt.
*/
public function __invoke(Request $request): RedirectResponse|View
{
return $request->user()->hasVerifiedEmail()
? redirect()->intended(route('dashboard', absolute: false))
: view('auth.verify-email');
}
}

View File

@@ -1,62 +0,0 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Auth\Events\PasswordReset;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Str;
use Illuminate\Validation\Rules;
use Illuminate\View\View;
class NewPasswordController extends Controller
{
/**
* Display the password reset view.
*/
public function create(Request $request): View
{
return view('auth.reset-password', ['request' => $request]);
}
/**
* Handle an incoming new password request.
*
* @throws \Illuminate\Validation\ValidationException
*/
public function store(Request $request): RedirectResponse
{
$request->validate([
'token' => ['required'],
'email' => ['required', 'email'],
'password' => ['required', 'confirmed', Rules\Password::defaults()],
]);
// Here we will attempt to reset the user's password. If it is successful we
// will update the password on an actual user model and persist it to the
// database. Otherwise we will parse the error and return the response.
$status = Password::reset(
$request->only('email', 'password', 'password_confirmation', 'token'),
function (User $user) use ($request) {
$user->forceFill([
'password' => Hash::make($request->password),
'remember_token' => Str::random(60),
])->save();
event(new PasswordReset($user));
}
);
// If the password was successfully reset, we will redirect the user back to
// the application's home authenticated view. If there is an error we can
// redirect them back to where they came from with their error message.
return $status == Password::PASSWORD_RESET
? redirect()->route('login')->with('status', __($status))
: back()->withInput($request->only('email'))
->withErrors(['email' => __($status)]);
}
}

View File

@@ -1,29 +0,0 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rules\Password;
class PasswordController extends Controller
{
/**
* Update the user's password.
*/
public function update(Request $request): RedirectResponse
{
$validated = $request->validateWithBag('updatePassword', [
'current_password' => ['required', 'current_password'],
'password' => ['required', Password::defaults(), 'confirmed'],
]);
$request->user()->update([
'password' => Hash::make($validated['password']),
]);
return back()->with('status', 'password-updated');
}
}

View File

@@ -1,44 +0,0 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Password;
use Illuminate\View\View;
class PasswordResetLinkController extends Controller
{
/**
* Display the password reset link request view.
*/
public function create(): View
{
return view('auth.forgot-password');
}
/**
* Handle an incoming password reset link request.
*
* @throws \Illuminate\Validation\ValidationException
*/
public function store(Request $request): RedirectResponse
{
$request->validate([
'email' => ['required', 'email'],
]);
// We will send the password reset link to this user. Once we have attempted
// to send the link, we will examine the response then see the message we
// need to show to the user. Finally, we'll send out a proper response.
$status = Password::sendResetLink(
$request->only('email')
);
return $status == Password::RESET_LINK_SENT
? back()->with('status', __($status))
: back()->withInput($request->only('email'))
->withErrors(['email' => __($status)]);
}
}

View File

@@ -1,50 +0,0 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Auth\Events\Registered;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rules;
use Illuminate\View\View;
class RegisteredUserController extends Controller
{
/**
* Display the registration view.
*/
public function create(): View
{
return view('auth.register');
}
/**
* Handle an incoming registration request.
*
* @throws \Illuminate\Validation\ValidationException
*/
public function store(Request $request): RedirectResponse
{
$request->validate([
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'lowercase', 'email', 'max:255', 'unique:'.User::class],
'password' => ['required', 'confirmed', Rules\Password::defaults()],
]);
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
event(new Registered($user));
Auth::login($user);
return redirect(route('billets.index'));
}
}

View File

@@ -1,27 +0,0 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Auth\Events\Verified;
use Illuminate\Foundation\Auth\EmailVerificationRequest;
use Illuminate\Http\RedirectResponse;
class VerifyEmailController extends Controller
{
/**
* Mark the authenticated user's email address as verified.
*/
public function __invoke(EmailVerificationRequest $request): RedirectResponse
{
if ($request->user()->hasVerifiedEmail()) {
return redirect()->intended(route('dashboard', absolute: false).'?verified=1');
}
if ($request->user()->markEmailAsVerified()) {
event(new Verified($request->user()));
}
return redirect()->intended(route('dashboard', absolute: false).'?verified=1');
}
}

49
laravel/app/Http/Controllers/BilletController.php Executable file → Normal file
View File

@@ -2,12 +2,10 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Http\Requests\StoreBilletRequest;
use App\Http\Requests\UpdateBilletRequest;
use App\Models\Billet; use App\Models\Billet;
use App\Http\Resources\BilletResource;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Illuminate\Database\QueryException;
class BilletController extends Controller class BilletController extends Controller
{ {
@@ -16,27 +14,22 @@ class BilletController extends Controller
*/ */
public function index() public function index()
{ {
//Return all posts in json format
try { try {
$billets = Billet::all(); return BilletResource::collection(Billet::with('commentaires')->get());
} catch (QueryException $e) {
Log::channel('projectError')->error('Erreur d\'accès à la base de données');
return view('errors.dberror');
} }
return view('index', compact('billets')); catch (\Illuminate\Database\QueryException $e){
Log::channel('projectError')->error('Erreur accès base de données');
return response()->json([
'message' => 'Ressource indinponible.'
],500);
} }
/**
* Show the form for creating a new resource.
*/
public function create()
{
//
} }
/** /**
* Store a newly created resource in storage. * Store a newly created resource in storage.
*/ */
public function store(StoreBilletRequest $request) public function store(Request $request)
{ {
// //
} }
@@ -46,27 +39,21 @@ class BilletController extends Controller
*/ */
public function show(Billet $billet) public function show(Billet $billet)
{ {
// try{
try { return new BilletResource($billet);
$commentaires = $billet->commentaires;
} catch (QueryException $e) {
return view('errors.dberror');
} }
return view('vBillet', compact('billet', 'commentaires')); catch (\Illuminate\Database\QueryException $e){
Log::channel('projectError')->error('Erreur accès base de données');
return response()->json([
'message' => 'Ressource indinponible.'
],500);
} }
/**
* Show the form for editing the specified resource.
*/
public function edit(Billet $billet)
{
//
} }
/** /**
* Update the specified resource in storage. * Update the specified resource in storage.
*/ */
public function update(UpdateBilletRequest $request, Billet $billet) public function update(Request $request, Billet $billet)
{ {
// //
} }

View File

@@ -1,66 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Http\Requests\StoreCategorieRequest;
use App\Http\Requests\UpdateCategorieRequest;
use App\Models\Categorie;
class CategorieController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
//
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*/
public function store(StoreCategorieRequest $request)
{
//
}
/**
* Display the specified resource.
*/
public function show(Categorie $categorie)
{
//
}
/**
* Show the form for editing the specified resource.
*/
public function edit(Categorie $categorie)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(UpdateCategorieRequest $request, Categorie $categorie)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(Categorie $categorie)
{
//
}
}

54
laravel/app/Http/Controllers/CommentaireController.php Executable file → Normal file
View File

@@ -2,10 +2,9 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Http\Requests\StoreCommentaireRequest; use App\Http\Requests\CommentaireRequest;
use App\Http\Requests\UpdateCommentaireRequest;
use App\Models\Commentaire; use App\Models\Commentaire;
use App\Models\Billet; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
class CommentaireController extends Controller class CommentaireController extends Controller
@@ -18,40 +17,23 @@ class CommentaireController extends Controller
// //
} }
/**
* Show the form for creating a new resource.
*/
public function create($idBillet)
{
try {
$billet = Billet::findOrFail($idBillet);
}
catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
Log::channel('projectError')->error('Commentaire : Billet non trouvé');
return view('errors.unavailable');
}
catch (\Illuminate\Database\QueryException $e) {
Log::channel('projectError')->error('Erreur accès base de données');
return view('errors.dberror');
}
return view('vCommenter', compact('idBillet', 'billet'));
}
/** /**
* Store a newly created resource in storage. * Store a newly created resource in storage.
*/ */
public function store(StoreCommentaireRequest $request) public function store(CommentaireRequest $request)
{ {
//
try { try {
Commentaire::create($request->all()); $commentaire = Commentaire::create($request->all());
return response()->json($commentaire,201);
} }
catch (\Illuminate\Database\QueryException $e) { catch(\Illuminate\Database\QueryException $e){
Log::channel('projectError')->error('Insertion en base de données impossible'); Log::channel('projectError')->error('Erreur accès base de données\n'.$e->getMessage());
return view('errors.dberror'); return response()->json([
} 'message' => 'Ressource indisponible.'
Log::channel('projectInfo')->info('Commentaire ajouté par : '.$request->ip()); ],500);
return view('vConfirmStore');
} }
}
/** /**
* Display the specified resource. * Display the specified resource.
@@ -61,18 +43,10 @@ class CommentaireController extends Controller
// //
} }
/**
* Show the form for editing the specified resource.
*/
public function edit(Commentaire $commentaire)
{
//
}
/** /**
* Update the specified resource in storage. * Update the specified resource in storage.
*/ */
public function update(UpdateCommentaireRequest $request, Commentaire $commentaire) public function update(Request $request, Commentaire $commentaire)
{ {
// //
} }

View File

@@ -1,60 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Http\Requests\ProfileUpdateRequest;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redirect;
use Illuminate\View\View;
class ProfileController extends Controller
{
/**
* Display the user's profile form.
*/
public function edit(Request $request): View
{
return view('profile.edit', [
'user' => $request->user(),
]);
}
/**
* Update the user's profile information.
*/
public function update(ProfileUpdateRequest $request): RedirectResponse
{
$request->user()->fill($request->validated());
if ($request->user()->isDirty('email')) {
$request->user()->email_verified_at = null;
}
$request->user()->save();
return Redirect::route('profile.edit')->with('status', 'profile-updated');
}
/**
* Delete the user's account.
*/
public function destroy(Request $request): RedirectResponse
{
$request->validateWithBag('userDeletion', [
'password' => ['required', 'current_password'],
]);
$user = $request->user();
Auth::logout();
$user->delete();
$request->session()->invalidate();
$request->session()->regenerateToken();
return Redirect::to('/');
}
}

View File

@@ -1,85 +0,0 @@
<?php
namespace App\Http\Requests\Auth;
use Illuminate\Auth\Events\Lockout;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
class LoginRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'email' => ['required', 'string', 'email'],
'password' => ['required', 'string'],
];
}
/**
* Attempt to authenticate the request's credentials.
*
* @throws \Illuminate\Validation\ValidationException
*/
public function authenticate(): void
{
$this->ensureIsNotRateLimited();
if (! Auth::attempt($this->only('email', 'password'), $this->boolean('remember'))) {
RateLimiter::hit($this->throttleKey());
throw ValidationException::withMessages([
'email' => trans('auth.failed'),
]);
}
RateLimiter::clear($this->throttleKey());
}
/**
* Ensure the login request is not rate limited.
*
* @throws \Illuminate\Validation\ValidationException
*/
public function ensureIsNotRateLimited(): void
{
if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) {
return;
}
event(new Lockout($this));
$seconds = RateLimiter::availableIn($this->throttleKey());
throw ValidationException::withMessages([
'email' => trans('auth.throttle', [
'seconds' => $seconds,
'minutes' => ceil($seconds / 60),
]),
]);
}
/**
* Get the rate limiting throttle key for the request.
*/
public function throttleKey(): string
{
return Str::transliterate(Str::lower($this->string('email')).'|'.$this->ip());
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Contracts\Validation\Validator;
class CommentaireRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'COM_DATE' => ['required', 'date'],
'COM_AUTEUR' => ['required', 'string', 'max:100'],
'COM_CONTENU' => ['required', 'string', 'max:200'],
'billet_id' => ['required', 'integer'],
];
}
public function failedValidation(Validator $validator){
throw new HttpResponseException(response()->json([
'success' => false,
'message' => 'Validation errors',
'data' => $validator->errors()
]));
}
}

View File

@@ -1,30 +0,0 @@
<?php
namespace App\Http\Requests;
use App\Models\User;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class ProfileUpdateRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'name' => ['required', 'string', 'max:255'],
'email' => [
'required',
'string',
'lowercase',
'email',
'max:255',
Rule::unique(User::class)->ignore($this->user()->id),
],
];
}
}

View File

@@ -1,28 +0,0 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreCategorieRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return false;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
//
];
}
}

View File

@@ -1,45 +0,0 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreCommentaireRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'COM_AUTEUR' => ['required', 'alpha', 'max:100'],
'COM_CONTENU' => ['required', 'string', 'max:200'],
];
}
/**
* Get the error messages for the defined validation rules.
*
* @return array
*/
public function messages() {
return [
'COM_AUTEUR.required' => 'Le nom de l\'auteur est requis.',
'COM_AUTEUR.alpha' => 'Le nom de l\'auteur ne doit contenir que des lettres.',
'COM_AUTEUR.max' => 'Le nom de l\'auteur ne doit pas dépasser 100 caractères.',
'COM_CONTENU.required' => 'Le contenu du commentaire est requis.',
'COM_CONTENU.string' => 'Le contenu du commentaire doit être une chaîne de caractères.',
'COM_CONTENU.max' => 'Le contenu du commentaire ne doit pas dépasser 200 caractères.',
];
}
}

View File

@@ -1,28 +0,0 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UpdateCategorieRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return false;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
//
];
}
}

View File

@@ -1,28 +0,0 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UpdateCommentaireRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return false;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
//
];
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class BilletResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
//return parent::toArray($request);
return [
'Date' => $this->BIL_DATE,
'Titre' => $this->BIL_TITRE,
'Contenu' => $this->BIL_CONTENU,
'Commentaires' => CommentaireResource::collection($this->commentaires),
];
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class CommentaireResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
//return parent::toArray($request);
return [
'Date' => $this->COM_DATE,
'Auteur' => $this->COM_AUTEUR,
'Contenu' => $this->COM_CONTENU,
];
}
}

47
laravel/app/Models/Billet.php Executable file → Normal file
View File

@@ -1,30 +1,59 @@
<?php <?php
/**
* Created by Reliese Model.
*/
namespace App\Models; namespace App\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/**
* Class Billet
*
* @property int $id
* @property Carbon $BIL_DATE
* @property string $BIL_TITRE
* @property string $BIL_CONTENU
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
*
* @property Collection|BilletCategorie[] $billet_categories
* @property Collection|Commentaire[] $commentaires
*
* @package App\Models
*/
class Billet extends Model class Billet extends Model
{ {
/** @use HasFactory<\Database\Factories\BilletFactory> */
use HasFactory; use HasFactory;
protected $table = 'billets';
protected $casts = [
'BIL_DATE' => 'datetime'
];
protected $fillable = [ protected $fillable = [
'BIL_DATE', 'BIL_DATE',
'BIL_TITRE', 'BIL_TITRE',
'BIL_CONTENU', 'BIL_CONTENU'
'created_at',
'updated_at',
]; ];
protected $hidden = [
'id',
'created_at',
'updated_at'
];
public function billet_categories()
{
return $this->hasMany(BilletCategorie::class);
}
public function commentaires() public function commentaires()
{ {
return $this->hasMany(Commentaire::class); return $this->hasMany(Commentaire::class);
} }
public function categories()
{
return $this->belongsToMany(Categorie::class);
}
} }

View File

@@ -0,0 +1,49 @@
<?php
/**
* Created by Reliese Model.
*/
namespace App\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
/**
* Class BilletCategorie
*
* @property int $id
* @property int $billet_id
* @property int $categorie_id
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
*
* @property Billet $billet
* @property Category $category
*
* @package App\Models
*/
class BilletCategorie extends Model
{
protected $table = 'billet_categorie';
protected $casts = [
'billet_id' => 'int',
'categorie_id' => 'int'
];
protected $fillable = [
'billet_id',
'categorie_id'
];
public function billet()
{
return $this->belongsTo(Billet::class);
}
public function category()
{
return $this->belongsTo(Category::class, 'categorie_id');
}
}

35
laravel/app/Models/Cache.php Executable file
View File

@@ -0,0 +1,35 @@
<?php
/**
* Created by Reliese Model.
*/
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
/**
* Class Cache
*
* @property string $key
* @property string $value
* @property int $expiration
*
* @package App\Models
*/
class Cache extends Model
{
protected $table = 'cache';
protected $primaryKey = 'key';
public $incrementing = false;
public $timestamps = false;
protected $casts = [
'expiration' => 'int'
];
protected $fillable = [
'value',
'expiration'
];
}

View File

@@ -0,0 +1,35 @@
<?php
/**
* Created by Reliese Model.
*/
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
/**
* Class CacheLock
*
* @property string $key
* @property string $owner
* @property int $expiration
*
* @package App\Models
*/
class CacheLock extends Model
{
protected $table = 'cache_locks';
protected $primaryKey = 'key';
public $incrementing = false;
public $timestamps = false;
protected $casts = [
'expiration' => 'int'
];
protected $fillable = [
'owner',
'expiration'
];
}

View File

@@ -1,17 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Categorie extends Model
{
/** @use HasFactory<\Database\Factories\CategorieFactory> */
use HasFactory;
public function billets()
{
return $this->belongsToMany(Billet::class);
}
}

View File

@@ -0,0 +1,37 @@
<?php
/**
* Created by Reliese Model.
*/
namespace App\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
/**
* Class Category
*
* @property int $id
* @property string $CAT_NOM
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
*
* @property Collection|BilletCategorie[] $billet_categories
*
* @package App\Models
*/
class Category extends Model
{
protected $table = 'categories';
protected $fillable = [
'CAT_NOM'
];
public function billet_categories()
{
return $this->hasMany(BilletCategorie::class, 'categorie_id');
}
}

38
laravel/app/Models/Commentaire.php Executable file → Normal file
View File

@@ -1,26 +1,54 @@
<?php <?php
/**
* Created by Reliese Model.
*/
namespace App\Models; namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/**
* Class Commentaire
*
* @property int $id
* @property Carbon $COM_DATE
* @property string $COM_AUTEUR
* @property string $COM_CONTENU
* @property int $billet_id
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
*
* @property Billet $billet
*
* @package App\Models
*/
class Commentaire extends Model class Commentaire extends Model
{ {
/** @use HasFactory<\Database\Factories\CommentaireFactory> */ protected $table = 'commentaires';
use HasFactory;
protected $casts = [
'COM_DATE' => 'datetime',
'billet_id' => 'int'
];
protected $fillable = [ protected $fillable = [
'COM_DATE', 'COM_DATE',
'COM_AUTEUR', 'COM_AUTEUR',
'COM_CONTENU', 'COM_CONTENU',
'billet_id', 'billet_id'
];
protected $hidden = [
'id',
'created_at', 'created_at',
'updated_at', 'updated_at',
'billet_id'
]; ];
public function billet() public function billet()
{ {
return $this->belongsTo(Billet::class, 'billet_id'); return $this->belongsTo(Billet::class);
} }
} }

42
laravel/app/Models/Job.php Executable file
View File

@@ -0,0 +1,42 @@
<?php
/**
* Created by Reliese Model.
*/
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
/**
* Class Job
*
* @property int $id
* @property string $queue
* @property string $payload
* @property int $attempts
* @property int|null $reserved_at
* @property int $available_at
* @property int $created_at
*
* @package App\Models
*/
class Job extends Model
{
protected $table = 'jobs';
public $timestamps = false;
protected $casts = [
'attempts' => 'int',
'reserved_at' => 'int',
'available_at' => 'int'
];
protected $fillable = [
'queue',
'payload',
'attempts',
'reserved_at',
'available_at'
];
}

51
laravel/app/Models/JobBatch.php Executable file
View File

@@ -0,0 +1,51 @@
<?php
/**
* Created by Reliese Model.
*/
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
/**
* Class JobBatch
*
* @property string $id
* @property string $name
* @property int $total_jobs
* @property int $pending_jobs
* @property int $failed_jobs
* @property string $failed_job_ids
* @property string|null $options
* @property int|null $cancelled_at
* @property int $created_at
* @property int|null $finished_at
*
* @package App\Models
*/
class JobBatch extends Model
{
protected $table = 'job_batches';
public $incrementing = false;
public $timestamps = false;
protected $casts = [
'total_jobs' => 'int',
'pending_jobs' => 'int',
'failed_jobs' => 'int',
'cancelled_at' => 'int',
'finished_at' => 'int'
];
protected $fillable = [
'name',
'total_jobs',
'pending_jobs',
'failed_jobs',
'failed_job_ids',
'options',
'cancelled_at',
'finished_at'
];
}

41
laravel/app/Models/Session.php Executable file
View File

@@ -0,0 +1,41 @@
<?php
/**
* Created by Reliese Model.
*/
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
/**
* Class Session
*
* @property string $id
* @property int|null $user_id
* @property string|null $ip_address
* @property string|null $user_agent
* @property string $payload
* @property int $last_activity
*
* @package App\Models
*/
class Session extends Model
{
protected $table = 'sessions';
public $incrementing = false;
public $timestamps = false;
protected $casts = [
'user_id' => 'int',
'last_activity' => 'int'
];
protected $fillable = [
'user_id',
'ip_address',
'user_agent',
'payload',
'last_activity'
];
}

View File

@@ -1,48 +1,49 @@
<?php <?php
/**
* Created by Reliese Model.
*/
namespace App\Models; namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail; use Carbon\Carbon;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable /**
{ * Class User
/** @use HasFactory<\Database\Factories\UserFactory> */
use HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
* *
* @var list<string> * @property int $id
* @property string $name
* @property string $email
* @property Carbon|null $email_verified_at
* @property string $password
* @property string|null $remember_token
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
*
* @package App\Models
*/ */
class User extends Model
{
use HasFactory;
protected $table = 'users';
protected $casts = [
'email_verified_at' => 'datetime'
];
protected $hidden = [
'password',
'remember_token'
];
protected $fillable = [ protected $fillable = [
'name', 'name',
'email', 'email',
'email_verified_at',
'password', 'password',
'remember_token'
]; ];
/**
* The attributes that should be hidden for serialization.
*
* @var list<string>
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
}
} }

View File

@@ -1,12 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class billet_categorie extends Model
{
/** @use HasFactory<\Database\Factories\BilletCategorieFactory> */
use HasFactory;
}

View File

@@ -1,66 +0,0 @@
<?php
namespace App\Policies;
use App\Models\Categorie;
use App\Models\User;
use Illuminate\Auth\Access\Response;
class CategoriePolicy
{
/**
* Determine whether the user can view any models.
*/
public function viewAny(User $user): bool
{
return false;
}
/**
* Determine whether the user can view the model.
*/
public function view(User $user, Categorie $categorie): bool
{
return false;
}
/**
* Determine whether the user can create models.
*/
public function create(User $user): bool
{
return false;
}
/**
* Determine whether the user can update the model.
*/
public function update(User $user, Categorie $categorie): bool
{
return false;
}
/**
* Determine whether the user can delete the model.
*/
public function delete(User $user, Categorie $categorie): bool
{
return false;
}
/**
* Determine whether the user can restore the model.
*/
public function restore(User $user, Categorie $categorie): bool
{
return false;
}
/**
* Determine whether the user can permanently delete the model.
*/
public function forceDelete(User $user, Categorie $categorie): bool
{
return false;
}
}

View File

@@ -1,66 +0,0 @@
<?php
namespace App\Policies;
use App\Models\Commentaire;
use App\Models\User;
use Illuminate\Auth\Access\Response;
class CommentairePolicy
{
/**
* Determine whether the user can view any models.
*/
public function viewAny(User $user): bool
{
return false;
}
/**
* Determine whether the user can view the model.
*/
public function view(User $user, Commentaire $commentaire): bool
{
return false;
}
/**
* Determine whether the user can create models.
*/
public function create(User $user): bool
{
return false;
}
/**
* Determine whether the user can update the model.
*/
public function update(User $user, Commentaire $commentaire): bool
{
return false;
}
/**
* Determine whether the user can delete the model.
*/
public function delete(User $user, Commentaire $commentaire): bool
{
return false;
}
/**
* Determine whether the user can restore the model.
*/
public function restore(User $user, Commentaire $commentaire): bool
{
return false;
}
/**
* Determine whether the user can permanently delete the model.
*/
public function forceDelete(User $user, Commentaire $commentaire): bool
{
return false;
}
}

View File

@@ -1,17 +0,0 @@
<?php
namespace App\View\Components;
use Illuminate\View\Component;
use Illuminate\View\View;
class AppLayout extends Component
{
/**
* Get the view / contents that represents the component.
*/
public function render(): View
{
return view('layouts.app');
}
}

View File

@@ -1,17 +0,0 @@
<?php
namespace App\View\Components;
use Illuminate\View\Component;
use Illuminate\View\View;
class GuestLayout extends Component
{
/**
* Get the view / contents that represents the component.
*/
public function render(): View
{
return view('layouts.guest');
}
}

View File

@@ -3,10 +3,12 @@
use Illuminate\Foundation\Application; use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions; use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware; use Illuminate\Foundation\Configuration\Middleware;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
return Application::configure(basePath: dirname(__DIR__)) return Application::configure(basePath: dirname(__DIR__))
->withRouting( ->withRouting(
web: __DIR__.'/../routes/web.php', web: __DIR__.'/../routes/web.php',
api: __DIR__.'/../routes/api.php',
commands: __DIR__.'/../routes/console.php', commands: __DIR__.'/../routes/console.php',
health: '/up', health: '/up',
) )
@@ -14,5 +16,9 @@ return Application::configure(basePath: dirname(__DIR__))
// //
}) })
->withExceptions(function (Exceptions $exceptions) { ->withExceptions(function (Exceptions $exceptions) {
// $exceptions->renderable(function (NotFoundHttpException $e){
return response()->json([
'message' => 'Ressource non trouvée.'
],404);
});
})->create(); })->create();

View File

@@ -8,17 +8,18 @@
"require": { "require": {
"php": "^8.2", "php": "^8.2",
"laravel/framework": "^12.0", "laravel/framework": "^12.0",
"laravel/sanctum": "^4.0",
"laravel/tinker": "^2.10.1" "laravel/tinker": "^2.10.1"
}, },
"require-dev": { "require-dev": {
"fakerphp/faker": "^1.23", "fakerphp/faker": "^1.23",
"laravel/breeze": "^2.3",
"laravel/pail": "^1.2.2", "laravel/pail": "^1.2.2",
"laravel/pint": "^1.13", "laravel/pint": "^1.13",
"laravel/sail": "^1.41", "laravel/sail": "^1.41",
"mockery/mockery": "^1.6", "mockery/mockery": "^1.6",
"nunomaduro/collision": "^8.6", "nunomaduro/collision": "^8.6",
"phpunit/phpunit": "^11.5.3" "phpunit/phpunit": "^11.5.3",
"reliese/laravel": "^1.4"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

393
laravel/composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "d6c73ea5dadcd971050eeb806511e47d", "content-hash": "cc1f42d2dd2bf6629798006e6a8a4606",
"packages": [ "packages": [
{ {
"name": "brick/math", "name": "brick/math",
@@ -1328,6 +1328,70 @@
}, },
"time": "2025-02-11T13:34:40+00:00" "time": "2025-02-11T13:34:40+00:00"
}, },
{
"name": "laravel/sanctum",
"version": "v4.1.1",
"source": {
"type": "git",
"url": "https://github.com/laravel/sanctum.git",
"reference": "a360a6a1fd2400ead4eb9b6a9c1bb272939194f5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/sanctum/zipball/a360a6a1fd2400ead4eb9b6a9c1bb272939194f5",
"reference": "a360a6a1fd2400ead4eb9b6a9c1bb272939194f5",
"shasum": ""
},
"require": {
"ext-json": "*",
"illuminate/console": "^11.0|^12.0",
"illuminate/contracts": "^11.0|^12.0",
"illuminate/database": "^11.0|^12.0",
"illuminate/support": "^11.0|^12.0",
"php": "^8.2",
"symfony/console": "^7.0"
},
"require-dev": {
"mockery/mockery": "^1.6",
"orchestra/testbench": "^9.0|^10.0",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^11.3"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Laravel\\Sanctum\\SanctumServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Laravel\\Sanctum\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "Laravel Sanctum provides a featherweight authentication system for SPAs and simple APIs.",
"keywords": [
"auth",
"laravel",
"sanctum"
],
"support": {
"issues": "https://github.com/laravel/sanctum/issues",
"source": "https://github.com/laravel/sanctum"
},
"time": "2025-04-23T13:03:38+00:00"
},
{ {
"name": "laravel/serializable-closure", "name": "laravel/serializable-closure",
"version": "v2.0.4", "version": "v2.0.4",
@@ -5787,6 +5851,160 @@
} }
], ],
"packages-dev": [ "packages-dev": [
{
"name": "doctrine/dbal",
"version": "4.2.3",
"source": {
"type": "git",
"url": "https://github.com/doctrine/dbal.git",
"reference": "33d2d7fe1269b2301640c44cf2896ea607b30e3e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/dbal/zipball/33d2d7fe1269b2301640c44cf2896ea607b30e3e",
"reference": "33d2d7fe1269b2301640c44cf2896ea607b30e3e",
"shasum": ""
},
"require": {
"doctrine/deprecations": "^0.5.3|^1",
"php": "^8.1",
"psr/cache": "^1|^2|^3",
"psr/log": "^1|^2|^3"
},
"require-dev": {
"doctrine/coding-standard": "12.0.0",
"fig/log-test": "^1",
"jetbrains/phpstorm-stubs": "2023.2",
"phpstan/phpstan": "2.1.1",
"phpstan/phpstan-phpunit": "2.0.3",
"phpstan/phpstan-strict-rules": "^2",
"phpunit/phpunit": "10.5.39",
"slevomat/coding-standard": "8.13.1",
"squizlabs/php_codesniffer": "3.10.2",
"symfony/cache": "^6.3.8|^7.0",
"symfony/console": "^5.4|^6.3|^7.0"
},
"suggest": {
"symfony/console": "For helpful console commands such as SQL execution and import of files."
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\DBAL\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
}
],
"description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.",
"homepage": "https://www.doctrine-project.org/projects/dbal.html",
"keywords": [
"abstraction",
"database",
"db2",
"dbal",
"mariadb",
"mssql",
"mysql",
"oci8",
"oracle",
"pdo",
"pgsql",
"postgresql",
"queryobject",
"sasql",
"sql",
"sqlite",
"sqlserver",
"sqlsrv"
],
"support": {
"issues": "https://github.com/doctrine/dbal/issues",
"source": "https://github.com/doctrine/dbal/tree/4.2.3"
},
"funding": [
{
"url": "https://www.doctrine-project.org/sponsorship.html",
"type": "custom"
},
{
"url": "https://www.patreon.com/phpdoctrine",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdbal",
"type": "tidelift"
}
],
"time": "2025-03-07T18:29:05+00:00"
},
{
"name": "doctrine/deprecations",
"version": "1.1.5",
"source": {
"type": "git",
"url": "https://github.com/doctrine/deprecations.git",
"reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/deprecations/zipball/459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38",
"reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"conflict": {
"phpunit/phpunit": "<=7.5 || >=13"
},
"require-dev": {
"doctrine/coding-standard": "^9 || ^12 || ^13",
"phpstan/phpstan": "1.4.10 || 2.1.11",
"phpstan/phpstan-phpunit": "^1.0 || ^2",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12",
"psr/log": "^1 || ^2 || ^3"
},
"suggest": {
"psr/log": "Allows logging deprecations via PSR-3 logger implementation"
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\Deprecations\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.",
"homepage": "https://www.doctrine-project.org/",
"support": {
"issues": "https://github.com/doctrine/deprecations/issues",
"source": "https://github.com/doctrine/deprecations/tree/1.1.5"
},
"time": "2025-04-07T20:06:18+00:00"
},
{ {
"name": "fakerphp/faker", "name": "fakerphp/faker",
"version": "v1.24.1", "version": "v1.24.1",
@@ -5972,67 +6190,6 @@
}, },
"time": "2020-07-09T08:09:16+00:00" "time": "2020-07-09T08:09:16+00:00"
}, },
{
"name": "laravel/breeze",
"version": "v2.3.6",
"source": {
"type": "git",
"url": "https://github.com/laravel/breeze.git",
"reference": "390cbc433cb72fa6050965000b2d56c9ba6fd713"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/breeze/zipball/390cbc433cb72fa6050965000b2d56c9ba6fd713",
"reference": "390cbc433cb72fa6050965000b2d56c9ba6fd713",
"shasum": ""
},
"require": {
"illuminate/console": "^11.0|^12.0",
"illuminate/filesystem": "^11.0|^12.0",
"illuminate/support": "^11.0|^12.0",
"illuminate/validation": "^11.0|^12.0",
"php": "^8.2.0",
"symfony/console": "^7.0"
},
"require-dev": {
"laravel/framework": "^11.0|^12.0",
"orchestra/testbench-core": "^9.0|^10.0",
"phpstan/phpstan": "^2.0"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Laravel\\Breeze\\BreezeServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Laravel\\Breeze\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "Minimal Laravel authentication scaffolding with Blade and Tailwind.",
"keywords": [
"auth",
"laravel"
],
"support": {
"issues": "https://github.com/laravel/breeze/issues",
"source": "https://github.com/laravel/breeze"
},
"time": "2025-03-06T14:02:32+00:00"
},
{ {
"name": "laravel/pail", "name": "laravel/pail",
"version": "v1.2.2", "version": "v1.2.2",
@@ -7024,6 +7181,118 @@
], ],
"time": "2025-04-08T07:59:11+00:00" "time": "2025-04-08T07:59:11+00:00"
}, },
{
"name": "psr/cache",
"version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/cache.git",
"reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
"reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
"shasum": ""
},
"require": {
"php": ">=8.0.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Cache\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for caching libraries",
"keywords": [
"cache",
"psr",
"psr-6"
],
"support": {
"source": "https://github.com/php-fig/cache/tree/3.0.0"
},
"time": "2021-02-03T23:26:27+00:00"
},
{
"name": "reliese/laravel",
"version": "v1.4.0",
"source": {
"type": "git",
"url": "https://github.com/reliese/laravel.git",
"reference": "2181113d420cae67ec68b6bbe6f325900856d6b9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/reliese/laravel/zipball/2181113d420cae67ec68b6bbe6f325900856d6b9",
"reference": "2181113d420cae67ec68b6bbe6f325900856d6b9",
"shasum": ""
},
"require": {
"doctrine/dbal": ">=2.5",
"illuminate/console": ">=5.1",
"illuminate/contracts": ">=5.1",
"illuminate/database": ">=5.1",
"illuminate/filesystem": ">=5.1",
"illuminate/support": ">=5.1",
"php": "^7.3|^8.0"
},
"require-dev": {
"fzaninotto/faker": "~1.4",
"mockery/mockery": ">=1.4",
"phpunit/phpunit": "^9"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Reliese\\Coders\\CodersServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Reliese\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Cristian Llanos",
"email": "cristianllanos@outlook.com"
}
],
"description": "Reliese Components for Laravel Framework code generation.",
"homepage": "http://cristianllanos.com",
"keywords": [
"laravel",
"reliese"
],
"support": {
"issues": "https://github.com/reliese/laravel/issues",
"source": "https://github.com/reliese/laravel"
},
"time": "2025-03-20T16:16:48+00:00"
},
{ {
"name": "sebastian/cli-parser", "name": "sebastian/cli-parser",
"version": "3.0.2", "version": "3.0.2",

View File

@@ -127,18 +127,6 @@ return [
'path' => storage_path('logs/laravel.log'), 'path' => storage_path('logs/laravel.log'),
], ],
"projectError" => [
'driver' => 'single',
'path' => storage_path('logs/project.log'),
'level' => 'error',
],
"projectInfo" => [
'driver' => 'single',
'path' => storage_path('logs/project.log'),
'level' => 'info',
],
], ],
]; ];

534
laravel/config/models.php Executable file
View File

@@ -0,0 +1,534 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Configurations
|--------------------------------------------------------------------------
|
| In this section you may define the default configuration for each model
| that will be generated from any database.
|
*/
'*' => [
/*
|--------------------------------------------------------------------------
| Model Files Location
|--------------------------------------------------------------------------
|
| We need a location to store your new generated files. All files will be
| placed within this directory. When you turn on base files, they will
| be placed within a Base directory inside this location.
|
*/
'path' => app_path('Models'),
/*
|--------------------------------------------------------------------------
| Model Namespace
|--------------------------------------------------------------------------
|
| Every generated model will belong to this namespace. It is suggested
| that this namespace should follow PSR-4 convention and be very
| similar to the path of your models defined above.
|
*/
'namespace' => 'App\Models',
/*
|--------------------------------------------------------------------------
| Parent Class
|--------------------------------------------------------------------------
|
| All Eloquent models should inherit from Eloquent Model class. However,
| you can define a custom Eloquent model that suits your needs.
| As an example one custom model has been added for you which
| will allow you to create custom database castings.
|
*/
'parent' => Illuminate\Database\Eloquent\Model::class,
/*
|--------------------------------------------------------------------------
| Traits
|--------------------------------------------------------------------------
|
| Sometimes you may want to append certain traits to all your models.
| If that is what you need, you may list them bellow.
| As an example we have a BitBooleans trait which will treat MySQL bit
| data type as booleans. You might probably not need it, but it is
| an example of how you can customize your models.
|
*/
'use' => [
// Reliese\Database\Eloquent\BitBooleans::class,
// Reliese\Database\Eloquent\BlamableBehavior::class,
],
/*
|--------------------------------------------------------------------------
| Model Connection
|--------------------------------------------------------------------------
|
| If you wish your models had appended the connection from which they
| were generated, you should set this value to true and your
| models will have the connection property filled.
|
*/
'connection' => false,
/*
|--------------------------------------------------------------------------
| Timestamps
|--------------------------------------------------------------------------
|
| If your tables have CREATED_AT and UPDATED_AT timestamps you may
| enable them and your models will fill their values as needed.
| You can also specify which fields should be treated as timestamps
| in case you don't follow the naming convention Eloquent uses.
| If your table doesn't have these fields, timestamps will be
| disabled for your model.
|
*/
'timestamps' => true,
// 'timestamps' => [
// 'enabled' => true,
// 'fields' => [
// 'CREATED_AT' => 'created_at',
// 'UPDATED_AT' => 'updated_at',
// ]
// ],
/*
|--------------------------------------------------------------------------
| Soft Deletes
|--------------------------------------------------------------------------
|
| If your tables support soft deletes with a DELETED_AT attribute,
| you can enable them here. You can also specify which field
| should be treated as a soft delete attribute in case you
| don't follow the naming convention Eloquent uses.
| If your table doesn't have this field, soft deletes will be
| disabled for your model.
|
*/
'soft_deletes' => true,
// 'soft_deletes' => [
// 'enabled' => true,
// 'field' => 'deleted_at',
// ],
/*
|--------------------------------------------------------------------------
| Date Format
|--------------------------------------------------------------------------
|
| Here you may define your models' date format. The following format
| is the default format Eloquent uses. You won't see it in your
| models unless you change it to a more convenient value.
|
*/
'date_format' => 'Y-m-d H:i:s',
/*
|--------------------------------------------------------------------------
| Pagination
|--------------------------------------------------------------------------
|
| Here you may define how many models Eloquent should display when
| paginating them. The default number is 15, so you might not
| see this number in your models unless you change it.
|
*/
'per_page' => 15,
/*
|--------------------------------------------------------------------------
| Base Files
|--------------------------------------------------------------------------
|
| By default, your models will be generated in your models path, but
| when you generate them again they will be replaced by new ones.
| You may want to customize your models and, at the same time, be
| able to generate them as your tables change. For that, you
| can enable base files. These files will be replaced whenever
| you generate them, but your customized files will not be touched.
|
*/
'base_files' => false,
/*
|--------------------------------------------------------------------------
| Snake Attributes
|--------------------------------------------------------------------------
|
| Eloquent treats your model attributes as snake cased attributes, but
| if you have camel-cased fields in your database you can disable
| that behaviour and use camel case attributes in your models.
|
*/
'snake_attributes' => true,
/*
|--------------------------------------------------------------------------
| Indent options
|--------------------------------------------------------------------------
|
| As default indention is done with tabs, but you can change it by setting
| this to the amount of spaces you that you want to use for indentation.
| Usually you will use 4 spaces instead of tabs.
|
*/
'indent_with_space' => 0,
/*
|--------------------------------------------------------------------------
| Qualified Table Names
|--------------------------------------------------------------------------
|
| If some of your tables have cross-database relationships (probably in
| MySQL), you can make sure your models take into account their
| respective database schema.
|
| Can Either be NULL, FALSE or TRUE
| TRUE: Schema name will be prepended on the table
| FALSE:Table name will be set without schema name.
| NULL: Table name will follow laravel pattern,
| i.e. if class name(plural) matches table name, then table name will not be added
*/
'qualified_tables' => false,
/*
|--------------------------------------------------------------------------
| Hidden Attributes
|--------------------------------------------------------------------------
|
| When casting your models into arrays or json, the need to hide some
| attributes sometimes arise. If your tables have some fields you
| want to hide, you can define them bellow.
| Some fields were defined for you.
|
*/
'hidden' => [
'*secret*', '*password', '*token',
],
/*
|--------------------------------------------------------------------------
| Mass Assignment Guarded Attributes
|--------------------------------------------------------------------------
|
| You may want to protect some fields from mass assignment. You can
| define them bellow. Some fields were defined for you.
| Your fillable attributes will be those which are not in the list
| excluding your models' primary keys.
|
*/
'guarded' => [
// 'created_by', 'updated_by'
],
/*
|--------------------------------------------------------------------------
| Casts
|--------------------------------------------------------------------------
|
| You may want to specify which of your table fields should be cast as
| something other than a string. For instance, you may want a
| text field be cast as an array or and object.
|
| You may define column patterns which will be cast using the value
| assigned. We have defined some fields for you. Feel free to
| modify them to fit your needs.
|
*/
'casts' => [
'*_json' => 'json',
],
/*
|--------------------------------------------------------------------------
| Excluded Tables
|--------------------------------------------------------------------------
|
| When performing the generation of models you may want to skip some of
| them, because you don't want a model for them or any other reason.
| You can define those tables bellow. The migrations table was
| filled for you, since you may not want a model for it.
|
*/
'except' => [
'migrations',
'failed_jobs',
'password_resets',
'personal_access_tokens',
'password_reset_tokens',
],
/*
|--------------------------------------------------------------------------
| Specified Tables
|--------------------------------------------------------------------------
|
| You can specify specific tables. This will generate the models only
| for selected tables, ignoring the rest.
|
*/
'only' => [
// 'users',
],
/*
|--------------------------------------------------------------------------
| Table Prefix
|--------------------------------------------------------------------------
|
| If you have a prefix on your table names but don't want it in the model
| and relation names, specify it here.
|
*/
'table_prefix' => '',
/*
|--------------------------------------------------------------------------
| Lower table name before doing studly
|--------------------------------------------------------------------------
|
| If tables names are capitalised using studly produces incorrect name
| this can help fix it ie TABLE_NAME now becomes TableName
|
*/
'lower_table_name_first' => false,
/*
|--------------------------------------------------------------------------
| Model Names
|--------------------------------------------------------------------------
|
| By default the generator will create models with names that match your tables.
| However, if you wish to manually override the naming, you can specify a mapping
| here between table and model names.
|
| Example:
| A table called 'billing_invoices' will generate a model called `BillingInvoice`,
| but you'd prefer it to generate a model called 'Invoice'. Therefore, you'd add
| the following array key and value:
| 'billing_invoices' => 'Invoice',
*/
'model_names' => [
],
/*
|--------------------------------------------------------------------------
| Relation Name Strategy
|--------------------------------------------------------------------------
|
| How the relations should be named in your models.
|
| 'related' Use the related table as the relation name.
| (post.author --> user.id)
generates Post::user() and User::posts()
|
| 'foreign_key' Use the foreign key as the relation name.
| This can help to provide more meaningful relationship names, and avoids naming conflicts
| if you have more than one relationship between two tables.
| (post.author_id --> user.id)
| generates Post::author() and User::posts_where_author()
| (post.editor_id --> user.id)
| generates Post::editor() and User::posts_where_editor()
| ID suffixes can be omitted from foreign keys.
| (post.author --> user.id)
| (post.editor --> user.id)
| generates the same as above.
| Where the foreign key matches the related table name, it behaves as per the 'related' strategy.
| (post.user_id --> user.id)
| generates Post::user() and User::posts()
*/
'relation_name_strategy' => 'related',
// 'relation_name_strategy' => 'foreign_key',
/*
|--------------------------------------------------------------------------
| Determines need or not to generate constants with properties names like
|
| ...
| const AGE = 'age';
| const USER_NAME = 'user_name';
| ...
|
| that later can be used in QueryBuilder like
|
| ...
| $builder->select([User::USER_NAME])->where(User::AGE, '<=', 18);
| ...
|
| that helps to avoid typos in strings when typing field names and allows to use
| code competition with available model's field names.
*/
'with_property_constants' => false,
/*
|--------------------------------------------------------------------------
| Optionally includes a full list of columns in the base generated models,
| which can be used to avoid making calls like
|
| ...
| \Illuminate\Support\Facades\Schema::getColumnListing
| ...
|
| which can be slow, especially for large tables.
*/
'with_column_list' => false,
/*
|--------------------------------------------------------------------------
| Disable Pluralization Name
|--------------------------------------------------------------------------
|
| You can disable pluralization tables and relations
|
*/
'pluralize' => true,
/*
|--------------------------------------------------------------------------
| Disable Pluralization Except For Certain Tables
|--------------------------------------------------------------------------
|
| You can enable pluralization for certain tables
|
*/
'override_pluralize_for' => [
],
/*
|--------------------------------------------------------------------------
| Move $hidden property to base files
|--------------------------------------------------------------------------
| When base_files is true you can set hidden_in_base_files to true
| if you want the $hidden to be generated in base files
|
*/
'hidden_in_base_files' => false,
/*
|--------------------------------------------------------------------------
| Move $fillable property to base files
|--------------------------------------------------------------------------
| When base_files is true you can set fillable_in_base_files to true
| if you want the $fillable to be generated in base files
|
*/
'fillable_in_base_files' => false,
/*
|--------------------------------------------------------------------------
| Generate return types for relation methods.
|--------------------------------------------------------------------------
| When enable_return_types is set to true, return type declarations are added
| to all generated relation methods for your models.
|
| NOTE: This requires PHP 7.0 or later.
|
*/
'enable_return_types' => false,
],
/*
|--------------------------------------------------------------------------
| Database Specifics
|--------------------------------------------------------------------------
|
| In this section you may define the default configuration for each model
| that will be generated from a specific database. You can also nest
| table specific configurations.
| These values will override those defined in the section above.
|
*/
// 'shop' => [
// 'path' => app_path(),
// 'namespace' => 'App',
// 'snake_attributes' => false,
// 'qualified_tables' => true,
// 'use' => [
// Reliese\Database\Eloquent\BitBooleans::class,
// ],
// 'except' => ['migrations'],
// 'only' => ['users'],
// // Table Specifics Bellow:
// 'user' => [
// // Don't use any default trait
// 'use' => [],
// ]
// ],
/*
|--------------------------------------------------------------------------
| Connection Specifics
|--------------------------------------------------------------------------
|
| In this section you may define the default configuration for each model
| that will be generated from a specific connection. You can also nest
| database and table specific configurations.
|
| You may wish to use connection specific config for setting a parent
| model with a read only setup, or enforcing a different set of rules
| for a connection, e.g. using snake_case naming over CamelCase naming.
|
| This supports nesting with the following key configuration values, in
| reverse precedence order (i.e. the last one found becomes the value).
|
| connections.{connection_name}.property
| connections.{connection_name}.{database_name}.property
| connections.{connection_name}.{table_name}.property
| connections.{connection_name}.{database_name}.{table_name}.property
|
| These values will override those defined in the section above.
|
*/
// 'connections' => [
// 'read_only_external' => [
// 'parent' => \App\Models\ReadOnlyModel::class,
// 'connection' => true,
// 'users' => [
// 'connection' => false,
// ],
// 'my_other_database' => [
// 'password_resets' => [
// 'connection' => false,
// ]
// ]
// ],
// ],
];

84
laravel/config/sanctum.php Executable file
View File

@@ -0,0 +1,84 @@
<?php
use Laravel\Sanctum\Sanctum;
return [
/*
|--------------------------------------------------------------------------
| Stateful Domains
|--------------------------------------------------------------------------
|
| Requests from the following domains / hosts will receive stateful API
| authentication cookies. Typically, these should include your local
| and production domains which access your API via a frontend SPA.
|
*/
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'%s%s',
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
Sanctum::currentApplicationUrlWithPort(),
// Sanctum::currentRequestHost(),
))),
/*
|--------------------------------------------------------------------------
| Sanctum Guards
|--------------------------------------------------------------------------
|
| This array contains the authentication guards that will be checked when
| Sanctum is trying to authenticate a request. If none of these guards
| are able to authenticate the request, Sanctum will use the bearer
| token that's present on an incoming request for authentication.
|
*/
'guard' => ['web'],
/*
|--------------------------------------------------------------------------
| Expiration Minutes
|--------------------------------------------------------------------------
|
| This value controls the number of minutes until an issued token will be
| considered expired. This will override any values set in the token's
| "expires_at" attribute, but first-party sessions are not affected.
|
*/
'expiration' => null,
/*
|--------------------------------------------------------------------------
| Token Prefix
|--------------------------------------------------------------------------
|
| Sanctum can prefix new tokens in order to take advantage of numerous
| security scanning initiatives maintained by open source platforms
| that notify developers if they commit tokens into repositories.
|
| See: https://docs.github.com/en/code-security/secret-scanning/about-secret-scanning
|
*/
'token_prefix' => env('SANCTUM_TOKEN_PREFIX', ''),
/*
|--------------------------------------------------------------------------
| Sanctum Middleware
|--------------------------------------------------------------------------
|
| When authenticating your first-party SPA with Sanctum you may need to
| customize some of the middleware Sanctum uses while processing the
| request. You may change the middleware listed below as required.
|
*/
'middleware' => [
'authenticate_session' => Laravel\Sanctum\Http\Middleware\AuthenticateSession::class,
'encrypt_cookies' => Illuminate\Cookie\Middleware\EncryptCookies::class,
'validate_csrf_token' => Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class,
],
];

View File

@@ -1,23 +0,0 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\billet_categorie>
*/
class BilletCategorieFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
//
];
}
}

View File

@@ -1,24 +0,0 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Categorie>
*/
class CategorieFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
//
'CAT_NOM' => fake()->text(10),
];
}
}

View File

@@ -1,29 +0,0 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Commentaire>
*/
class CommentaireFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
//
'COM_DATE' => now(),
'COM_AUTEUR' => fake()->lastName(),
'COM_CONTENU' => fake()->text(200),
'billet_id' => fake()->numberBetween(1,10),
'created_at' => now(),
'updated_at' => now(),
];
}
}

View File

@@ -1,36 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('commentaires', function (Blueprint $table) {
$table->id();
$table->date('COM_DATE');
$table->text('COM_AUTEUR');
$table->text('COM_CONTENU');
$table->unsignedBigInteger('billet_id');
$table->foreign('billet_id')
->references('id')
->on('billets')
->onDelete('cascade')
->onUpdate('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('commentaires');
}
};

View File

@@ -1,28 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->text('CAT_NOM');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('categories');
}
};

View File

@@ -1,39 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('billet_categorie', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('billet_id');
$table->foreign('billet_id')
->references('id')
->on('billets')
->onDelete('cascade')
->onUpdate('cascade');
$table->unsignedBigInteger('categorie_id');
$table->foreign('categorie_id')
->references('id')
->on('categories')
->onDelete('cascade')
->onUpdate('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('billet_categories');
}
};

View File

@@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('personal_access_tokens', function (Blueprint $table) {
$table->id();
$table->morphs('tokenable');
$table->string('name');
$table->string('token', 64)->unique();
$table->text('abilities')->nullable();
$table->timestamp('last_used_at')->nullable();
$table->timestamp('expires_at')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('personal_access_tokens');
}
};

View File

@@ -1,19 +0,0 @@
<?php
namespace Database\Seeders;
use App\Models\Categorie;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class CategorieSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
//
Categorie::factory(10)->create();
}
}

View File

@@ -1,20 +0,0 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use App\Models\Commentaire;
class CommentaireSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
//
// Create 10 comments
Commentaire::factory(10)->create();
}
}

3850
laravel/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,15 +6,11 @@
"dev": "vite" "dev": "vite"
}, },
"devDependencies": { "devDependencies": {
"@tailwindcss/forms": "^0.5.2",
"@tailwindcss/vite": "^4.0.0", "@tailwindcss/vite": "^4.0.0",
"alpinejs": "^3.4.2",
"autoprefixer": "^10.4.2",
"axios": "^1.8.2", "axios": "^1.8.2",
"concurrently": "^9.0.1", "concurrently": "^9.0.1",
"laravel-vite-plugin": "^1.2.0", "laravel-vite-plugin": "^1.2.0",
"postcss": "^8.4.31", "tailwindcss": "^4.0.0",
"tailwindcss": "^3.1.0",
"vite": "^6.0.11" "vite": "^6.0.11"
} }
} }

View File

@@ -1,6 +0,0 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};

View File

@@ -1,15 +1,9 @@
:root { html, body {
--main-color: #333534;
--text-color: #bfbfbf;
}
html,
body {
height: 100%; height: 100%;
} }
body { body {
color: var(--text-color); color: #bfbfbf;
background: black; background: black;
font-family: 'Futura-Medium', 'Futura', 'Trebuchet MS', sans-serif; font-family: 'Futura-Medium', 'Futura', 'Trebuchet MS', sans-serif;
} }
@@ -19,62 +13,30 @@ h1 {
} }
.titreBillet { .titreBillet {
margin-bottom: 0px; margin-bottom : 0px;
} }
#global { #global {
min-height: 100%; min-height: 100%; /* Voir commentaire sur html et body plus haut */
/* Voir commentaire sur html et body plus haut */ background: #333534;
background: var(--main-color);
width: 70%; width: 70%;
margin: auto; margin: auto; /* Permet de centrer la div */
/* Permet de centrer la div */
text-align: justify; text-align: justify;
padding: 5px 20px; padding: 5px 20px;
} }
#contenu { #contenu {
margin-bottom: 30px; margin-bottom : 30px;
} }
#titreBlog, #titreBlog, #piedBlog {
#piedBlog {
text-align: center; text-align: center;
} }
#titreReponses { #titreReponses {
font-size: 100%; font-size : 100%;
} }
#txtCommentaire { #txtCommentaire {
width: 50%; width: 50%;
} }
#titreReponses {
font-size: 100%;
}
#txtCommentaire {
width: 50%;
}
#organizer {
display: flex;
justify-content: space-between;
align-items: center;
}
a#logout-button {
text-decoration: none;
color: white;
background-color: var(--main-color);
padding: 5px 10px;
border: 1px solid #fff;
border-radius: 5px;
transition: background-color 0.3s, color 0.3s;
&:hover {
background-color: #fff;
color: var(--main-color);
}
}

View File

@@ -1,3 +1,11 @@
@tailwind base; @import 'tailwindcss';
@tailwind components;
@tailwind utilities; @source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php';
@source '../../storage/framework/views/*.php';
@source '../**/*.blade.php';
@source '../**/*.js';
@theme {
--font-sans: 'Instrument Sans', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
'Segoe UI Symbol', 'Noto Color Emoji';
}

View File

@@ -1,7 +1 @@
import './bootstrap'; import './bootstrap';
import Alpine from 'alpinejs';
window.Alpine = Alpine;
Alpine.start();

View File

@@ -1,27 +0,0 @@
<x-guest-layout>
<div class="mb-4 text-sm text-gray-600 dark:text-gray-400">
{{ __('This is a secure area of the application. Please confirm your password before continuing.') }}
</div>
<form method="POST" action="{{ route('password.confirm') }}">
@csrf
<!-- Password -->
<div>
<x-input-label for="password" :value="__('Password')" />
<x-text-input id="password" class="block mt-1 w-full"
type="password"
name="password"
required autocomplete="current-password" />
<x-input-error :messages="$errors->get('password')" class="mt-2" />
</div>
<div class="flex justify-end mt-4">
<x-primary-button>
{{ __('Confirm') }}
</x-primary-button>
</div>
</form>
</x-guest-layout>

View File

@@ -1,25 +0,0 @@
<x-guest-layout>
<div class="mb-4 text-sm text-gray-600 dark:text-gray-400">
{{ __('Forgot your password? No problem. Just let us know your email address and we will email you a password reset link that will allow you to choose a new one.') }}
</div>
<!-- Session Status -->
<x-auth-session-status class="mb-4" :status="session('status')" />
<form method="POST" action="{{ route('password.email') }}">
@csrf
<!-- Email Address -->
<div>
<x-input-label for="email" :value="__('Email')" />
<x-text-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email')" required autofocus />
<x-input-error :messages="$errors->get('email')" class="mt-2" />
</div>
<div class="flex items-center justify-end mt-4">
<x-primary-button>
{{ __('Email Password Reset Link') }}
</x-primary-button>
</div>
</form>
</x-guest-layout>

View File

@@ -1,47 +0,0 @@
<x-guest-layout>
<!-- Session Status -->
<x-auth-session-status class="mb-4" :status="session('status')" />
<form method="POST" action="{{ route('login') }}">
@csrf
<!-- Email Address -->
<div>
<x-input-label for="email" :value="__('Email')" />
<x-text-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email')" required autofocus autocomplete="username" />
<x-input-error :messages="$errors->get('email')" class="mt-2" />
</div>
<!-- Password -->
<div class="mt-4">
<x-input-label for="password" :value="__('Password')" />
<x-text-input id="password" class="block mt-1 w-full"
type="password"
name="password"
required autocomplete="current-password" />
<x-input-error :messages="$errors->get('password')" class="mt-2" />
</div>
<!-- Remember Me -->
<div class="block mt-4">
<label for="remember_me" class="inline-flex items-center">
<input id="remember_me" type="checkbox" class="rounded dark:bg-gray-900 border-gray-300 dark:border-gray-700 text-indigo-600 shadow-sm focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:focus:ring-offset-gray-800" name="remember">
<span class="ms-2 text-sm text-gray-600 dark:text-gray-400">{{ __('Remember me') }}</span>
</label>
</div>
<div class="flex items-center justify-end mt-4">
@if (Route::has('password.request'))
<a class="underline text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-offset-gray-800" href="{{ route('password.request') }}">
{{ __('Forgot your password?') }}
</a>
@endif
<x-primary-button class="ms-3">
{{ __('Log in') }}
</x-primary-button>
</div>
</form>
</x-guest-layout>

View File

@@ -1,52 +0,0 @@
<x-guest-layout>
<form method="POST" action="{{ route('register') }}">
@csrf
<!-- Name -->
<div>
<x-input-label for="name" :value="__('Name')" />
<x-text-input id="name" class="block mt-1 w-full" type="text" name="name" :value="old('name')" required autofocus autocomplete="name" />
<x-input-error :messages="$errors->get('name')" class="mt-2" />
</div>
<!-- Email Address -->
<div class="mt-4">
<x-input-label for="email" :value="__('Email')" />
<x-text-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email')" required autocomplete="username" />
<x-input-error :messages="$errors->get('email')" class="mt-2" />
</div>
<!-- Password -->
<div class="mt-4">
<x-input-label for="password" :value="__('Password')" />
<x-text-input id="password" class="block mt-1 w-full"
type="password"
name="password"
required autocomplete="new-password" />
<x-input-error :messages="$errors->get('password')" class="mt-2" />
</div>
<!-- Confirm Password -->
<div class="mt-4">
<x-input-label for="password_confirmation" :value="__('Confirm Password')" />
<x-text-input id="password_confirmation" class="block mt-1 w-full"
type="password"
name="password_confirmation" required autocomplete="new-password" />
<x-input-error :messages="$errors->get('password_confirmation')" class="mt-2" />
</div>
<div class="flex items-center justify-end mt-4">
<a class="underline text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-offset-gray-800" href="{{ route('login') }}">
{{ __('Already registered?') }}
</a>
<x-primary-button class="ms-4">
{{ __('Register') }}
</x-primary-button>
</div>
</form>
</x-guest-layout>

View File

@@ -1,39 +0,0 @@
<x-guest-layout>
<form method="POST" action="{{ route('password.store') }}">
@csrf
<!-- Password Reset Token -->
<input type="hidden" name="token" value="{{ $request->route('token') }}">
<!-- Email Address -->
<div>
<x-input-label for="email" :value="__('Email')" />
<x-text-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email', $request->email)" required autofocus autocomplete="username" />
<x-input-error :messages="$errors->get('email')" class="mt-2" />
</div>
<!-- Password -->
<div class="mt-4">
<x-input-label for="password" :value="__('Password')" />
<x-text-input id="password" class="block mt-1 w-full" type="password" name="password" required autocomplete="new-password" />
<x-input-error :messages="$errors->get('password')" class="mt-2" />
</div>
<!-- Confirm Password -->
<div class="mt-4">
<x-input-label for="password_confirmation" :value="__('Confirm Password')" />
<x-text-input id="password_confirmation" class="block mt-1 w-full"
type="password"
name="password_confirmation" required autocomplete="new-password" />
<x-input-error :messages="$errors->get('password_confirmation')" class="mt-2" />
</div>
<div class="flex items-center justify-end mt-4">
<x-primary-button>
{{ __('Reset Password') }}
</x-primary-button>
</div>
</form>
</x-guest-layout>

View File

@@ -1,31 +0,0 @@
<x-guest-layout>
<div class="mb-4 text-sm text-gray-600 dark:text-gray-400">
{{ __('Thanks for signing up! Before getting started, could you verify your email address by clicking on the link we just emailed to you? If you didn\'t receive the email, we will gladly send you another.') }}
</div>
@if (session('status') == 'verification-link-sent')
<div class="mb-4 font-medium text-sm text-green-600 dark:text-green-400">
{{ __('A new verification link has been sent to the email address you provided during registration.') }}
</div>
@endif
<div class="mt-4 flex items-center justify-between">
<form method="POST" action="{{ route('verification.send') }}">
@csrf
<div>
<x-primary-button>
{{ __('Resend Verification Email') }}
</x-primary-button>
</div>
</form>
<form method="POST" action="{{ route('logout') }}">
@csrf
<button type="submit" class="underline text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-offset-gray-800">
{{ __('Log Out') }}
</button>
</form>
</div>
</x-guest-layout>

View File

@@ -1,3 +0,0 @@
<svg viewBox="0 0 316 316" xmlns="http://www.w3.org/2000/svg" {{ $attributes }}>
<path d="M305.8 81.125C305.77 80.995 305.69 80.885 305.65 80.755C305.56 80.525 305.49 80.285 305.37 80.075C305.29 79.935 305.17 79.815 305.07 79.685C304.94 79.515 304.83 79.325 304.68 79.175C304.55 79.045 304.39 78.955 304.25 78.845C304.09 78.715 303.95 78.575 303.77 78.475L251.32 48.275C249.97 47.495 248.31 47.495 246.96 48.275L194.51 78.475C194.33 78.575 194.19 78.725 194.03 78.845C193.89 78.955 193.73 79.045 193.6 79.175C193.45 79.325 193.34 79.515 193.21 79.685C193.11 79.815 192.99 79.935 192.91 80.075C192.79 80.285 192.71 80.525 192.63 80.755C192.58 80.875 192.51 80.995 192.48 81.125C192.38 81.495 192.33 81.875 192.33 82.265V139.625L148.62 164.795V52.575C148.62 52.185 148.57 51.805 148.47 51.435C148.44 51.305 148.36 51.195 148.32 51.065C148.23 50.835 148.16 50.595 148.04 50.385C147.96 50.245 147.84 50.125 147.74 49.995C147.61 49.825 147.5 49.635 147.35 49.485C147.22 49.355 147.06 49.265 146.92 49.155C146.76 49.025 146.62 48.885 146.44 48.785L93.99 18.585C92.64 17.805 90.98 17.805 89.63 18.585L37.18 48.785C37 48.885 36.86 49.035 36.7 49.155C36.56 49.265 36.4 49.355 36.27 49.485C36.12 49.635 36.01 49.825 35.88 49.995C35.78 50.125 35.66 50.245 35.58 50.385C35.46 50.595 35.38 50.835 35.3 51.065C35.25 51.185 35.18 51.305 35.15 51.435C35.05 51.805 35 52.185 35 52.575V232.235C35 233.795 35.84 235.245 37.19 236.025L142.1 296.425C142.33 296.555 142.58 296.635 142.82 296.725C142.93 296.765 143.04 296.835 143.16 296.865C143.53 296.965 143.9 297.015 144.28 297.015C144.66 297.015 145.03 296.965 145.4 296.865C145.5 296.835 145.59 296.775 145.69 296.745C145.95 296.655 146.21 296.565 146.45 296.435L251.36 236.035C252.72 235.255 253.55 233.815 253.55 232.245V174.885L303.81 145.945C305.17 145.165 306 143.725 306 142.155V82.265C305.95 81.875 305.89 81.495 305.8 81.125ZM144.2 227.205L100.57 202.515L146.39 176.135L196.66 147.195L240.33 172.335L208.29 190.625L144.2 227.205ZM244.75 114.995V164.795L226.39 154.225L201.03 139.625V89.825L219.39 100.395L244.75 114.995ZM249.12 57.105L292.81 82.265L249.12 107.425L205.43 82.265L249.12 57.105ZM114.49 184.425L96.13 194.995V85.305L121.49 70.705L139.85 60.135V169.815L114.49 184.425ZM91.76 27.425L135.45 52.585L91.76 77.745L48.07 52.585L91.76 27.425ZM43.67 60.135L62.03 70.705L87.39 85.305V202.545V202.555V202.565C87.39 202.735 87.44 202.895 87.46 203.055C87.49 203.265 87.49 203.485 87.55 203.695V203.705C87.6 203.875 87.69 204.035 87.76 204.195C87.84 204.375 87.89 204.575 87.99 204.745C87.99 204.745 87.99 204.755 88 204.755C88.09 204.905 88.22 205.035 88.33 205.175C88.45 205.335 88.55 205.495 88.69 205.635L88.7 205.645C88.82 205.765 88.98 205.855 89.12 205.965C89.28 206.085 89.42 206.225 89.59 206.325C89.6 206.325 89.6 206.325 89.61 206.335C89.62 206.335 89.62 206.345 89.63 206.345L139.87 234.775V285.065L43.67 229.705V60.135ZM244.75 229.705L148.58 285.075V234.775L219.8 194.115L244.75 179.875V229.705ZM297.2 139.625L253.49 164.795V114.995L278.85 100.395L297.21 89.825V139.625H297.2Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -1,7 +0,0 @@
@props(['status'])
@if ($status)
<div {{ $attributes->merge(['class' => 'font-medium text-sm text-green-600 dark:text-green-400']) }}>
{{ $status }}
</div>
@endif

View File

@@ -1,3 +0,0 @@
<button {{ $attributes->merge(['type' => 'submit', 'class' => 'inline-flex items-center px-4 py-2 bg-red-600 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-red-500 active:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 transition ease-in-out duration-150']) }}>
{{ $slot }}
</button>

View File

@@ -1 +0,0 @@
<a {{ $attributes->merge(['class' => 'block w-full px-4 py-2 text-start text-sm leading-5 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 focus:outline-none focus:bg-gray-100 dark:focus:bg-gray-800 transition duration-150 ease-in-out']) }}>{{ $slot }}</a>

View File

@@ -1,35 +0,0 @@
@props(['align' => 'right', 'width' => '48', 'contentClasses' => 'py-1 bg-white dark:bg-gray-700'])
@php
$alignmentClasses = match ($align) {
'left' => 'ltr:origin-top-left rtl:origin-top-right start-0',
'top' => 'origin-top',
default => 'ltr:origin-top-right rtl:origin-top-left end-0',
};
$width = match ($width) {
'48' => 'w-48',
default => $width,
};
@endphp
<div class="relative" x-data="{ open: false }" @click.outside="open = false" @close.stop="open = false">
<div @click="open = ! open">
{{ $trigger }}
</div>
<div x-show="open"
x-transition:enter="transition ease-out duration-200"
x-transition:enter-start="opacity-0 scale-95"
x-transition:enter-end="opacity-100 scale-100"
x-transition:leave="transition ease-in duration-75"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
class="absolute z-50 mt-2 {{ $width }} rounded-md shadow-lg {{ $alignmentClasses }}"
style="display: none;"
@click="open = false">
<div class="rounded-md ring-1 ring-black ring-opacity-5 {{ $contentClasses }}">
{{ $content }}
</div>
</div>
</div>

View File

@@ -1,9 +0,0 @@
@props(['messages'])
@if ($messages)
<ul {{ $attributes->merge(['class' => 'text-sm text-red-600 dark:text-red-400 space-y-1']) }}>
@foreach ((array) $messages as $message)
<li>{{ $message }}</li>
@endforeach
</ul>
@endif

View File

@@ -1,5 +0,0 @@
@props(['value'])
<label {{ $attributes->merge(['class' => 'block font-medium text-sm text-gray-700 dark:text-gray-300']) }}>
{{ $value ?? $slot }}
</label>

View File

@@ -1,78 +0,0 @@
@props([
'name',
'show' => false,
'maxWidth' => '2xl'
])
@php
$maxWidth = [
'sm' => 'sm:max-w-sm',
'md' => 'sm:max-w-md',
'lg' => 'sm:max-w-lg',
'xl' => 'sm:max-w-xl',
'2xl' => 'sm:max-w-2xl',
][$maxWidth];
@endphp
<div
x-data="{
show: @js($show),
focusables() {
// All focusable element types...
let selector = 'a, button, input:not([type=\'hidden\']), textarea, select, details, [tabindex]:not([tabindex=\'-1\'])'
return [...$el.querySelectorAll(selector)]
// All non-disabled elements...
.filter(el => ! el.hasAttribute('disabled'))
},
firstFocusable() { return this.focusables()[0] },
lastFocusable() { return this.focusables().slice(-1)[0] },
nextFocusable() { return this.focusables()[this.nextFocusableIndex()] || this.firstFocusable() },
prevFocusable() { return this.focusables()[this.prevFocusableIndex()] || this.lastFocusable() },
nextFocusableIndex() { return (this.focusables().indexOf(document.activeElement) + 1) % (this.focusables().length + 1) },
prevFocusableIndex() { return Math.max(0, this.focusables().indexOf(document.activeElement)) -1 },
}"
x-init="$watch('show', value => {
if (value) {
document.body.classList.add('overflow-y-hidden');
{{ $attributes->has('focusable') ? 'setTimeout(() => firstFocusable().focus(), 100)' : '' }}
} else {
document.body.classList.remove('overflow-y-hidden');
}
})"
x-on:open-modal.window="$event.detail == '{{ $name }}' ? show = true : null"
x-on:close-modal.window="$event.detail == '{{ $name }}' ? show = false : null"
x-on:close.stop="show = false"
x-on:keydown.escape.window="show = false"
x-on:keydown.tab.prevent="$event.shiftKey || nextFocusable().focus()"
x-on:keydown.shift.tab.prevent="prevFocusable().focus()"
x-show="show"
class="fixed inset-0 overflow-y-auto px-4 py-6 sm:px-0 z-50"
style="display: {{ $show ? 'block' : 'none' }};"
>
<div
x-show="show"
class="fixed inset-0 transform transition-all"
x-on:click="show = false"
x-transition:enter="ease-out duration-300"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="ease-in duration-200"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
>
<div class="absolute inset-0 bg-gray-500 dark:bg-gray-900 opacity-75"></div>
</div>
<div
x-show="show"
class="mb-6 bg-white dark:bg-gray-800 rounded-lg overflow-hidden shadow-xl transform transition-all sm:w-full {{ $maxWidth }} sm:mx-auto"
x-transition:enter="ease-out duration-300"
x-transition:enter-start="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
x-transition:enter-end="opacity-100 translate-y-0 sm:scale-100"
x-transition:leave="ease-in duration-200"
x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100"
x-transition:leave-end="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
{{ $slot }}
</div>
</div>

View File

@@ -1,11 +0,0 @@
@props(['active'])
@php
$classes = ($active ?? false)
? 'inline-flex items-center px-1 pt-1 border-b-2 border-indigo-400 dark:border-indigo-600 text-sm font-medium leading-5 text-gray-900 dark:text-gray-100 focus:outline-none focus:border-indigo-700 transition duration-150 ease-in-out'
: 'inline-flex items-center px-1 pt-1 border-b-2 border-transparent text-sm font-medium leading-5 text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 hover:border-gray-300 dark:hover:border-gray-700 focus:outline-none focus:text-gray-700 dark:focus:text-gray-300 focus:border-gray-300 dark:focus:border-gray-700 transition duration-150 ease-in-out';
@endphp
<a {{ $attributes->merge(['class' => $classes]) }}>
{{ $slot }}
</a>

View File

@@ -1,3 +0,0 @@
<button {{ $attributes->merge(['type' => 'submit', 'class' => 'inline-flex items-center px-4 py-2 bg-gray-800 dark:bg-gray-200 border border-transparent rounded-md font-semibold text-xs text-white dark:text-gray-800 uppercase tracking-widest hover:bg-gray-700 dark:hover:bg-white focus:bg-gray-700 dark:focus:bg-white active:bg-gray-900 dark:active:bg-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 transition ease-in-out duration-150']) }}>
{{ $slot }}
</button>

View File

@@ -1,11 +0,0 @@
@props(['active'])
@php
$classes = ($active ?? false)
? 'block w-full ps-3 pe-4 py-2 border-l-4 border-indigo-400 dark:border-indigo-600 text-start text-base font-medium text-indigo-700 dark:text-indigo-300 bg-indigo-50 dark:bg-indigo-900/50 focus:outline-none focus:text-indigo-800 dark:focus:text-indigo-200 focus:bg-indigo-100 dark:focus:bg-indigo-900 focus:border-indigo-700 dark:focus:border-indigo-300 transition duration-150 ease-in-out'
: 'block w-full ps-3 pe-4 py-2 border-l-4 border-transparent text-start text-base font-medium text-gray-600 dark:text-gray-400 hover:text-gray-800 dark:hover:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 hover:border-gray-300 dark:hover:border-gray-600 focus:outline-none focus:text-gray-800 dark:focus:text-gray-200 focus:bg-gray-50 dark:focus:bg-gray-700 focus:border-gray-300 dark:focus:border-gray-600 transition duration-150 ease-in-out';
@endphp
<a {{ $attributes->merge(['class' => $classes]) }}>
{{ $slot }}
</a>

View File

@@ -1,3 +0,0 @@
<button {{ $attributes->merge(['type' => 'button', 'class' => 'inline-flex items-center px-4 py-2 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-500 rounded-md font-semibold text-xs text-gray-700 dark:text-gray-300 uppercase tracking-widest shadow-sm hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 disabled:opacity-25 transition ease-in-out duration-150']) }}>
{{ $slot }}
</button>

View File

@@ -1,3 +0,0 @@
@props(['disabled' => false])
<input @disabled($disabled) {{ $attributes->merge(['class' => 'border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 rounded-md shadow-sm']) }}>

View File

@@ -1,17 +0,0 @@
<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
{{ __('Dashboard') }}
</h2>
</x-slot>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 text-gray-900 dark:text-gray-100">
{{ __("You're logged in!") }}
</div>
</div>
</div>
</div>
</x-app-layout>

View File

@@ -1,4 +0,0 @@
@extends('layout')
@section('contenu')
<h2>La page demandée n'est pas disponible</h2>
@endsection

View File

@@ -1,5 +0,0 @@
@extends('layout')
@section('contenu')
<h2>Une erreur est survenue. Veuillez réessayer ultérieurement</h2>
@endsection

View File

@@ -1,4 +0,0 @@
@extends('layout')
@section('contenu')
<h2>La ressource demandée n'est pas disponible</h2>
@endsection

View File

@@ -1,28 +1,31 @@
@extends('layout') <!doctype html>
@section('contenu') <html lang="fr">
<head>
<meta charset="UTF-8" />
<link rel="stylesheet" href="style.css" />
<title>Mon Blog</title>
</head>
<body>
<div id="global">
<header>
<a href="index.php"><h1 id="titreBlog">Mon Blog</h1></a>
<p>Je vous souhaite la bienvenue sur ce modeste blog.</p>
</header>
<div id="contenu">
@foreach($billets as $billet) @foreach($billets as $billet)
<article> <article>
<header> <header>
<a href="{{ route('billets.show', $billet->id) }}"><h1 class="titreBillet">{{ $billet->BIL_TITRE }}</h1></a> <h1 class="titreBillet">{{ $billet->BIL_TITRE }}</h1>
<time>{{ $billet->BIL_DATE }}</time> <time>{{ $billet->BIL_DATE }}</time>
</header> </header>
<p>
Dans :
@php
$counter = 0;
@endphp
@foreach($billet->categories as $categorie)
{{ $categorie->CAT_NOM }}
@php
$counter++;
@endphp
@if(count($billet->categories) > $counter)
/
@endif
@endforeach
</p>
<p>{{ $billet->BIL_CONTENU }}</p> <p>{{ $billet->BIL_CONTENU }}</p>
<a href="{{ route('commenter', ['id'=>$billet->id]) }}"><h3 class="titre-billet">Ecrire un commentaire</h3></a>
</article> </article>
<hr />
@endforeach @endforeach
@endsection </div> <!-- #contenu -->
<footer id="piedBlog">
Blog réalisé avec PHP, HTML5 et CSS.
</footer>
</div> <!-- #global -->
</body>
</html>

View File

@@ -1,47 +0,0 @@
<!doctype html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<!--link rel="stylesheet" href="style.css" /-->
<link rel="stylesheet" href="{{ URL::asset('style.css') }}" />
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/toastify-js/src/toastify.min.css">
<title>Mon Blog</title>
</head>
<body>
<div id="global">
<header>
<div id="organizer">
<div></div>
<a href="{{ route('billets.index') }}"><h1 id="titreBlog">Mon Blog</h1></a>
<a href="{{ route('logout') }}" onclick="event.preventDefault(); document.getElementById('logout-form').submit();" id="logout-button">Se déconnecter</a>
</div>
<p>Je vous souhaite la bienvenue sur ce modeste blog.</p>
<form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
@csrf
</form>
</header>
<div id="contenu">
@yield('contenu')
</div> <!-- #contenu -->
<footer id="piedBlog">
Blog réalisé avec PHP, HTML5 et CSS.
</footer>
</div> <!-- #global -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/toastify-js"></script>
@auth
<script type="text/javascript">
Toastify({
text: "Bienvenue, {{ Auth::user()->name }}",
duration: 3000,
position: "left",
newWindow: true,
style : {
background: "linear-gradient(to right, #00b09b, #96c93d)",
}
}).showToast();
</script>
@endauth
</body>
</html>

View File

@@ -1,36 +0,0 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=figtree:400,500,600&display=swap" rel="stylesheet" />
<!-- Scripts -->
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body class="font-sans antialiased">
<div class="min-h-screen bg-gray-100 dark:bg-gray-900">
@include('layouts.navigation')
<!-- Page Heading -->
@isset($header)
<header class="bg-white dark:bg-gray-800 shadow">
<div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
{{ $header }}
</div>
</header>
@endisset
<!-- Page Content -->
<main>
{{ $slot }}
</main>
</div>
</body>
</html>

View File

@@ -1,30 +0,0 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=figtree:400,500,600&display=swap" rel="stylesheet" />
<!-- Scripts -->
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body class="font-sans text-gray-900 antialiased">
<div class="min-h-screen flex flex-col sm:justify-center items-center pt-6 sm:pt-0 bg-gray-100 dark:bg-gray-900">
<div>
<a href="/">
<x-application-logo class="w-20 h-20 fill-current text-gray-500" />
</a>
</div>
<div class="w-full sm:max-w-md mt-6 px-6 py-4 bg-white dark:bg-gray-800 shadow-md overflow-hidden sm:rounded-lg">
{{ $slot }}
</div>
</div>
</body>
</html>

View File

@@ -1,100 +0,0 @@
<nav x-data="{ open: false }" class="bg-white dark:bg-gray-800 border-b border-gray-100 dark:border-gray-700">
<!-- Primary Navigation Menu -->
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between h-16">
<div class="flex">
<!-- Logo -->
<div class="shrink-0 flex items-center">
<a href="{{ route('dashboard') }}">
<x-application-logo class="block h-9 w-auto fill-current text-gray-800 dark:text-gray-200" />
</a>
</div>
<!-- Navigation Links -->
<div class="hidden space-x-8 sm:-my-px sm:ms-10 sm:flex">
<x-nav-link :href="route('dashboard')" :active="request()->routeIs('dashboard')">
{{ __('Dashboard') }}
</x-nav-link>
</div>
</div>
<!-- Settings Dropdown -->
<div class="hidden sm:flex sm:items-center sm:ms-6">
<x-dropdown align="right" width="48">
<x-slot name="trigger">
<button class="inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-gray-500 dark:text-gray-400 bg-white dark:bg-gray-800 hover:text-gray-700 dark:hover:text-gray-300 focus:outline-none transition ease-in-out duration-150">
<div>{{ Auth::user()->name }}</div>
<div class="ms-1">
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
</svg>
</div>
</button>
</x-slot>
<x-slot name="content">
<x-dropdown-link :href="route('profile.edit')">
{{ __('Profile') }}
</x-dropdown-link>
<!-- Authentication -->
<form method="POST" action="{{ route('logout') }}">
@csrf
<x-dropdown-link :href="route('logout')"
onclick="event.preventDefault();
this.closest('form').submit();">
{{ __('Log Out') }}
</x-dropdown-link>
</form>
</x-slot>
</x-dropdown>
</div>
<!-- Hamburger -->
<div class="-me-2 flex items-center sm:hidden">
<button @click="open = ! open" class="inline-flex items-center justify-center p-2 rounded-md text-gray-400 dark:text-gray-500 hover:text-gray-500 dark:hover:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-900 focus:outline-none focus:bg-gray-100 dark:focus:bg-gray-900 focus:text-gray-500 dark:focus:text-gray-400 transition duration-150 ease-in-out">
<svg class="h-6 w-6" stroke="currentColor" fill="none" viewBox="0 0 24 24">
<path :class="{'hidden': open, 'inline-flex': ! open }" class="inline-flex" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
<path :class="{'hidden': ! open, 'inline-flex': open }" class="hidden" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
</div>
</div>
<!-- Responsive Navigation Menu -->
<div :class="{'block': open, 'hidden': ! open}" class="hidden sm:hidden">
<div class="pt-2 pb-3 space-y-1">
<x-responsive-nav-link :href="route('dashboard')" :active="request()->routeIs('dashboard')">
{{ __('Dashboard') }}
</x-responsive-nav-link>
</div>
<!-- Responsive Settings Options -->
<div class="pt-4 pb-1 border-t border-gray-200 dark:border-gray-600">
<div class="px-4">
<div class="font-medium text-base text-gray-800 dark:text-gray-200">{{ Auth::user()->name }}</div>
<div class="font-medium text-sm text-gray-500">{{ Auth::user()->email }}</div>
</div>
<div class="mt-3 space-y-1">
<x-responsive-nav-link :href="route('profile.edit')">
{{ __('Profile') }}
</x-responsive-nav-link>
<!-- Authentication -->
<form method="POST" action="{{ route('logout') }}">
@csrf
<x-responsive-nav-link :href="route('logout')"
onclick="event.preventDefault();
this.closest('form').submit();">
{{ __('Log Out') }}
</x-responsive-nav-link>
</form>
</div>
</div>
</div>
</nav>

View File

@@ -1,29 +0,0 @@
<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
{{ __('Profile') }}
</h2>
</x-slot>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8 space-y-6">
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="max-w-xl">
@include('profile.partials.update-profile-information-form')
</div>
</div>
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="max-w-xl">
@include('profile.partials.update-password-form')
</div>
</div>
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="max-w-xl">
@include('profile.partials.delete-user-form')
</div>
</div>
</div>
</div>
</x-app-layout>

View File

@@ -1,55 +0,0 @@
<section class="space-y-6">
<header>
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
{{ __('Delete Account') }}
</h2>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
{{ __('Once your account is deleted, all of its resources and data will be permanently deleted. Before deleting your account, please download any data or information that you wish to retain.') }}
</p>
</header>
<x-danger-button
x-data=""
x-on:click.prevent="$dispatch('open-modal', 'confirm-user-deletion')"
>{{ __('Delete Account') }}</x-danger-button>
<x-modal name="confirm-user-deletion" :show="$errors->userDeletion->isNotEmpty()" focusable>
<form method="post" action="{{ route('profile.destroy') }}" class="p-6">
@csrf
@method('delete')
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
{{ __('Are you sure you want to delete your account?') }}
</h2>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
{{ __('Once your account is deleted, all of its resources and data will be permanently deleted. Please enter your password to confirm you would like to permanently delete your account.') }}
</p>
<div class="mt-6">
<x-input-label for="password" value="{{ __('Password') }}" class="sr-only" />
<x-text-input
id="password"
name="password"
type="password"
class="mt-1 block w-3/4"
placeholder="{{ __('Password') }}"
/>
<x-input-error :messages="$errors->userDeletion->get('password')" class="mt-2" />
</div>
<div class="mt-6 flex justify-end">
<x-secondary-button x-on:click="$dispatch('close')">
{{ __('Cancel') }}
</x-secondary-button>
<x-danger-button class="ms-3">
{{ __('Delete Account') }}
</x-danger-button>
</div>
</form>
</x-modal>
</section>

View File

@@ -1,48 +0,0 @@
<section>
<header>
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
{{ __('Update Password') }}
</h2>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
{{ __('Ensure your account is using a long, random password to stay secure.') }}
</p>
</header>
<form method="post" action="{{ route('password.update') }}" class="mt-6 space-y-6">
@csrf
@method('put')
<div>
<x-input-label for="update_password_current_password" :value="__('Current Password')" />
<x-text-input id="update_password_current_password" name="current_password" type="password" class="mt-1 block w-full" autocomplete="current-password" />
<x-input-error :messages="$errors->updatePassword->get('current_password')" class="mt-2" />
</div>
<div>
<x-input-label for="update_password_password" :value="__('New Password')" />
<x-text-input id="update_password_password" name="password" type="password" class="mt-1 block w-full" autocomplete="new-password" />
<x-input-error :messages="$errors->updatePassword->get('password')" class="mt-2" />
</div>
<div>
<x-input-label for="update_password_password_confirmation" :value="__('Confirm Password')" />
<x-text-input id="update_password_password_confirmation" name="password_confirmation" type="password" class="mt-1 block w-full" autocomplete="new-password" />
<x-input-error :messages="$errors->updatePassword->get('password_confirmation')" class="mt-2" />
</div>
<div class="flex items-center gap-4">
<x-primary-button>{{ __('Save') }}</x-primary-button>
@if (session('status') === 'password-updated')
<p
x-data="{ show: true }"
x-show="show"
x-transition
x-init="setTimeout(() => show = false, 2000)"
class="text-sm text-gray-600 dark:text-gray-400"
>{{ __('Saved.') }}</p>
@endif
</div>
</form>
</section>

View File

@@ -1,64 +0,0 @@
<section>
<header>
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
{{ __('Profile Information') }}
</h2>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
{{ __("Update your account's profile information and email address.") }}
</p>
</header>
<form id="send-verification" method="post" action="{{ route('verification.send') }}">
@csrf
</form>
<form method="post" action="{{ route('profile.update') }}" class="mt-6 space-y-6">
@csrf
@method('patch')
<div>
<x-input-label for="name" :value="__('Name')" />
<x-text-input id="name" name="name" type="text" class="mt-1 block w-full" :value="old('name', $user->name)" required autofocus autocomplete="name" />
<x-input-error class="mt-2" :messages="$errors->get('name')" />
</div>
<div>
<x-input-label for="email" :value="__('Email')" />
<x-text-input id="email" name="email" type="email" class="mt-1 block w-full" :value="old('email', $user->email)" required autocomplete="username" />
<x-input-error class="mt-2" :messages="$errors->get('email')" />
@if ($user instanceof \Illuminate\Contracts\Auth\MustVerifyEmail && ! $user->hasVerifiedEmail())
<div>
<p class="text-sm mt-2 text-gray-800 dark:text-gray-200">
{{ __('Your email address is unverified.') }}
<button form="send-verification" class="underline text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-offset-gray-800">
{{ __('Click here to re-send the verification email.') }}
</button>
</p>
@if (session('status') === 'verification-link-sent')
<p class="mt-2 font-medium text-sm text-green-600 dark:text-green-400">
{{ __('A new verification link has been sent to your email address.') }}
</p>
@endif
</div>
@endif
</div>
<div class="flex items-center gap-4">
<x-primary-button>{{ __('Save') }}</x-primary-button>
@if (session('status') === 'profile-updated')
<p
x-data="{ show: true }"
x-show="show"
x-transition
x-init="setTimeout(() => show = false, 2000)"
class="text-sm text-gray-600 dark:text-gray-400"
>{{ __('Saved.') }}</p>
@endif
</div>
</form>
</section>

View File

@@ -1,24 +0,0 @@
@extends('layout')
@section('contenu')
<article>
<header>
<h1 class="titreBillet">{{ $billet->BIL_TITRE }}</h1>
<time>{{ $billet->BIL_DATE }}</time>
</header>
<p>{{ $billet->BIL_CONTENU }}</p>
</article>
<hr />
@if (count($commentaires) > 0)
<header>
<h1 id="titreReponses">Réponses à {{ $billet->BIL_TITRE }}</h1>
</header>
@foreach($commentaires as $commentaire)
<p>{{ $commentaire->COM_AUTEUR }} dit :</p>
<p>{{ $commentaire->COM_CONTENU }}</p>
@endforeach
@else
<header>
<h1 id="titreReponses">Il n'y a pas de réponse à ce billet.</h1>
</header>
@endif
@endsection

View File

@@ -1,40 +0,0 @@
@extends('layout')
@section('contenu')
@php
$today = date('Y-m-d');
@endphp
<h2>Commenter le billet : {{ $billet->BIL_TITRE }}</h2>
<form action="{{ route('commentaires.store') }}" method="POST">
@csrf
<p><i>Complétez le formulaire. Les champs marqué par </i><em>*</em> sont <em>obligatoires</em></p>
<fieldset>
<legend>Entrez votre commentaire :</legend>
<div>
<label for="COM_AUTEUR">Nom : <em>*</em></label>
<input type="text" @error('COM_AUTEUR') is-invalid @enderror name="COM_AUTEUR" placeholder="Entrez votre nom"></input>
@error('COM_AUTEUR')
<div><em>{{ $message }}</em></div>
@enderror
</div>
<br>
<div>
<label for="COM_CONTENU">Message : <em>*</em></label>
<textarea name="COM_CONTENU" @error('COM_CONTENU') is-invalid @enderror name="COM_CONTENU" placeholder="Votre commentaire :"></textarea>
@error('COM_CONTENU')
<div><em>{{ $message }}</em></div>
@enderror
</div>
<div>
<input type="hidden" name="COM_DATE" value="{{ $today }}"></input>
</div>
<div>
<input type="hidden" name="created_at" value="{{ $today }}"></input>
</div>
<div>
<input type="hidden" name="billet_id" value="{{ $idBillet }}"></input>
</div>
<br>
<button type="submit">Envoyer !</button>
</fieldset>
</form>
@endsection

View File

@@ -1,5 +0,0 @@
@extends('layout')
@section('contenu')
<h2>Merci ! Nous avons bien enregistré votre commentaire.</h2>
@endsection

13
laravel/routes/api.php Executable file
View File

@@ -0,0 +1,13 @@
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\BilletController;
use App\Http\Controllers\CommentaireController;
Route::get('/user', function (Request $request) {
return $request->user();
})->middleware('auth:sanctum');
Route::apiResource('billets', BilletController::class);
Route::post('/commentaires',[CommentaireController::class,"store"]);

Some files were not shown because too many files have changed in this diff Show More