fix(forum): complete member profiles — counts, avatars, strip AI metadata
This commit is contained in:
@@ -21,11 +21,17 @@ interface ForumCategory {
|
||||
last_activity_at?: string | null;
|
||||
}
|
||||
|
||||
function profileHref(thread: { author_username?: string | null; author_name: string }): string {
|
||||
const slug = thread.author_username || thread.author_name;
|
||||
return `/forum/user/${encodeURIComponent(slug)}`;
|
||||
}
|
||||
|
||||
interface ForumThread {
|
||||
id: string;
|
||||
title: string;
|
||||
author_id?: string | null;
|
||||
author_name: string;
|
||||
author_username?: string | null;
|
||||
reply_count: number;
|
||||
view_count: number;
|
||||
last_reply_at: string;
|
||||
@@ -175,7 +181,7 @@ function TopThreadsWidget({ categoryId }: { categoryId?: string }) {
|
||||
{thread.title}
|
||||
</p>
|
||||
<p className="text-[#475569] font-body text-xs mt-0.5">
|
||||
<Link href={`/forum/user/${encodeURIComponent(thread.author_name)}`} className="text-[#475569] hover:text-[#1D4ED8] hover:underline" onClick={(e) => e.stopPropagation()}>{thread.author_name}</Link>
|
||||
<Link href={profileHref(thread)} className="text-[#475569] hover:text-[#1D4ED8] hover:underline" onClick={(e) => e.stopPropagation()}>{thread.author_name}</Link>
|
||||
{thread.forum_categories && (
|
||||
<> · <span className="text-[#1D4ED8]">{thread.forum_categories.name}</span></>
|
||||
)}
|
||||
@@ -407,7 +413,7 @@ export default function ForumIndexPage() {
|
||||
<p className="text-[#666] font-body text-xs mt-0.5">
|
||||
by{' '}
|
||||
<Link
|
||||
href={`/profile/${thread.author_id}`}
|
||||
href={profileHref(thread)}
|
||||
onClick={e => e.stopPropagation()}
|
||||
className="text-[#1D4ED8] hover:underline"
|
||||
>
|
||||
@@ -530,7 +536,7 @@ export default function ForumIndexPage() {
|
||||
{thread.title}
|
||||
</h3>
|
||||
<p className="text-[#666] font-body text-xs mt-0.5">
|
||||
by <Link href={`/forum/user/${encodeURIComponent(thread.author_name)}`} className="text-[#888] hover:text-[#1D4ED8] hover:underline" onClick={(e) => e.stopPropagation()}>{thread.author_name}</Link>
|
||||
by <Link href={profileHref(thread)} className="text-[#888] hover:text-[#1D4ED8] hover:underline" onClick={(e) => e.stopPropagation()}>{thread.author_name}</Link>
|
||||
{thread.forum_categories && (
|
||||
<> · <span className="text-[#1D4ED8]">{thread.forum_categories.name}</span></>
|
||||
)}
|
||||
|
||||
@@ -26,11 +26,17 @@ function InThreadAd({ adIndex }: { adIndex: number }) {
|
||||
);
|
||||
}
|
||||
|
||||
function profileHref(author: { author_username?: string | null; author_name: string }): string {
|
||||
const slug = author.author_username || author.author_name;
|
||||
return `/forum/user/${encodeURIComponent(slug)}`;
|
||||
}
|
||||
|
||||
interface ForumThread {
|
||||
id: string;
|
||||
title: string;
|
||||
body: string;
|
||||
author_name: string;
|
||||
author_username?: string | null;
|
||||
status: string;
|
||||
reply_count: number;
|
||||
view_count: number;
|
||||
@@ -45,7 +51,7 @@ interface ForumReply {
|
||||
id: string;
|
||||
body: string;
|
||||
author_name: string;
|
||||
is_ai_response: boolean;
|
||||
author_username?: string | null;
|
||||
upvotes: number;
|
||||
downvotes: number;
|
||||
vote_score: number;
|
||||
@@ -322,7 +328,7 @@ export default function ForumThreadPage() {
|
||||
<Avatar name={thread.author_name} />
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<Link href={`/forum/user/${encodeURIComponent(thread.author_name)}`} className="text-white font-body font-semibold text-sm hover:text-[#1D4ED8] hover:underline">{thread.author_name}</Link>
|
||||
<Link href={profileHref(thread)} className="text-white font-body font-semibold text-sm hover:text-[#1D4ED8] hover:underline">{thread.author_name}</Link>
|
||||
<span className="text-[#555] font-body text-xs">·</span>
|
||||
<span className="text-[#555] font-body text-xs">{timeAgo(thread.created_at)}</span>
|
||||
<span className="text-[#555] font-body text-xs">·</span>
|
||||
@@ -353,7 +359,7 @@ export default function ForumThreadPage() {
|
||||
<Avatar name={reply.author_name} />
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center gap-2 mb-2 flex-wrap">
|
||||
<Link href={`/forum/user/${encodeURIComponent(reply.author_name)}`} className="text-white font-body font-semibold text-sm hover:text-[#1D4ED8] hover:underline">{reply.author_name}</Link>
|
||||
<Link href={profileHref(reply)} className="text-white font-body font-semibold text-sm hover:text-[#1D4ED8] hover:underline">{reply.author_name}</Link>
|
||||
<span className="text-[#555] font-body text-xs">·</span>
|
||||
<span className="text-[#555] font-body text-xs">#{idx + 1}</span>
|
||||
<span className="text-[#555] font-body text-xs">·</span>
|
||||
|
||||
@@ -17,15 +17,14 @@ interface ForumUserProfile {
|
||||
location_city: string | null;
|
||||
location_country: string | null;
|
||||
years_experience: number | null;
|
||||
ai_persona_archetype: string | null;
|
||||
expertise_level: string | null;
|
||||
expertise_tags: string[];
|
||||
writing_voice: string | null;
|
||||
signature: string | null;
|
||||
join_date: string | null;
|
||||
last_seen_at: string | null;
|
||||
thread_count: number;
|
||||
reply_count: number;
|
||||
post_count: number;
|
||||
}
|
||||
|
||||
interface UserThread {
|
||||
@@ -47,22 +46,6 @@ interface UserReply {
|
||||
forum_threads?: { title: string };
|
||||
}
|
||||
|
||||
const ARCHETYPE_LABELS: Record<string, string> = {
|
||||
audio_engineer: "Audio Engineer",
|
||||
motion_designer: "Motion Designer",
|
||||
broadcast_engineer: "Broadcast Engineer",
|
||||
colorist: "Colorist",
|
||||
editor: "Editor",
|
||||
vfx_artist: "VFX Artist",
|
||||
camera_operator: "Camera Operator",
|
||||
lighting_designer: "Lighting Designer",
|
||||
post_supervisor: "Post Supervisor",
|
||||
gear_specialist: "Gear Specialist",
|
||||
livestream_producer: "Livestream Producer",
|
||||
generalist: "Generalist",
|
||||
video_editor: "Video Editor",
|
||||
};
|
||||
|
||||
function fmtDate(iso: string | null): string {
|
||||
if (!iso) return "—";
|
||||
try {
|
||||
@@ -134,7 +117,6 @@ export default function ForumUserPage() {
|
||||
|
||||
const { profile, threads, replies } = data;
|
||||
const location = [profile.location_city, profile.location_country].filter(Boolean).join(", ");
|
||||
const archetypeLabel = profile.ai_persona_archetype ? (ARCHETYPE_LABELS[profile.ai_persona_archetype] || profile.ai_persona_archetype) : null;
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -171,11 +153,6 @@ export default function ForumUserPage() {
|
||||
<p className="font-body text-sm text-[#1D4ED8] mt-0.5">@{profile.username}</p>
|
||||
|
||||
<div className="flex flex-wrap items-center gap-2 mt-3">
|
||||
{archetypeLabel && (
|
||||
<span className="font-body text-[10px] font-bold uppercase tracking-wider text-[#10b981] bg-[#10b981]/10 border border-[#10b981]/40 px-2 py-1 rounded-sm">
|
||||
{archetypeLabel}
|
||||
</span>
|
||||
)}
|
||||
{profile.expertise_level && (
|
||||
<span className="font-body text-[10px] font-bold uppercase tracking-wider text-[#a78bfa] bg-[#a78bfa]/10 border border-[#a78bfa]/40 px-2 py-1 rounded-sm">
|
||||
{profile.expertise_level}
|
||||
@@ -271,6 +248,7 @@ export default function ForumUserPage() {
|
||||
<dl className="text-sm space-y-2">
|
||||
<div><dt className="text-[#666] text-[11px] uppercase tracking-wider">Role</dt><dd className="text-[#0F172A]">{profile.role_title || "—"}</dd></div>
|
||||
{profile.company && <div><dt className="text-[#666] text-[11px] uppercase tracking-wider">Company</dt><dd className="text-[#0F172A]">{profile.company}</dd></div>}
|
||||
<div><dt className="text-[#666] text-[11px] uppercase tracking-wider">Posts</dt><dd className="text-[#0F172A]">{profile.post_count}</dd></div>
|
||||
<div><dt className="text-[#666] text-[11px] uppercase tracking-wider">Threads</dt><dd className="text-[#0F172A]">{profile.thread_count}</dd></div>
|
||||
<div><dt className="text-[#666] text-[11px] uppercase tracking-wider">Replies</dt><dd className="text-[#0F172A]">{profile.reply_count}</dd></div>
|
||||
{profile.years_experience && <div><dt className="text-[#666] text-[11px] uppercase tracking-wider">Years in industry</dt><dd className="text-[#0F172A]">{profile.years_experience}</dd></div>}
|
||||
|
||||
Reference in New Issue
Block a user