Files
vibe-kanban/frontend/src/components/ui-new/primitives/conversation/ChatScriptEntry.tsx
Louis Knight-Webb ea5954c8f5 Refactor WorkspacesLayout (#2052)
* init refactor

* changes context

* wip

* logs context

* workspaces layout context breakdown

* sidebar context

* move diffs to workspace context

* compress workspaces layout

* refactors

* types

* always show archived
2026-01-14 22:07:00 +00:00

94 lines
2.7 KiB
TypeScript

import { useTranslation } from 'react-i18next';
import { TerminalIcon, WrenchIcon } from '@phosphor-icons/react';
import { cn } from '@/lib/utils';
import { ToolStatus } from 'shared/types';
import { ToolStatusDot } from './ToolStatusDot';
import { useLogsPanel } from '@/contexts/LogsPanelContext';
interface ChatScriptEntryProps {
title: string;
processId: string;
exitCode?: number | null;
className?: string;
status: ToolStatus;
onFix?: () => void;
}
export function ChatScriptEntry({
title,
processId,
exitCode,
className,
status,
onFix,
}: ChatScriptEntryProps) {
const { t } = useTranslation('tasks');
const { viewProcessInPanel } = useLogsPanel();
const isRunning = status.status === 'created';
const isSuccess = status.status === 'success';
const isFailed = status.status === 'failed';
const handleFixClick = (e: React.MouseEvent) => {
e.stopPropagation();
onFix?.();
};
const handleClick = () => {
viewProcessInPanel(processId);
};
const getSubtitle = () => {
if (isRunning) {
return t('conversation.script.running');
}
if (isFailed && exitCode !== null && exitCode !== undefined) {
return t('conversation.script.exitCode', { code: exitCode });
}
if (isSuccess) {
return t('conversation.script.completedSuccessfully');
}
return t('conversation.script.clickToViewLogs');
};
return (
<div
className={cn(
'flex items-start gap-base text-sm cursor-pointer hover:bg-secondary/50 rounded-md -mx-half px-half py-half transition-colors',
className
)}
onClick={handleClick}
role="button"
tabIndex={0}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
handleClick();
}
}}
>
<span className="relative shrink-0 mt-0.5">
<TerminalIcon className="size-icon-base text-low" />
<ToolStatusDot
status={status}
className="absolute -bottom-0.5 -left-0.5"
/>
</span>
<div className="flex flex-col min-w-0 flex-1">
<span className="text-normal font-medium">{title}</span>
<span className="text-low text-xs">{getSubtitle()}</span>
</div>
{isFailed && onFix && (
<button
type="button"
onClick={handleFixClick}
className="shrink-0 flex items-center gap-1 px-2 py-1 text-xs text-brand hover:text-brand-hover hover:bg-secondary rounded transition-colors"
title={t('scriptFixer.fixScript')}
>
<WrenchIcon className="size-icon-xs" />
<span>{t('scriptFixer.fixScript')}</span>
</button>
)}
</div>
);
}