fix(routine): resolove routine blocker logic bug and white screen
continuous-integration/drone/push Build is passing

feat(gamification): add streak bonuses, tooltip, and improved history details

fix(ep): resolve double counting ep bug

ui: update app icon and translations
This commit is contained in:
2025-12-15 23:17:59 +01:00
parent 9736864425
commit 7b79015ac2
17 changed files with 884 additions and 299 deletions
+19 -11
View File
@@ -1,4 +1,3 @@
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
@@ -491,21 +490,30 @@ export default function AchievementsPage({ user }: { user: User }) {
history.map((event) => (
<div key={event.id} className="flex items-center justify-between py-3 border-b last:border-0 hover:bg-muted/50 px-2 rounded-md transition-colors">
<div className="flex items-center gap-3">
<div className={`p-2 rounded-full ${event.source === 'task_completion' ? 'bg-green-100 text-green-600 dark:bg-green-900/30 dark:text-green-400' :
event.source === 'daily_streak' ? 'bg-orange-100 text-orange-600 dark:bg-orange-900/30 dark:text-orange-400' :
'bg-blue-100 text-blue-600 dark:bg-blue-900/30 dark:text-blue-400'
<div className={`p-2 rounded-full ${event.source === 'complete_task_late' ? 'bg-red-100 text-red-600 dark:bg-red-900/30 dark:text-red-400' :
(event.source === 'task_completion' || event.source === 'complete_task') ? 'bg-green-100 text-green-600 dark:bg-green-900/30 dark:text-green-400' :
event.source === 'daily_streak' ? 'bg-orange-100 text-orange-600 dark:bg-orange-900/30 dark:text-orange-400' :
'bg-blue-100 text-blue-600 dark:bg-blue-900/30 dark:text-blue-400'
}`}>
{event.source === 'task_completion' ? <CheckCircle2 className="h-4 w-4" /> :
event.source === 'daily_streak' ? <Flame className="h-4 w-4" /> :
<Trophy className="h-4 w-4" />}
{event.source === 'complete_task_late' ? <Clock className="h-4 w-4" /> :
event.source.includes('complete') ? <CheckCircle2 className="h-4 w-4" /> :
event.source === 'daily_streak' ? <Flame className="h-4 w-4" /> :
<Trophy className="h-4 w-4" />}
</div>
<div>
<p className="font-medium text-sm">
{t(`gamification.source.${event.source}`, { defaultValue: event.source }) as string}
</p>
<p className="text-xs text-muted-foreground">
{new Date(event.createdAt).toLocaleString()}
{event.details?.taskTitle ? event.details.taskTitle : (t(`gamification.source.${event.source}`, { defaultValue: event.source }) as string)}
{event.source === 'complete_task_late' && <span className="ml-2 text-xs text-red-500 font-normal">({t('gamification.source.complete_task_late')})</span>}
</p>
<div className="text-xs text-muted-foreground flex items-center gap-1">
<span>{new Date(event.createdAt).toLocaleString()}</span>
{event.details?.taskTitle && (
<>
<span></span>
<span>{t(`gamification.source.${event.source}`, { defaultValue: event.source })}</span>
</>
)}
</div>
</div>
</div>
<span className="font-bold text-green-600 dark:text-green-400">
+10
View File
@@ -8,6 +8,8 @@ import { useLocation } from "wouter";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { AuditLogsTable } from "@/components/admin/AuditLogsTable";
import { McpSettingsCard } from "@/components/admin/McpSettingsCard";
import { RoutineSettingsCard } from "@/components/admin/RoutineSettingsCard";
import { Clock } from "lucide-react";
export default function AdminSettings() {
const { t } = useTranslation();
@@ -41,6 +43,10 @@ export default function AdminSettings() {
<Sparkles className="h-4 w-4" />
{t('settings.admin.tabs.ai')}
</TabsTrigger>
<TabsTrigger value="routines" className="flex items-center gap-2">
<Clock className="h-4 w-4" />
{t('settings.admin.tabs.routines', 'Routines')}
</TabsTrigger>
<TabsTrigger value="mcp" className="flex items-center gap-2">
<Bot className="h-4 w-4" />
{t('settings.admin.tabs.mcp')}
@@ -59,6 +65,10 @@ export default function AdminSettings() {
<AiSettingsCard />
</TabsContent>
<TabsContent value="routines">
<RoutineSettingsCard />
</TabsContent>
<TabsContent value="mcp">
<McpSettingsCard />
</TabsContent>
+10
View File
@@ -38,11 +38,21 @@ export default function FocusRoutinePage() {
// Handlers
const handleComplete = async () => {
try {
await apiRequest("POST", `/api/user/routine/${type}/complete`);
// Invalidate user query to update lastMorningRoutine/lastEveningRoutine
await queryClient.invalidateQueries({ queryKey: ["/api/user"] });
} catch (e) {
console.error(e);
toast({ title: t('routine.error', 'Failed to save progress'), variant: 'destructive' });
}
if (type === 'morning') {
setLocation('/focus');
} else {
triggerConfetti(0.5, 0.5);
toast({ title: t('routine.dayComplete', "Day Complete! Great job.") });
// For evening, maybe logout or home? Or achievements
setLocation('/achievements');
}
};