Merge pull request #51 from R0m1k3/claude/integrate-google-calendar-api-011CV44Nie9HB7U35ArSUnNa

Fix: Correction modal ajout RDV et réorganisation layout
This commit is contained in:
LogiFlow authored and GitHub committed 2025-11-12 16:08:59 +01:00
commit 0336c049ce
1 file changed
+68 -91
+68 -91
View File
@@ -56,7 +56,6 @@ const Index = () => {
const [loadingModels, setLoadingModels] = useState(false); const [loadingModels, setLoadingModels] = useState(false);
const [currentDateTime, setCurrentDateTime] = useState(new Date()); const [currentDateTime, setCurrentDateTime] = useState(new Date());
const [upcomingAlert, setUpcomingAlert] = useState<CalendarEvent | null>(null); const [upcomingAlert, setUpcomingAlert] = useState<CalendarEvent | null>(null);
const [rssDisplayOffset, setRssDisplayOffset] = useState(0);
const [calendarAuthStatus, setCalendarAuthStatus] = useState<{ const [calendarAuthStatus, setCalendarAuthStatus] = useState<{
isAuthenticated: boolean; isAuthenticated: boolean;
isExpired: boolean; isExpired: boolean;
@@ -111,18 +110,6 @@ const Index = () => {
return () => clearInterval(timer); return () => clearInterval(timer);
}, [calendarEvents]); }, [calendarEvents]);
// RSS articles rotation every 20 seconds
useEffect(() => {
if (rssArticles.length > 3) {
const timer = setInterval(() => {
setRssDisplayOffset(prev => {
const maxOffset = Math.max(0, rssArticles.length - 3);
return (prev + 3) % (maxOffset + 3);
});
}, 20000); // Rotate every 20 seconds
return () => clearInterval(timer);
}
}, [rssArticles.length]);
useEffect(() => { useEffect(() => {
const userFromAuth = AuthService.getUser(); const userFromAuth = AuthService.getUser();
@@ -702,8 +689,8 @@ const Index = () => {
{/* Main Content */} {/* Main Content */}
<div className="max-w-[1920px] mx-auto px-8 py-8"> <div className="max-w-[1920px] mx-auto px-8 py-8">
{/* Three Column Layout: Calendar Left | Notes Middle | Todo/RSS Right */} {/* Three Column Layout: Calendar Left | Notes Middle | Todo+RSS Right */}
<div className="grid grid-cols-[300px,1fr,380px] gap-6"> <div className="grid grid-cols-[300px,1fr,760px] gap-6">
{/* Left Column: Calendar */} {/* Left Column: Calendar */}
<div className="space-y-6"> <div className="space-y-6">
<Card className="shadow-lg"> <Card className="shadow-lg">
@@ -1192,8 +1179,8 @@ const Index = () => {
)} )}
</div> </div>
{/* Right Column: Todos & RSS Boxes stacked */} {/* Right Column: Todos & RSS Boxes side by side */}
<div className="space-y-6 h-fit sticky top-24"> <div className="grid grid-cols-2 gap-6">
{/* Todos Box */} {/* Todos Box */}
<Card className="shadow-lg"> <Card className="shadow-lg">
<CardHeader className="pb-3"> <CardHeader className="pb-3">
@@ -1215,7 +1202,7 @@ const Index = () => {
</TabsList> </TabsList>
<TabsContent value="active" className="mt-0"> <TabsContent value="active" className="mt-0">
<div className="space-y-1.5 max-h-[350px] overflow-y-auto"> <div className="space-y-1.5 max-h-[calc(100vh-300px)] overflow-y-auto">
{todos.filter(t => !t.completed).length > 0 ? ( {todos.filter(t => !t.completed).length > 0 ? (
todos.filter(t => !t.completed).map(todo => ( todos.filter(t => !t.completed).map(todo => (
<div key={todo.id} className="flex items-center gap-2 p-2 border rounded hover:bg-accent/50 transition-colors group"> <div key={todo.id} className="flex items-center gap-2 p-2 border rounded hover:bg-accent/50 transition-colors group">
@@ -1244,7 +1231,7 @@ const Index = () => {
</TabsContent> </TabsContent>
<TabsContent value="completed" className="mt-0"> <TabsContent value="completed" className="mt-0">
<div className="space-y-1.5 max-h-[350px] overflow-y-auto"> <div className="space-y-1.5 max-h-[calc(100vh-300px)] overflow-y-auto">
{todos.filter(t => t.completed).length > 0 ? ( {todos.filter(t => t.completed).length > 0 ? (
todos.filter(t => t.completed).map(todo => ( todos.filter(t => t.completed).map(todo => (
<div key={todo.id} className="flex items-center gap-2 p-2 border rounded hover:bg-accent/50 transition-colors group"> <div key={todo.id} className="flex items-center gap-2 p-2 border rounded hover:bg-accent/50 transition-colors group">
@@ -1294,9 +1281,9 @@ const Index = () => {
</div> </div>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<div className="space-y-2"> <div className="space-y-2 max-h-[calc(100vh-300px)] overflow-y-auto">
{rssArticles.length > 0 ? ( {rssArticles.length > 0 ? (
rssArticles.slice(rssDisplayOffset, rssDisplayOffset + 3).map(article => ( rssArticles.map(article => (
<div <div
key={article.id} key={article.id}
className="p-2.5 border rounded hover:bg-accent/50 transition-colors cursor-pointer" className="p-2.5 border rounded hover:bg-accent/50 transition-colors cursor-pointer"
@@ -1328,20 +1315,6 @@ const Index = () => {
</Button> </Button>
</p> </p>
)} )}
{rssArticles.length > 3 && (
<div className="flex justify-center pt-2">
<div className="flex gap-1">
{Array.from({ length: Math.ceil(rssArticles.length / 3) }).map((_, i) => (
<div
key={i}
className={`h-1.5 w-1.5 rounded-full transition-colors ${
i === Math.floor(rssDisplayOffset / 3) ? 'bg-primary' : 'bg-muted'
}`}
/>
))}
</div>
</div>
)}
</div> </div>
</CardContent> </CardContent>
</Card> </Card>
@@ -1954,6 +1927,9 @@ const Index = () => {
const formData = new FormData(e.currentTarget); const formData = new FormData(e.currentTarget);
try { try {
const reminderMinutes = formData.get('reminderMinutes') as string;
const recurrenceValue = formData.get('recurrence') as string;
const eventData = { const eventData = {
title: formData.get('title') as string, title: formData.get('title') as string,
description: formData.get('description') as string || undefined, description: formData.get('description') as string || undefined,
@@ -1961,10 +1937,10 @@ const Index = () => {
endDateTime: new Date(formData.get('endDateTime') as string).toISOString(), endDateTime: new Date(formData.get('endDateTime') as string).toISOString(),
location: formData.get('location') as string || undefined, location: formData.get('location') as string || undefined,
attendees: (formData.get('attendees') as string || '').split(',').map(e => e.trim()).filter(e => e), attendees: (formData.get('attendees') as string || '').split(',').map(e => e.trim()).filter(e => e),
reminders: formData.get('reminderMinutes') ? [ reminders: reminderMinutes && reminderMinutes !== '0' ? [
{ method: 'popup', minutes: parseInt(formData.get('reminderMinutes') as string) } { method: 'popup', minutes: parseInt(reminderMinutes) }
] : undefined, ] : undefined,
recurrence: formData.get('recurrence') ? [formData.get('recurrence') as string] : undefined, recurrence: recurrenceValue ? [recurrenceValue] : undefined,
visibility: formData.get('visibility') as string || 'default', visibility: formData.get('visibility') as string || 'default',
colorId: formData.get('colorId') as string || undefined colorId: formData.get('colorId') as string || undefined
}; };
@@ -1973,6 +1949,7 @@ const Index = () => {
showSuccess('Événement créé avec succès'); showSuccess('Événement créé avec succès');
setAddEventModal(false); setAddEventModal(false);
await loadCalendarEvents(); await loadCalendarEvents();
e.currentTarget.reset();
} catch (error: any) { } catch (error: any) {
showError(error.response?.data?.error || 'Erreur lors de la création de l\'événement'); showError(error.response?.data?.error || 'Erreur lors de la création de l\'événement');
} }
@@ -2032,71 +2009,71 @@ const Index = () => {
<div className="space-y-2"> <div className="space-y-2">
<Label htmlFor="reminderMinutes">Rappel (minutes avant)</Label> <Label htmlFor="reminderMinutes">Rappel (minutes avant)</Label>
<Select name="reminderMinutes" defaultValue="30"> <select
<SelectTrigger> id="reminderMinutes"
<SelectValue placeholder="Sélectionner un rappel" /> name="reminderMinutes"
</SelectTrigger> className="w-full h-10 px-3 py-2 border border-input rounded-md bg-background"
<SelectContent> defaultValue="30"
<SelectItem value="0">Aucun</SelectItem> >
<SelectItem value="10">10 minutes</SelectItem> <option value="0">Aucun</option>
<SelectItem value="30">30 minutes</SelectItem> <option value="10">10 minutes</option>
<SelectItem value="60">1 heure</SelectItem> <option value="30">30 minutes</option>
<SelectItem value="1440">1 jour</SelectItem> <option value="60">1 heure</option>
</SelectContent> <option value="1440">1 jour</option>
</Select> </select>
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
<Label htmlFor="recurrence">Récurrence</Label> <Label htmlFor="recurrence">Récurrence</Label>
<Select name="recurrence" defaultValue=""> <select
<SelectTrigger> id="recurrence"
<SelectValue placeholder="Pas de récurrence" /> name="recurrence"
</SelectTrigger> className="w-full h-10 px-3 py-2 border border-input rounded-md bg-background"
<SelectContent> defaultValue=""
<SelectItem value="">Pas de récurrence</SelectItem> >
<SelectItem value="RRULE:FREQ=DAILY">Tous les jours</SelectItem> <option value="">Pas de récurrence</option>
<SelectItem value="RRULE:FREQ=WEEKLY">Toutes les semaines</SelectItem> <option value="RRULE:FREQ=DAILY">Tous les jours</option>
<SelectItem value="RRULE:FREQ=MONTHLY">Tous les mois</SelectItem> <option value="RRULE:FREQ=WEEKLY">Toutes les semaines</option>
<SelectItem value="RRULE:FREQ=YEARLY">Tous les ans</SelectItem> <option value="RRULE:FREQ=MONTHLY">Tous les mois</option>
</SelectContent> <option value="RRULE:FREQ=YEARLY">Tous les ans</option>
</Select> </select>
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
<Label htmlFor="visibility">Visibilité</Label> <Label htmlFor="visibility">Visibilité</Label>
<Select name="visibility" defaultValue="default"> <select
<SelectTrigger> id="visibility"
<SelectValue placeholder="Sélectionner la visibilité" /> name="visibility"
</SelectTrigger> className="w-full h-10 px-3 py-2 border border-input rounded-md bg-background"
<SelectContent> defaultValue="default"
<SelectItem value="default">Par défaut</SelectItem> >
<SelectItem value="public">Public</SelectItem> <option value="default">Par défaut</option>
<SelectItem value="private">Privé</SelectItem> <option value="public">Public</option>
</SelectContent> <option value="private">Privé</option>
</Select> </select>
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
<Label htmlFor="colorId">Couleur</Label> <Label htmlFor="colorId">Couleur</Label>
<Select name="colorId" defaultValue=""> <select
<SelectTrigger> id="colorId"
<SelectValue placeholder="Couleur par défaut" /> name="colorId"
</SelectTrigger> className="w-full h-10 px-3 py-2 border border-input rounded-md bg-background"
<SelectContent> defaultValue=""
<SelectItem value="">Par défaut</SelectItem> >
<SelectItem value="1">Lavande</SelectItem> <option value="">Par défaut</option>
<SelectItem value="2">Sauge</SelectItem> <option value="1">Lavande</option>
<SelectItem value="3">Raisin</SelectItem> <option value="2">Sauge</option>
<SelectItem value="4">Flamant rose</SelectItem> <option value="3">Raisin</option>
<SelectItem value="5">Banane</SelectItem> <option value="4">Flamant rose</option>
<SelectItem value="6">Mandarine</SelectItem> <option value="5">Banane</option>
<SelectItem value="7">Paon</SelectItem> <option value="6">Mandarine</option>
<SelectItem value="8">Graphite</SelectItem> <option value="7">Paon</option>
<SelectItem value="9">Myrtille</SelectItem> <option value="8">Graphite</option>
<SelectItem value="10">Basilic</SelectItem> <option value="9">Myrtille</option>
<SelectItem value="11">Tomate</SelectItem> <option value="10">Basilic</option>
</SelectContent> <option value="11">Tomate</option>
</Select> </select>
</div> </div>
<div className="flex justify-end gap-2 pt-4"> <div className="flex justify-end gap-2 pt-4">