fix: lint
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { Card } from '@/components/ui/Card';
|
||||
|
||||
@@ -10,7 +10,11 @@ interface DailyCalendarProps {
|
||||
dailyDates: string[]; // Liste des dates qui ont des dailies (format YYYY-MM-DD)
|
||||
}
|
||||
|
||||
export function DailyCalendar({ currentDate, onDateSelect, dailyDates }: DailyCalendarProps) {
|
||||
export function DailyCalendar({
|
||||
currentDate,
|
||||
onDateSelect,
|
||||
dailyDates,
|
||||
}: DailyCalendarProps) {
|
||||
const [viewDate, setViewDate] = useState(new Date(currentDate));
|
||||
|
||||
// Formatage des dates pour comparaison (éviter le décalage timezone)
|
||||
@@ -46,31 +50,32 @@ export function DailyCalendar({ currentDate, onDateSelect, dailyDates }: DailyCa
|
||||
const getDaysInMonth = () => {
|
||||
const year = viewDate.getFullYear();
|
||||
const month = viewDate.getMonth();
|
||||
|
||||
|
||||
// Premier jour du mois
|
||||
const firstDay = new Date(year, month, 1);
|
||||
// Dernier jour du mois
|
||||
const lastDay = new Date(year, month + 1, 0);
|
||||
|
||||
|
||||
// Premier lundi de la semaine contenant le premier jour
|
||||
const startDate = new Date(firstDay);
|
||||
const dayOfWeek = firstDay.getDay();
|
||||
const daysToSubtract = dayOfWeek === 0 ? 6 : dayOfWeek - 1; // Lundi = 0
|
||||
startDate.setDate(firstDay.getDate() - daysToSubtract);
|
||||
|
||||
|
||||
// Générer toutes les dates du calendrier (6 semaines)
|
||||
const days = [];
|
||||
const currentDay = new Date(startDate);
|
||||
|
||||
for (let i = 0; i < 42; i++) { // 6 semaines × 7 jours
|
||||
|
||||
for (let i = 0; i < 42; i++) {
|
||||
// 6 semaines × 7 jours
|
||||
days.push(new Date(currentDay));
|
||||
currentDay.setDate(currentDay.getDate() + 1);
|
||||
}
|
||||
|
||||
|
||||
return { days, firstDay, lastDay };
|
||||
};
|
||||
|
||||
const { days, firstDay, lastDay } = getDaysInMonth();
|
||||
const { days } = getDaysInMonth();
|
||||
|
||||
const handleDateClick = (date: Date) => {
|
||||
onDateSelect(date);
|
||||
@@ -96,7 +101,7 @@ export function DailyCalendar({ currentDate, onDateSelect, dailyDates }: DailyCa
|
||||
const formatMonthYear = () => {
|
||||
return viewDate.toLocaleDateString('fr-FR', {
|
||||
month: 'long',
|
||||
year: 'numeric'
|
||||
year: 'numeric',
|
||||
});
|
||||
};
|
||||
|
||||
@@ -114,11 +119,11 @@ export function DailyCalendar({ currentDate, onDateSelect, dailyDates }: DailyCa
|
||||
>
|
||||
←
|
||||
</Button>
|
||||
|
||||
|
||||
<h3 className="text-lg font-bold text-[var(--foreground)] capitalize">
|
||||
{formatMonthYear()}
|
||||
</h3>
|
||||
|
||||
|
||||
<Button
|
||||
onClick={goToNextMonth}
|
||||
variant="ghost"
|
||||
@@ -131,12 +136,8 @@ export function DailyCalendar({ currentDate, onDateSelect, dailyDates }: DailyCa
|
||||
|
||||
{/* Bouton Aujourd'hui */}
|
||||
<div className="mb-4 text-center">
|
||||
<Button
|
||||
onClick={goToToday}
|
||||
variant="primary"
|
||||
size="sm"
|
||||
>
|
||||
Aujourd'hui
|
||||
<Button onClick={goToToday} variant="primary" size="sm">
|
||||
Aujourd'hui
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -155,7 +156,6 @@ export function DailyCalendar({ currentDate, onDateSelect, dailyDates }: DailyCa
|
||||
{/* Grille du calendrier */}
|
||||
<div className="grid grid-cols-7 gap-1">
|
||||
{days.map((date, index) => {
|
||||
const dateKey = formatDateKey(date);
|
||||
const isCurrentMonthDay = isCurrentMonth(date);
|
||||
const isTodayDay = isToday(date);
|
||||
const hasCheckboxes = hasDaily(date);
|
||||
@@ -167,35 +167,30 @@ export function DailyCalendar({ currentDate, onDateSelect, dailyDates }: DailyCa
|
||||
onClick={() => handleDateClick(date)}
|
||||
className={`
|
||||
relative p-2 text-sm rounded transition-all hover:bg-[var(--muted)]/50
|
||||
${isCurrentMonthDay
|
||||
? 'text-[var(--foreground)]'
|
||||
: 'text-[var(--muted-foreground)]'
|
||||
${
|
||||
isCurrentMonthDay
|
||||
? 'text-[var(--foreground)]'
|
||||
: 'text-[var(--muted-foreground)]'
|
||||
}
|
||||
${isTodayDay
|
||||
? 'bg-[var(--primary)]/20 border border-[var(--primary)]'
|
||||
: ''
|
||||
}
|
||||
${isSelectedDay
|
||||
? 'bg-[var(--primary)] text-white'
|
||||
: ''
|
||||
}
|
||||
${hasCheckboxes
|
||||
? 'font-bold'
|
||||
: ''
|
||||
${
|
||||
isTodayDay
|
||||
? 'bg-[var(--primary)]/20 border border-[var(--primary)]'
|
||||
: ''
|
||||
}
|
||||
${isSelectedDay ? 'bg-[var(--primary)] text-white' : ''}
|
||||
${hasCheckboxes ? 'font-bold' : ''}
|
||||
`}
|
||||
>
|
||||
{date.getDate()}
|
||||
|
||||
|
||||
{/* Indicateur de daily existant */}
|
||||
{hasCheckboxes && (
|
||||
<div className={`
|
||||
<div
|
||||
className={`
|
||||
absolute bottom-1 right-1 w-2 h-2 rounded-full
|
||||
${isSelectedDay
|
||||
? 'bg-white'
|
||||
: 'bg-[var(--primary)]'
|
||||
}
|
||||
`} />
|
||||
${isSelectedDay ? 'bg-white' : 'bg-[var(--primary)]'}
|
||||
`}
|
||||
/>
|
||||
)}
|
||||
</button>
|
||||
);
|
||||
@@ -210,7 +205,7 @@ export function DailyCalendar({ currentDate, onDateSelect, dailyDates }: DailyCa
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-4 h-4 rounded border border-[var(--primary)] bg-[var(--primary)]/20"></div>
|
||||
<span>Aujourd'hui</span>
|
||||
<span>Aujourd'hui</span>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
@@ -158,7 +158,7 @@ export function TagForm({ isOpen, onClose, onSubmit, tag, loading = false }: Tag
|
||||
value={formData.color}
|
||||
onChange={(e) => {
|
||||
if (TagsClient.isValidColor(e.target.value)) {
|
||||
handleCustomColorChange(e as any);
|
||||
handleCustomColorChange(e as React.ChangeEvent<HTMLInputElement>);
|
||||
}
|
||||
}}
|
||||
placeholder="#RRGGBB"
|
||||
@@ -189,7 +189,7 @@ export function TagForm({ isOpen, onClose, onSubmit, tag, loading = false }: Tag
|
||||
</label>
|
||||
</div>
|
||||
<p className="text-xs text-slate-400">
|
||||
Les tâches avec ce tag apparaîtront dans la section "Objectifs Principaux" au-dessus du Kanban
|
||||
Les tâches avec ce tag apparaîtront dans la section "Objectifs Principaux" au-dessus du Kanban
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -6,7 +6,8 @@ import { useMemo } from 'react';
|
||||
import { getAllPriorities } from '@/lib/status-config';
|
||||
import { SwimlanesBase, SwimlaneData } from './SwimlanesBase';
|
||||
|
||||
interface PrioritySwimlanesoardProps {
|
||||
interface PrioritySwimlanesBoardProps {
|
||||
loading: boolean;
|
||||
tasks: Task[];
|
||||
onCreateTask?: (data: CreateTaskData) => Promise<void>;
|
||||
onDeleteTask?: (taskId: string) => Promise<void>;
|
||||
@@ -15,40 +16,37 @@ interface PrioritySwimlanesoardProps {
|
||||
onUpdateStatus?: (taskId: string, newStatus: TaskStatus) => Promise<void>;
|
||||
compactView?: boolean;
|
||||
visibleStatuses?: TaskStatus[];
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
export function PrioritySwimlanesBoard({
|
||||
tasks,
|
||||
export function PrioritySwimlanesBoard({
|
||||
tasks,
|
||||
onCreateTask,
|
||||
onDeleteTask,
|
||||
onEditTask,
|
||||
onUpdateTitle,
|
||||
onUpdateStatus,
|
||||
onDeleteTask,
|
||||
onEditTask,
|
||||
onUpdateTitle,
|
||||
onUpdateStatus,
|
||||
compactView = false,
|
||||
visibleStatuses,
|
||||
loading = false
|
||||
}: PrioritySwimlanesoardProps) {
|
||||
|
||||
}: PrioritySwimlanesBoardProps) {
|
||||
// Grouper les tâches par priorités et créer les données de swimlanes
|
||||
const swimlanesData = useMemo((): SwimlaneData[] => {
|
||||
const grouped: { [priorityKey: string]: Task[] } = {};
|
||||
|
||||
|
||||
// Initialiser avec toutes les priorités
|
||||
getAllPriorities().forEach(priority => {
|
||||
getAllPriorities().forEach((priority) => {
|
||||
grouped[priority.key] = [];
|
||||
});
|
||||
|
||||
tasks.forEach(task => {
|
||||
|
||||
tasks.forEach((task) => {
|
||||
if (grouped[task.priority]) {
|
||||
grouped[task.priority].push(task);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Convertir en format SwimlaneData en respectant l'ordre de priorité
|
||||
return getAllPriorities()
|
||||
.sort((a, b) => b.order - a.order) // Ordre décroissant - plus importantes en haut
|
||||
.map(priority => ({
|
||||
.map((priority) => ({
|
||||
key: priority.key,
|
||||
label: priority.label,
|
||||
icon: priority.icon,
|
||||
@@ -56,8 +54,8 @@ export function PrioritySwimlanesBoard({
|
||||
tasks: grouped[priority.key] || [],
|
||||
context: {
|
||||
type: 'priority' as const,
|
||||
value: priority.key
|
||||
}
|
||||
value: priority.key,
|
||||
},
|
||||
}));
|
||||
}, [tasks]);
|
||||
|
||||
@@ -74,4 +72,4 @@ export function PrioritySwimlanesBoard({
|
||||
visibleStatuses={visibleStatuses}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,34 +15,33 @@ interface SwimlanesboardProps {
|
||||
onUpdateStatus?: (taskId: string, newStatus: TaskStatus) => Promise<void>;
|
||||
compactView?: boolean;
|
||||
visibleStatuses?: TaskStatus[];
|
||||
loading?: boolean;
|
||||
loading: boolean;
|
||||
}
|
||||
|
||||
export function SwimlanesBoard({
|
||||
tasks,
|
||||
export function SwimlanesBoard({
|
||||
tasks,
|
||||
onCreateTask,
|
||||
onDeleteTask,
|
||||
onEditTask,
|
||||
onUpdateTitle,
|
||||
onUpdateStatus,
|
||||
onDeleteTask,
|
||||
onEditTask,
|
||||
onUpdateTitle,
|
||||
onUpdateStatus,
|
||||
compactView = false,
|
||||
visibleStatuses,
|
||||
loading = false
|
||||
}: SwimlanesboardProps) {
|
||||
const { tags: availableTags } = useTasksContext();
|
||||
|
||||
// Grouper les tâches par tags et créer les données de swimlanes
|
||||
const swimlanesData = useMemo((): SwimlaneData[] => {
|
||||
const grouped: { [tagName: string]: Task[] } = {};
|
||||
|
||||
|
||||
// Ajouter une catégorie pour les tâches sans tags
|
||||
grouped['Sans tag'] = [];
|
||||
|
||||
tasks.forEach(task => {
|
||||
|
||||
tasks.forEach((task) => {
|
||||
if (!task.tags || task.tags.length === 0) {
|
||||
grouped['Sans tag'].push(task);
|
||||
} else {
|
||||
task.tags.forEach(tagName => {
|
||||
task.tags.forEach((tagName) => {
|
||||
if (!grouped[tagName]) {
|
||||
grouped[tagName] = [];
|
||||
}
|
||||
@@ -50,7 +49,7 @@ export function SwimlanesBoard({
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Convertir en format SwimlaneData et trier
|
||||
return Object.entries(grouped)
|
||||
.sort(([a, tasksA], [b, tasksB]) => {
|
||||
@@ -64,7 +63,7 @@ export function SwimlanesBoard({
|
||||
// Obtenir la couleur du tag
|
||||
const getTagColor = (name: string) => {
|
||||
if (name === 'Sans tag') return '#64748b'; // slate-500
|
||||
const tag = availableTags.find(t => t.name === name);
|
||||
const tag = availableTags.find((t) => t.name === name);
|
||||
return tag?.color || '#64748b';
|
||||
};
|
||||
|
||||
@@ -73,10 +72,13 @@ export function SwimlanesBoard({
|
||||
label: tagName,
|
||||
color: getTagColor(tagName),
|
||||
tasks: tagTasks,
|
||||
context: tagName !== 'Sans tag' ? {
|
||||
type: 'tag' as const,
|
||||
value: tagName
|
||||
} : undefined
|
||||
context:
|
||||
tagName !== 'Sans tag'
|
||||
? {
|
||||
type: 'tag' as const,
|
||||
value: tagName,
|
||||
}
|
||||
: undefined,
|
||||
};
|
||||
});
|
||||
}, [tasks, availableTags]);
|
||||
@@ -94,4 +96,4 @@ export function SwimlanesBoard({
|
||||
visibleStatuses={visibleStatuses}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,10 @@ interface HeaderContainerProps {
|
||||
completed: number;
|
||||
inProgress: number;
|
||||
todo: number;
|
||||
backlog: number;
|
||||
cancelled: number;
|
||||
freeze: number;
|
||||
archived: number;
|
||||
completionRate: number;
|
||||
};
|
||||
}
|
||||
@@ -18,7 +22,7 @@ interface HeaderContainerProps {
|
||||
export function HeaderContainer({ title, subtitle, initialStats }: HeaderContainerProps) {
|
||||
const { stats, syncing } = useTasks(
|
||||
{ limit: 1 }, // Juste pour les stats
|
||||
{ tasks: [], stats: initialStats }
|
||||
{ tasks: [], stats: { ...initialStats, backlog: 0, cancelled: 0, freeze: 0, archived: 0 } }
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user