11import { ShieldCheckIcon } from 'lucide-react-native' ;
22import { useColorScheme } from 'nativewind' ;
3- import React from 'react' ;
3+ import React , { useMemo } from 'react' ;
44import { useTranslation } from 'react-i18next' ;
55import { View } from 'react-native' ;
66
@@ -10,6 +10,8 @@ import { HStack } from '@/components/ui/hstack';
1010import { Text } from '@/components/ui/text' ;
1111import { VStack } from '@/components/ui/vstack' ;
1212import { type CheckInTimerStatusResultData } from '@/models/v4/checkIn/checkInTimerStatusResultData' ;
13+ import { usePersonnelStore } from '@/stores/personnel/store' ;
14+ import { useUnitsStore } from '@/stores/units/store' ;
1315
1416const STATUS_COLORS : Record < string , string > = {
1517 Ok : '#22C55E' ,
@@ -39,13 +41,54 @@ interface CheckInTimerCardProps {
3941export const CheckInTimerCard : React . FC < CheckInTimerCardProps > = React . memo ( ( { timer, onCheckIn } ) => {
4042 const { t } = useTranslation ( ) ;
4143 const { colorScheme } = useColorScheme ( ) ;
44+ const units = useUnitsStore ( ( s ) => s . units ) ;
45+ const personnel = usePersonnelStore ( ( s ) => s . personnel ) ;
4246
4347 const statusColor = STATUS_COLORS [ timer . Status ] || '#6B7280' ;
4448 const progress = timer . DurationMinutes > 0 ? Math . min ( ( timer . ElapsedMinutes / timer . DurationMinutes ) * 100 , 100 ) : 0 ;
4549
4650 // Use TargetTypeName from API, fall back to translation key lookup
4751 const typeLabel = timer . TargetTypeName || ( CHECK_IN_TYPE_KEYS [ String ( timer . TargetType ) ] ? t ( CHECK_IN_TYPE_KEYS [ String ( timer . TargetType ) ] ) : String ( timer . TargetType ) ) ;
4852
53+ // The API's TargetName often contains the check-in TYPE name (e.g. "UnitType")
54+ // rather than the actual entity name (e.g. "Engine 1"). Detect this and look up
55+ // the real name from the units/personnel stores using TargetEntityId.
56+ const isTargetNameActuallyTypeName = ! timer . TargetName
57+ || timer . TargetName === timer . TargetTypeName
58+ || / t y p e $ / i. test ( timer . TargetName )
59+ || Object . keys ( CHECK_IN_TYPE_KEYS ) . some ( ( k ) => k . toLowerCase ( ) === timer . TargetName . toLowerCase ( ) )
60+ || timer . TargetName . toLowerCase ( ) === 'unittype'
61+ || timer . TargetName . toLowerCase ( ) === 'personneltype' ;
62+
63+ const displayName = useMemo ( ( ) => {
64+ // If TargetName is a real entity name (not a type label), use it directly
65+ if ( timer . TargetName && ! isTargetNameActuallyTypeName ) return timer . TargetName ;
66+
67+ const entityId = timer . TargetEntityId ;
68+ const unitId = timer . UnitId ;
69+
70+ // Look up from units store by TargetEntityId or UnitId
71+ if ( units . length > 0 ) {
72+ for ( const u of units ) {
73+ if ( entityId && u . UnitId === entityId ) return u . Name ;
74+ if ( unitId > 0 && u . UnitId === String ( unitId ) ) return u . Name ;
75+ if ( unitId > 0 && parseInt ( u . UnitId , 10 ) === unitId ) return u . Name ;
76+ if ( entityId && ! isNaN ( parseInt ( entityId , 10 ) ) && parseInt ( u . UnitId , 10 ) === parseInt ( entityId , 10 ) ) return u . Name ;
77+ }
78+ }
79+
80+ // Look up from personnel store by TargetEntityId
81+ if ( personnel . length > 0 && entityId ) {
82+ for ( const p of personnel ) {
83+ if ( p . UserId === entityId || p . IdentificationNumber === entityId ) {
84+ return `${ p . FirstName } ${ p . LastName } ` . trim ( ) ;
85+ }
86+ }
87+ }
88+
89+ return entityId || typeLabel ;
90+ } , [ timer . TargetName , timer . TargetEntityId , timer . UnitId , isTargetNameActuallyTypeName , units , personnel , typeLabel ] ) ;
91+
4992 const statusKey = `check_in.status_${ timer . Status . toLowerCase ( ) } ` as const ;
5093
5194 const elapsedText = timer . LastCheckIn ? t ( 'check_in.minutes_ago' , { count : Math . round ( timer . ElapsedMinutes ) } ) : '' ;
@@ -57,15 +100,8 @@ export const CheckInTimerCard: React.FC<CheckInTimerCardProps> = React.memo(({ t
57100 < HStack className = "flex-1 items-center gap-2" >
58101 < ShieldCheckIcon size = { 16 } color = { statusColor } />
59102 < VStack className = "ml-2 flex-1" >
60- < Text className = "text-sm font-bold" > { timer . TargetName || timer . TargetEntityId || typeLabel } </ Text >
61- { timer . TargetName ? (
62- < Text className = "text-xs font-medium text-gray-500" > { typeLabel } </ Text >
63- ) : (
64- < Text className = "text-xs font-medium text-gray-500" >
65- { timer . TargetTypeName || String ( timer . TargetType ) }
66- { timer . TargetEntityId ? ` #${ timer . TargetEntityId } ` : '' }
67- </ Text >
68- ) }
103+ < Text className = "text-sm font-bold" > { displayName } </ Text >
104+ < Text className = "text-xs font-medium text-gray-500" > { typeLabel } </ Text >
69105 </ VStack >
70106 </ HStack >
71107 < Box className = "rounded-full px-2 py-0.5" style = { { backgroundColor : statusColor + '20' } } >
0 commit comments