feat: Add Time Tracking page with analytics and time distribution charts
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
- Add TimeTrackingPage with pie/bar charts for time spent per label - Add task_time_logs schema for tracking time entries - Add /api/analytics/time-distribution endpoint - Update sidebar navigation with time tracking link - Update App routing for new pages - Fix routine blocker and settings card issues - Add German translations for analytics Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Home, Calendar, List, LayoutGrid, Settings, CheckSquare, Target, Trophy, LogOut, Award, Bot, CalendarOff, Bell } from 'lucide-react';
|
||||
import { Home, Calendar, List, LayoutGrid, Settings, CheckSquare, Target, Trophy, LogOut, Award, Bot, CalendarOff, Bell, Clock } from 'lucide-react';
|
||||
import { useQueryClient, useMutation, useQuery } from '@tanstack/react-query';
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import { Button } from "@/components/ui/button";
|
||||
@@ -60,6 +60,7 @@ export function AppSidebar({ user, ...props }: AppSidebarProps) {
|
||||
{ title: t('navigation.kanban'), id: 'kanban', path: '/kanban', icon: LayoutGrid, color: 'text-orange-500' },
|
||||
{ title: t('navigation.achievements'), id: 'achievements', path: '/achievements', icon: Trophy, color: 'text-yellow-500' },
|
||||
{ title: t('navigation.leaderboard'), id: 'leaderboard', path: '/leaderboard', icon: Award, color: 'text-yellow-500' },
|
||||
{ title: t('analytics.timeTracking'), id: 'time-tracking', path: '/time-tracking', icon: Clock, color: 'text-teal-500' },
|
||||
...(user?.aiEnabled ? [{ title: t('navigation.aiChat', 'AI Chat'), id: 'ai-chat', path: '/ai', icon: Bot, color: 'text-indigo-500' }] : []),
|
||||
{ title: t('navigation.settings'), id: 'settings', path: '/settings', icon: Settings, color: 'text-gray-500' },
|
||||
]
|
||||
|
||||
@@ -34,7 +34,7 @@ export function useRoutineBlocker() {
|
||||
|
||||
// Evening Routine Check
|
||||
const eveningEnabled = settings.evening_routine_enabled !== "false";
|
||||
const eveningStartTime = parseTime(settings.evening_routine_time || "17:00"); // 17:00 default
|
||||
const eveningStartTime = parseTime(settings.evening_routine_time || "22:00"); // 22:00 default
|
||||
|
||||
// If it is Evening time (>= start time), we primarily check Evening Routine.
|
||||
if (eveningEnabled) {
|
||||
@@ -89,7 +89,7 @@ export function useRoutineBlocker() {
|
||||
|
||||
const eveningEnabled = settings.evening_routine_enabled !== "false";
|
||||
// Safe parse
|
||||
const [eh, em] = (settings.evening_routine_time || "17:00").split(':').map(Number);
|
||||
const [eh, em] = (settings.evening_routine_time || "22:00").split(':').map(Number);
|
||||
const eveningStartVal = (eh || 0) * 60 + (em || 0);
|
||||
|
||||
const morningEnabled = settings.morning_routine_enabled !== "false";
|
||||
@@ -118,7 +118,8 @@ export function useRoutineBlocker() {
|
||||
const eveningEnabled = settings.evening_routine_enabled !== "false";
|
||||
if (!eveningEnabled) return false;
|
||||
|
||||
const [eh, em] = (settings.evening_routine_time || "17:00").split(':').map(Number);
|
||||
const rawTime = settings.evening_routine_time || "22:00";
|
||||
const [eh, em] = rawTime.split(':').map(Number);
|
||||
const startVal = (eh || 0) * 60 + (em || 0);
|
||||
|
||||
if (currentTimeVal >= startVal && !isSameDay(user.lastEveningRoutine, now)) return true;
|
||||
|
||||
@@ -18,7 +18,7 @@ export function RoutineSettingsCard() {
|
||||
const [morningEnabled, setMorningEnabled] = useState(true);
|
||||
const [morningTime, setMorningTime] = useState("09:00");
|
||||
const [eveningEnabled, setEveningEnabled] = useState(true);
|
||||
const [eveningTime, setEveningTime] = useState("17:00");
|
||||
const [eveningTime, setEveningTime] = useState("22:00");
|
||||
|
||||
const { data: settings, isLoading } = useQuery<Record<string, string>>({
|
||||
queryKey: ['/api/admin/settings'],
|
||||
@@ -34,7 +34,7 @@ export function RoutineSettingsCard() {
|
||||
setMorningEnabled(settings.morning_routine_enabled !== "false");
|
||||
setMorningTime(settings.morning_routine_time || "09:00");
|
||||
setEveningEnabled(settings.evening_routine_enabled !== "false");
|
||||
setEveningTime(settings.evening_routine_time || "17:00");
|
||||
setEveningTime(settings.evening_routine_time || "22:00");
|
||||
}
|
||||
}, [settings]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user