"use client"; import { useEffect, useState, useCallback } from "react"; import { useRouter } from "next/navigation"; import { useAuth } from "@/lib/auth"; import { getTasks, getGroups, Task, Group } from "@/lib/api"; function getActiveGroup(groups: Group[]): Group | null { const now = new Date(); const currentDay = now.getDay(); const pad = (n: number) => String(n).padStart(2, "0"); const currentTime = `${pad(now.getHours())}:${pad(now.getMinutes())}`; for (const group of groups) { for (const tz of group.time_zones || []) { if (tz.days?.length && !tz.days.includes(currentDay)) continue; if (tz.from && tz.to && tz.from <= currentTime && currentTime <= tz.to) return group; } } return groups[0] || null; } function hexToRgb(hex: string): string { const r = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); if (!r) return "29, 78, 216"; return `${parseInt(r[1], 16)}, ${parseInt(r[2], 16)}, ${parseInt(r[3], 16)}`; } export default function LockScreen() { const { token } = useAuth(); const router = useRouter(); const [now, setNow] = useState(new Date()); const [tasks, setTasks] = useState([]); const [groups, setGroups] = useState([]); const [swipeStart, setSwipeStart] = useState(null); const [swipeOffset, setSwipeOffset] = useState(0); useEffect(() => { const t = setInterval(() => setNow(new Date()), 1000); return () => clearInterval(t); }, []); const loadData = useCallback(async () => { if (!token) return; try { const [tasksRes, groupsRes] = await Promise.all([getTasks(token), getGroups(token)]); setTasks(tasksRes.data || []); setGroups(groupsRes.data || []); } catch { /* ignore */ } }, [token]); useEffect(() => { loadData(); }, [loadData]); // Reload data every 5 minutes useEffect(() => { const i = setInterval(loadData, 5 * 60 * 1000); return () => clearInterval(i); }, [loadData]); function handleUnlock() { router.push("/tasks"); } function handleTouchStart(e: React.TouchEvent) { setSwipeStart(e.touches[0].clientY); setSwipeOffset(0); } function handleTouchMove(e: React.TouchEvent) { if (swipeStart === null) return; const delta = swipeStart - e.touches[0].clientY; if (delta > 0) setSwipeOffset(Math.min(delta, 150)); } function handleTouchEnd() { if (swipeOffset > 80) handleUnlock(); setSwipeStart(null); setSwipeOffset(0); } const activeGroup = getActiveGroup(groups); const activeTasks = tasks .filter(t => t.status === "pending" || t.status === "in_progress") .slice(0, 4); const color = activeGroup?.color || "#1D4ED8"; const rgb = hexToRgb(color); const pad = (n: number) => String(n).padStart(2, "0"); const timeStr = `${pad(now.getHours())}:${pad(now.getMinutes())}`; const seconds = pad(now.getSeconds()); const dateStr = now.toLocaleDateString("cs-CZ", { weekday: "long", day: "numeric", month: "long" }); return (
0 ? `translateY(-${swipeOffset * 0.3}px)` : undefined, transition: swipeOffset === 0 ? "transform 0.3s ease" : "none", overflow: "hidden", }} onTouchStart={handleTouchStart} onTouchMove={handleTouchMove} onTouchEnd={handleTouchEnd} onClick={handleUnlock} > {/* Ambient glow */}
{/* Clock section */}
{timeStr} {seconds}
{dateStr}
{/* Active group badge */} {activeGroup && (
{activeGroup.icon || "\uD83D\uDCC1"}
{activeGroup.display_name || activeGroup.name}
{activeGroup.time_zones?.[0] && (
{activeGroup.time_zones[0].from} \u2013 {activeGroup.time_zones[0].to}
)}
)}
{/* Tasks panel */} {activeTasks.length > 0 && (
\u00DAkoly ({activeTasks.length})
{activeTasks.map(task => (
{task.title} {task.group_icon && {task.group_icon}}
))}
)} {/* Unlock indicator */}
Klepn\u011Bte nebo p\u0159eje\u010Fte nahoru
); }