feat: added connected chain ad sound into timer
This commit is contained in:
35
client/src/composables/chainTimer.ts
Normal file
35
client/src/composables/chainTimer.ts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import { TypeTimer } from '@/types/timerType';
|
||||||
|
import { getTimer } from '@/db/crud/timerCrud';
|
||||||
|
|
||||||
|
|
||||||
|
/** Фомирует цепочку таймеров */
|
||||||
|
export async function queueTimer(TimerId: number): Promise<TypeTimer[]> {
|
||||||
|
let timers: TypeTimer[] = [];
|
||||||
|
|
||||||
|
const result = await getTimer(TimerId);
|
||||||
|
const timerData = Array.isArray(result) ? result[0] : result;
|
||||||
|
|
||||||
|
for (let i = 0; i < timerData.count_pomodoro; i++) {
|
||||||
|
timers.push({
|
||||||
|
title: timerData.title,
|
||||||
|
time: timerData.pomodoro_time,
|
||||||
|
typeTimer: "Помидор"
|
||||||
|
});
|
||||||
|
|
||||||
|
if (i === timerData.count_pomodoro - 1) {
|
||||||
|
timers.push({
|
||||||
|
title: timerData.title,
|
||||||
|
time: timerData.break_long_time,
|
||||||
|
typeTimer: "Перерывище"
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
timers.push({
|
||||||
|
title: timerData.title,
|
||||||
|
time: timerData.break_time,
|
||||||
|
typeTimer: "Перерыв"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return timers;
|
||||||
|
}
|
||||||
@@ -1,31 +1,74 @@
|
|||||||
import { ref, computed } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
import { CountdownOptions, CountdownReturn } from '@/types/timerType';
|
import { CountdownOptions, CountdownReturn } from '@/types/timerType';
|
||||||
|
import { stopSound } from '@/composables/useAudio';
|
||||||
|
import { TypeTimer } from '@/types/timerType';
|
||||||
|
|
||||||
|
|
||||||
/** Composable для управления обратным отсчётом времени */
|
/** Composable для управления обратным отсчётом времени */
|
||||||
export function useCountdown({ seconds, onFinish }: CountdownOptions): CountdownReturn {
|
export function useCountdown({ timers, onFinish }: CountdownOptions): CountdownReturn {
|
||||||
const totalSeconds = seconds * 60;
|
const totalSeconds = ref<number>(0);
|
||||||
|
const timerNow = ref<TypeTimer | undefined>(timers.shift());
|
||||||
|
|
||||||
|
if (timerNow.value) {
|
||||||
|
totalSeconds.value = timerNow.value.time * 60;
|
||||||
|
}
|
||||||
|
|
||||||
/** Реактивное оставшееся время в секундах */
|
/** Реактивное оставшееся время в секундах */
|
||||||
const timeLeft = ref<number>(totalSeconds);
|
const timeLeft = ref<number>(totalSeconds.value);
|
||||||
|
|
||||||
/** Флаг активного состояния таймера */
|
/** Флаг активного состояния таймера */
|
||||||
const isRunning = ref<boolean>(false);
|
const isRunning = ref<boolean>(false);
|
||||||
|
|
||||||
let interval: ReturnType<typeof setInterval> | null = null;
|
let interval: ReturnType<typeof setInterval> | null = null;
|
||||||
|
|
||||||
/** Форматирует оставшееся время в строку ЧЧ:ММ:СС */
|
/** Форматирует оставшееся время в строку ЧЧ:ММ:СС или сообщение о прохождении таймера */
|
||||||
const formatted = computed<string>(() => {
|
const formatted = computed<string>(() => {
|
||||||
const hours = Math.floor(timeLeft.value / 3600);
|
const hours = Math.floor(timeLeft.value / 3600);
|
||||||
const mins = Math.floor((timeLeft.value % 3600) / 60);
|
const mins = Math.floor((timeLeft.value % 3600) / 60);
|
||||||
const secs = timeLeft.value % 60;
|
const secs = timeLeft.value % 60;
|
||||||
return `${String(hours).padStart(2, '0')}:${String(mins).padStart(2, '0')}:${String(secs).padStart(2, '0')}`;
|
|
||||||
|
if (timerNow.value) {
|
||||||
|
return `${String(hours).padStart(2, '0')}:${String(mins).padStart(2, '0')}:${String(secs).padStart(2, '0')}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Завершён!";
|
||||||
});
|
});
|
||||||
|
|
||||||
/** Вычисляет процент прошедшего времени от общего */
|
/** Вычисляет процент прошедшего времени от общего */
|
||||||
const progress = computed<number>(() => {
|
const progress = computed<number>(() => {
|
||||||
return ((totalSeconds - timeLeft.value) / totalSeconds) * 100;
|
if (totalSeconds.value === 0) return 0;
|
||||||
|
|
||||||
|
return ((totalSeconds.value - timeLeft.value) / totalSeconds.value) * 100;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/** Отслеживает завершённость таймера */
|
||||||
|
const isFinished = computed<boolean>(() => {
|
||||||
|
return !timerNow.value || timeLeft.value <= 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
/** Задаёт следующий таймер */
|
||||||
|
const setNextTimer = (): void => {
|
||||||
|
timerNow.value = timers.shift();
|
||||||
|
|
||||||
|
if (timerNow.value) {
|
||||||
|
totalSeconds.value = timerNow.value.time * 60;
|
||||||
|
timeLeft.value = totalSeconds.value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//** Заканчивает таймер */
|
||||||
|
const finish = (): void => {
|
||||||
|
if (interval) {
|
||||||
|
clearInterval(interval);
|
||||||
|
interval = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
isRunning.value = false;
|
||||||
|
timeLeft.value = 0;
|
||||||
|
|
||||||
|
onFinish?.();
|
||||||
|
};
|
||||||
|
|
||||||
/** Запускает таймер */
|
/** Запускает таймер */
|
||||||
const start = (): void => {
|
const start = (): void => {
|
||||||
if (isRunning.value) return
|
if (isRunning.value) return
|
||||||
@@ -35,20 +78,22 @@ export function useCountdown({ seconds, onFinish }: CountdownOptions): Countdown
|
|||||||
if (timeLeft.value > 0) {
|
if (timeLeft.value > 0) {
|
||||||
timeLeft.value--;
|
timeLeft.value--;
|
||||||
} else {
|
} else {
|
||||||
stop();
|
finish();
|
||||||
onFinish?.();
|
|
||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Останавливает таймер и сбрасывает время до начального */
|
/** Останавливает таймер и сбрасывает время до следующего таймера */
|
||||||
const stop = (): void => {
|
const stop = (): void => {
|
||||||
if (interval) {
|
if (interval) {
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
interval = null;
|
interval = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
isRunning.value = false;
|
isRunning.value = false;
|
||||||
timeLeft.value = totalSeconds;
|
|
||||||
|
stopSound();
|
||||||
|
setNextTimer()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Приостанавливает таймер без сброса оставшегося времени */
|
/** Приостанавливает таймер без сброса оставшегося времени */
|
||||||
@@ -64,8 +109,10 @@ export function useCountdown({ seconds, onFinish }: CountdownOptions): Countdown
|
|||||||
return {
|
return {
|
||||||
timeLeft,
|
timeLeft,
|
||||||
isRunning,
|
isRunning,
|
||||||
|
isFinished,
|
||||||
formatted,
|
formatted,
|
||||||
progress,
|
progress,
|
||||||
|
timerNow,
|
||||||
start,
|
start,
|
||||||
stop,
|
stop,
|
||||||
pause
|
pause
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export type TimerRow = {
|
|||||||
|
|
||||||
/** Параметры инициализации обратного отсчёта */
|
/** Параметры инициализации обратного отсчёта */
|
||||||
export type CountdownOptions = {
|
export type CountdownOptions = {
|
||||||
seconds: number;
|
timers: TypeTimer[];
|
||||||
onFinish?: () => void;
|
onFinish?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,4 +36,13 @@ export type CountdownReturn = {
|
|||||||
start: () => void;
|
start: () => void;
|
||||||
stop: () => void;
|
stop: () => void;
|
||||||
pause: () => void;
|
pause: () => void;
|
||||||
|
timerNow: Ref<TypeTimer | undefined>;
|
||||||
|
isFinished: ComputedRef<boolean>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Тип таймеров */
|
||||||
|
export type TypeTimer = {
|
||||||
|
title: string;
|
||||||
|
time: number;
|
||||||
|
typeTimer: string;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user