2026-06-01 16:42:36 +07:00
|
|
|
import type { ActiveSpeaker } from "../../../shared/api/client";
|
2026-06-03 03:21:20 +07:00
|
|
|
import { EmptyStateMascot, Skeleton } from "../../../shared/ui";
|
2026-06-01 16:42:36 +07:00
|
|
|
|
|
|
|
|
interface ActiveSpeakersProps {
|
|
|
|
|
speakers: ActiveSpeaker[];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function ActiveSpeakers({ speakers }: ActiveSpeakersProps) {
|
|
|
|
|
if (speakers.length === 0) {
|
2026-06-03 13:56:11 +07:00
|
|
|
return <EmptyStateMascot />;
|
2026-06-01 16:42:36 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="space-y-2">
|
|
|
|
|
{speakers.map((s) => {
|
|
|
|
|
// BUG 4 FIX: stable key — no index fallback
|
|
|
|
|
const key = s.userId ?? s.id ?? `speaker-${s.username}`;
|
|
|
|
|
return (
|
2026-06-01 21:44:29 +07:00
|
|
|
<div
|
|
|
|
|
key={key}
|
2026-06-12 23:00:52 +07:00
|
|
|
className="flex items-center gap-3 rounded-xl border border-border bg-card p-3"
|
2026-06-01 21:44:29 +07:00
|
|
|
>
|
|
|
|
|
<img
|
|
|
|
|
src={s.avatar}
|
|
|
|
|
alt=""
|
2026-06-12 23:00:52 +07:00
|
|
|
className="h-8 w-8 rounded-full object-cover ring-2 ring-primary/30"
|
2026-06-01 21:44:29 +07:00
|
|
|
/>
|
2026-06-01 16:42:36 +07:00
|
|
|
<div className="min-w-0">
|
|
|
|
|
<div className="truncate text-sm font-medium">{s.username}</div>
|
2026-06-03 03:16:06 +07:00
|
|
|
<div className="text-xs font-medium text-emerald-700">
|
|
|
|
|
Speaking
|
|
|
|
|
</div>
|
2026-06-01 16:42:36 +07:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function ActiveSpeakersSkeleton() {
|
|
|
|
|
return (
|
|
|
|
|
<div className="space-y-2">
|
|
|
|
|
{[1, 2, 3].map((i) => (
|
2026-06-01 21:44:29 +07:00
|
|
|
<div
|
|
|
|
|
key={i}
|
|
|
|
|
className="flex items-center gap-3 rounded-xl border border-border bg-background/60 p-3"
|
|
|
|
|
>
|
2026-06-01 16:42:36 +07:00
|
|
|
<Skeleton className="h-8 w-8 rounded-full" />
|
|
|
|
|
<div className="flex-1 space-y-1">
|
|
|
|
|
<Skeleton className="h-4 w-24" />
|
|
|
|
|
<Skeleton className="h-3 w-16" />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|