forked from Mike/freno-dev
Dead code: 77 verified-unused exports, files (BackArrow, MenuBars, cookies.ts, db/create.ts, schemas/comment.ts, security-headers.ts) and 12 unused dependencies removed Comments: ~370 RESTATE comments stripped across 53 files; 2 verbose blocks tightened; dead commented-out config removed Complexity: bulkUpsert extracted into 11 per-entity helpers (CCN 156->~10); login formHandler split into 3 submitters (CCN 63->~5); account page render split into 8 section components (CCN 40); updatePost SQL builder rebuilt; assert*Owned consolidated behind generic assertOwnedBy Defensive guards: 4 redundant rethrow/nullish guards removed
75 lines
1.7 KiB
TypeScript
75 lines
1.7 KiB
TypeScript
import { createSignal, onCleanup } from "solid-js";
|
|
|
|
export interface UseCountdownOptions {
|
|
/**
|
|
* Initial remaining time in seconds
|
|
*/
|
|
initialTime?: number;
|
|
/**
|
|
* Cookie name to read expiration time from
|
|
*/
|
|
cookieName?: string;
|
|
/**
|
|
* Callback when countdown reaches zero
|
|
*/
|
|
onComplete?: () => void;
|
|
}
|
|
|
|
/**
|
|
* Hook for managing countdown timers from expiration timestamps
|
|
* @param options Configuration options
|
|
* @returns [remainingTime, startCountdown]
|
|
*/
|
|
export function useCountdown(options: UseCountdownOptions = {}) {
|
|
const [remainingTime, setRemainingTime] = createSignal(
|
|
options.initialTime ?? 0
|
|
);
|
|
let intervalId: ReturnType<typeof setInterval> | null = null;
|
|
|
|
const calculateRemaining = (expiresAt: string | Date) => {
|
|
const expires =
|
|
typeof expiresAt === "string" ? new Date(expiresAt) : expiresAt;
|
|
const remaining = expires.getTime() - Date.now();
|
|
const remainingInSeconds = remaining / 1000;
|
|
|
|
if (remainingInSeconds <= 0) {
|
|
setRemainingTime(0);
|
|
if (intervalId !== null) {
|
|
clearInterval(intervalId);
|
|
intervalId = null;
|
|
}
|
|
options.onComplete?.();
|
|
} else {
|
|
setRemainingTime(remainingInSeconds);
|
|
}
|
|
};
|
|
|
|
const startCountdown = (expiresAt: string | Date) => {
|
|
if (intervalId !== null) {
|
|
clearInterval(intervalId);
|
|
}
|
|
|
|
calculateRemaining(expiresAt);
|
|
|
|
intervalId = setInterval(() => calculateRemaining(expiresAt), 1000);
|
|
};
|
|
|
|
const stopCountdown = () => {
|
|
if (intervalId !== null) {
|
|
clearInterval(intervalId);
|
|
intervalId = null;
|
|
}
|
|
};
|
|
|
|
onCleanup(() => {
|
|
stopCountdown();
|
|
});
|
|
|
|
return {
|
|
remainingTime,
|
|
startCountdown,
|
|
stopCountdown,
|
|
setRemainingTime
|
|
};
|
|
}
|