Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
d0f1eec
Merge pull request #5 from COCOUVI/main
COCOUVI Oct 12, 2025
b7be6de
blog corection avec page d'accueil
kabiraladjiboni Oct 12, 2025
00971d3
boutique corection avec page d'accueil
kabiraladjiboni Oct 13, 2025
2419132
Merge branch 'main' into Boutique
kabiraladjiboni Oct 13, 2025
72e397e
Merge pull request #7 from COCOUVI/Boutique
kabiraladjiboni Oct 13, 2025
4947c3e
14/10/25
allmight777 Oct 14, 2025
2f2668b
Merge remote-tracking branch 'origin/Ange' into xandrothedev
COCOUVI Oct 14, 2025
fefc231
new updates space studnet
COCOUVI Oct 15, 2025
fa3bf1e
new updates space studnet
COCOUVI Oct 15, 2025
9eaf048
Remplacement complet
allmight777 Oct 16, 2025
d2689f0
Merge remote-tracking branch 'origin/Ange' into xandrothedev
COCOUVI Oct 16, 2025
15c0529
new updates
COCOUVI Oct 16, 2025
28952bf
18/10/2025
allmight777 Oct 18, 2025
176067b
Merge remote-tracking branch 'origin/Ange' into xandrothedev
COCOUVI Oct 18, 2025
38020bb
Change the logic of failed quizz Time
COCOUVI Oct 18, 2025
b1f2b7f
19/10/2025
allmight777 Oct 19, 2025
ccacdff
20/10/2025
allmight777 Oct 20, 2025
9a82627
Change the logic of failed quizz Time
COCOUVI Oct 20, 2025
a0388db
Change the logic of failed quizz Time
COCOUVI Oct 20, 2025
7797734
Update
kabiraladjiboni Oct 25, 2025
5d53607
merging with correction
COCOUVI Oct 26, 2025
7f1052a
add forgot passaword && verify email
COCOUVI Oct 28, 2025
c37aac0
connect payment to product
COCOUVI Nov 4, 2025
5535059
Update total
kabiraladjiboni Nov 8, 2025
6a88ce3
final work
COCOUVI Nov 10, 2025
f0f0258
final work
COCOUVI Nov 10, 2025
4198de2
final work
COCOUVI Nov 10, 2025
088c80c
final work
COCOUVI Nov 10, 2025
0a1f28e
final work
COCOUVI Nov 10, 2025
5810c77
final work
COCOUVI Nov 10, 2025
b1d2bd5
final work
COCOUVI Nov 11, 2025
e90801d
Rename Master.blade.php to master.blade.php
COCOUVI Nov 11, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
138 changes: 138 additions & 0 deletions app/Http/Controllers/AdminClientController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;

class AdminClientController extends Controller
{
/**
* Liste de tous les clients
*/
public function index(Request $request)
{
$query = User::withCount(['orders', 'paiements']);

// Recherche
if ($request->filled('search')) {
$search = $request->search;
$query->where(function($q) use ($search) {
$q->where('nom', 'like', "%{$search}%")
->where('prenom', 'like', "%{$search}%")
->orWhere('email', 'like', "%{$search}%")
->orWhere('telephone', 'like', "%{$search}%");
});
}

// Filtre par activité
if ($request->filled('filter')) {
switch ($request->filter) {
case 'active':
$query->has('orders');
break;
case 'inactive':
$query->doesntHave('orders');
break;
}
}

// Tri
$sortBy = $request->get('sort', 'created_at');
$sortOrder = $request->get('order', 'desc');

if ($sortBy === 'orders_count') {
$query->orderBy('orders_count', $sortOrder);
} else {
$query->orderBy($sortBy, $sortOrder);
}

$clients = $query->paginate(20);

// Statistiques
$stats = [
'total' => User::count(),
'with_orders' => User::has('orders')->count(),
'without_orders' => User::doesntHave('orders')->count(),
'this_month' => User::whereMonth('created_at', date('m'))
->whereYear('created_at', date('Y'))
->count(),
];

return view('admin.layout.boutique.clients.index', compact('clients', 'stats'));
}

/**
* Détails d'un client
*/
public function show($id)
{
$client = User::with([
'orders' => function($query) {
$query->with('products')->latest();
},
'paiements' => function($query) {
$query->latest();
}
])->findOrFail($id);

// Statistiques du client
$clientStats = [
'total_commandes' => $client->orders->count(),
'montant_total' => $client->orders->sum('price_total_order'),
'commande_moyenne' => $client->orders->count() > 0
? $client->orders->avg('price_total_order')
: 0,
'derniere_commande' => $client->orders->first()?->created_at,
];

return view('admin.layout.boutique.clients.show', compact('client', 'clientStats'));
}

/**
* Exporter la liste des clients
*/
public function export()
{
$clients = User::withCount('orders')->get();

$filename = 'clients_' . date('Y-m-d') . '.csv';

$headers = [
'Content-Type' => 'text/csv',
'Content-Disposition' => "attachment; filename={$filename}",
];

$callback = function() use ($clients) {
$file = fopen('php://output', 'w');

// En-têtes
fputcsv($file, [
'ID',
'Nom',
'Prenom',
'Email',
'Téléphone',
'Nombre de commandes',
'Date d\'inscription'
]);

foreach ($clients as $client) {
fputcsv($file, [
$client->id,
$client->nom,
$client->prenom,
$client->email,
$client->telephone ?? 'N/A',
$client->orders_count,
$client->created_at->format('d/m/Y')
]);
}

fclose($file);
};

return response()->stream($callback, 200, $headers);
}
}
13 changes: 10 additions & 3 deletions app/Http/Controllers/AdminController.php
Original file line number Diff line number Diff line change
Expand Up @@ -460,10 +460,8 @@ public function updateLesson(UpdateLessonRequest $request, $lessonId)
]);
}


