phase 3 initial completion

This commit is contained in:
2026-05-07 00:22:45 +02:00
parent 5d8662595c
commit ce2aa2c776
19 changed files with 1216 additions and 37 deletions
@@ -0,0 +1,56 @@
import { Link } from 'react-router-dom'
import type { Repository } from '../../types/api'
interface RepoCardProps {
repo: Repository
}
export function RepoCard({ repo }: RepoCardProps) {
const ago = timeAgo(repo.updatedAt)
return (
<Link
to={`/repos/${repo.ownerId}/${repo.name}`}
className="flex items-start gap-4 p-4 border border-[#DFE1E6] rounded hover:border-[#4C9AFF] hover:bg-[#FAFBFC] transition-colors group"
>
{/* Icon */}
<div className="flex items-center justify-center w-9 h-9 rounded bg-[#0052CC]/10 text-[#0052CC] shrink-0">
<svg width="18" height="18" fill="none" stroke="currentColor" strokeWidth="1.5" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" d="M3.75 9.776c.112-.017.227-.026.344-.026h15.812c.117 0 .232.009.344.026m-16.5 0a2.25 2.25 0 0 0-1.883 2.542l.857 6a2.25 2.25 0 0 0 2.227 1.932H19.05a2.25 2.25 0 0 0 2.227-1.932l.857-6a2.25 2.25 0 0 0-1.883-2.542m-16.5 0V6A2.25 2.25 0 0 1 6 3.75h3.879a1.5 1.5 0 0 1 1.06.44l2.122 2.12a1.5 1.5 0 0 0 1.06.44H18A2.25 2.25 0 0 1 20.25 9v.776" />
</svg>
</div>
{/* Info */}
<div className="flex-1 min-w-0">
<div className="flex items-center gap-2 flex-wrap">
<span className="text-sm font-semibold text-[#0052CC] group-hover:underline truncate">
{repo.name}
</span>
{repo.isPrivate && (
<span className="text-[10px] font-medium px-1.5 py-0.5 rounded-full border border-[#DFE1E6] text-[#5E6C84] shrink-0">
Private
</span>
)}
</div>
{repo.description && (
<p className="text-xs text-[#5E6C84] mt-0.5 truncate">{repo.description}</p>
)}
<p className="text-xs text-[#5E6C84] mt-1">
Updated {ago} · {repo.defaultBranch}
</p>
</div>
</Link>
)
}
function timeAgo(iso: string): string {
const diff = Date.now() - new Date(iso).getTime()
const m = Math.floor(diff / 60000)
if (m < 1) return 'just now'
if (m < 60) return `${m}m ago`
const h = Math.floor(m / 60)
if (h < 24) return `${h}h ago`
const d = Math.floor(h / 24)
if (d < 30) return `${d}d ago`
return new Date(iso).toLocaleDateString()
}