101 lines
2.4 KiB
TypeScript
101 lines
2.4 KiB
TypeScript
import { useEffect, useRef, useState } from 'react';
|
|
import { useRouter } from 'next/navigation';
|
|
|
|
import { getCurrentVoyage, getPreferences, saveCurrentVoyage } from '@/shared/lib/store';
|
|
import { Voyage } from '@/shared/types';
|
|
|
|
const getVoyageFromStore = () => {
|
|
const current = getCurrentVoyage();
|
|
if (!current || current.status !== 'in_progress') {
|
|
return null;
|
|
}
|
|
return current;
|
|
};
|
|
|
|
const getEndTime = (voyage: Voyage | null) => {
|
|
if (!voyage) return 0;
|
|
return voyage.startedAt + voyage.durationMinutes * 60 * 1000;
|
|
};
|
|
|
|
export function useFlightSession() {
|
|
const router = useRouter();
|
|
const [voyage] = useState<Voyage | null>(() => getVoyageFromStore());
|
|
const [timeLeft, setTimeLeft] = useState<number>(() => {
|
|
const current = getVoyageFromStore();
|
|
const endTime = getEndTime(current);
|
|
if (!endTime) return 0;
|
|
return Math.max(0, Math.ceil((endTime - Date.now()) / 1000));
|
|
});
|
|
const [isPaused, setIsPaused] = useState(false);
|
|
const [hideSeconds] = useState(() => getPreferences().hideSeconds);
|
|
const endTimeRef = useRef<number>(getEndTime(getVoyageFromStore()));
|
|
|
|
useEffect(() => {
|
|
if (voyage) return;
|
|
|
|
router.replace('/');
|
|
}, [voyage, router]);
|
|
|
|
useEffect(() => {
|
|
if (!voyage || isPaused) return;
|
|
|
|
const interval = setInterval(() => {
|
|
const diff = endTimeRef.current - Date.now();
|
|
|
|
if (diff <= 0) {
|
|
setTimeLeft(0);
|
|
clearInterval(interval);
|
|
return;
|
|
}
|
|
|
|
setTimeLeft(Math.ceil(diff / 1000));
|
|
}, 1000);
|
|
|
|
return () => clearInterval(interval);
|
|
}, [voyage, isPaused]);
|
|
|
|
const handlePauseToggle = () => {
|
|
if (isPaused) {
|
|
endTimeRef.current = Date.now() + timeLeft * 1000;
|
|
setIsPaused(false);
|
|
return;
|
|
}
|
|
|
|
setIsPaused(true);
|
|
};
|
|
|
|
const handleFinish = () => {
|
|
if (!voyage) return;
|
|
|
|
const endedVoyage: Voyage = {
|
|
...voyage,
|
|
endedAt: Date.now(),
|
|
};
|
|
|
|
saveCurrentVoyage(endedVoyage);
|
|
router.push('/debrief');
|
|
};
|
|
|
|
const formatTime = (seconds: number) => {
|
|
const minutes = Math.floor(seconds / 60);
|
|
const remainingSeconds = seconds % 60;
|
|
|
|
if (hideSeconds) {
|
|
return `${minutes}m`;
|
|
}
|
|
|
|
return `${minutes.toString().padStart(2, '0')}:${remainingSeconds
|
|
.toString()
|
|
.padStart(2, '0')}`;
|
|
};
|
|
|
|
return {
|
|
voyage,
|
|
timeLeft,
|
|
isPaused,
|
|
formattedTime: formatTime(timeLeft),
|
|
handlePauseToggle,
|
|
handleFinish,
|
|
};
|
|
}
|