public function destroyLesson($lessonId)
public function destroyLesson(Lesson $lesson)
{
$lesson = Lesson::find($lessonId);
$lesson->delete();

return response()->json([
Expand Down Expand Up @@ -502,6 +500,15 @@ public function Showpaiements()

return view('admin.layout.formations.list_paiements', compact("paiements"));
}
public function ShowPaiementsBoutique()
{
$paiements = Paiement::with(['user', 'commande'])
->whereNotNull('order_id')
->paginate(10);

return view('admin.layout.boutique.list_paiements', compact('paiements'));
}


public function ShowCertifications()
{
Expand Down
186 changes: 186 additions & 0 deletions app/Http/Controllers/AdminOrderController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Models\Order;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use App\Mail\OrderStatusChanged;

class AdminOrderController extends Controller
{
/**
* Liste de toutes les commandes
*/
public function index(Request $request)
{
$query = Order::with(['user', 'products', 'paiement']);

// Filtre par statut
if ($request->filled('status')) {
$query->where('status', $request->status);
}

// Filtre par date
if ($request->filled('date_from')) {
$query->whereDate('created_at', '>=', $request->date_from);
}
if ($request->filled('date_to')) {
$query->whereDate('created_at', '<=', $request->date_to);
}

// Recherche par code de commande ou nom client
if ($request->filled('search')) {
$search = $request->search;
$query->where(function($q) use ($search) {
$q->where('order_code', 'like', "%{$search}%")
->orWhereHas('user', function($userQuery) use ($search) {
$userQuery->where('name', 'like', "%{$search}%")
->orWhere('email', 'like', "%{$search}%");
});
});
}

$orders = $query->latest()->paginate(15);

// Statistiques
$stats = [
'total' => Order::count(),
'pending' => Order::pending()->count(),
'confirmed' => Order::confirmed()->count(),
'processing' => Order::processing()->count(),
'shipped' => Order::shipped()->count(),
'delivered' => Order::delivered()->count(),
];

return view('admin.layout.boutique.orders.index', compact('orders', 'stats'));
}

/**
* Détails d'une commande
*/
public function show($id)
{
$order = Order::with(['user', 'products', 'paiement'])->findOrFail($id);

return view('admin.layout.boutique.orders.show', compact('order'));
}

/**
* Changer le statut d'une commande
*/
public function updateStatus(Request $request, $id)
{
$request->validate([
'status' => 'required|in:pending,confirmed,processing,shipped,delivered,cancelled',
'note' => 'nullable|string|max:500'
]);

$order = Order::findOrFail($id);
$oldStatus = $order->status;
$newStatus = $request->status;

$order->update([
'status' => $newStatus
]);

// Envoyer une notification email au client
if ($newStatus === 'confirmed') {
try {
Mail::to($order->user->email)->send(new OrderStatusChanged($order, $oldStatus, $newStatus));
} catch (\Exception $e) {
// Log l'erreur mais ne bloque pas le processus
\Log::error('Email notification failed: ' . $e->getMessage());
}
}

return back()->with('success', 'Statut de la commande mis à jour avec succès.');
}

/**
* Valider le paiement d'une commande
*/
public function validatePayment($id)
{
$order = Order::with('paiement')->findOrFail($id);

if (!$order->paiement) {
return back()->with('error', 'Aucun paiement trouvé pour cette commande.');
}

$order->paiement->update([
'status' => 'completed'
]);

$order->update([
'status' => 'confirmed'
]);

// Envoyer notification
try {
Mail::to($order->user->email)->send(new OrderStatusChanged($order, 'pending', 'confirmed'));
} catch (\Exception $e) {
\Log::error('Email notification failed: ' . $e->getMessage());
}

return back()->with('success', 'Paiement validé et commande confirmée.');
}

/**
* Ajouter une note à la commande
*/
public function addNote(Request $request, $id)
{
$request->validate([
'note' => 'required|string|max:1000'
]);

$order = Order::findOrFail($id);

// Vous pouvez créer une table 'order_notes' séparée
// Ou stocker dans un champ JSON
// Pour l'instant, on utilise un champ texte simple

return back()->with('success', 'Note ajoutée avec succès.');
}

/**
* Exporter les commandes en CSV
*/
public function export(Request $request)
{
$orders = Order::with(['user', 'products'])->get();

$filename = 'commandes_' . date('Y-m-d') . '.csv';

$headers = [
'Content-Type' => 'text/csv',
'Content-Disposition' => "attachment; filename={$filename}",
];

$callback = function() use ($orders) {
$file = fopen('php://output', 'w');

// En-têtes
fputcsv($file, ['Code', 'Client', 'Email', 'Téléphone', 'Montant', 'Statut', 'Date']);

foreach ($orders as $order) {
fputcsv($file, [
$order->order_code,
$order->user->name,
$order->user->email,
$order->telephone,
$order->price_total_order . ' FCFA',
$order->statusLabel,
$order->created_at->format('d/m/Y H:i')
]);
}

fclose($file);
};

return response()->stream($callback, 200, $headers);
}
}
Loading