feat: transformer le Pomodoro Timer en modal avec icône dans le header

- Créer un composant PomodoroModal pour afficher le timer
- Ajouter une icône Clock dans le header qui affiche le temps restant quand le timer est actif
- Modifier PomodoroTimer pour accepter une callback onStateChange
- Retirer la box Pomodoro de la page principale
- L'icône change de style quand le timer est en cours et affiche le décompte
This commit is contained in:
Claude committed 2025-11-28 20:34:32 +00:00
1 parent c66e5adc4a
commit 2b84ac0e97
3 files changed
+84 -6

No files matched your search

+28
View File
@@ -0,0 +1,28 @@
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { PomodoroTimer } from "./PomodoroTimer";
interface PomodoroModalProps {
open: boolean;
onOpenChange: (open: boolean) => void;
onTimerStateChange?: (isRunning: boolean, timeLeft: number, mode: string) => void;
}
export function PomodoroModal({ open, onOpenChange, onTimerStateChange }: PomodoroModalProps) {
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-md">
<DialogHeader>
<DialogTitle className="text-2xl">Pomodoro Timer</DialogTitle>
</DialogHeader>
<div className="mt-4">
<PomodoroTimer onStateChange={onTimerStateChange} />
</div>
</DialogContent>
</Dialog>
);
}
+12 -1
View File
@@ -15,7 +15,11 @@ const TIMER_DURATIONS = {
const SESSIONS_BEFORE_LONG_BREAK = 4;
export function PomodoroTimer() {
interface PomodoroTimerProps {
onStateChange?: (isRunning: boolean, timeLeft: number, mode: TimerMode) => void;
}
export function PomodoroTimer({ onStateChange }: PomodoroTimerProps = {}) {
const [mode, setMode] = useState<TimerMode>('work');
const [timeLeft, setTimeLeft] = useState(TIMER_DURATIONS.work);
const [isRunning, setIsRunning] = useState(false);
@@ -64,6 +68,13 @@ export function PomodoroTimer() {
}
};
// Notify parent component of state changes
useEffect(() => {
if (onStateChange) {
onStateChange(isRunning, timeLeft, mode);
}
}, [isRunning, timeLeft, mode, onStateChange]);
useEffect(() => {
if (isRunning && timeLeft > 0) {
intervalRef.current = setInterval(() => {
+44 -5
View File
@@ -37,7 +37,7 @@ import { downloadNoteAsMarkdown, downloadAllNotesAsMarkdown, downloadTodosAsMark
import { TemplateSelector } from "@/components/TemplateSelector";
import type { NoteTemplate } from "@/utils/noteTemplates";
import { AdvancedSearch, type SearchFilters, type TagOption } from "@/components/AdvancedSearch";
import { PomodoroTimer } from "@/components/PomodoroTimer";
import { PomodoroModal } from "@/components/PomodoroModal";
import { KanbanBoard } from "@/components/KanbanBoard";
import { getSmartTagSuggestions } from "@/utils/smartTags";
import { QuickCaptureWidget } from "@/components/QuickCaptureWidget";
@@ -193,6 +193,12 @@ const Index = () => {
const [editEventModal, setEditEventModal] = useState<{ open: boolean, event?: CalendarEvent }>({ open: false });
const [showKeyboardHelp, setShowKeyboardHelp] = useState(false);
const [showStatsDashboard, setShowStatsDashboard] = useState(false);
const [showPomodoroModal, setShowPomodoroModal] = useState(false);
// Pomodoro timer states
const [pomodoroRunning, setPomodoroRunning] = useState(false);
const [pomodoroTimeLeft, setPomodoroTimeLeft] = useState(25 * 60);
const [pomodoroMode, setPomodoroMode] = useState<'work' | 'shortBreak' | 'longBreak'>('work');
// Pagination states
const [notesPage, setNotesPage] = useState(0);
@@ -271,6 +277,20 @@ const Index = () => {
return () => clearInterval(interval);
}, []);
// Handle Pomodoro timer state changes
const handlePomodoroStateChange = (isRunning: boolean, timeLeft: number, mode: 'work' | 'shortBreak' | 'longBreak') => {
setPomodoroRunning(isRunning);
setPomodoroTimeLeft(timeLeft);
setPomodoroMode(mode);
};
// Format time for Pomodoro display
const formatPomodoroTime = (seconds: number): string => {
const mins = Math.floor(seconds / 60);
const secs = seconds % 60;
return `${mins}:${secs.toString().padStart(2, '0')}`;
};
const loadNotes = async () => {
try {
const fetchedNotes = await NotesService.getNotes();
@@ -1120,6 +1140,21 @@ const Index = () => {
<BarChart3 className="h-5 w-5" />
</Button>
<Button
variant={pomodoroRunning ? "default" : "ghost"}
size="icon"
onClick={() => setShowPomodoroModal(true)}
title="Pomodoro Timer"
className="relative"
>
<Clock className="h-5 w-5" />
{pomodoroRunning && (
<span className="absolute -bottom-1 -right-1 text-[10px] font-mono bg-primary text-primary-foreground px-1 rounded">
{formatPomodoroTime(pomodoroTimeLeft)}
</span>
)}
</Button>
<ModeToggle />
{user && (
@@ -1930,11 +1965,8 @@ const Index = () => {
)}
</div>
{/* Right Column: Pomodoro Timer, Todos & RSS */}
{/* Right Column: Todos & RSS */}
<div className="space-y-6">
{/* Pomodoro Timer */}
<PomodoroTimer />
{/* Todos & RSS Boxes side by side */}
<div className="grid grid-cols-2 gap-6">
{/* Todos Box */}
@@ -3181,6 +3213,13 @@ const Index = () => {
todos={todos}
/>
{/* Pomodoro Timer Modal */}
<PomodoroModal
open={showPomodoroModal}
onOpenChange={setShowPomodoroModal}
onTimerStateChange={handlePomodoroStateChange}
/>
{/* Quick Capture Widget */}
<QuickCaptureWidget onNoteCaptured={loadNotes} />
</div>