feat(BAP): remplacer destinataire Celia par Jeremy

This commit is contained in:
Michael committed 2026-01-12 14:13:21 +01:00
commit 78adc2c5ae
11 files changed
+285 -182

No files matched your search

+24 -16
View File
@@ -51,8 +51,8 @@ export default function PublicityForm({ publicity, groups, onSuccess, selectedYe
defaultValues: {
pubNumber: publicity?.pubNumber || "",
designation: publicity?.designation || "",
startDate: publicity?.startDate ? safeDate(publicity.startDate) : undefined,
endDate: publicity?.endDate ? safeDate(publicity.endDate) : undefined,
startDate: (publicity?.startDate ? safeDate(publicity.startDate) : undefined) as Date,
endDate: (publicity?.endDate ? safeDate(publicity.endDate) : undefined) as Date,
year: publicity?.year || selectedYear || 2025, // Utilise l'année sélectionnée ou 2025 par défaut
participatingGroups: publicity?.participations?.map(p => p.groupId) || [],
},
@@ -62,7 +62,7 @@ export default function PublicityForm({ publicity, groups, onSuccess, selectedYe
const createMutation = useMutation({
mutationFn: async (data: PublicityFormData) => {
const response = await fetch('/api/publicities', {
const response = await fetch('/api/ad-campaigns', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
@@ -81,21 +81,21 @@ export default function PublicityForm({ publicity, groups, onSuccess, selectedYe
return response.json();
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['/api/publicities'] });
queryClient.invalidateQueries({ queryKey: ['/api/ad-campaigns'] });
toast({ description: "Publicité créée avec succès" });
onSuccess();
},
onError: (error: Error) => {
toast({
toast({
variant: "destructive",
description: error.message || "Erreur lors de la création"
description: error.message || "Erreur lors de la création"
});
}
});
const updateMutation = useMutation({
mutationFn: async (data: PublicityFormData) => {
const response = await fetch(`/api/publicities/${publicity!.id}`, {
const response = await fetch(`/api/ad-campaigns/${publicity!.id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
@@ -114,23 +114,31 @@ export default function PublicityForm({ publicity, groups, onSuccess, selectedYe
return response.json();
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['/api/publicities'] });
queryClient.invalidateQueries({ queryKey: ['/api/ad-campaigns'] });
toast({ description: "Publicité modifiée avec succès" });
onSuccess();
},
onError: (error: Error) => {
toast({
toast({
variant: "destructive",
description: error.message || "Erreur lors de la modification"
description: error.message || "Erreur lors de la modification"
});
}
});
const onSubmit = (data: PublicityFormData) => {
const onSubmit = (data: any) => {
// Transformer l'année en nombre si c'est une string
const formattedData = {
...data,
year: parseInt(data.year.toString()),
// s'assurer que les dates sont bien des objets Date ou null
startDate: data.startDate ? new Date(data.startDate) : undefined,
endDate: data.endDate ? new Date(data.endDate) : undefined,
};
if (publicity) {
updateMutation.mutate(data);
updateMutation.mutate(formattedData);
} else {
createMutation.mutate(data);
createMutation.mutate(formattedData);
}
};
@@ -284,9 +292,9 @@ export default function PublicityForm({ publicity, groups, onSuccess, selectedYe
htmlFor={`group-${group.id}`}
className="flex items-center space-x-2 cursor-pointer"
>
<div
className="w-3 h-3 rounded-full"
style={{ backgroundColor: group.color }}
<div
className="w-3 h-3 rounded-full"
style={{ backgroundColor: group.color || '#cccccc' }}
/>
<span>{group.name}</span>
</Label>
+13 -2
View File
@@ -1,4 +1,5 @@
import { Switch, Route } from "wouter";
import { useEffect } from "react";
import { Switch, Route, useLocation } from "wouter";
import { useAuthUnified } from "@/hooks/useAuthUnified";
import { useScreenSize } from "@/hooks/use-screen-size";
import NotFound from "@/pages/not-found";
@@ -42,6 +43,15 @@ import MobileDlcPage from "@/pages/mobile/DlcPage";
import MobileSavPage from "@/pages/mobile/SavPage";
import MobileAvoirsPage from "@/pages/mobile/AvoirsPage";
// Helper component to handle redirection
const RedirectToAuth = () => {
const [, setLocation] = useLocation();
useEffect(() => {
setLocation("/auth");
}, [setLocation]);
return <AuthPage />;
};
function RouterProduction() {
const { isAuthenticated, isLoading, user, environment, error } = useAuthUnified();
const { isMobile } = useScreenSize();
@@ -86,7 +96,8 @@ function RouterProduction() {
<Switch>
<Route path="/auth" component={AuthPage} />
<Route path="/" component={AuthPage} />
<Route component={NotFound} />
{/* Redirect all other routes to auth */}
<Route component={RedirectToAuth} />
</Switch>
);
}
+22 -22
View File
@@ -35,9 +35,9 @@ export default function Calendar() {
// Fetch orders and deliveries for the current month with store filtering
const { data: orders = [], isLoading: loadingOrders } = useQuery({
queryKey: ['/api/orders', selectedStoreId, {
startDate: format(monthStart, 'yyyy-MM-dd'),
endDate: format(monthEnd, 'yyyy-MM-dd')
queryKey: ['/api/orders', selectedStoreId, {
startDate: format(monthStart, 'yyyy-MM-dd'),
endDate: format(monthEnd, 'yyyy-MM-dd')
}],
queryFn: async () => {
const params = new URLSearchParams({
@@ -48,7 +48,7 @@ export default function Calendar() {
if (selectedStoreId) {
params.append('storeId', selectedStoreId.toString());
}
const url = `/api/orders?${params.toString()}`;
if (import.meta.env.DEV) {
console.log('📅 Calendar fetching orders:', {
@@ -58,20 +58,20 @@ export default function Calendar() {
params: params.toString()
});
}
const response = await fetch(url, {
credentials: 'include'
});
if (!response.ok) {
throw new Error('Failed to fetch orders');
}
const data = await response.json();
if (import.meta.env.DEV) {
console.log('📅 Calendar orders received:', Array.isArray(data) ? data.length : 'NOT_ARRAY', 'items');
}
// Protection contre les données invalides en production
if (!Array.isArray(data)) {
console.warn('⚠️ Orders data is not an array, returning empty array');
@@ -84,9 +84,9 @@ export default function Calendar() {
});
const { data: deliveries = [], isLoading: loadingDeliveries } = useQuery({
queryKey: ['/api/deliveries', selectedStoreId, {
startDate: format(monthStart, 'yyyy-MM-dd'),
endDate: format(monthEnd, 'yyyy-MM-dd')
queryKey: ['/api/deliveries', selectedStoreId, {
startDate: format(monthStart, 'yyyy-MM-dd'),
endDate: format(monthEnd, 'yyyy-MM-dd')
}],
queryFn: async () => {
const params = new URLSearchParams({
@@ -97,7 +97,7 @@ export default function Calendar() {
if (selectedStoreId) {
params.append('storeId', selectedStoreId.toString());
}
const url = `/api/deliveries?${params.toString()}`;
if (import.meta.env.DEV) {
console.log('📅 Calendar fetching deliveries:', {
@@ -107,20 +107,20 @@ export default function Calendar() {
params: params.toString()
});
}
const response = await fetch(url, {
credentials: 'include'
});
if (!response.ok) {
throw new Error('Failed to fetch deliveries');
}
const data = await response.json();
if (import.meta.env.DEV) {
console.log('📅 Calendar deliveries received:', Array.isArray(data) ? data.length : 'NOT_ARRAY', 'items');
}
// Protection contre les données invalides en production
if (!Array.isArray(data)) {
console.warn('⚠️ Deliveries data is not an array, returning empty array');
@@ -134,15 +134,15 @@ export default function Calendar() {
// Fetch publicities for the current year
const { data: publicities = [], isLoading: loadingPublicities } = useQuery({
queryKey: ['/api/publicities', currentDate.getFullYear(), selectedStoreId],
queryKey: ['/api/ad-campaigns', currentDate.getFullYear(), selectedStoreId],
queryFn: async () => {
const params = new URLSearchParams();
params.append('year', currentDate.getFullYear().toString());
if (selectedStoreId && user?.role === 'admin') {
params.append('storeId', selectedStoreId.toString());
}
const url = `/api/publicities?${params.toString()}`;
const url = `/api/ad-campaigns?${params.toString()}`;
if (import.meta.env.DEV) {
console.log('📅 Calendar fetching publicities:', {
url,
@@ -151,15 +151,15 @@ export default function Calendar() {
year: currentDate.getFullYear()
});
}
const response = await fetch(url, {
credentials: 'include'
});
if (!response.ok) {
throw new Error('Failed to fetch publicities');
}
const data = await response.json();
if (import.meta.env.DEV) {
console.log('📅 Calendar publicities received:', Array.isArray(data) ? data.length : 'NOT_ARRAY', 'items');
+81 -82
View File
@@ -33,19 +33,19 @@ export default function Dashboard() {
year: currentDate.getFullYear().toString(),
month: (currentDate.getMonth() + 1).toString(),
});
if (selectedStoreId && user?.role === 'admin') {
params.append('storeId', selectedStoreId.toString());
}
const response = await fetch(`/api/stats/monthly?${params.toString()}`, {
credentials: 'include'
});
if (!response.ok) {
throw new Error('Failed to fetch stats');
}
return response.json();
},
});
@@ -58,19 +58,19 @@ export default function Dashboard() {
const params = new URLSearchParams({
year: currentDate.getFullYear().toString(),
});
if (selectedStoreId && user?.role === 'admin') {
params.append('storeId', selectedStoreId.toString());
}
const response = await fetch(`/api/stats/yearly?${params.toString()}`, {
credentials: 'include'
});
if (!response.ok) {
throw new Error('Failed to fetch yearly stats');
}
return response.json();
},
});
@@ -102,34 +102,34 @@ export default function Dashboard() {
params.append('storeId', selectedStoreId.toString());
}
params.append('recent', 'true');
const response = await fetch(`/api/announcements?${params.toString()}`, {
credentials: 'include'
});
if (!response.ok) {
return null;
}
const announcements: DashboardMessage[] = await response.json();
// Filtrer les annonces créées il y a moins de 2 jours côté client
const twoDaysAgo = new Date();
twoDaysAgo.setDate(twoDaysAgo.getDate() - 2);
const recentAnnouncements = announcements.filter(announcement => {
if (!announcement.createdAt) return false;
const createdAt = safeDate(announcement.createdAt);
return createdAt && createdAt >= twoDaysAgo;
});
// Retourner la plus récente
return recentAnnouncements.length > 0
return recentAnnouncements.length > 0
? recentAnnouncements.sort((a, b) => {
const dateA = safeDate(a.createdAt);
const dateB = safeDate(b.createdAt);
return (dateB?.getTime() || 0) - (dateA?.getTime() || 0);
})[0]
const dateA = safeDate(a.createdAt);
const dateB = safeDate(b.createdAt);
return (dateB?.getTime() || 0) - (dateA?.getTime() || 0);
})[0]
: null;
},
enabled: !!user,
@@ -139,30 +139,30 @@ export default function Dashboard() {
const getAnnouncementPriorityConfig = (type: string) => {
switch (type) {
case 'error':
return {
label: 'Nouveauté',
return {
label: 'Nouveauté',
color: 'bg-purple-100 text-purple-800',
icon: Sparkles,
iconColor: 'text-purple-600'
};
case 'warning':
return {
label: 'Attention',
return {
label: 'Attention',
color: 'bg-orange-100 text-orange-800',
icon: AlertTriangle,
iconColor: 'text-orange-600'
};
case 'success':
return {
label: 'Important',
return {
label: 'Important',
color: 'bg-red-100 text-red-800',
icon: Star,
iconColor: 'text-red-600'
};
case 'info':
default:
return {
label: 'Information',
return {
label: 'Information',
color: 'bg-blue-100 text-blue-800',
icon: Info,
iconColor: 'text-blue-600'
@@ -195,19 +195,19 @@ export default function Dashboard() {
// Récupérer les publicités à venir (chercher dans 2024 ET 2025) - TOUTES les publicités
const { data: upcomingPublicities = [] } = useQuery<PublicityWithRelations[]>({
queryKey: ['/api/publicities', 'upcoming'],
queryKey: ['/api/ad-campaigns', 'upcoming'],
queryFn: async () => {
// Essayer d'abord 2024, puis 2025 pour avoir toutes les publicités
const years = [2024, 2025];
let allPublicities: PublicityWithRelations[] = [];
for (const year of years) {
const params = new URLSearchParams();
params.append('year', year.toString());
// NE PAS filtrer par magasin - on veut toutes les publicités
try {
const response = await fetch(`/api/publicities?${params}`, { credentials: 'include' });
const response = await fetch(`/api/ad-campaigns?${params}`, { credentials: 'include' });
if (response.ok) {
const yearPublicities = await response.json();
allPublicities = [...allPublicities, ...yearPublicities];
@@ -216,12 +216,12 @@ export default function Dashboard() {
console.log(`Erreur lors de la récupération des publicités ${year}:`, error);
}
}
// Filtrer les publicités à venir et les trier par date
const futurePublicities = allPublicities
.filter((publicity: any) => new Date(publicity.startDate) > new Date())
.sort((a: any, b: any) => new Date(a.startDate).getTime() - new Date(b.startDate).getTime());
return futurePublicities;
},
});
@@ -249,10 +249,10 @@ export default function Dashboard() {
}
return;
}
// Vérifier s'il y a des problèmes DLC
const shouldShowDlcModal = dlcStats.expired > 0 || dlcStats.expiringSoon > 0;
if (shouldShowDlcModal && !showDlcAlertModal) {
// Vérifier s'il n'y a pas de snooze actif
const snoozedUntil = localStorage.getItem('dlcAlertSnooze');
@@ -305,7 +305,7 @@ export default function Dashboard() {
const dateB = safeDate(b.createdAt);
return (dateB ? dateB.getTime() : 0) - (dateA ? dateA.getTime() : 0);
}) : []; // Afficher toutes les commandes en attente
const upcomingDeliveries = Array.isArray(allDeliveries) ? allDeliveries
.filter((d: any) => {
const isPlanned = d.status === 'planned';
@@ -314,7 +314,7 @@ export default function Dashboard() {
})
.sort((a: any, b: any) => new Date(a.scheduledDate).getTime() - new Date(b.scheduledDate).getTime())
.slice(0, 4) : []; // Afficher les 4 prochaines livraisons
console.log('🚚 Dashboard - Upcoming deliveries result:', upcomingDeliveries.length, upcomingDeliveries);
// Calculs pour les statistiques
@@ -324,9 +324,9 @@ export default function Dashboard() {
const deliveryDate = safeDate(delivery.deliveredDate || delivery.createdAt);
if (!deliveryDate) return false;
const now = new Date();
return deliveryDate.getMonth() === now.getMonth() &&
deliveryDate.getFullYear() === now.getFullYear() &&
delivery.status === 'delivered';
return deliveryDate.getMonth() === now.getMonth() &&
deliveryDate.getFullYear() === now.getFullYear() &&
delivery.status === 'delivered';
}).length : 0;
// Calculer le total des palettes pour les livraisons 'delivered' du mois en cours
@@ -346,35 +346,35 @@ export default function Dashboard() {
const getPriorityConfig = (priority: string) => {
switch (priority) {
case 'high':
return {
color: 'destructive' as const,
icon: AlertTriangle,
label: 'Élevée'
return {
color: 'destructive' as const,
icon: AlertTriangle,
label: 'Élevée'
};
case 'medium':
return {
color: 'default' as const,
icon: Clock,
label: 'Moyenne'
return {
color: 'default' as const,
icon: Clock,
label: 'Moyenne'
};
case 'low':
return {
color: 'secondary' as const,
icon: Circle,
label: 'Faible'
return {
color: 'secondary' as const,
icon: Circle,
label: 'Faible'
};
default:
return {
color: 'secondary' as const,
icon: Circle,
label: 'Moyenne'
return {
color: 'secondary' as const,
icon: Circle,
label: 'Moyenne'
};
}
};
console.log('📊 Dashboard Debug - Raw Data:', {
allOrders: Array.isArray(allOrders) ? allOrders.length : 'NOT_ARRAY',
allDeliveries: Array.isArray(allDeliveries) ? allDeliveries.length : 'NOT_ARRAY',
allDeliveries: Array.isArray(allDeliveries) ? allDeliveries.length : 'NOT_ARRAY',
customerOrders: Array.isArray(customerOrders) ? customerOrders.length : 'NOT_ARRAY',
upcomingPublicities: Array.isArray(upcomingPublicities) ? upcomingPublicities.length : 'NOT_ARRAY',
stats: stats,
@@ -423,7 +423,7 @@ export default function Dashboard() {
{/* Alerts */}
<div className="space-y-3">
{dlcStats.expiringSoon > 0 && (
<div className="bg-yellow-50 border-l-4 border-yellow-400 p-4 flex items-center space-x-3 shadow-sm">
<Clock className="h-5 w-5 text-yellow-600" />
@@ -432,7 +432,7 @@ export default function Dashboard() {
</span>
</div>
)}
{dlcStats.expired > 0 && (
<div className="bg-red-50 border-l-4 border-red-400 p-4 flex items-center space-x-3 shadow-sm">
<XCircle className="h-5 w-5 text-red-600" />
@@ -523,11 +523,10 @@ export default function Dashboard() {
const orderDate = safeDate(order.plannedDate);
const daysPending = orderDate ? Math.floor((new Date().getTime() - orderDate.getTime()) / (1000 * 60 * 60 * 24)) : 0;
const isOverdue = daysPending > 10;
return (
<div key={order.id} className={`flex items-center justify-between p-4 transition-colors border-l-3 ${
isOverdue ? 'bg-red-50 hover:bg-red-100 border-red-500' : 'bg-orange-50 hover:bg-orange-100 border-orange-500'
}`}>
<div key={order.id} className={`flex items-center justify-between p-4 transition-colors border-l-3 ${isOverdue ? 'bg-red-50 hover:bg-red-100 border-red-500' : 'bg-orange-50 hover:bg-orange-100 border-orange-500'
}`}>
<div className="flex items-center space-x-3">
<div className={`h-2 w-2 ${isOverdue ? 'bg-red-500' : 'bg-orange-500'}`}></div>
<div>
@@ -536,7 +535,7 @@ export default function Dashboard() {
</div>
</div>
<div className="text-right">
<Badge
<Badge
variant={isOverdue ? 'destructive' : 'secondary'}
className="text-xs"
>
@@ -604,7 +603,7 @@ export default function Dashboard() {
.map((publicity: any) => {
const participatingStores = publicity.participations || [];
const isCurrentStoreParticipating = selectedStoreId && participatingStores.some((p: any) => p.groupId === parseInt(selectedStoreId.toString()));
return (
<div key={publicity.id} className="p-4 bg-gray-50 hover:bg-gray-100 transition-colors border-l-3 border-purple-500 space-y-2">
<div className="flex items-center justify-between">
@@ -624,7 +623,7 @@ export default function Dashboard() {
</p>
</div>
</div>
{/* Magasins participants */}
<div className="flex items-center space-x-2 text-xs">
<span className="text-gray-500">Magasins:</span>
@@ -635,12 +634,12 @@ export default function Dashboard() {
{participatingStores.map((participation: any) => {
const isCurrentStore = selectedStoreId && participation.groupId === parseInt(selectedStoreId.toString());
const groupColor = participation.group?.color || '#1976D2';
return (
<Badge
key={participation.groupId}
<Badge
key={participation.groupId}
className={`text-xs text-white border ${isCurrentStore ? 'ring-2 ring-white ring-offset-1' : ''}`}
style={{
style={{
backgroundColor: groupColor,
borderColor: groupColor
}}
@@ -690,7 +689,7 @@ export default function Dashboard() {
.map((task: any) => {
const priorityConfig = getPriorityConfig(task.priority);
const PriorityIcon = priorityConfig.icon;
return (
<div key={task.id} className="flex items-center justify-between p-4 bg-gray-50 hover:bg-gray-100 transition-colors border-l-3 border-blue-500">
<div className="flex items-center space-x-3">
@@ -702,7 +701,7 @@ export default function Dashboard() {
</div>
<div className="text-right space-y-1">
<div className="flex items-center justify-end space-x-2">
<Badge
<Badge
className={`text-xs flex items-center gap-1 ${priorityConfig.color}`}
>
<PriorityIcon className="h-3 w-3" />
@@ -716,11 +715,11 @@ export default function Dashboard() {
</div>
);
}) : (
<div className="text-center py-8">
<p className="text-gray-600">Aucune tâche en cours</p>
<p className="text-xs text-gray-400 mt-1">Toutes les tâches sont terminées</p>
</div>
)}
<div className="text-center py-8">
<p className="text-gray-600">Aucune tâche en cours</p>
<p className="text-xs text-gray-400 mt-1">Toutes les tâches sont terminées</p>
</div>
)}
</CardContent>
</Card>
</div>
@@ -734,7 +733,7 @@ export default function Dashboard() {
Nouvelle Annonce
</DialogTitle>
</DialogHeader>
{recentAnnouncement && (
<div className="space-y-4">
<div className="flex items-center justify-between">
@@ -756,7 +755,7 @@ export default function Dashboard() {
{safeFormat(recentAnnouncement.createdAt, "d MMMM yyyy 'à' HH:mm")}
</p>
</div>
<div>
<h3 className="text-lg font-semibold text-gray-900 mb-2">
{recentAnnouncement.title}
@@ -767,7 +766,7 @@ export default function Dashboard() {
</p>
</div>
</div>
{recentAnnouncement.createdBy && (
<div className="flex items-center gap-2 pt-2 border-t border-gray-100">
<User className="h-4 w-4 text-gray-400" />
@@ -778,7 +777,7 @@ export default function Dashboard() {
)}
</div>
)}
<div className="flex justify-end pt-4">
<Button onClick={handleCloseAnnouncementModal} className="flex items-center gap-2">
<X className="h-4 w-4" />
@@ -793,7 +792,7 @@ export default function Dashboard() {
isOpen={showDlcAlertModal}
onClose={handleCloseDlcAlertModal}
dlcStats={dlcStats}
selectedStoreId={selectedStoreId}
selectedStoreId={selectedStoreId ?? undefined}
/>
</div>
);
+9 -8
View File
@@ -34,19 +34,20 @@ export default function Publicities() {
// Seuls les admins peuvent modifier/supprimer
const canModify = user?.role === 'admin';
// Generate year options (2025 to 2035)
// Generate year options (current year - 2 to current year + 10)
const currentYear = new Date().getFullYear();
const yearOptions = Array.from({ length: 11 }, (_, i) => currentYear + i);
const startYear = currentYear - 2;
const yearOptions = Array.from({ length: 13 }, (_, i) => startYear + i);
const { data: publicities = [], isLoading } = useQuery({
queryKey: ['/api/publicities', selectedYear, selectedStoreId],
const { data: publicities = [], isLoading } = useQuery<PublicityWithRelations[]>({
queryKey: ['/api/ad-campaigns', selectedYear, selectedStoreId],
queryFn: async () => {
const params = new URLSearchParams();
params.append('year', selectedYear.toString());
if (selectedStoreId) {
params.append('storeId', selectedStoreId.toString());
}
const response = await fetch(`/api/publicities?${params}`);
const response = await fetch(`/api/ad-campaigns?${params}`);
if (!response.ok) {
throw new Error('Failed to fetch publicities');
}
@@ -98,7 +99,7 @@ export default function Publicities() {
console.log(`🗑️ [Frontend] Attempting to delete publicity ${id} using POST method`);
try {
const response = await fetch(`/api/publicities/${id}/delete`, {
const response = await fetch(`/api/ad-campaigns/${id}/delete`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({})
@@ -110,7 +111,7 @@ export default function Publicities() {
} else if (response.status === 404) {
// Route not found, try DELETE method as fallback (for dev environment)
console.log(`⚠️ [Frontend] POST route not found, trying DELETE method`);
const deleteResponse = await fetch(`/api/publicities/${id}`, { method: 'DELETE' });
const deleteResponse = await fetch(`/api/ad-campaigns/${id}`, { method: 'DELETE' });
if (!deleteResponse.ok) {
const error = await deleteResponse.json();
@@ -132,7 +133,7 @@ export default function Publicities() {
}
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['/api/publicities'] });
queryClient.invalidateQueries({ queryKey: ['/api/ad-campaigns'] });
toast({ description: "Publicité supprimée avec succès" });
setIsDeleteModalOpen(false);
setSelectedPublicity(null);
+5 -4
View File
@@ -34,16 +34,17 @@ export default function MobilePublicitiesPage() {
const [selectedYear, setSelectedYear] = useState<number>(new Date().getFullYear());
const [searchTerm, setSearchTerm] = useState("");
// Générer les années pour le select (année courante +/- 2 ans)
// Générer les années pour le select (année courante - 2 ans à + 10 ans)
const currentYear = new Date().getFullYear();
const years = Array.from({ length: 5 }, (_, i) => currentYear - 2 + i);
const startYear = currentYear - 2;
const years = Array.from({ length: 13 }, (_, i) => startYear + i);
const { data: publicities = [], isLoading } = useQuery({
queryKey: ["/api/publicities", selectedStoreId, selectedYear],
queryKey: ["/api/ad-campaigns", selectedStoreId, selectedYear],
queryFn: async () => {
if (!selectedStoreId) return [];
const response = await fetch(
`/api/publicities?storeId=${selectedStoreId}&year=${selectedYear}`,
`/api/ad-campaigns?storeId=${selectedStoreId}&year=${selectedYear}`,
{ credentials: 'include' }
);
if (!response.ok) throw new Error("Failed to fetch publicities");