Skip to content
Snippets Groups Projects
Commit 749ed869 authored by AKIFI NAIL's avatar AKIFI NAIL
Browse files

ajout d ela focntionnalité"

parent 862d1fc3
Branches
No related merge requests found
......@@ -15,12 +15,12 @@
class PostController extends Controller
{
use AuthorizesRequests;
public function index()
{
Gate::authorize('viewAny', Post::class);
$posts = Post::orderBy('created_at', 'desc')->get();
return view('posts.index', ['posts' => $posts]);
return view('posts.index', ['posts' => $posts]);
}
......@@ -29,29 +29,29 @@ public function create()
Gate::authorize('create', Post::class);
$tags = Tag::all();
return view('posts.create' , ['tags' => $tags]);
$tags = Tag::all();
return view('posts.create', ['tags' => $tags]);
}
public function store(PostRequest $request)
{
Gate::authorize('create', Post::class);
$data = $request->validated();
$data = $request->validated();
// Gérer l'upload de l'image
if ($request->hasFile('image')) {
$imagePath = $request->file('image')->store('images', 'public');
$data['image'] = $imagePath;
}
$data['user_id'] = Auth::id(); // Ajoute l'id de l'utilisateur connecté dans les données à sauvegarder
$data['can_contact'] = $request->has('can_contact');
// Créer le post avec les données et gérer la relation avec les tags
$post = Post::create($data);
$post->tags()->sync($request->input('tags', []));
$post = Post::create($data);
$post->tags()->sync($request->input('tags', []));
if ($post->video) {
$parsedUrl = parse_url($post->video);
......@@ -60,41 +60,41 @@ public function store(PostRequest $request)
if (isset($queryParams['v'])) {
$post->video = "https://www.youtube.com/embed/" . $queryParams['v'];
$post->save();
$post->save();
}
}
}
return redirect()->route('posts.show', ['post' => $post]);
}
public function show(Post $post)
{
return view('posts.show', ['post' => $post]);
return view('posts.show', ['post' => $post]);
}
public function edit(Post $post)
{
{
Gate::authorize('update', $post);
$tags = Tag::all(); // Récupère tous les tags
return view('posts.edit' , ['post' => $post , 'tags' => $tags]); // Retourne la vue pour éditer un post
return view('posts.edit', ['post' => $post, 'tags' => $tags]); // Retourne la vue pour éditer un post
}
public function update(PostRequest $request, Post $post)
{
Gate::authorize('update', $post);
$data = $request->validated();
$data = $request->validated();
if ($request->hasFile('image')) {
if ($post->image) {
Storage::disk('public')->delete($post->image);
}
// Stocker la nouvelle image
$imagePath = $request->file('image')->store('images', 'public');
$data['image'] = $imagePath;
$data['image'] = $imagePath;
} else {
$data['image'] = $post->image;
}
......@@ -113,21 +113,20 @@ public function update(PostRequest $request, Post $post)
}
}
}
$post->fill($data);
$post->save();
return redirect()->route('posts.show', ['post' => $post]);
return redirect()->route('posts.show', ['post' => $post]);
}
public function destroy(Post $post)
{
Gate::authorize('delete', $post);
$tags = $post->tags->pluck('id')->toArray();
$tags = $post->tags->pluck('id')->toArray();
\App\Models\SupprimerRecemment::create([
'user_id' => $post->user_id,
'titre' => $post->titre,
......@@ -140,9 +139,9 @@ public function destroy(Post $post)
'tags' => json_encode($tags)
]);
$post->delete();
$post->delete();
return redirect()->route('posts.index')->with('status', 'Post déplacé dans supprimer récemment.');
}
......@@ -150,15 +149,15 @@ public function destroyForEver($id)
{
$supprimerRecemment = \App\Models\SupprimerRecemment::findOrFail($id);
$supprimerRecemment->forceDelete();
return redirect()->route('posts.index')->with('status', 'Post supprimé définitivement.');
}
public function restore($id)
{
$supprimerRecemment = \App\Models\SupprimerRecemment::findOrFail($id);
$post = Post::create([
'user_id' => $supprimerRecemment->user_id,
'titre' => $supprimerRecemment->titre,
......@@ -169,25 +168,78 @@ public function restore($id)
'date' => $supprimerRecemment->date,
'can_contact' => $supprimerRecemment->can_contact,
]);
$tags = json_decode($supprimerRecemment->tags, true);
if (!empty($tags)) {
$post->tags()->sync($tags);
}
$supprimerRecemment->delete();
if ($supprimerRecemment->trashed()) {
$supprimerRecemment->forceDelete();
}
return redirect()->route('posts.index')->with('status', 'Post restauré avec succès.');
}
public function archive(Post $post)
{
Gate::authorize('update', $post); // Vérifie si l'utilisateur est autorisé à archiver
// Récupérer les tags liés au post
$tags = $post->tags->pluck('id')->toArray();
// Créer une entrée dans la table `archives`
\App\Models\Archive::create([
'user_id' => $post->user_id,
'titre' => $post->titre,
'description' => $post->description,
'big_description' => $post->big_description,
'image' => $post->image,
'video' => $post->video,
'date' => $post->date,
'can_contact' => $post->can_contact,
'tags' => json_encode($tags), // Enregistrer les tags en JSON
]);
// Supprimer le post de la table `posts`
$post->delete();
return redirect()->route('posts.index')->with('status', 'Post archivé avec succès.');
}
public function restoreFromArchive($id)
{
$archives = \App\Models\Archive::findOrFail($id);
$post = Post::create([
'user_id' => $archives->user_id,
'titre' => $archives->titre,
'description' => $archives->description,
'big_description' => $archives->big_description,
'image' => $archives->image,
'video' => $archives->video,
'date' => $archives->date,
'can_contact' => $archives->can_contact,
]);
$tags = json_decode($archives->tags, true);
if (!empty($tags)) {
$post->tags()->sync($tags);
}
$archives->delete();
return redirect()->route('posts.index')->with('status', 'Post restauré avec succès.');
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Archive extends Model
{
use HasFactory;
protected $table = 'archives';
protected $fillable = [
'user_id',
'titre',
'description',
'big_description',
'image',
'video',
'date',
'can_contact',
'tags',
];
}
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
public function up()
{
Schema::create('archives', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id')->nullable();
$table->string('titre');
$table->text('description')->nullable();
$table->text('big_description')->nullable();
$table->string('image')->nullable();
$table->string('video')->nullable();
$table->date('date')->nullable();
$table->boolean('can_contact')->default(false);
$table->json('tags')->nullable();
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('archives');
}
};
......@@ -351,15 +351,6 @@ .round-briefcase{
font-size: 1.5rem;
}
.hover-shadow {
transition: box-shadow 0.3s ease;
/* Animation douce */
}
.hover-shadow:hover {
box-shadow: 0px 10px 20px rgba(0, 0, 0, 0.2);
/* Ombre augmentée */
}
@keyframes slide-right {
......
This diff is collapsed.
......@@ -2,29 +2,28 @@
<div class="container mt-5">
<div class="row align-items-center justify-content-center g-5">
<div class="col-12 col-md-6">
<img src="{{ asset('storage/' . $post->image) }}"
alt="image de {{ $post->titre }}"
class="img-fluid rounded-4 w-100">
<img src="{{ asset('storage/' . $post->image) }}" alt="image de {{ $post->titre }}"
class="img-fluid rounded-4 w-100">
</div>
<!-- Colonne du texte -->
<div class="col-12 col-md-6 pt-4 d-flex flex-column gap-3">
<h2 class="fs-1">{{ $post->titre }}</h2>
<p class="fs-6">{!! nl2br(e($post->big_description)) !!}</p>
<!-- Tags -->
<div class="d-flex gap-3 tags-color mb-4">
<i class="bi bi-tags"></i>
@if ($post->tags->isEmpty())
<span>Aucun tag</span>
@else
@foreach($post->tags as $tag)
@foreach ($post->tags as $tag)
<span>{{ $tag->name }}</span>
@endforeach
@endif
</div>
<!-- Bouton contacter -->
@if ($post->can_contact)
......@@ -37,15 +36,19 @@ class="img-fluid rounded-4 w-100">
<!-- Boutons d'actions pour l'admin -->
<div class="d-flex gap-3">
@if (auth()->check() && auth()->user()->role_id === 1)
<a href="{{ route('posts.edit', $post) }}" class="btn btn-warning">Edit project</a>
<button class="btn btn-danger del " data-target="modale-{{ $post->id }}">Supprimer le projet </button>
<a href="{{ route('posts.edit', $post) }}" class="btn btn-warning">Edit project</a>
<button class="btn btn-danger del " data-target="modale-{{ $post->id }}">Supprimer le projet
</button>
</div>
<div id="modale-{{ $post->id }}" class="modale d-flex align-items-center justify-content-center hidden">
<div id="modale-{{ $post->id }}"
class="modale d-flex align-items-center justify-content-center hidden">
<div class="modale-content bg-white p-5 shadow-lg">
<h3 class="text-center mb-3">Êtes-vous sûr de vouloir supprimer cet élément ?</h3>
<p class="text-center text-muted">
Aucune donnée ne pourra être récupérée, et l'élément restera dans les éléments supprimés récemment pendant un maximum de <span class="red"> 30 jours, </span> après quoi il sera définitivement supprimé pour tous les utilisateurs du site.
Aucune donnée ne pourra être récupérée, et l'élément restera dans les éléments supprimés
récemment pendant un maximum de <span class="red"> 30 jours, </span> après quoi il sera
définitivement supprimé pour tous les utilisateurs du site.
</p>
<div class="d-flex justify-content-between gap-3 mt-4">
<form method="POST" action="{{ route('posts.destroy', $post) }}">
......@@ -58,115 +61,112 @@ class="img-fluid rounded-4 w-100">
</div>
</div>
<form action="{{ route('posts.archive', $post->id) }}" method="POST">
@csrf
<button type="submit" class="btn btn-secondary">
<i class="bi bi-archive"></i>
Archiver</button>
</form>
@endif
</div>
</div>
@if ($post->video)
</div>
@if ($post->video)
<div class="col-12 d-flex justify-content-center mb-5 mt-5">
<iframe width="1000" height="500"
src="{{ $post->video }}"
title="YouTube video player"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen>
<iframe width="1000" height="500" src="{{ $post->video }}" title="YouTube video player"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen>
</iframe>
</div>
@endif
@if ($post->can_contact)
<h3 class="text-center mt-3 mb-5 fs-1" id="contact">Nous Contacter</h3>
<div class="col-12 d-flex flex-wrap shadow-lg position-relative z-4">
<div class="col-12 col-md-6 mb-3 mb-md-0 d-none d-md-block">
<img src="{{ asset('images/contact3.jpg') }}"
alt="illustration de contact"
class="img-fluid rounded-start w-100 h-100 object-fit-contain interactive-image">
</div>
<div class="col-12 col-md-6 d-flex flex-column align-items-center justify-content-center">
<div class="logo-container mt-5">
<img src="{{ asset('images/Icube-remove.png') }}" alt="Logo de l'entreprise" class="img-fluid" style="max-width: 100px; height: auto;">
</div>
<form class="w-100 p-4 rounded form-contact">
<div class="mb-3 position-relative">
<label for="name" class="form-label">Nom</label>
<input type="text" id="name" class="form-control" maxlength="20" required>
<i class="bi bi-person-vcard icon-form"></i>
</div>
<div class="mb-3 position-relative">
<label for="subject" class="form-label">Prenom</label>
<input type="text" id="subject" class="form-control" maxlength="20" required>
<i class="bi bi-person icon-form"></i>
</div>
<div class="mb-3 position-relative">
<label for="email" class="form-label">Email</label>
<input type="email" id="email" class="form-control" maxlength="50" required>
<i class="bi bi-envelope icon-form"></i>
</div>
<div class="mb-3 position-relative">
<label for="objet" class="form-label">Objet</label>
<input type="text" id="objet" class="form-control" maxlength="50" required>
<i class="bi bi-paperclip icon-form"></i>
</div>
<div class="mb-3 position-relative">
<label for="organisation" class="form-label">Organisation</label>
<input type="text" id="organisation" class="form-control" maxlength="50" required>
<i class="bi bi-buildings icon-form"></i>
@if ($post->can_contact)
<h3 class="text-center mt-3 mb-5 fs-1" id="contact">Nous Contacter</h3>
<div class="col-12 d-flex flex-wrap shadow-lg position-relative z-4">
<div class="col-12 col-md-6 mb-3 mb-md-0 d-none d-md-block">
<img src="{{ asset('images/contact3.jpg') }}" alt="illustration de contact"
class="img-fluid rounded-start w-100 h-100 object-fit-contain interactive-image">
</div>
<div class="col-12 col-md-6 d-flex flex-column align-items-center justify-content-center">
<div class="logo-container mt-5">
<img src="{{ asset('images/Icube-remove.png') }}" alt="Logo de l'entreprise" class="img-fluid"
style="max-width: 100px; height: auto;">
</div>
<form class="w-100 p-4 rounded form-contact">
<div class="mb-3 position-relative">
<label for="name" class="form-label">Nom</label>
<input type="text" id="name" class="form-control" maxlength="20" required>
<i class="bi bi-person-vcard icon-form"></i>
</div>
<div class="mb-3 position-relative">
<label for="subject" class="form-label">Prenom</label>
<input type="text" id="subject" class="form-control" maxlength="20" required>
<i class="bi bi-person icon-form"></i>
</div>
<div class="mb-3 position-relative">
<label for="email" class="form-label">Email</label>
<input type="email" id="email" class="form-control" maxlength="50" required>
<i class="bi bi-envelope icon-form"></i>
</div>
<div class="mb-3 position-relative">
<label for="objet" class="form-label">Objet</label>
<input type="text" id="objet" class="form-control" maxlength="50" required>
<i class="bi bi-paperclip icon-form"></i>
</div>
<div class="mb-3 position-relative">
<label for="organisation" class="form-label">Organisation</label>
<input type="text" id="organisation" class="form-control" maxlength="50" required>
<i class="bi bi-buildings icon-form"></i>
</div>
<div class="mb-3">
<label for="message" class="form-label">Message</label>
<textarea id="message" class="form-control" rows="5" maxlength="1000" required></textarea>
</div>
<div class="d-flex justify-content-center">
<button class="button-contact-send">
<div class="svg-wrapper-1-contact-send">
<div class="svg-wrapper-contact-send">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24"
height="24">
<path fill="none" d="M0 0h24v24H0z"></path>
<path fill="currentColor"
d="M1.946 9.315c-.522-.174-.527-.455.01-.634l19.087-6.362c.529-.176.832.12.684.638l-5.454 19.086c-.15.529-.455.547-.679.045L12 14l6-8-8 6-8.054-2.685z">
</path>
</svg>
</div>
</div>
<span class="span-contact-send">Envoyer</span>
</button>
</div>
</form>
</div>
</div>
<div class="mb-3">
<label for="message" class="form-label">Message</label>
<textarea id="message" class="form-control" rows="5" maxlength="1000" required></textarea>
</div>
<div class="d-flex justify-content-center">
<button class="button-contact-send">
<div class="svg-wrapper-1-contact-send">
<div class="svg-wrapper-contact-send">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"
>
<path fill="none" d="M0 0h24v24H0z"></path>
<path
fill="currentColor"
d="M1.946 9.315c-.522-.174-.527-.455.01-.634l19.087-6.362c.529-.176.832.12.684.638l-5.454 19.086c-.15.529-.455.547-.679.045L12 14l6-8-8 6-8.054-2.685z"
></path>
</svg>
</div>
</div>
<span class="span-contact-send">Envoyer</span>
</button>
</div>
</form>
</div>
</div>
@endif
</div>
<script>
document.addEventListener("DOMContentLoaded", () => {
const image = document.querySelector(".interactive-image");
const image = document.querySelector(".interactive-image");
image.addEventListener("mousemove", (e) => {
const rect = image.getBoundingClientRect();
const x = (e.clientX - rect.left) / rect.width - 0.5;
const y = (e.clientY - rect.top) / rect.height - 0.5;
image.addEventListener("mousemove", (e) => {
const rect = image.getBoundingClientRect();
const x = (e.clientX - rect.left) / rect.width - 0.5;
const y = (e.clientY - rect.top) / rect.height - 0.5;
const rotationX = y * 40;
const rotationY = x * 40;
const rotationX = y * 40;
const rotationY = x * 40;
image.style.transform = `rotateX(${rotationX}deg) rotateY(${rotationY}deg)`;
});
image.style.transform = `rotateX(${rotationX}deg) rotateY(${rotationY}deg)`;
});
image.addEventListener("mouseleave", () => {
image.addEventListener("mouseleave", () => {
image.style.transform = "rotateX(0deg) rotateY(0deg)";
});
});
image.style.transform = "rotateX(0deg) rotateY(0deg)";
});
});
</script>
</x-layout.front>
......@@ -10,6 +10,7 @@
use App\Models\Tag;
use App\Models\Membre;
use App\Models\Offre;
use App\Models\Archive;
use App\Models\SupprimerRecemment;
Route::get('/', function () {
......@@ -27,8 +28,9 @@
$tag = Tag::all();
$membre = Membre::all();
$offre = Offre::all();
$archive = Archive::all();
$supprimerRecemment = SupprimerRecemment::all();
return view('dashboard', compact('post', 'tag', 'membre', 'offre', 'supprimerRecemment'));
return view('dashboard', compact('post', 'tag', 'membre', 'offre', 'supprimerRecemment', 'archive'));
})->middleware(['auth', 'verified'])->name('dashboard');
Route::middleware('auth')->group(function () {
......@@ -42,6 +44,8 @@
Route::resource('posts', PostController::class);
Route::patch('posts/{id}/restore', [PostController::class, 'restore'])->name('posts.restore');
Route::delete('posts/{id}/destroyForEver', [PostController::class, 'destroyForEver'])->name('posts.destroyForEver');
Route::post('/posts/{post}/archive', [PostController::class, 'archive'])->name('posts.archive');
Route::post('/archives/{id}/restore', [PostController::class, 'restoreFromArchive'])->name('archives.restore');
Route::resource('membres', MembreController::class);
Route::resource('tags', TagController::class);
Route::resource('offres', OffreController::class);
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment