Move src/ → apps/server/ and packages/web/ → apps/web/ to adopt standard monorepo conventions (apps/ for runnable apps, packages/ for reusable libraries). Update all config files, shared package imports, test fixtures, and documentation to reflect new paths. Key fixes: - Update workspace config to ["apps/*", "packages/*"] - Update tsconfig.json rootDir/include for apps/server/ - Add apps/web/** to vitest exclude list - Update drizzle.config.ts schema path - Fix ensure-schema.ts migration path detection (3 levels up in dev, 2 levels up in dist) - Fix tests/integration/cli-server.test.ts import paths - Update packages/shared imports to apps/server/ paths - Update all docs/ files with new paths
87 lines
2.7 KiB
TypeScript
87 lines
2.7 KiB
TypeScript
import { useState } from "react";
|
|
import { ChevronDown, ChevronRight, Plus, Minus } from "lucide-react";
|
|
import { Badge } from "@/components/ui/badge";
|
|
import type { FileDiff, DiffLine, ReviewComment } from "./types";
|
|
import { HunkRows } from "./HunkRows";
|
|
|
|
interface FileCardProps {
|
|
file: FileDiff;
|
|
comments: ReviewComment[];
|
|
onAddComment: (
|
|
filePath: string,
|
|
lineNumber: number,
|
|
lineType: DiffLine["type"],
|
|
body: string,
|
|
) => void;
|
|
onResolveComment: (commentId: string) => void;
|
|
onUnresolveComment: (commentId: string) => void;
|
|
}
|
|
|
|
export function FileCard({
|
|
file,
|
|
comments,
|
|
onAddComment,
|
|
onResolveComment,
|
|
onUnresolveComment,
|
|
}: FileCardProps) {
|
|
const [expanded, setExpanded] = useState(true);
|
|
const commentCount = comments.length;
|
|
|
|
return (
|
|
<div className="rounded-lg border border-border overflow-hidden">
|
|
{/* File header */}
|
|
<button
|
|
className="flex w-full items-center gap-2 px-3 py-2 bg-muted/50 hover:bg-muted text-left text-sm font-mono transition-colors"
|
|
onClick={() => setExpanded(!expanded)}
|
|
>
|
|
{expanded ? (
|
|
<ChevronDown className="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
|
|
) : (
|
|
<ChevronRight className="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
|
|
)}
|
|
<span className="truncate flex-1">{file.newPath}</span>
|
|
<span className="flex items-center gap-2 shrink-0 text-xs">
|
|
{file.additions > 0 && (
|
|
<span className="flex items-center gap-0.5 text-green-600">
|
|
<Plus className="h-3 w-3" />
|
|
{file.additions}
|
|
</span>
|
|
)}
|
|
{file.deletions > 0 && (
|
|
<span className="flex items-center gap-0.5 text-red-600">
|
|
<Minus className="h-3 w-3" />
|
|
{file.deletions}
|
|
</span>
|
|
)}
|
|
{commentCount > 0 && (
|
|
<Badge variant="secondary" className="text-[10px] px-1.5 py-0">
|
|
{commentCount}
|
|
</Badge>
|
|
)}
|
|
</span>
|
|
</button>
|
|
|
|
{/* Diff content */}
|
|
{expanded && (
|
|
<div className="overflow-x-auto">
|
|
<table className="w-full text-xs font-mono border-collapse">
|
|
<tbody>
|
|
{file.hunks.map((hunk, hi) => (
|
|
<HunkRows
|
|
key={hi}
|
|
hunk={hunk}
|
|
filePath={file.newPath}
|
|
comments={comments}
|
|
onAddComment={onAddComment}
|
|
onResolveComment={onResolveComment}
|
|
onUnresolveComment={onUnresolveComment}
|
|
/>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|