Skip to content

Commit d14009a

Browse files
committed
feat(submissions): link submission card avatars to profile pages
Wrap the individual avatar on SubmissionCard in a profile link and forward team-member usernames to GroupAvatar so each clustered avatar opens that user's profile in a new tab.
1 parent 3e377d4 commit d14009a

2 files changed

Lines changed: 48 additions & 10 deletions

File tree

app/(landing)/hackathons/[slug]/components/tabs/contents/submissions/SubmissionCard.tsx

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use client';
22

33
import { useState } from 'react';
4+
import Link from 'next/link';
45
import { useParams, useRouter } from 'next/navigation';
56
import { useQueryClient } from '@tanstack/react-query';
67
import { LayoutGrid, Loader2, Pencil, Trash2 } from 'lucide-react';
@@ -142,7 +143,24 @@ const SubmissionCard = ({ submission }: SubmissionCardProps) => {
142143
<div className='flex items-center justify-between gap-2 border-t border-white/5 pt-5'>
143144
<div className='flex items-center gap-3'>
144145
{isTeam ? (
145-
<GroupAvatar members={teamMembers.map(m => m.avatar ?? '')} />
146+
<GroupAvatar
147+
members={teamMembers.map(m => m.avatar ?? '')}
148+
usernames={teamMembers.map(m => m.username)}
149+
/>
150+
) : participant?.username ? (
151+
<Link
152+
href={`/profile/${participant.username}`}
153+
target='_blank'
154+
rel='noopener noreferrer'
155+
aria-label={`View @${participant.username} profile`}
156+
className='hover:opacity-90'
157+
>
158+
<BasicAvatar
159+
image={submitterAvatar}
160+
name={submitterName}
161+
username={participant.username}
162+
/>
163+
</Link>
146164
) : (
147165
<BasicAvatar
148166
image={submitterAvatar}

components/avatars/GroupAvatar.tsx

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import Link from 'next/link';
12
import {
23
Avatar,
34
AvatarFallback,
@@ -8,24 +9,43 @@ import {
89

910
interface GroupAvatarProps {
1011
members: string[];
12+
usernames?: (string | undefined)[];
1113
}
1214

13-
const GroupAvatar = ({ members }: GroupAvatarProps) => {
15+
const GroupAvatar = ({ members, usernames }: GroupAvatarProps) => {
1416
const showCount = members.length > 3;
1517
const maxVisible = showCount ? 3 : members.length;
1618
const visibleMembers = members.slice(0, maxVisible);
1719
const remainingCount = members.length - maxVisible;
1820

1921
return (
2022
<AvatarGroup>
21-
{visibleMembers.map((member, index) => (
22-
<Avatar key={index} className='size-8 border-none! sm:size-6'>
23-
<AvatarImage src={member} alt={`Member ${index + 1}`} />
24-
<AvatarFallback className='bg-[#1E2329] text-[10px] text-white'>
25-
{member.slice(0, 2).toUpperCase()}
26-
</AvatarFallback>
27-
</Avatar>
28-
))}
23+
{visibleMembers.map((member, index) => {
24+
const username = usernames?.[index];
25+
const avatar = (
26+
<Avatar className='size-8 border-none! sm:size-6'>
27+
<AvatarImage src={member} alt={`Member ${index + 1}`} />
28+
<AvatarFallback className='bg-[#1E2329] text-[10px] text-white'>
29+
{member.slice(0, 2).toUpperCase()}
30+
</AvatarFallback>
31+
</Avatar>
32+
);
33+
if (username) {
34+
return (
35+
<Link
36+
key={index}
37+
href={`/profile/${username}`}
38+
target='_blank'
39+
rel='noopener noreferrer'
40+
aria-label={`View @${username} profile`}
41+
className='hover:ring-primary/40 rounded-full transition-all hover:ring-2'
42+
>
43+
{avatar}
44+
</Link>
45+
);
46+
}
47+
return <div key={index}>{avatar}</div>;
48+
})}
2949
{remainingCount > 0 && (
3050
<AvatarGroupCount className='bg-background text-foreground ring-border size-8 text-xs font-bold ring-2 sm:size-6 sm:text-xs'>
3151
+{remainingCount}

0 commit comments

Comments
 (0)