mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Brain <21994759fc7a6fa6b965551d35cfd7897d262f2495467f2d78694ddcfa6a5c7e@sprout-oss.stage.blox.sqprod.co>
This commit is contained in:
@@ -15,6 +15,7 @@ import { useUsersBatchQuery } from "@/features/profile/hooks";
|
||||
import { resolveUserLabel } from "@/features/profile/lib/identity";
|
||||
import { isSafeUrl } from "@/shared/lib/url";
|
||||
import { Button } from "@/shared/ui/button";
|
||||
import { TopChromeBackdrop } from "@/shared/ui/TopChromeBackdrop";
|
||||
import { UserAvatar } from "@/shared/ui/UserAvatar";
|
||||
|
||||
function CloneUrlRow({ url }: { url: string }) {
|
||||
@@ -123,108 +124,111 @@ export function ProjectDetailScreen({ projectId }: ProjectDetailScreenProps) {
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="flex min-h-0 min-w-0 flex-1 flex-col overflow-y-auto p-4 pt-14">
|
||||
<div className="mb-4">
|
||||
<Button
|
||||
className="gap-1.5 text-muted-foreground"
|
||||
onClick={() => {
|
||||
void goProjects();
|
||||
}}
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
>
|
||||
<ArrowLeft className="h-3.5 w-3.5" />
|
||||
Back to Projects
|
||||
</Button>
|
||||
</div>
|
||||
<div className="relative flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden">
|
||||
<TopChromeBackdrop />
|
||||
<div className="flex min-h-0 min-w-0 flex-1 flex-col overflow-y-auto p-4 pt-14">
|
||||
<div className="mb-4">
|
||||
<Button
|
||||
className="gap-1.5 text-muted-foreground"
|
||||
onClick={() => {
|
||||
void goProjects();
|
||||
}}
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
>
|
||||
<ArrowLeft className="h-3.5 w-3.5" />
|
||||
Back to Projects
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="mx-auto w-full max-w-2xl space-y-6">
|
||||
<section className="space-y-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<FolderGit2 className="h-5 w-5 text-muted-foreground" />
|
||||
<h2 className="text-lg font-semibold">{project.name}</h2>
|
||||
</div>
|
||||
{project.description ? (
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{project.description}
|
||||
</p>
|
||||
<div className="mx-auto w-full max-w-2xl space-y-6">
|
||||
<section className="space-y-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<FolderGit2 className="h-5 w-5 text-muted-foreground" />
|
||||
<h2 className="text-lg font-semibold">{project.name}</h2>
|
||||
</div>
|
||||
{project.description ? (
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{project.description}
|
||||
</p>
|
||||
) : null}
|
||||
</section>
|
||||
|
||||
{project.cloneUrls.length > 0 ? (
|
||||
<section className="space-y-2">
|
||||
<h3 className="text-xs font-medium uppercase tracking-wider text-muted-foreground">
|
||||
Clone
|
||||
</h3>
|
||||
<div className="space-y-1.5">
|
||||
{project.cloneUrls.map((url) => (
|
||||
<CloneUrlRow key={url} url={url} />
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
) : null}
|
||||
|
||||
{project.webUrl && isSafeUrl(project.webUrl) ? (
|
||||
<section className="space-y-2">
|
||||
<h3 className="text-xs font-medium uppercase tracking-wider text-muted-foreground">
|
||||
Web
|
||||
</h3>
|
||||
<a
|
||||
className="inline-flex items-center gap-1.5 text-sm text-primary hover:underline"
|
||||
href={project.webUrl}
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
<ExternalLink className="h-3.5 w-3.5" />
|
||||
{project.webUrl}
|
||||
</a>
|
||||
</section>
|
||||
) : null}
|
||||
|
||||
{project.contributors.length > 0 ? (
|
||||
<section className="space-y-2">
|
||||
<h3 className="text-xs font-medium uppercase tracking-wider text-muted-foreground">
|
||||
<span className="flex items-center gap-1.5">
|
||||
<Users className="h-3.5 w-3.5" />
|
||||
Contributors ({project.contributors.length})
|
||||
</span>
|
||||
</h3>
|
||||
<div className="space-y-1.5">
|
||||
{project.contributors.map((pubkey) => {
|
||||
const label = resolveUserLabel({ pubkey, profiles });
|
||||
const avatarUrl =
|
||||
profiles?.[pubkey.toLowerCase()]?.avatarUrl ?? null;
|
||||
return (
|
||||
<div
|
||||
className="flex items-center gap-2 rounded-md bg-muted/30 px-3 py-1.5"
|
||||
key={pubkey}
|
||||
>
|
||||
<UserAvatar
|
||||
avatarUrl={avatarUrl}
|
||||
displayName={label}
|
||||
size="xs"
|
||||
/>
|
||||
<span className="truncate text-sm text-muted-foreground">
|
||||
{label}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</section>
|
||||
) : null}
|
||||
</section>
|
||||
|
||||
{project.cloneUrls.length > 0 ? (
|
||||
<section className="space-y-2">
|
||||
<h3 className="text-xs font-medium uppercase tracking-wider text-muted-foreground">
|
||||
Clone
|
||||
Details
|
||||
</h3>
|
||||
<div className="space-y-1.5">
|
||||
{project.cloneUrls.map((url) => (
|
||||
<CloneUrlRow key={url} url={url} />
|
||||
))}
|
||||
<div className="space-y-1 text-sm text-muted-foreground">
|
||||
<p>Created: {createdDate}</p>
|
||||
<p className="truncate">
|
||||
Owner: {resolveUserLabel({ pubkey: project.owner, profiles })}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
) : null}
|
||||
|
||||
{project.webUrl && isSafeUrl(project.webUrl) ? (
|
||||
<section className="space-y-2">
|
||||
<h3 className="text-xs font-medium uppercase tracking-wider text-muted-foreground">
|
||||
Web
|
||||
</h3>
|
||||
<a
|
||||
className="inline-flex items-center gap-1.5 text-sm text-primary hover:underline"
|
||||
href={project.webUrl}
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
<ExternalLink className="h-3.5 w-3.5" />
|
||||
{project.webUrl}
|
||||
</a>
|
||||
</section>
|
||||
) : null}
|
||||
|
||||
{project.contributors.length > 0 ? (
|
||||
<section className="space-y-2">
|
||||
<h3 className="text-xs font-medium uppercase tracking-wider text-muted-foreground">
|
||||
<span className="flex items-center gap-1.5">
|
||||
<Users className="h-3.5 w-3.5" />
|
||||
Contributors ({project.contributors.length})
|
||||
</span>
|
||||
</h3>
|
||||
<div className="space-y-1.5">
|
||||
{project.contributors.map((pubkey) => {
|
||||
const label = resolveUserLabel({ pubkey, profiles });
|
||||
const avatarUrl =
|
||||
profiles?.[pubkey.toLowerCase()]?.avatarUrl ?? null;
|
||||
return (
|
||||
<div
|
||||
className="flex items-center gap-2 rounded-md bg-muted/30 px-3 py-1.5"
|
||||
key={pubkey}
|
||||
>
|
||||
<UserAvatar
|
||||
avatarUrl={avatarUrl}
|
||||
displayName={label}
|
||||
size="xs"
|
||||
/>
|
||||
<span className="truncate text-sm text-muted-foreground">
|
||||
{label}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</section>
|
||||
) : null}
|
||||
|
||||
<section className="space-y-2">
|
||||
<h3 className="text-xs font-medium uppercase tracking-wider text-muted-foreground">
|
||||
Details
|
||||
</h3>
|
||||
<div className="space-y-1 text-sm text-muted-foreground">
|
||||
<p>Created: {createdDate}</p>
|
||||
<p className="truncate">
|
||||
Owner: {resolveUserLabel({ pubkey: project.owner, profiles })}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { ProjectsView } from "@/features/projects/ui/ProjectsView";
|
||||
import { TopChromeBackdrop } from "@/shared/ui/TopChromeBackdrop";
|
||||
|
||||
export function ProjectsScreen() {
|
||||
return (
|
||||
<div className="flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden">
|
||||
<div className="relative flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden">
|
||||
<TopChromeBackdrop />
|
||||
<ProjectsView />
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user