'use client';
import { memo, useMemo, useState } from 'react';
import {
IconArrowBackUp,
IconExternalLink,
IconPlus,
IconCircleFilled,
IconMinus,
IconCheck,
} from '@tabler/icons-react';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@kandev/ui/tabs';
import { Tooltip, TooltipContent, TooltipTrigger } from '@kandev/ui/tooltip';
import { LineStat } from '@/components/diff-stat';
import { useAppStore } from '@/components/state-provider';
import { useOpenSessionInEditor } from '@/hooks/use-open-session-in-editor';
import { useSessionGitStatus } from '@/hooks/use-session-git-status';
import { useGitOperations } from '@/hooks/use-git-operations';
import type { FileInfo } from '@/lib/state/store';
import { FileBrowser } from '@/components/task/file-browser';
type OpenFileTab = {
path: string;
name: string;
content: string;
};
type TaskFilesPanelProps = {
onSelectDiffPath: (path: string) => void;
onOpenFile: (file: OpenFileTab) => void;
};
const StatusIcon = ({ status }: { status: FileInfo['status'] }) => {
switch (status) {
case 'added':
case 'untracked':
return (
);
case 'modified':
return (
);
case 'deleted':
return (
);
case 'renamed':
return (
);
default:
return (
);
}
};
const splitPath = (path: string) => {
const lastSlash = path.lastIndexOf('/');
if (lastSlash === -1) return { folder: '', file: path };
return {
folder: path.slice(0, lastSlash),
file: path.slice(lastSlash + 1),
};
};
const TaskFilesPanel = memo(function TaskFilesPanel({ onSelectDiffPath, onOpenFile }: TaskFilesPanelProps) {
const [topTab, setTopTab] = useState<'diff' | 'files'>('diff');
const activeSessionId = useAppStore((state) => state.tasks.activeSessionId);
const gitStatus = useSessionGitStatus(activeSessionId);
const openEditor = useOpenSessionInEditor(activeSessionId ?? null);
const gitOps = useGitOperations(activeSessionId ?? null);
// Convert git status files to array for display
const changedFiles = useMemo(() => {
if (!gitStatus?.files || Object.keys(gitStatus.files).length === 0) {
return [];
}
return Object.values(gitStatus.files).map((file) => ({
path: file.path,
status: file.status,
staged: file.staged,
plus: file.additions,
minus: file.deletions,
oldPath: file.old_path,
}));
}, [gitStatus]);
return (
setTopTab(value as 'diff' | 'files')} className="flex-1 min-h-0">
Diff files {changedFiles.length > 0 && `(${changedFiles.length})`}
All files
{changedFiles.length === 0 ? (
No changes detected
) : (
{changedFiles.map((file) => {
const { folder, file: name } = splitPath(file.path);
return (
- onSelectDiffPath(file.path)}
>
{/* Staged indicator */}
{file.staged ? (
Staged for commit
) : (
Stage file
)}
Discard changes
Open in editor
);
})}
)}
{activeSessionId ? (
) : (
No task selected
)}
);
});
export { TaskFilesPanel };