New core product layout: resizable chat + artifacts panel replaces the old wizard-only flow. Front door (create/grow), onboarding exits to chat, CEO discusses strategy before planning. Approval actions live in the artifacts pane, not inline in chat. Chat history drawer, animated paperclip thinking indicator, optimistic typing, faster polling. Rename Issue → Task across all frontend UI labels (16 files). Add global pause/resume all agents on dashboard with sidebar badge. Move toasts to bottom-right. Add Artifacts page and sidebar nav item. Reorder wizard: Mission → CEO config → Launch (exits to chat). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
75 lines
2.4 KiB
TypeScript
75 lines
2.4 KiB
TypeScript
import { useEffect } from "react";
|
|
import { useQuery } from "@tanstack/react-query";
|
|
import { issuesApi } from "../api/issues";
|
|
import { useCompany } from "../context/CompanyContext";
|
|
import { useBreadcrumbs } from "../context/BreadcrumbContext";
|
|
import { queryKeys } from "../lib/queryKeys";
|
|
import { StatusIcon } from "../components/StatusIcon";
|
|
import { PriorityIcon } from "../components/PriorityIcon";
|
|
import { EntityRow } from "../components/EntityRow";
|
|
import { EmptyState } from "../components/EmptyState";
|
|
import { PageSkeleton } from "../components/PageSkeleton";
|
|
import { formatDate } from "../lib/utils";
|
|
import { ListTodo } from "lucide-react";
|
|
|
|
export function MyIssues() {
|
|
const { selectedCompanyId } = useCompany();
|
|
const { setBreadcrumbs } = useBreadcrumbs();
|
|
|
|
useEffect(() => {
|
|
setBreadcrumbs([{ label: "My Tasks" }]);
|
|
}, [setBreadcrumbs]);
|
|
|
|
const { data: issues, isLoading, error } = useQuery({
|
|
queryKey: queryKeys.issues.list(selectedCompanyId!),
|
|
queryFn: () => issuesApi.list(selectedCompanyId!),
|
|
enabled: !!selectedCompanyId,
|
|
});
|
|
|
|
if (!selectedCompanyId) {
|
|
return <EmptyState icon={ListTodo} message="Select a company to view your tasks." />;
|
|
}
|
|
|
|
if (isLoading) {
|
|
return <PageSkeleton variant="list" />;
|
|
}
|
|
|
|
// Show issues that are not assigned (user-created or unassigned)
|
|
const myIssues = (issues ?? []).filter(
|
|
(i) => !i.assigneeAgentId && !["done", "cancelled"].includes(i.status)
|
|
);
|
|
|
|
return (
|
|
<div className="space-y-4">
|
|
{error && <p className="text-sm text-destructive">{error.message}</p>}
|
|
|
|
{myIssues.length === 0 && (
|
|
<EmptyState icon={ListTodo} message="No tasks assigned to you." />
|
|
)}
|
|
|
|
{myIssues.length > 0 && (
|
|
<div className="border border-border">
|
|
{myIssues.map((issue) => (
|
|
<EntityRow
|
|
key={issue.id}
|
|
identifier={issue.identifier ?? issue.id.slice(0, 8)}
|
|
title={issue.title}
|
|
to={`/issues/${issue.identifier ?? issue.id}`}
|
|
leading={
|
|
<>
|
|
<PriorityIcon priority={issue.priority} />
|
|
<StatusIcon status={issue.status} />
|
|
</>
|
|
}
|
|
trailing={
|
|
<span className="text-xs text-muted-foreground">
|
|
{formatDate(issue.createdAt)}
|
|
</span>
|
|
}
|
|
/>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|