feat: update employee pages with admin-style design
This commit is contained in:
parent
e7fef17831
commit
29b4e27baa
|
|
@ -1,13 +1,18 @@
|
|||
'use client';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useAuth } from '@/hooks';
|
||||
import { Card } from '@/components/ui';
|
||||
import { Loading } from '@/components/ui/Loading';
|
||||
import { ROUTES, API_BASE_URL } from '@/utils/constants';
|
||||
import toast from 'react-hot-toast';
|
||||
import { API_BASE_URL } from '@/utils/constants';
|
||||
import Link from 'next/link';
|
||||
import {
|
||||
LayoutDashboard,
|
||||
Clock,
|
||||
CheckCircle,
|
||||
BarChart3,
|
||||
Search,
|
||||
Gift,
|
||||
ClipboardList
|
||||
} from 'lucide-react';
|
||||
|
||||
interface PendingTicket {
|
||||
id: string;
|
||||
|
|
@ -97,141 +102,125 @@ export default function EmployeDashboardPage() {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-full bg-gradient-to-br from-gray-50 via-white to-gray-50 p-8">
|
||||
{/* Welcome Section */}
|
||||
<div className="mb-8">
|
||||
<h1 className="text-4xl font-bold text-[#2d5a3d] mb-2">
|
||||
Bonjour {user?.firstName} ! 👋
|
||||
</h1>
|
||||
<p className="text-gray-600 text-lg">
|
||||
Bienvenue dans votre espace employé. Voici un aperçu de votre activité.
|
||||
</p>
|
||||
<div className="p-6">
|
||||
{/* Header */}
|
||||
<div className="mb-6">
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<div className="w-12 h-12 bg-gradient-to-br from-green-600 to-green-700 rounded-xl flex items-center justify-center shadow-lg">
|
||||
<LayoutDashboard className="w-6 h-6 text-white" />
|
||||
</div>
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold bg-gradient-to-r from-green-600 to-green-700 bg-clip-text text-transparent">
|
||||
Dashboard
|
||||
</h1>
|
||||
<p className="text-gray-500">
|
||||
Bonjour {user?.firstName}, bienvenue dans votre espace employé
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Statistics Cards */}
|
||||
<div className="grid md:grid-cols-3 gap-6 mb-8">
|
||||
<div className="bg-white rounded-xl shadow-md p-6 border border-gray-100 hover:shadow-lg transition-shadow">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium text-gray-500 mb-2">
|
||||
Tickets en attente
|
||||
</p>
|
||||
<p className="text-4xl font-bold text-yellow-500">
|
||||
{stats.pendingTickets}
|
||||
</p>
|
||||
<div className="grid md:grid-cols-3 gap-4 mb-6">
|
||||
<div className="bg-gradient-to-br from-amber-50 to-amber-100 rounded-xl p-4 border border-amber-200">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-12 h-12 bg-amber-200 rounded-lg flex items-center justify-center">
|
||||
<Clock className="w-6 h-6 text-amber-600" />
|
||||
</div>
|
||||
<div className="w-16 h-16 bg-yellow-100 rounded-full flex items-center justify-center">
|
||||
<svg className="w-8 h-8 text-yellow-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
<div>
|
||||
<p className="text-3xl font-bold text-amber-700">{stats.pendingTickets}</p>
|
||||
<p className="text-sm text-amber-600">En attente</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white rounded-xl shadow-md p-6 border border-gray-100 hover:shadow-lg transition-shadow">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium text-gray-500 mb-2">
|
||||
Réclamés aujourd'hui
|
||||
</p>
|
||||
<p className="text-4xl font-bold text-green-600">
|
||||
{stats.claimedToday}
|
||||
</p>
|
||||
<div className="bg-gradient-to-br from-green-50 to-green-100 rounded-xl p-4 border border-green-200">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-12 h-12 bg-green-200 rounded-lg flex items-center justify-center">
|
||||
<CheckCircle className="w-6 h-6 text-green-600" />
|
||||
</div>
|
||||
<div className="w-16 h-16 bg-green-100 rounded-full flex items-center justify-center">
|
||||
<svg className="w-8 h-8 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
<div>
|
||||
<p className="text-3xl font-bold text-green-700">{stats.claimedToday}</p>
|
||||
<p className="text-sm text-green-600">Validés aujourd'hui</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white rounded-xl shadow-md p-6 border border-gray-100 hover:shadow-lg transition-shadow">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium text-gray-500 mb-2">
|
||||
Total réclamés
|
||||
</p>
|
||||
<p className="text-4xl font-bold text-blue-600">
|
||||
{stats.totalClaimed}
|
||||
</p>
|
||||
<div className="bg-gradient-to-br from-blue-50 to-blue-100 rounded-xl p-4 border border-blue-200">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-12 h-12 bg-blue-200 rounded-lg flex items-center justify-center">
|
||||
<BarChart3 className="w-6 h-6 text-blue-600" />
|
||||
</div>
|
||||
<div className="w-16 h-16 bg-blue-100 rounded-full flex items-center justify-center">
|
||||
<svg className="w-8 h-8 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
|
||||
</svg>
|
||||
<div>
|
||||
<p className="text-3xl font-bold text-blue-700">{stats.totalClaimed}</p>
|
||||
<p className="text-sm text-blue-600">Total validés</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Quick Actions Title */}
|
||||
<div className="mb-6">
|
||||
<h2 className="text-2xl font-bold text-gray-800">Actions rapides</h2>
|
||||
<p className="text-gray-500">Accédez rapidement aux fonctionnalités principales</p>
|
||||
</div>
|
||||
|
||||
{/* Quick Actions */}
|
||||
<div className="grid md:grid-cols-3 gap-6">
|
||||
<Link href="/employe/verification">
|
||||
<div className="bg-gradient-to-br from-green-600 to-green-800 text-white rounded-xl shadow-md p-6 hover:shadow-xl transition-all hover:scale-[1.02] cursor-pointer">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-14 h-14 bg-white/20 rounded-xl flex items-center justify-center">
|
||||
<svg className="w-7 h-7 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-bold mb-1">
|
||||
Validation des gains
|
||||
</h3>
|
||||
<p className="text-white/80 text-sm">
|
||||
Rechercher et valider les tickets
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
<div className="bg-white rounded-2xl shadow-sm border border-gray-100 overflow-hidden">
|
||||
<div className="px-6 py-4 border-b border-gray-100 bg-gradient-to-r from-gray-50 to-gray-100">
|
||||
<h2 className="text-lg font-bold text-gray-800">Actions rapides</h2>
|
||||
<p className="text-sm text-gray-500">Accédez rapidement aux fonctionnalités principales</p>
|
||||
</div>
|
||||
|
||||
<Link href="/employe/gains-client">
|
||||
<div className="bg-gradient-to-br from-purple-600 to-purple-800 text-white rounded-xl shadow-md p-6 hover:shadow-xl transition-all hover:scale-[1.02] cursor-pointer">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-14 h-14 bg-white/20 rounded-xl flex items-center justify-center">
|
||||
<svg className="w-7 h-7 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v13m0-13V6a2 2 0 112 2h-2zm0 0V5.5A2.5 2.5 0 109.5 8H12zm-7 4h14M5 12a2 2 0 110-4h14a2 2 0 110 4M5 12v7a2 2 0 002 2h10a2 2 0 002-2v-7" />
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-bold mb-1">
|
||||
Gains du Client
|
||||
</h3>
|
||||
<p className="text-white/80 text-sm">
|
||||
Rechercher les gains d'un client
|
||||
</p>
|
||||
<div className="p-6 grid md:grid-cols-3 gap-4">
|
||||
<Link href="/employe/verification">
|
||||
<div className="bg-gradient-to-br from-emerald-600 to-teal-600 text-white rounded-xl p-5 hover:shadow-xl transition-all hover:scale-[1.02] cursor-pointer">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-12 h-12 bg-white/20 rounded-xl flex items-center justify-center">
|
||||
<Search className="w-6 h-6 text-white" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg font-bold mb-1">
|
||||
Validation des gains
|
||||
</h3>
|
||||
<p className="text-white/80 text-sm">
|
||||
Rechercher et valider les tickets
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
</Link>
|
||||
|
||||
<Link href="/employe/historique">
|
||||
<div className="bg-gradient-to-br from-slate-600 to-slate-800 text-white rounded-xl shadow-md p-6 hover:shadow-xl transition-all hover:scale-[1.02] cursor-pointer">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-14 h-14 bg-white/20 rounded-xl flex items-center justify-center">
|
||||
<svg className="w-7 h-7 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01" />
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-bold mb-1">
|
||||
Historique
|
||||
</h3>
|
||||
<p className="text-white/80 text-sm">
|
||||
Consulter l'historique des validations
|
||||
</p>
|
||||
<Link href="/employe/gains-client">
|
||||
<div className="bg-gradient-to-br from-purple-600 to-pink-600 text-white rounded-xl p-5 hover:shadow-xl transition-all hover:scale-[1.02] cursor-pointer">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-12 h-12 bg-white/20 rounded-xl flex items-center justify-center">
|
||||
<Gift className="w-6 h-6 text-white" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg font-bold mb-1">
|
||||
Gains du Client
|
||||
</h3>
|
||||
<p className="text-white/80 text-sm">
|
||||
Rechercher les gains d'un client
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
</Link>
|
||||
|
||||
<Link href="/employe/historique">
|
||||
<div className="bg-gradient-to-br from-slate-600 to-slate-700 text-white rounded-xl p-5 hover:shadow-xl transition-all hover:scale-[1.02] cursor-pointer">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-12 h-12 bg-white/20 rounded-xl flex items-center justify-center">
|
||||
<ClipboardList className="w-6 h-6 text-white" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg font-bold mb-1">
|
||||
Historique
|
||||
</h3>
|
||||
<p className="text-white/80 text-sm">
|
||||
Consulter l'historique des validations
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { Card, EmptyState, StatusBadge } from '@/components/ui';
|
||||
import Button from '@/components/Button';
|
||||
import { StatusBadge } from '@/components/ui';
|
||||
import { api } from '@/hooks/useApi';
|
||||
import toast from 'react-hot-toast';
|
||||
import {
|
||||
Search,
|
||||
User,
|
||||
Gift,
|
||||
CheckCircle,
|
||||
Phone,
|
||||
Mail,
|
||||
Package,
|
||||
Clock,
|
||||
User,
|
||||
} from 'lucide-react';
|
||||
|
||||
interface ClientPrize {
|
||||
|
|
@ -94,55 +94,62 @@ export default function GainsClientPage() {
|
|||
|
||||
|
||||
return (
|
||||
<div className="min-h-full bg-gradient-to-br from-gray-50 via-white to-gray-50 p-8">
|
||||
<div className="p-6">
|
||||
{/* Header */}
|
||||
<div className="mb-8">
|
||||
<h1 className="text-4xl font-bold text-[#2d5a3d] mb-2">
|
||||
Gains du Client
|
||||
</h1>
|
||||
<p className="text-gray-600 text-lg">
|
||||
Recherchez un client pour visualiser tous ses gains et les remettre
|
||||
</p>
|
||||
<div className="mb-6">
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<div className="w-12 h-12 bg-gradient-to-br from-purple-600 to-pink-600 rounded-xl flex items-center justify-center shadow-lg">
|
||||
<Gift className="w-6 h-6 text-white" />
|
||||
</div>
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold bg-gradient-to-r from-purple-600 to-pink-600 bg-clip-text text-transparent">
|
||||
Gains du Client
|
||||
</h1>
|
||||
<p className="text-gray-500">
|
||||
Recherchez un client pour visualiser tous ses gains et les remettre
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Search Section */}
|
||||
<div className="bg-gradient-to-r from-purple-600 to-purple-700 rounded-2xl shadow-lg p-8 mb-8">
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
<div className="w-10 h-10 bg-white/20 rounded-lg flex items-center justify-center">
|
||||
<Search className="w-5 h-5 text-white" />
|
||||
<div className="bg-[#faf8f5] rounded-2xl p-6 mb-6 border border-gray-200">
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<div className="w-10 h-10 bg-purple-100 rounded-lg flex items-center justify-center">
|
||||
<Search className="w-5 h-5 text-purple-600" />
|
||||
</div>
|
||||
<h2 className="text-xl font-bold text-white">
|
||||
<h2 className="text-lg font-bold text-gray-800">
|
||||
Rechercher un client
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
{/* Search Type Selection */}
|
||||
<div className="flex gap-6">
|
||||
<label className={`flex items-center gap-3 cursor-pointer px-4 py-2 rounded-lg transition-all ${searchType === 'email' ? 'bg-white/20' : 'hover:bg-white/10'}`}>
|
||||
<div className="flex gap-4">
|
||||
<label className={`flex items-center gap-3 cursor-pointer px-4 py-2 rounded-lg transition-all border ${searchType === 'email' ? 'bg-purple-100 border-purple-300' : 'bg-white border-gray-200 hover:bg-gray-50'}`}>
|
||||
<input
|
||||
type="radio"
|
||||
name="searchType"
|
||||
value="email"
|
||||
checked={searchType === 'email'}
|
||||
onChange={(e) => setSearchType(e.target.value as 'email')}
|
||||
className="w-4 h-4 accent-white"
|
||||
className="w-4 h-4 accent-purple-600"
|
||||
/>
|
||||
<Mail className="w-5 h-5 text-white" />
|
||||
<span className="text-sm font-medium text-white">Email</span>
|
||||
<Mail className="w-5 h-5 text-purple-600" />
|
||||
<span className="text-sm font-medium text-gray-700">Email</span>
|
||||
</label>
|
||||
|
||||
<label className={`flex items-center gap-3 cursor-pointer px-4 py-2 rounded-lg transition-all ${searchType === 'phone' ? 'bg-white/20' : 'hover:bg-white/10'}`}>
|
||||
<label className={`flex items-center gap-3 cursor-pointer px-4 py-2 rounded-lg transition-all border ${searchType === 'phone' ? 'bg-purple-100 border-purple-300' : 'bg-white border-gray-200 hover:bg-gray-50'}`}>
|
||||
<input
|
||||
type="radio"
|
||||
name="searchType"
|
||||
value="phone"
|
||||
checked={searchType === 'phone'}
|
||||
onChange={(e) => setSearchType(e.target.value as 'phone')}
|
||||
className="w-4 h-4 accent-white"
|
||||
className="w-4 h-4 accent-purple-600"
|
||||
/>
|
||||
<Phone className="w-5 h-5 text-white" />
|
||||
<span className="text-sm font-medium text-white">Téléphone</span>
|
||||
<Phone className="w-5 h-5 text-purple-600" />
|
||||
<span className="text-sm font-medium text-gray-700">Téléphone</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
|
@ -154,12 +161,12 @@ export default function GainsClientPage() {
|
|||
value={searchValue}
|
||||
onChange={(e) => setSearchValue(e.target.value)}
|
||||
onKeyPress={(e) => e.key === 'Enter' && handleSearch()}
|
||||
className="flex-1 px-5 py-4 border-2 border-white/20 bg-white/10 text-white placeholder-white/60 rounded-xl focus:ring-2 focus:ring-white focus:border-transparent text-lg backdrop-blur-sm"
|
||||
className="flex-1 px-4 py-3 border border-gray-200 bg-white rounded-xl focus:ring-2 focus:ring-purple-500 focus:border-transparent text-gray-800"
|
||||
/>
|
||||
<button
|
||||
onClick={handleSearch}
|
||||
disabled={loading}
|
||||
className="flex items-center gap-2 px-8 py-4 bg-white text-purple-700 rounded-xl hover:bg-purple-50 transition-all font-bold shadow-lg hover:shadow-xl hover:scale-[1.02] disabled:opacity-50"
|
||||
className="flex items-center gap-2 px-6 py-3 bg-gradient-to-r from-purple-600 to-pink-600 text-white rounded-xl hover:from-purple-700 hover:to-pink-700 transition-all font-semibold shadow-lg hover:shadow-xl disabled:opacity-50"
|
||||
>
|
||||
<Search className="w-5 h-5" />
|
||||
{loading ? 'Recherche...' : 'Rechercher'}
|
||||
|
|
@ -172,10 +179,10 @@ export default function GainsClientPage() {
|
|||
{clientData && (
|
||||
<>
|
||||
{/* Client Info Card */}
|
||||
<div className="bg-white rounded-2xl shadow-md border border-gray-100 p-6 mb-6">
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="bg-white rounded-2xl shadow-sm border border-gray-100 p-6 mb-6">
|
||||
<div className="flex flex-col lg:flex-row items-start justify-between gap-6">
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="w-16 h-16 bg-gradient-to-br from-purple-500 to-purple-600 rounded-xl flex items-center justify-center text-white font-bold text-xl shadow-lg">
|
||||
<div className="w-16 h-16 bg-gradient-to-br from-purple-500 to-pink-500 rounded-xl flex items-center justify-center text-white font-bold text-xl shadow-lg">
|
||||
{clientData.client.firstName?.charAt(0)}{clientData.client.lastName?.charAt(0)}
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -198,31 +205,31 @@ export default function GainsClientPage() {
|
|||
</div>
|
||||
|
||||
<div className="flex gap-4">
|
||||
<div className="bg-gray-50 rounded-xl p-4 text-center min-w-[100px]">
|
||||
<div className="bg-gradient-to-br from-gray-50 to-gray-100 rounded-xl p-4 text-center min-w-[100px] border border-gray-200">
|
||||
<p className="text-xs font-medium text-gray-500 mb-1">Total</p>
|
||||
<p className="text-3xl font-bold text-gray-900">{clientData.totalPrizes}</p>
|
||||
<p className="text-3xl font-bold text-gray-700">{clientData.totalPrizes}</p>
|
||||
</div>
|
||||
<div className="bg-yellow-50 rounded-xl p-4 text-center min-w-[100px]">
|
||||
<p className="text-xs font-medium text-yellow-600 mb-1">À remettre</p>
|
||||
<p className="text-3xl font-bold text-yellow-600">{clientData.pendingPrizes}</p>
|
||||
<div className="bg-gradient-to-br from-amber-50 to-amber-100 rounded-xl p-4 text-center min-w-[100px] border border-amber-200">
|
||||
<p className="text-xs font-medium text-amber-600 mb-1">À remettre</p>
|
||||
<p className="text-3xl font-bold text-amber-700">{clientData.pendingPrizes}</p>
|
||||
</div>
|
||||
<div className="bg-green-50 rounded-xl p-4 text-center min-w-[100px]">
|
||||
<div className="bg-gradient-to-br from-green-50 to-green-100 rounded-xl p-4 text-center min-w-[100px] border border-green-200">
|
||||
<p className="text-xs font-medium text-green-600 mb-1">Remis</p>
|
||||
<p className="text-3xl font-bold text-green-600">{clientData.claimedPrizes}</p>
|
||||
<p className="text-3xl font-bold text-green-700">{clientData.claimedPrizes}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Prizes List */}
|
||||
<div className="bg-white rounded-2xl shadow-md border border-gray-100 overflow-hidden">
|
||||
<div className="px-6 py-5 border-b border-gray-100 bg-gradient-to-r from-gray-50 to-white">
|
||||
<div className="bg-white rounded-2xl shadow-sm border border-gray-100 overflow-hidden">
|
||||
<div className="px-6 py-4 border-b border-gray-100 bg-gradient-to-r from-gray-50 to-gray-100">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-10 h-10 bg-purple-100 rounded-lg flex items-center justify-center">
|
||||
<Gift className="w-5 h-5 text-purple-600" />
|
||||
<Package className="w-5 h-5 text-purple-600" />
|
||||
</div>
|
||||
<div>
|
||||
<h2 className="text-xl font-bold text-gray-800">
|
||||
<h2 className="text-lg font-bold text-gray-800">
|
||||
Lots gagnés
|
||||
</h2>
|
||||
<p className="text-sm text-gray-500">{clientData.prizes.length} lot(s) au total</p>
|
||||
|
|
@ -245,13 +252,16 @@ export default function GainsClientPage() {
|
|||
key={prize.ticketId}
|
||||
className={`border-2 rounded-xl p-5 transition-all hover:shadow-md ${
|
||||
prize.status === 'PENDING'
|
||||
? 'border-yellow-200 bg-yellow-50/30'
|
||||
? 'border-amber-200 bg-amber-50/30'
|
||||
: 'border-gray-100 bg-white'
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex flex-col lg:flex-row items-start justify-between gap-4">
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center gap-3 mb-3">
|
||||
<div className="w-10 h-10 bg-purple-100 rounded-lg flex items-center justify-center">
|
||||
<Gift className="w-5 h-5 text-purple-600" />
|
||||
</div>
|
||||
<h3 className="text-lg font-bold text-gray-900">
|
||||
{prize.prize.name}
|
||||
</h3>
|
||||
|
|
@ -268,6 +278,7 @@ export default function GainsClientPage() {
|
|||
<span className="font-mono font-semibold bg-gray-100 px-2 py-1 rounded">{prize.ticketCode}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Clock className="w-4 h-4 text-gray-400" />
|
||||
<span className="text-gray-500">Gagné le:</span>
|
||||
<span className="font-medium">
|
||||
{new Date(prize.playedAt).toLocaleDateString('fr-FR')}
|
||||
|
|
@ -275,6 +286,7 @@ export default function GainsClientPage() {
|
|||
</div>
|
||||
{prize.claimedAt && (
|
||||
<div className="flex items-center gap-2">
|
||||
<CheckCircle className="w-4 h-4 text-green-500" />
|
||||
<span className="text-gray-500">Remis le:</span>
|
||||
<span className="font-medium text-green-600">
|
||||
{new Date(prize.claimedAt).toLocaleDateString('fr-FR')}
|
||||
|
|
@ -282,8 +294,9 @@ export default function GainsClientPage() {
|
|||
</div>
|
||||
)}
|
||||
{prize.validatedBy && (
|
||||
<div className="col-span-2 flex items-center gap-2">
|
||||
<span className="text-gray-500">Remis par:</span>
|
||||
<div className="flex items-center gap-2">
|
||||
<User className="w-4 h-4 text-gray-400" />
|
||||
<span className="text-gray-500">Par:</span>
|
||||
<span className="font-medium">{prize.validatedBy}</span>
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -294,7 +307,7 @@ export default function GainsClientPage() {
|
|||
<button
|
||||
onClick={() => handleValidatePrize(prize.ticketId)}
|
||||
disabled={validatingTicketId === prize.ticketId}
|
||||
className="ml-4 flex items-center gap-2 px-5 py-3 bg-gradient-to-r from-green-600 to-green-700 text-white font-semibold rounded-xl hover:from-green-700 hover:to-green-800 transition-all shadow-sm hover:shadow-md disabled:opacity-50"
|
||||
className="flex items-center gap-2 px-5 py-3 bg-gradient-to-r from-green-600 to-green-700 text-white font-semibold rounded-xl hover:from-green-700 hover:to-green-800 transition-all shadow-sm hover:shadow-md disabled:opacity-50"
|
||||
>
|
||||
<CheckCircle className="w-5 h-5" />
|
||||
{validatingTicketId === prize.ticketId ? 'Validation...' : 'Marquer comme remis'}
|
||||
|
|
|
|||
|
|
@ -2,15 +2,19 @@
|
|||
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useAuth } from '@/hooks';
|
||||
import { Card, EmptyState, StatusBadge } from '@/components/ui';
|
||||
import { StatusBadge } from '@/components/ui';
|
||||
import { Loading } from '@/components/ui/Loading';
|
||||
import { api } from '@/hooks/useApi';
|
||||
import toast from 'react-hot-toast';
|
||||
import {
|
||||
ClipboardList,
|
||||
Calendar,
|
||||
User,
|
||||
Gift,
|
||||
RefreshCw,
|
||||
CheckCircle,
|
||||
XCircle,
|
||||
BarChart3,
|
||||
User,
|
||||
} from 'lucide-react';
|
||||
|
||||
interface HistoryTicket {
|
||||
|
|
@ -73,70 +77,71 @@ export default function EmployeeHistoryPage() {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-full bg-gradient-to-br from-gray-50 via-white to-gray-50 p-8">
|
||||
<div className="p-6">
|
||||
{/* Header */}
|
||||
<div className="mb-8">
|
||||
<h1 className="text-4xl font-bold text-[#2d5a3d] mb-2">
|
||||
Historique des Validations
|
||||
</h1>
|
||||
<p className="text-gray-600 text-lg">
|
||||
Consultez l'historique de vos validations de tickets
|
||||
</p>
|
||||
<div className="mb-6">
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<div className="w-12 h-12 bg-gradient-to-br from-slate-600 to-slate-700 rounded-xl flex items-center justify-center shadow-lg">
|
||||
<ClipboardList className="w-6 h-6 text-white" />
|
||||
</div>
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold bg-gradient-to-r from-slate-600 to-slate-700 bg-clip-text text-transparent">
|
||||
Historique des Validations
|
||||
</h1>
|
||||
<p className="text-gray-500">
|
||||
Consultez l'historique de vos validations de tickets
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Statistics Cards */}
|
||||
<div className="grid md:grid-cols-3 gap-6 mb-8">
|
||||
<div className="bg-white rounded-xl shadow-md p-6 border border-gray-100 hover:shadow-lg transition-shadow">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium text-gray-500 mb-2">Total traités</p>
|
||||
<p className="text-4xl font-bold text-blue-600">{stats.total}</p>
|
||||
<div className="grid md:grid-cols-3 gap-4 mb-6">
|
||||
<div className="bg-gradient-to-br from-blue-50 to-blue-100 rounded-xl p-4 border border-blue-200">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-12 h-12 bg-blue-200 rounded-lg flex items-center justify-center">
|
||||
<BarChart3 className="w-6 h-6 text-blue-600" />
|
||||
</div>
|
||||
<div className="w-16 h-16 bg-blue-100 rounded-full flex items-center justify-center">
|
||||
<svg className="w-8 h-8 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
|
||||
</svg>
|
||||
<div>
|
||||
<p className="text-3xl font-bold text-blue-700">{stats.total}</p>
|
||||
<p className="text-sm text-blue-600">Total traités</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white rounded-xl shadow-md p-6 border border-gray-100 hover:shadow-lg transition-shadow">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium text-gray-500 mb-2">Validés</p>
|
||||
<p className="text-4xl font-bold text-green-600">{stats.claimed}</p>
|
||||
<div className="bg-gradient-to-br from-green-50 to-green-100 rounded-xl p-4 border border-green-200">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-12 h-12 bg-green-200 rounded-lg flex items-center justify-center">
|
||||
<CheckCircle className="w-6 h-6 text-green-600" />
|
||||
</div>
|
||||
<div className="w-16 h-16 bg-green-100 rounded-full flex items-center justify-center">
|
||||
<svg className="w-8 h-8 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
<div>
|
||||
<p className="text-3xl font-bold text-green-700">{stats.claimed}</p>
|
||||
<p className="text-sm text-green-600">Validés</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white rounded-xl shadow-md p-6 border border-gray-100 hover:shadow-lg transition-shadow">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium text-gray-500 mb-2">Rejetés</p>
|
||||
<p className="text-4xl font-bold text-red-600">{stats.rejected}</p>
|
||||
<div className="bg-gradient-to-br from-red-50 to-red-100 rounded-xl p-4 border border-red-200">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-12 h-12 bg-red-200 rounded-lg flex items-center justify-center">
|
||||
<XCircle className="w-6 h-6 text-red-600" />
|
||||
</div>
|
||||
<div className="w-16 h-16 bg-red-100 rounded-full flex items-center justify-center">
|
||||
<svg className="w-8 h-8 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
<div>
|
||||
<p className="text-3xl font-bold text-red-700">{stats.rejected}</p>
|
||||
<p className="text-sm text-red-600">Rejetés</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Filters & History List */}
|
||||
<div className="bg-white rounded-2xl shadow-md border border-gray-100 overflow-hidden">
|
||||
<div className="px-6 py-5 border-b border-gray-100 bg-gradient-to-r from-gray-50 to-white">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex gap-2">
|
||||
<div className="bg-white rounded-2xl shadow-sm border border-gray-100 overflow-hidden">
|
||||
<div className="px-6 py-4 border-b border-gray-100 bg-gradient-to-r from-gray-50 to-gray-100">
|
||||
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4">
|
||||
<div className="flex gap-2 flex-wrap">
|
||||
<button
|
||||
onClick={() => setFilter('ALL')}
|
||||
className={`px-5 py-2.5 rounded-xl font-semibold transition-all ${
|
||||
className={`px-4 py-2 rounded-xl font-semibold transition-all ${
|
||||
filter === 'ALL'
|
||||
? 'bg-gradient-to-r from-slate-600 to-slate-700 text-white shadow-md'
|
||||
: 'bg-gray-100 text-gray-600 hover:bg-gray-200'
|
||||
|
|
@ -146,7 +151,7 @@ export default function EmployeeHistoryPage() {
|
|||
</button>
|
||||
<button
|
||||
onClick={() => setFilter('CLAIMED')}
|
||||
className={`px-5 py-2.5 rounded-xl font-semibold transition-all ${
|
||||
className={`px-4 py-2 rounded-xl font-semibold transition-all ${
|
||||
filter === 'CLAIMED'
|
||||
? 'bg-gradient-to-r from-green-600 to-green-700 text-white shadow-md'
|
||||
: 'bg-gray-100 text-gray-600 hover:bg-gray-200'
|
||||
|
|
@ -156,7 +161,7 @@ export default function EmployeeHistoryPage() {
|
|||
</button>
|
||||
<button
|
||||
onClick={() => setFilter('REJECTED')}
|
||||
className={`px-5 py-2.5 rounded-xl font-semibold transition-all ${
|
||||
className={`px-4 py-2 rounded-xl font-semibold transition-all ${
|
||||
filter === 'REJECTED'
|
||||
? 'bg-gradient-to-r from-red-600 to-red-700 text-white shadow-md'
|
||||
: 'bg-gray-100 text-gray-600 hover:bg-gray-200'
|
||||
|
|
@ -168,7 +173,7 @@ export default function EmployeeHistoryPage() {
|
|||
|
||||
<button
|
||||
onClick={loadHistory}
|
||||
className="flex items-center gap-2 px-4 py-2 text-green-700 bg-green-50 hover:bg-green-100 rounded-lg transition-colors font-medium"
|
||||
className="flex items-center gap-2 px-4 py-2 text-slate-700 bg-slate-100 hover:bg-slate-200 rounded-lg transition-colors font-medium"
|
||||
>
|
||||
<RefreshCw className="w-4 h-4" />
|
||||
Actualiser
|
||||
|
|
@ -200,7 +205,7 @@ export default function EmployeeHistoryPage() {
|
|||
: 'border-gray-100 bg-white'
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex flex-col lg:flex-row items-start justify-between gap-4">
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<span className="font-mono font-bold text-lg bg-gray-100 px-3 py-1 rounded-lg text-gray-900">
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user