extract components from website

This commit is contained in:
2025-12-21 13:55:31 +01:00
parent 13d8563feb
commit b52474d792
65 changed files with 3234 additions and 1361 deletions

View File

@@ -0,0 +1,46 @@
import React from 'react';
import Image from 'next/image';
import Link from 'next/link';
import { useServices } from '@/lib/services/ServiceProvider';
interface Friend {
id: string;
name: string;
country: string;
}
interface FriendPillProps {
friend: Friend;
}
function getCountryFlag(countryCode: string): string {
const code = countryCode.toUpperCase();
if (code.length === 2) {
const codePoints = [...code].map(char => 127397 + char.charCodeAt(0));
return String.fromCodePoint(...codePoints);
}
return '🏁';
}
export default function FriendPill({ friend }: FriendPillProps) {
const { mediaService } = useServices();
return (
<Link
href={`/drivers/${friend.id}`}
className="flex items-center gap-2 px-3 py-2 rounded-lg bg-iron-gray/50 border border-charcoal-outline hover:border-purple-400/30 hover:bg-iron-gray transition-all"
>
<div className="w-8 h-8 rounded-full overflow-hidden bg-gradient-to-br from-primary-blue to-purple-600">
<Image
src={mediaService.getDriverAvatar(friend.id)}
alt={friend.name}
width={32}
height={32}
className="w-full h-full object-cover"
/>
</div>
<span className="text-sm text-white">{friend.name}</span>
<span className="text-lg">{getCountryFlag(friend.country)}</span>
</Link>
);
}

View File

@@ -0,0 +1,63 @@
import React from 'react';
import { MessageCircle, Twitter, Youtube, Twitch } from 'lucide-react';
import type { DriverProfileSocialHandleViewModel } from '@/lib/view-models/DriverProfileViewModel';
interface SocialHandlesProps {
socialHandles: DriverProfileSocialHandleViewModel[];
}
function getSocialIcon(platform: DriverProfileSocialHandleViewModel['platform']) {
switch (platform) {
case 'twitter':
return Twitter;
case 'youtube':
return Youtube;
case 'twitch':
return Twitch;
case 'discord':
return MessageCircle;
}
}
function getSocialColor(platform: DriverProfileSocialHandleViewModel['platform']) {
switch (platform) {
case 'twitter':
return 'hover:text-sky-400 hover:bg-sky-400/10';
case 'youtube':
return 'hover:text-red-500 hover:bg-red-500/10';
case 'twitch':
return 'hover:text-purple-400 hover:bg-purple-400/10';
case 'discord':
return 'hover:text-indigo-400 hover:bg-indigo-400/10';
}
}
export default function SocialHandles({ socialHandles }: SocialHandlesProps) {
if (socialHandles.length === 0) return null;
return (
<div className="mt-6 pt-6 border-t border-charcoal-outline/50">
<div className="flex flex-wrap items-center gap-2">
<span className="text-sm text-gray-500 mr-2">Connect:</span>
{socialHandles.map((social) => {
const Icon = getSocialIcon(social.platform);
return (
<a
key={social.platform}
href={social.url}
target="_blank"
rel="noopener noreferrer"
className={`flex items-center gap-2 px-3 py-1.5 rounded-lg bg-iron-gray/50 border border-charcoal-outline text-gray-400 transition-all ${getSocialColor(social.platform)}`}
>
<Icon className="w-4 h-4" />
<span className="text-sm">{social.handle}</span>
<svg className="w-3 h-3 opacity-50" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
</svg>
</a>
);
})}
</div>
</div>
);
}