feat: Complete AI Chat Agent, Admin Settings (MCP/AI), and Translations
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -31,6 +31,10 @@ import { triggerConfetti } from "@/lib/confetti";
|
||||
import { playSuccessSound } from "@/lib/sounds";
|
||||
import { simulateAIDecomposition } from "@/lib/ai-simulator";
|
||||
import { Wand2, Loader2 } from "lucide-react";
|
||||
import { apiRequest } from "@/lib/queryClient";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
|
||||
|
||||
|
||||
interface TaskCardProps {
|
||||
task: Task;
|
||||
@@ -120,6 +124,7 @@ function SharedMenuItem({ task, onShare }: { task: Task, onShare: () => void })
|
||||
|
||||
export default function TaskCard({ task, onStartTimer, onStopTimer, onEdit, onDelete, onStatusChange, onUpdate, isDragging }: TaskCardProps) {
|
||||
const { t } = useTranslation();
|
||||
const { toast } = useToast();
|
||||
const [isAnalyzing, setIsAnalyzing] = useState(false);
|
||||
const [isShareModalOpen, setIsShareModalOpen] = useState(false);
|
||||
|
||||
@@ -201,6 +206,56 @@ export default function TaskCard({ task, onStartTimer, onStopTimer, onEdit, onDe
|
||||
return `${hours}h ${mins}m`;
|
||||
};
|
||||
|
||||
/* AI Follow-up Check */
|
||||
const checkFollowUp = async () => {
|
||||
// Fire and forget - don't block UI
|
||||
try {
|
||||
const res = await apiRequest("POST", "/api/ai/analyze-completion", { taskId: task.id });
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
if (data.needed && data.title) {
|
||||
toast({
|
||||
title: t('ai.followUpSuggestion', 'Follow-up Suggested'),
|
||||
description: `${data.title} - ${data.description || ''}`,
|
||||
action: (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={async (e) => {
|
||||
e.stopPropagation(); // prevent toast click from doing generic things
|
||||
// Create the task immediately
|
||||
try {
|
||||
await apiRequest("POST", "/api/tasks", {
|
||||
title: data.title,
|
||||
description: data.description,
|
||||
status: "todo",
|
||||
priority: "medium",
|
||||
labelId: task.labelId, // Inherit label
|
||||
dueDate: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString() // Tomorrow
|
||||
});
|
||||
toast({ title: t('ai.taskCreated', 'Follow-up task created!') });
|
||||
// Invalidate queries to show new task
|
||||
// queryClient.invalidateQueries... (Need queryClient access)
|
||||
// Since we don't have queryClient here easily without import useQueryClient
|
||||
// We can just reload or rely on auto-refetch
|
||||
window.location.reload(); // Crude but effective for now, or useQueryClient
|
||||
} catch (err) {
|
||||
toast({ title: t('ai.errorCreating', 'Failed to create task'), variant: "destructive" });
|
||||
}
|
||||
}}
|
||||
>
|
||||
{t('common.create', 'Create')}
|
||||
</Button>
|
||||
),
|
||||
duration: 8000,
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Follow-up check failed", e);
|
||||
}
|
||||
};
|
||||
|
||||
const handleToggleComplete = (e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
if (isBlocked) return;
|
||||
@@ -210,6 +265,8 @@ export default function TaskCard({ task, onStartTimer, onStopTimer, onEdit, onDe
|
||||
triggerConfetti(e.clientX / window.innerWidth, e.clientY / window.innerHeight);
|
||||
playSuccessSound();
|
||||
onStatusChange?.('done');
|
||||
// Trigger AI check
|
||||
checkFollowUp();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user