import React from "react"; import { Box, Text } from "ink"; import type { Project } from "../types/index.ts"; interface ProjectItemProps { project: Project; isSelected: boolean; isCursor: boolean; } /** * Get status icon for a project */ function getStatusIcon(project: Project): { icon: string; color: string } { if (project.type === "non-git") { return { icon: "-", color: "gray" }; } if (project.type === "git-submodule") { return { icon: "○", color: "magenta" }; } if (!project.status) { return { icon: "?", color: "gray" }; } if (project.status.isDirty) { return { icon: "●", color: "yellow" }; } return { icon: "✓", color: "green" }; } /** * Format sync status badges */ function getSyncBadges(project: Project): React.ReactNode[] { const badges: React.ReactNode[] = []; if (!project.status) return badges; if (project.status.isAhead && project.status.unpushedCommits > 0) { badges.push( ↑{project.status.unpushedCommits} ); } if (project.status.isBehind && project.status.unpulledCommits > 0) { badges.push( ↓{project.status.unpulledCommits} ); } if (!project.status.hasRemote && project.type === "git") { badges.push( no-remote ); } return badges; } /** * Format the last activity date */ function formatLastActivity(date: Date | null | undefined): string { if (!date) return ""; const now = new Date(); const diff = now.getTime() - date.getTime(); const days = Math.floor(diff / (1000 * 60 * 60 * 24)); if (days === 0) return "today"; if (days === 1) return "yesterday"; if (days < 7) return `${days}d ago`; if (days < 30) return `${Math.floor(days / 7)}w ago`; if (days < 365) return `${Math.floor(days / 30)}mo ago`; return `${Math.floor(days / 365)}y ago`; } export function ProjectItem({ project, isSelected, isCursor }: ProjectItemProps) { const { icon, color } = getStatusIcon(project); const syncBadges = getSyncBadges(project); const lastActivity = formatLastActivity(project.status?.lastLocalCommit); const bgColor = isCursor ? "blue" : undefined; const textColor = isCursor ? "white" : undefined; return ( {/* Cursor indicator */} {isCursor ? ">" : " "} {/* Selection checkbox */} {isSelected ? "[x]" : "[ ]"} {/* Status icon */} {icon} {/* Project name */} {project.name} {project.status?.currentBranch && ( ⎇ {project.status.currentBranch} )} {project.type === "git-submodule" && ( (sub) )} {project.projectMarker && project.type === "non-git" && ( [{project.projectMarker}] )} {/* Sync badges */} {syncBadges.map((badge, i) => ( {badge} ))} {/* Last activity */} {lastActivity} ); }