Skip to content

Commit 55c59f6

Browse files
committed
feat: add registrants avatar
1 parent 3045548 commit 55c59f6

File tree

7 files changed

+41
-39
lines changed

7 files changed

+41
-39
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ The architecture of this project revolves around a streamlined development and d
3232
- [x] Add auth with lucia
3333
- [x] Workshop creation
3434
- [x] Edit workshop
35+
- [x] Complete workshop page
3536
- [ ] Interactive workshop session(e.g video conferencing, live chat code editor)
3637
- [x] Delete workshop
3738
- [x] Participant registration

src/app/(app)/_components/user-dropdown.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export function UserDropdown({ user }: UserDropdownProps) {
3838
<DropdownMenuTrigger asChild>
3939
<Button variant="secondary" className="size-8 rounded-full">
4040
<Avatar className="size-8">
41-
<AvatarImage src={user.image} />
41+
<AvatarImage src={user.image} alt={`@${user.username}`} />
4242
<AvatarFallback>{initial}</AvatarFallback>
4343
</Avatar>
4444
</Button>
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,33 @@
1-
import { getWorkshopRegistrants } from "@/server/data/workshop"
1+
import { type getWorkshopRegistrants } from "@/server/data/registration"
2+
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
23

34
interface WorkshopRegistrantsProps {
4-
workshopId: string
5+
registrants: Awaited<ReturnType<typeof getWorkshopRegistrants>>
56
}
67

7-
export async function WorkshopRegistrants({
8-
workshopId,
9-
}: WorkshopRegistrantsProps) {
10-
const registrants = await getWorkshopRegistrants(workshopId)
8+
export function WorkshopRegistrants({ registrants }: WorkshopRegistrantsProps) {
9+
const displayedRegistrants = registrants.slice(0, 4)
10+
const extraRegistrantsCount = registrants.length - displayedRegistrants.length
1111

12-
if (!registrants.length) {
13-
return
14-
}
12+
return (
13+
<div className="flex -space-x-4 rtl:space-x-reverse">
14+
{displayedRegistrants.map((registrant) => (
15+
<Avatar key={registrant.id}>
16+
<AvatarImage
17+
src={registrant.image ?? ""}
18+
alt={`@${registrant.username}`}
19+
/>
20+
<AvatarFallback>
21+
{registrant.username?.charAt(0) ?? "R"}
22+
</AvatarFallback>
23+
</Avatar>
24+
))}
1525

16-
if (registrants.length <= 3) {
17-
return <></>
18-
}
19-
20-
return <></>
26+
{extraRegistrantsCount && (
27+
<div className="z-50 flex size-10 items-center justify-center rounded-full bg-muted text-xs font-medium text-white">
28+
+{extraRegistrantsCount}
29+
</div>
30+
)}
31+
</div>
32+
)
2133
}

src/app/(app)/workshop/[workshopId]/loading.tsx

+5
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ export default function WorkshopLoading() {
3232
/>
3333
<Skeleton className="h-5 w-10" />
3434
</div>
35+
<div className="flex -space-x-4 rtl:space-x-reverse">
36+
{Array.from({ length: 4 }).map((_, i) => (
37+
<Skeleton key={i} className="size-10 rounded-full" />
38+
))}
39+
</div>
3540
</div>
3641

3742
<Separator />

src/app/(app)/workshop/[workshopId]/page.tsx

+3-4
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ import { env } from "@/env"
55
import { eq } from "drizzle-orm"
66

77
import { redirects } from "@/config/constants"
8+
import { getWorkshopRegistrants } from "@/server/data/registration"
89
import { getUserSession } from "@/server/data/user"
9-
import { getWorkshop, getWorkshopRegistrants } from "@/server/data/workshop"
10+
import { getWorkshop } from "@/server/data/workshop"
1011
import { db } from "@/server/db"
1112
import { workshops } from "@/server/db/schema"
1213
import { getExactScheduled } from "@/utils/format-scheduled-date"
@@ -113,9 +114,7 @@ export default async function WorkshopPage({ params }: WorkshopPageProps) {
113114
</p>
114115
</div>
115116

116-
<React.Suspense>
117-
<WorkshopRegistrants workshopId={workshop.id} />
118-
</React.Suspense>
117+
<WorkshopRegistrants registrants={registrants} />
119118
</div>
120119

121120
<Separator />

src/server/data/registration.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,18 @@ import { eq } from "drizzle-orm"
66
import { db } from "../db"
77
import { registrations, users } from "../db/schema"
88

9-
export async function getWorkshopRegistrants(workshopId: string) {
9+
export async function getWorkshopRegistrants(currentWorkshopId: string) {
1010
noStore()
1111
try {
12-
await db
12+
return await db
1313
.select({
1414
id: users.id,
15+
username: users.username,
1516
image: users.image,
1617
})
1718
.from(registrations)
1819
.innerJoin(users, eq(registrations.registrantId, users.id))
19-
.where(eq(registrations.workshopId, workshopId))
20+
.where(eq(registrations.workshopId, currentWorkshopId))
2021
} catch (err) {
2122
return []
2223
}

src/server/data/workshop.ts

+1-17
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
import { asc, eq } from "drizzle-orm"
88

99
import { db } from "../db"
10-
import { registrations, users, workshops } from "../db/schema"
10+
import { users, workshops } from "../db/schema"
1111

1212
export async function getWorkshop(workshopId: string) {
1313
try {
@@ -70,22 +70,6 @@ export async function getWorkshops() {
7070
}
7171
}
7272

73-
export async function getWorkshopRegistrants(currentWorkshopId: string) {
74-
noStore()
75-
try {
76-
return await db
77-
.select({
78-
id: users.id,
79-
image: users.image,
80-
})
81-
.from(registrations)
82-
.innerJoin(users, eq(registrations.registrantId, users.id))
83-
.where(eq(registrations.workshopId, currentWorkshopId))
84-
} catch (err) {
85-
return []
86-
}
87-
}
88-
8973
export async function getWorkshopOrganizer(organizerId: string) {
9074
return await cache(async () => {
9175
return await db.query.users.findFirst({

0 commit comments

Comments
 (0)