mirror of
https://github.com/R0m1k3/noteflow.git
synced 2026-10-14 02:36:55 +02:00
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:
3 files changed
+84
-6
No files matched your search
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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
@@ -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>
|
||||
|
||||
Reference in new issue
Block a user