This commit is contained in:
2025-12-10 15:41:44 +01:00
parent fbbcf414a4
commit 6d61be9c51
22 changed files with 1721 additions and 1987 deletions

View File

@@ -2,7 +2,7 @@ import Card from '@/components/ui/Card';
import Button from '@/components/ui/Button';
import Image from 'next/image';
import type { FeedItem } from '@gridpilot/social/domain/entities/FeedItem';
import { friends } from '@gridpilot/testing-support';
import { getDriverRepository, getImageService, getSocialRepository } from '@/lib/di-container';
function timeAgo(timestamp: Date): string {
const diffMs = Date.now() - timestamp.getTime();
@@ -15,16 +15,39 @@ function timeAgo(timestamp: Date): string {
return `${diffDays} d ago`;
}
function getActor(item: FeedItem) {
async function resolveActor(item: FeedItem) {
const driverRepo = getDriverRepository();
const imageService = getImageService();
const socialRepo = getSocialRepository();
if (item.actorFriendId) {
const friend = friends.find(f => f.driverId === item.actorFriendId);
if (friend) {
return {
name: friend.displayName,
avatarUrl: friend.avatarUrl
};
// Try social graph first (friend display name/avatar)
try {
const friend = await socialRepo.getFriendByDriverId?.(item.actorFriendId);
if (friend) {
return {
name: friend.displayName ?? friend.driverName ?? `Driver ${item.actorFriendId}`,
avatarUrl: friend.avatarUrl ?? imageService.getDriverAvatar(item.actorFriendId),
};
}
} catch {
// fall through to driver lookup
}
// Fallback to driver entity + image service
try {
const driver = await driverRepo.findById(item.actorFriendId);
if (driver) {
return {
name: driver.name,
avatarUrl: imageService.getDriverAvatar(driver.id),
};
}
} catch {
// ignore and return null below
}
}
return null;
}
@@ -33,7 +56,22 @@ interface FeedItemCardProps {
}
export default function FeedItemCard({ item }: FeedItemCardProps) {
const actor = getActor(item);
const [actor, setActor] = useState<{ name: string; avatarUrl: string } | null>(null);
useEffect(() => {
let cancelled = false;
void (async () => {
const resolved = await resolveActor(item);
if (!cancelled) {
setActor(resolved);
}
})();
return () => {
cancelled = true;
};
}, [item]);
return (
<div className="flex gap-4">
@@ -68,7 +106,7 @@ export default function FeedItemCard({ item }: FeedItemCardProps) {
{timeAgo(item.timestamp)}
</span>
</div>
{(item.ctaHref && item.ctaLabel) && (
{item.ctaHref && item.ctaLabel && (
<div className="mt-3">
<Button
as="a"