From 61fdd3329f7ac177abc8eed2f94a80b3ee603617 Mon Sep 17 00:00:00 2001 From: igm Date: Mon, 12 Jan 2026 12:34:23 +0800 Subject: [PATCH] Add OrgAvatar component and frontend-utils package - Create @reviq/frontend-utils package for frontend-specific utilities - Add OrgAvatar component with size variants (xs, sm, md, lg, xl) - Display org initials with deterministic colors when no logo available - Add getOrgInitials and getOrgColor utility functions - Update org-switcher and all org display pages to use OrgAvatar - Add noNonNullAssertion lint rule as error in biome.jsonc Co-Authored-By: Claude Opus 4.5 --- apps/publisher-dashboard/package.json | 1 + .../layout/dashboard/org-switcher.svelte | 44 +++++----- .../src/lib/components/org/index.ts | 1 + .../src/lib/components/org/org-avatar.svelte | 46 ++++++++++ .../org-invites/[inviteId]/+page.svelte | 14 +-- .../src/routes/admin/orgs/[slug]/+page.svelte | 17 +--- .../src/routes/dashboard/+page.svelte | 26 +----- .../src/routes/dashboard/[slug]/+page.svelte | 15 +--- biome.jsonc | 7 ++ bun.lock | 14 +++ packages/frontend-utils/eslint.config.js | 15 ++++ packages/frontend-utils/package.json | 26 ++++++ packages/frontend-utils/src/index.ts | 1 + packages/frontend-utils/src/org.test.ts | 68 +++++++++++++++ packages/frontend-utils/src/org.ts | 86 +++++++++++++++++++ packages/frontend-utils/tsconfig.json | 6 ++ 16 files changed, 303 insertions(+), 84 deletions(-) create mode 100644 apps/publisher-dashboard/src/lib/components/org/org-avatar.svelte create mode 100644 packages/frontend-utils/eslint.config.js create mode 100644 packages/frontend-utils/package.json create mode 100644 packages/frontend-utils/src/index.ts create mode 100644 packages/frontend-utils/src/org.test.ts create mode 100644 packages/frontend-utils/src/org.ts create mode 100644 packages/frontend-utils/tsconfig.json diff --git a/apps/publisher-dashboard/package.json b/apps/publisher-dashboard/package.json index 2bad62f..b39e59a 100644 --- a/apps/publisher-dashboard/package.json +++ b/apps/publisher-dashboard/package.json @@ -16,6 +16,7 @@ "@orpc/contract": "^1.13.2", "@reviq/api-contract": "workspace:*", "@reviq/common": "workspace:*", + "@reviq/frontend-utils": "workspace:*", "@simplewebauthn/browser": "^13.2.2", "@tanstack/svelte-query": "^6.0.14", "@tanstack/svelte-query-devtools": "^6.0.3", diff --git a/apps/publisher-dashboard/src/lib/components/layout/dashboard/org-switcher.svelte b/apps/publisher-dashboard/src/lib/components/layout/dashboard/org-switcher.svelte index ebdcf0a..cff3453 100644 --- a/apps/publisher-dashboard/src/lib/components/layout/dashboard/org-switcher.svelte +++ b/apps/publisher-dashboard/src/lib/components/layout/dashboard/org-switcher.svelte @@ -1,9 +1,11 @@ @@ -30,17 +33,24 @@ function handleOrgSelect(slug: string) { {/snippet} @@ -59,18 +69,10 @@ function handleOrgSelect(slug: string) { class={cn(isActive && "bg-accent")} >
- {#if org.logoUrl} - - {:else} -
- {org.displayName.charAt(0).toUpperCase()} -
- {/if} + {org.displayName} {#if isActive} - - - + {/if}
diff --git a/apps/publisher-dashboard/src/lib/components/org/index.ts b/apps/publisher-dashboard/src/lib/components/org/index.ts index fe866d0..003e996 100644 --- a/apps/publisher-dashboard/src/lib/components/org/index.ts +++ b/apps/publisher-dashboard/src/lib/components/org/index.ts @@ -1,2 +1,3 @@ export { default as ConfirmDialog } from "./confirm-dialog.svelte"; +export { default as OrgAvatar } from "./org-avatar.svelte"; export { default as RoleBadge } from "./role-badge.svelte"; diff --git a/apps/publisher-dashboard/src/lib/components/org/org-avatar.svelte b/apps/publisher-dashboard/src/lib/components/org/org-avatar.svelte new file mode 100644 index 0000000..4ea4103 --- /dev/null +++ b/apps/publisher-dashboard/src/lib/components/org/org-avatar.svelte @@ -0,0 +1,46 @@ + + +{#if org?.logoUrl} + {org.displayName} logo +{:else} +
+ {initials} +
+{/if} diff --git a/apps/publisher-dashboard/src/routes/account/org-invites/[inviteId]/+page.svelte b/apps/publisher-dashboard/src/routes/account/org-invites/[inviteId]/+page.svelte index 9d9e9b7..844e99c 100644 --- a/apps/publisher-dashboard/src/routes/account/org-invites/[inviteId]/+page.svelte +++ b/apps/publisher-dashboard/src/routes/account/org-invites/[inviteId]/+page.svelte @@ -2,7 +2,6 @@ import { AlertCircle, ArrowLeft, - Building2, Calendar, CheckCircle2, Clock, @@ -21,6 +20,7 @@ import { goto } from "$app/navigation"; import { resolve } from "$app/paths"; import { page } from "$app/state"; import { api } from "$lib/api/client"; +import { OrgAvatar } from "$lib/components/org"; import { Alert, AlertDescription } from "$lib/components/ui/alert"; import { Button } from "$lib/components/ui/button"; import { @@ -121,17 +121,7 @@ function isExpiringSoon(expiresAt: Date): boolean {
- {#if invite.org.logoUrl} - {invite.org.displayName} logo - {:else} -
- -
- {/if} +
{invite.org.displayName} diff --git a/apps/publisher-dashboard/src/routes/admin/orgs/[slug]/+page.svelte b/apps/publisher-dashboard/src/routes/admin/orgs/[slug]/+page.svelte index 15f8377..f5e90a8 100644 --- a/apps/publisher-dashboard/src/routes/admin/orgs/[slug]/+page.svelte +++ b/apps/publisher-dashboard/src/routes/admin/orgs/[slug]/+page.svelte @@ -3,7 +3,6 @@ import { AlertCircle, AlertTriangle, ArrowLeft, - Building, Globe, Loader2, Plus, @@ -17,7 +16,7 @@ import { resolve } from "$app/paths"; import { page } from "$app/state"; import { api } from "$lib/api/client"; import { AdminLayout } from "$lib/components/layout"; -import { ConfirmDialog } from "$lib/components/org"; +import { ConfirmDialog, OrgAvatar } from "$lib/components/org"; import { Alert, AlertDescription } from "$lib/components/ui/alert"; import { Button } from "$lib/components/ui/button"; import { @@ -259,19 +258,7 @@ async function executeConfirmAction() {
- {#if org.logoUrl} - {org.displayName} logo - {:else} -
- -
- {/if} +
{org.displayName}

diff --git a/apps/publisher-dashboard/src/routes/dashboard/+page.svelte b/apps/publisher-dashboard/src/routes/dashboard/+page.svelte index 1a7667c..a8a94b5 100644 --- a/apps/publisher-dashboard/src/routes/dashboard/+page.svelte +++ b/apps/publisher-dashboard/src/routes/dashboard/+page.svelte @@ -11,6 +11,7 @@ import { createQuery } from "@tanstack/svelte-query"; import { resolve } from "$app/paths"; import { api } from "$lib/api/client"; import { DashboardLayout } from "$lib/components/layout"; +import { OrgAvatar } from "$lib/components/org"; import { Badge } from "$lib/components/ui/badge"; import { Card, @@ -70,17 +71,7 @@ $effect(() => {

- {#if invite.org.logoUrl} - {invite.org.displayName} logo - {:else} -
- -
- {/if} +
{invite.org.displayName} @@ -154,18 +145,7 @@ $effect(() => {
- - {#if org.logoUrl} - {org.displayName} logo - {:else} -
- -
- {/if} +
{org.displayName} diff --git a/apps/publisher-dashboard/src/routes/dashboard/[slug]/+page.svelte b/apps/publisher-dashboard/src/routes/dashboard/[slug]/+page.svelte index 91cd8f1..967c81f 100644 --- a/apps/publisher-dashboard/src/routes/dashboard/[slug]/+page.svelte +++ b/apps/publisher-dashboard/src/routes/dashboard/[slug]/+page.svelte @@ -1,7 +1,6 @@