From 59cb4822192140be604725eb9cff4c31587ebfa5 Mon Sep 17 00:00:00 2001 From: kyy Date: Fri, 8 May 2026 14:11:35 +0900 Subject: [PATCH] =?UTF-8?q?devfront=20=EC=95=B1=20=EB=AA=A9=EB=A1=9D=20?= =?UTF-8?q?=EB=A1=9C=EA=B3=A0=20=ED=91=9C=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devfront/src/features/clients/ClientsPage.tsx | 11 +--- .../clients/components/ClientLogo.tsx | 52 +++++++++++++++++++ 2 files changed, 54 insertions(+), 9 deletions(-) create mode 100644 devfront/src/features/clients/components/ClientLogo.tsx diff --git a/devfront/src/features/clients/ClientsPage.tsx b/devfront/src/features/clients/ClientsPage.tsx index 2d1fd352..bb0ebbe6 100644 --- a/devfront/src/features/clients/ClientsPage.tsx +++ b/devfront/src/features/clients/ClientsPage.tsx @@ -5,8 +5,6 @@ import { Filter, Plus, Search, - ServerCog, - ShieldHalf, X, } from "lucide-react"; import { useEffect, useState } from "react"; @@ -50,6 +48,7 @@ import { t } from "../../lib/i18n"; import { resolveProfileRole } from "../../lib/role"; import { cn } from "../../lib/utils"; import { fetchMe } from "../auth/authApi"; +import { ClientLogo } from "./components/ClientLogo"; function ClientsPage() { const navigate = useNavigate(); @@ -498,13 +497,7 @@ function ClientsPage() { to={`/clients/${client.id}`} className="flex items-center gap-3 transition-colors hover:text-primary" > -
- {client.type === "private" ? ( - - ) : ( - - )} -
+

{client.name || diff --git a/devfront/src/features/clients/components/ClientLogo.tsx b/devfront/src/features/clients/components/ClientLogo.tsx new file mode 100644 index 00000000..0c7b0a56 --- /dev/null +++ b/devfront/src/features/clients/components/ClientLogo.tsx @@ -0,0 +1,52 @@ +import { ServerCog, ShieldHalf } from "lucide-react"; +import { useMemo, useState } from "react"; +import { Avatar, AvatarFallback, AvatarImage } from "../../../components/ui/avatar"; +import type { ClientSummary, ClientType } from "../../../lib/devApi"; +import { t } from "../../../lib/i18n"; + +type ClientLogoProps = { + client: Pick; +}; + +function readLogoUrl(metadata?: Record): string | undefined { + const logoUrl = metadata?.logo_url; + if (typeof logoUrl !== "string") { + return undefined; + } + + const trimmedLogoUrl = logoUrl.trim(); + return trimmedLogoUrl.length > 0 ? trimmedLogoUrl : undefined; +} + +function TypeFallbackIcon({ type }: { type: ClientType }) { + if (type === "private") { + return