import { useCallback } from 'react'; import clsx from 'clsx'; import classes from './CharacterCard.module.scss'; import { SystemView } from '@/hooks/Mapper/components/ui-kit/SystemView'; import { CharacterTypeRaw, WithIsOwnCharacter } from '@/hooks/Mapper/types'; import { Commands } from '@/hooks/Mapper/types/mapHandlers'; import { emitMapEvent } from '@/hooks/Mapper/events'; type CharacterCardProps = { compact?: boolean; showSystem?: boolean; showShipName?: boolean; useSystemsCache?: boolean; } & CharacterTypeRaw & WithIsOwnCharacter; const SHIP_NAME_RX = /u'|'/g; export const getShipName = (name: string) => { return name .replace(SHIP_NAME_RX, '') .replace(/\\u([\dA-Fa-f]{4})/g, (_, grp) => String.fromCharCode(parseInt(grp, 16))) .replace(/\\x([\dA-Fa-f]{2})/g, (_, grp) => String.fromCharCode(parseInt(grp, 16))); }; // A small divider between fields: const Divider = () => ( ); export const CharacterCard = ({ compact = false, isOwn, showSystem, showShipName, useSystemsCache, ...char }: CharacterCardProps) => { const handleSelect = useCallback(() => { emitMapEvent({ name: Commands.centerSystem, data: char?.location?.solar_system_id?.toString(), }); }, [char]); // Precompute the ship name (decoded): const shipNameText = char.ship?.ship_name ? getShipName(char.ship.ship_name) : ''; // ----------------------------------------------------------------------------- // COMPACT MODE: Main line = // if (showShipName & haveShipName) => name | shipName (skip ticker) // else => name | [ticker] // ----------------------------------------------------------------------------- const compactLine = ( <> {/* Character Name (lighter shade) */} {char.name} {showShipName && shipNameText ? ( // Show the ship name in place of the ticker (use indigo color to match corp/alliance) {shipNameText} ) : ( // Show the [ticker] (indigo) [{char.alliance_id ? char.alliance_ticker : char.corporation_ticker}] )} ); // ----------------------------------------------------------------------------- // NON-COMPACT MODE: // Line 1 => name | [ticker] // Line 2 => (shipName) always, if it exists // ----------------------------------------------------------------------------- const nonCompactLine1 = (
{/* Character Name (lighter shade) */} {char.name} [{char.alliance_id ? char.alliance_ticker : char.corporation_ticker}]
); const nonCompactLine2 = ( <> {shipNameText && (
{shipNameText}
)} ); return (
{compact ? ( {`${char.name} ) : ( )} {/* Middle section: - In compact mode, everything is on one line (Name + possibly ShipName or ticker). - In non-compact mode, line 1 has (Name | Ticker), line 2 has shipName if it exists. */}
{/* This left border highlights "isOwn" in the same way as older code. */}
{compact ? compactLine : nonCompactLine1}
{/* Non-compact second line always shows shipName if available */} {!compact && nonCompactLine2}
{/* Right column for Ship Type (compact) or "pushed" to the right (non-compact). Ship Type remains text-yellow-400. */} {char.ship?.ship_type_info?.name && (
{char.ship.ship_type_info.name}
)}
{/* System row at the bottom if `showSystem && system exists`. */} {showSystem && char.location?.solar_system_id && (
)}
); };