1
0
Fork 0
mirror of https://gitbruv.vercel.app/api/git/bruv/gitbruv.git synced 2025-12-20 23:24:09 +01:00
This commit is contained in:
Ahmet Kilinc 2025-12-20 11:53:09 +00:00
parent c768b15bd7
commit 1a8b4c881f
6 changed files with 247 additions and 69 deletions

View file

@ -11,69 +11,67 @@ type Repository = {
visibility: "public" | "private";
updatedAt: Date;
starCount?: number;
owner?: {
username: string;
name: string | null;
};
};
export function RepoList({
repos,
username,
}: {
repos: Repository[];
username: string;
}) {
export function RepoList({ repos, username }: { repos: Repository[]; username?: string }) {
return (
<div className="space-y-3">
{repos.map((repo) => (
<Link
key={repo.id}
href={`/${username}/${repo.name}`}
className="block p-5 rounded-xl border border-border bg-card hover:border-accent/50 transition-all duration-200 group"
>
<div className="flex items-start justify-between gap-4">
<div className="min-w-0 flex-1">
<div className="flex items-center gap-3 mb-1.5">
<span className="font-semibold text-accent group-hover:underline text-lg">
{repo.name}
</span>
<span
className={`inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium border ${
repo.visibility === "private"
? "border-yellow-500/30 text-yellow-500 bg-yellow-500/10"
: "border-border text-muted-foreground bg-secondary"
}`}
>
{repo.visibility === "private" ? (
<>
<Lock className="h-3 w-3" />
Private
</>
) : (
<>
<Globe className="h-3 w-3" />
Public
</>
)}
</span>
</div>
{repo.description && (
<p className="text-sm text-muted-foreground line-clamp-2 mt-2">
{repo.description}
</p>
)}
</div>
<div className="flex flex-col items-end gap-1 shrink-0 pt-1">
{typeof repo.starCount === "number" && repo.starCount > 0 && (
<div className="flex items-center gap-1 text-muted-foreground">
<Star className="h-3.5 w-3.5" />
<span className="text-xs">{repo.starCount}</span>
{repos.map((repo) => {
const ownerUsername = repo.owner?.username || username || "";
const showOwner = repo.owner && repo.owner.username !== username;
return (
<Link
key={repo.id}
href={`/${ownerUsername}/${repo.name}`}
className="block p-5 rounded-xl border border-border bg-card hover:border-accent/50 transition-all duration-200 group"
>
<div className="flex items-start justify-between gap-4">
<div className="min-w-0 flex-1">
<div className="flex items-center gap-3 mb-1.5">
<span className="font-semibold text-accent group-hover:underline text-lg">
{showOwner && <span className="text-muted-foreground font-normal">{repo.owner?.username}/</span>}
{repo.name}
</span>
<span
className={`inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium border ${
repo.visibility === "private"
? "border-yellow-500/30 text-yellow-500 bg-yellow-500/10"
: "border-border text-muted-foreground bg-secondary"
}`}
>
{repo.visibility === "private" ? (
<>
<Lock className="h-3 w-3" />
Private
</>
) : (
<>
<Globe className="h-3 w-3" />
Public
</>
)}
</span>
</div>
)}
<p className="text-xs text-muted-foreground">
{formatDistanceToNow(new Date(repo.updatedAt), { addSuffix: true })}
</p>
{repo.description && <p className="text-sm text-muted-foreground line-clamp-2 mt-2">{repo.description}</p>}
</div>
<div className="flex flex-col items-end gap-1 shrink-0 pt-1">
{typeof repo.starCount === "number" && repo.starCount > 0 && (
<div className="flex items-center gap-1 text-muted-foreground">
<Star className="h-3.5 w-3.5" />
<span className="text-xs">{repo.starCount}</span>
</div>
)}
<p className="text-xs text-muted-foreground">{formatDistanceToNow(new Date(repo.updatedAt), { addSuffix: true })}</p>
</div>
</div>
</div>
</Link>
))}
</Link>
);
})}
</div>
);
}

66
components/ui/tabs.tsx Normal file
View file

@ -0,0 +1,66 @@
"use client"
import * as React from "react"
import * as TabsPrimitive from "@radix-ui/react-tabs"
import { cn } from "@/lib/utils"
function Tabs({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.Root>) {
return (
<TabsPrimitive.Root
data-slot="tabs"
className={cn("flex flex-col gap-2", className)}
{...props}
/>
)
}
function TabsList({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.List>) {
return (
<TabsPrimitive.List
data-slot="tabs-list"
className={cn(
"bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]",
className
)}
{...props}
/>
)
}
function TabsTrigger({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.Trigger>) {
return (
<TabsPrimitive.Trigger
data-slot="tabs-trigger"
className={cn(
"data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
{...props}
/>
)
}
function TabsContent({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.Content>) {
return (
<TabsPrimitive.Content
data-slot="tabs-content"
className={cn("flex-1 outline-none", className)}
{...props}
/>
)
}
export { Tabs, TabsList, TabsTrigger, TabsContent }