website refactor
This commit is contained in:
108
apps/website/ui/CountryFlag.tsx
Normal file
108
apps/website/ui/CountryFlag.tsx
Normal file
@@ -0,0 +1,108 @@
|
||||
'use client';
|
||||
|
||||
import React, { useState } from 'react';
|
||||
|
||||
// ISO 3166-1 alpha-2 country code to full country name mapping
|
||||
const countryNames: Record<string, string> = {
|
||||
'US': 'United States',
|
||||
'GB': 'United Kingdom',
|
||||
'CA': 'Canada',
|
||||
'AU': 'Australia',
|
||||
'NZ': 'New Zealand',
|
||||
'DE': 'Germany',
|
||||
'FR': 'France',
|
||||
'IT': 'Italy',
|
||||
'ES': 'Spain',
|
||||
'NL': 'Netherlands',
|
||||
'BE': 'Belgium',
|
||||
'SE': 'Sweden',
|
||||
'NO': 'Norway',
|
||||
'DK': 'Denmark',
|
||||
'FI': 'Finland',
|
||||
'PL': 'Poland',
|
||||
'CZ': 'Czech Republic',
|
||||
'AT': 'Austria',
|
||||
'CH': 'Switzerland',
|
||||
'PT': 'Portugal',
|
||||
'IE': 'Ireland',
|
||||
'BR': 'Brazil',
|
||||
'MX': 'Mexico',
|
||||
'AR': 'Argentina',
|
||||
'JP': 'Japan',
|
||||
'CN': 'China',
|
||||
'KR': 'South Korea',
|
||||
'IN': 'India',
|
||||
'SG': 'Singapore',
|
||||
'TH': 'Thailand',
|
||||
'MY': 'Malaysia',
|
||||
'ID': 'Indonesia',
|
||||
'PH': 'Philippines',
|
||||
'ZA': 'South Africa',
|
||||
'RU': 'Russia',
|
||||
'MC': 'Monaco',
|
||||
'TR': 'Turkey',
|
||||
'GR': 'Greece',
|
||||
'HU': 'Hungary',
|
||||
'RO': 'Romania',
|
||||
'BG': 'Bulgaria',
|
||||
'HR': 'Croatia',
|
||||
'SI': 'Slovenia',
|
||||
'SK': 'Slovakia',
|
||||
'LT': 'Lithuania',
|
||||
'LV': 'Latvia',
|
||||
'EE': 'Estonia',
|
||||
};
|
||||
|
||||
// ISO 3166-1 alpha-2 country code to flag emoji conversion
|
||||
const countryCodeToFlag = (countryCode: string): string => {
|
||||
if (!countryCode || countryCode.length !== 2) return '🏁';
|
||||
|
||||
// Convert ISO 3166-1 alpha-2 to regional indicator symbols
|
||||
const codePoints = countryCode
|
||||
.toUpperCase()
|
||||
.split('')
|
||||
.map(char => 127397 + char.charCodeAt(0));
|
||||
return String.fromCodePoint(...codePoints);
|
||||
};
|
||||
|
||||
interface CountryFlagProps {
|
||||
countryCode: string;
|
||||
size?: 'sm' | 'md' | 'lg';
|
||||
className?: string;
|
||||
showTooltip?: boolean;
|
||||
}
|
||||
|
||||
export function CountryFlag({
|
||||
countryCode,
|
||||
size = 'md',
|
||||
className = '',
|
||||
showTooltip = true
|
||||
}: CountryFlagProps) {
|
||||
const [showTooltipState, setShowTooltipState] = useState(false);
|
||||
|
||||
const sizeClasses = {
|
||||
sm: 'text-xs',
|
||||
md: 'text-sm',
|
||||
lg: 'text-base'
|
||||
};
|
||||
|
||||
const flag = countryCodeToFlag(countryCode);
|
||||
const countryName = countryNames[countryCode.toUpperCase()] || countryCode;
|
||||
|
||||
return (
|
||||
<span
|
||||
className={`inline-flex items-center relative ${sizeClasses[size]} ${className}`}
|
||||
onMouseEnter={() => setShowTooltipState(true)}
|
||||
onMouseLeave={() => setShowTooltipState(false)}
|
||||
title={showTooltip ? countryName : undefined}
|
||||
>
|
||||
<span className="select-none">{flag}</span>
|
||||
{showTooltip && showTooltipState && (
|
||||
<span className="absolute bottom-full left-1/2 -translate-x-1/2 mb-1 px-2 py-1 text-xs font-medium text-white bg-deep-graphite border border-charcoal-outline rounded shadow-lg whitespace-nowrap z-50">
|
||||
{countryName}
|
||||
<span className="absolute top-full left-1/2 -translate-x-1/2 -mt-px border-4 border-transparent border-t-charcoal-outline"></span>
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user