Loading profile…
+diff --git a/public/favicon.ico b/public/favicon.ico index 4eb44dd..2744e3b 100644 Binary files a/public/favicon.ico and b/public/favicon.ico differ diff --git a/public/static/favicons/favicon-16.png b/public/static/favicons/favicon-16.png new file mode 100644 index 0000000..f86d26c Binary files /dev/null and b/public/static/favicons/favicon-16.png differ diff --git a/public/static/favicons/favicon-192.png b/public/static/favicons/favicon-192.png new file mode 100644 index 0000000..1f3b4cb Binary files /dev/null and b/public/static/favicons/favicon-192.png differ diff --git a/public/static/favicons/favicon-256.png b/public/static/favicons/favicon-256.png new file mode 100644 index 0000000..80e5881 Binary files /dev/null and b/public/static/favicons/favicon-256.png differ diff --git a/public/static/favicons/favicon-32.png b/public/static/favicons/favicon-32.png new file mode 100644 index 0000000..df578f6 Binary files /dev/null and b/public/static/favicons/favicon-32.png differ diff --git a/public/static/favicons/favicon-48.png b/public/static/favicons/favicon-48.png new file mode 100644 index 0000000..7307e00 Binary files /dev/null and b/public/static/favicons/favicon-48.png differ diff --git a/public/static/favicons/favicon-64.png b/public/static/favicons/favicon-64.png new file mode 100644 index 0000000..04b4b6b Binary files /dev/null and b/public/static/favicons/favicon-64.png differ diff --git a/public/static/favicons/favicon-96.png b/public/static/favicons/favicon-96.png new file mode 100644 index 0000000..ff49d1f Binary files /dev/null and b/public/static/favicons/favicon-96.png differ diff --git a/public/static/favicons/favicon.svg b/public/static/favicons/favicon.svg new file mode 100644 index 0000000..0952fd4 --- /dev/null +++ b/public/static/favicons/favicon.svg @@ -0,0 +1,34 @@ + + diff --git a/src/app/api/forum/user-by-username/[username]/route.ts b/src/app/api/forum/user-by-username/[username]/route.ts new file mode 100644 index 0000000..a70950a --- /dev/null +++ b/src/app/api/forum/user-by-username/[username]/route.ts @@ -0,0 +1,94 @@ +import { NextResponse } from "next/server"; +import { createClient } from "@supabase/supabase-js"; + +export const runtime = "nodejs"; +export const revalidate = 120; + +const SUPABASE_URL = process.env.NEXT_PUBLIC_SUPABASE_URL!; +const SUPABASE_ANON = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!; +const SCHEMA = process.env.NEXT_PUBLIC_SUPABASE_SCHEMA || "bb"; + +function client() { + return createClient(SUPABASE_URL, SUPABASE_ANON, { + db: { schema: SCHEMA as "public" }, + auth: { persistSession: false }, + }); +} + +export async function GET( + req: Request, + { params }: { params: Promise<{ username: string }> }, +) { + const { username } = await params; + const sb = client(); + + // 1) Profile — accept EITHER username OR display_name (URL-encoded). + // forum_threads/forum_replies store author_name = display_name, + // so the link in the UI uses the display name; we resolve it here. + const decoded = decodeURIComponent(username); + let { data: profile } = await sb + .from("forum_user_profiles") + .select("*") + .eq("username", decoded) + .maybeSingle(); + if (!profile) { + const r2 = await sb + .from("forum_user_profiles") + .select("*") + .eq("display_name", decoded) + .maybeSingle(); + profile = r2.data; + } + + if (!profile) { + return NextResponse.json({ error: "not found" }, { status: 404 }); + } + + // 2) Their threads (use display_name match since virtual users live + // outside the auth.users / bb.user_profiles graph and the + // forum_threads.author_id is NULL for them). + const displayName = (profile as any).display_name as string; + const { data: threads } = await sb + .from("forum_threads") + .select("id,title,reply_count,view_count,vote_score,created_at,category_id,forum_categories(name,slug)") + .eq("author_name", displayName) + .order("created_at", { ascending: false }) + .limit(50); + + // 3) Recent replies + const { data: replies } = await sb + .from("forum_replies") + .select("id,thread_id,body,vote_score,created_at,forum_threads(title)") + .eq("author_name", displayName) + .order("created_at", { ascending: false }) + .limit(20); + + // 4) Computed counts + const threadCount = (threads || []).length; + const replyCount = (replies || []).length; + + return NextResponse.json({ + profile: { + username: (profile as any).username, + display_name: (profile as any).display_name, + bio: (profile as any).bio || null, + avatar_url: (profile as any).avatar_url || null, + role_title: (profile as any).role_title || null, + company: (profile as any).company || null, + location_city: (profile as any).location_city || null, + location_country: (profile as any).location_country || null, + years_experience: (profile as any).years_experience || null, + ai_persona_archetype: (profile as any).ai_persona_archetype || null, + expertise_level: (profile as any).expertise_level || null, + expertise_tags: (profile as any).expertise_tags || [], + writing_voice: (profile as any).writing_voice || null, + signature: (profile as any).signature || null, + join_date: (profile as any).join_date || null, + last_seen_at: (profile as any).last_seen_at || null, + thread_count: threadCount, + reply_count: replyCount, + }, + threads: threads || [], + replies: replies || [], + }); +} diff --git a/src/app/forum/[slug]/page.tsx b/src/app/forum/[slug]/page.tsx index 0c5bc52..37ffd3d 100644 --- a/src/app/forum/[slug]/page.tsx +++ b/src/app/forum/[slug]/page.tsx @@ -144,7 +144,7 @@ function TopThreadsWidget({ categoryId }: { categoryId: string }) { {thread.title}
- {thread.author_name} + e.stopPropagation()}>{thread.author_name} {' · '}{timeAgo(thread.created_at)}
@@ -441,7 +441,7 @@ export default function ForumCategoryPage() {- by {thread.author_name} + by e.stopPropagation()}>{thread.author_name} {' · '}{timeAgo(thread.created_at)}
diff --git a/src/app/forum/page.tsx b/src/app/forum/page.tsx index 2a49009..bc41473 100644 --- a/src/app/forum/page.tsx +++ b/src/app/forum/page.tsx @@ -153,7 +153,7 @@ function TopThreadsWidget({ categoryId }: { categoryId?: string }) { {thread.title}- {thread.author_name} + e.stopPropagation()}>{thread.author_name} {thread.forum_categories && ( <> · {thread.forum_categories.name}> )} @@ -483,7 +483,7 @@ export default function ForumIndexPage() { {thread.title}
- by {thread.author_name}
+ by e.stopPropagation()}>{thread.author_name}
{thread.forum_categories && (
<> · {thread.forum_categories.name}>
)}
diff --git a/src/app/forum/thread/[id]/page.tsx b/src/app/forum/thread/[id]/page.tsx
index 0316ab2..99ccf2a 100644
--- a/src/app/forum/thread/[id]/page.tsx
+++ b/src/app/forum/thread/[id]/page.tsx
@@ -354,7 +354,7 @@ export default function ForumThreadPage() {
Loading profile…
+No forum member with username "{username}".
+ ← Back to The Crew Lounge +@{profile.username}
+ ++ {profile.bio} +
+ )} + + {profile.expertise_tags && profile.expertise_tags.length > 0 && ( +No threads yet.
+ ) : ( +No replies yet.
+ ) : ( +{r.body}
+