Files
heygermany-e2e-mrg1d1zl/apps/website/components/company/CandidateProfileAvatar.tsx
e2e 59b4a7a404
Some checks failed
Main / Setup and Test (push) Has been cancelled
Main / Build Website (push) Has been cancelled
chore: heygermany customer project
2026-07-11 09:21:21 +02:00

219 lines
4.7 KiB
TypeScript

'use client'
import { Box } from '@pikku/mantine/core'
import { IconUser } from '@tabler/icons-react'
import { useEffect, useState } from 'react'
const countryCodeToEmoji: Record<string, string> = {
AFG: '🇦🇫',
ALB: '🇦🇱',
DZA: '🇩🇿',
AND: '🇦🇩',
AGO: '🇦🇴',
ARG: '🇦🇷',
ARM: '🇦🇲',
AUS: '🇦🇺',
AUT: '🇦🇹',
AZE: '🇦🇿',
BHR: '🇧🇭',
BGD: '🇧🇩',
BLR: '🇧🇾',
BEL: '🇧🇪',
BIH: '🇧🇦',
BOL: '🇧🇴',
BRA: '🇧🇷',
BGR: '🇧🇬',
KHM: '🇰🇭',
CMR: '🇨🇲',
CAN: '🇨🇦',
CHL: '🇨🇱',
CHN: '🇨🇳',
COL: '🇨🇴',
CRI: '🇨🇷',
HRV: '🇭🇷',
CUB: '🇨🇺',
CYP: '🇨🇾',
CZE: '🇨🇿',
DNK: '🇩🇰',
ECU: '🇪🇨',
EGY: '🇪🇬',
SLV: '🇸🇻',
EST: '🇪🇪',
ETH: '🇪🇹',
FIN: '🇫🇮',
FRA: '🇫🇷',
GEO: '🇬🇪',
DEU: '🇩🇪',
GHA: '🇬🇭',
GRC: '🇬🇷',
GTM: '🇬🇹',
HND: '🇭🇳',
HUN: '🇭🇺',
ISL: '🇮🇸',
IND: '🇮🇳',
IDN: '🇮🇩',
IRN: '🇮🇷',
IRQ: '🇮🇶',
IRL: '🇮🇪',
ISR: '🇮🇱',
ITA: '🇮🇹',
JPN: '🇯🇵',
JOR: '🇯🇴',
KAZ: '🇰🇿',
KEN: '🇰🇪',
KWT: '🇰🇼',
KGZ: '🇰🇬',
LAO: '🇱🇦',
LVA: '🇱🇻',
LBN: '🇱🇧',
LBY: '🇱🇾',
LTU: '🇱🇹',
LUX: '🇱🇺',
MYS: '🇲🇾',
MEX: '🇲🇽',
MDA: '🇲🇩',
MNG: '🇲🇳',
MNE: '🇲🇪',
MAR: '🇲🇦',
NPL: '🇳🇵',
NLD: '🇳🇱',
NZL: '🇳🇿',
NIC: '🇳🇮',
NGA: '🇳🇬',
MKD: '🇲🇰',
NOR: '🇳🇴',
OMN: '🇴🇲',
PAK: '🇵🇰',
PAN: '🇵🇦',
PRY: '🇵🇾',
PER: '🇵🇪',
PHL: '🇵🇭',
POL: '🇵🇱',
PRT: '🇵🇹',
QAT: '🇶🇦',
ROU: '🇷🇴',
RUS: '🇷🇺',
SAU: '🇸🇦',
SRB: '🇷🇸',
SGP: '🇸🇬',
SVK: '🇸🇰',
SVN: '🇸🇮',
ZAF: '🇿🇦',
KOR: '🇰🇷',
ESP: '🇪🇸',
LKA: '🇱🇰',
SDN: '🇸🇩',
SWE: '🇸🇪',
CHE: '🇨🇭',
SYR: '🇸🇾',
TWN: '🇹🇼',
TJK: '🇹🇯',
THA: '🇹🇭',
TUN: '🇹🇳',
TUR: '🇹🇷',
TKM: '🇹🇲',
UGA: '🇺🇬',
UKR: '🇺🇦',
ARE: '🇦🇪',
GBR: '🇬🇧',
USA: '🇺🇸',
URY: '🇺🇾',
UZB: '🇺🇿',
VEN: '🇻🇪',
VNM: '🇻🇳',
YEM: '🇾🇪',
ZMB: '🇿🇲',
ZWE: '🇿🇼',
}
const getCountryFlag = (countryCode: string | null): string => {
if (!countryCode) return '🌍'
return countryCodeToEmoji[countryCode.toUpperCase()] || '🌍'
}
type CandidateProfileAvatarProps = {
countryCode: string | null
imageBorderWidth: number
badgeBorderWidth: number
badgeOffset: number
badgeSize: number
iconSize: number
name: string
profileImageUrl?: string | null
size: number
}
export function CandidateProfileAvatar({
countryCode,
imageBorderWidth,
badgeBorderWidth,
badgeOffset,
badgeSize,
iconSize,
name,
profileImageUrl,
size,
}: CandidateProfileAvatarProps) {
const [imageFailed, setImageFailed] = useState(false)
useEffect(() => {
setImageFailed(false)
}, [profileImageUrl])
const showImage = Boolean(profileImageUrl) && !imageFailed
return (
<Box pos="relative" style={{ width: size, height: size, flexShrink: 0 }}>
<Box
style={{
width: size,
height: size,
borderRadius: '50%',
backgroundColor: 'var(--mantine-color-gray-1)',
border: `${imageBorderWidth}px solid var(--mantine-color-gray-3)`,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
overflow: 'hidden',
}}
>
{showImage ? (
<Box
component="img"
src={profileImageUrl!}
alt={`${name} profile image`}
onError={() => setImageFailed(true)}
style={{
width: '100%',
height: '100%',
objectFit: 'cover',
display: 'block',
}}
/>
) : (
<IconUser size={iconSize} color="var(--mantine-color-gray-5)" />
)}
</Box>
<Box
style={{
position: 'absolute',
bottom: badgeOffset,
right: badgeOffset,
fontSize: `${Math.round(badgeSize * 0.58)}px`,
width: badgeSize,
height: badgeSize,
backgroundColor: 'white',
border: `${badgeBorderWidth}px solid var(--mantine-color-gray-3)`,
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
{getCountryFlag(countryCode)}
</Box>
</Box>
)
}