import 'package:flutter/material.dart'; import 'package:uto_manager/domain/entities/personnel_record.dart'; import 'package:uto_manager/domain/entities/position_slot.dart'; /// Displays a single position slot as a card in the inspector panel. /// /// Shows the slot's position title, MOS, rank, and assigned soldier (or VACANT). /// Supports drag-and-drop target for soldier assignment. class PositionSlotCard extends StatelessWidget { const PositionSlotCard({ super.key, required this.slot, this.assignedSoldier, this.onUnassign, this.onAcceptDrop, }); final PositionSlot slot; final PersonnelRecord? assignedSoldier; final VoidCallback? onUnassign; final void Function(PersonnelRecord soldier)? onAcceptDrop; @override Widget build(BuildContext context) { final theme = Theme.of(context); return DragTarget( onWillAcceptWithDetails: (details) => slot.isVacant, onAcceptWithDetails: (details) => onAcceptDrop?.call(details.data), builder: (context, candidateData, rejectedData) { final isDragOver = candidateData.isNotEmpty; return AnimatedContainer( duration: const Duration(milliseconds: 120), margin: const EdgeInsets.symmetric(vertical: 3, horizontal: 8), decoration: BoxDecoration( color: isDragOver ? theme.colorScheme.primaryContainer.withValues(alpha: 0.6) : slot.isFilled ? theme.colorScheme.surfaceContainerHighest : theme.colorScheme.surfaceContainerLow, border: Border.all( color: isDragOver ? theme.colorScheme.primary : slot.isKeyLeader ? const Color(0xFFFFD700) // Gold for key leaders : theme.colorScheme.outlineVariant, width: isDragOver ? 2 : 1, ), borderRadius: BorderRadius.circular(6), ), child: ListTile( dense: true, contentPadding: const EdgeInsets.symmetric(horizontal: 10, vertical: 2), leading: _buildMosBadge(theme), title: Text( slot.positionTitle, style: theme.textTheme.bodySmall?.copyWith( fontWeight: slot.isKeyLeader ? FontWeight.bold : FontWeight.normal, ), ), subtitle: Text( slot.isFilled ? (assignedSoldier?.name ?? 'Assigned') : 'VACANT', style: theme.textTheme.labelSmall?.copyWith( color: slot.isFilled ? _readinessColor(assignedSoldier?.readinessState) : theme.colorScheme.error, fontWeight: slot.isVacant ? FontWeight.bold : FontWeight.normal, ), ), trailing: slot.isFilled && onUnassign != null ? IconButton( icon: const Icon(Icons.person_remove, size: 16), onPressed: onUnassign, tooltip: 'Unassign soldier', padding: EdgeInsets.zero, constraints: const BoxConstraints(minWidth: 28, minHeight: 28), ) : null, ), ); }, ); } Widget _buildMosBadge(ThemeData theme) { return Container( width: 40, height: 40, decoration: BoxDecoration( color: theme.colorScheme.primary.withValues(alpha: 0.15), borderRadius: BorderRadius.circular(4), ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( slot.dutyMos.code, style: theme.textTheme.labelSmall?.copyWith( fontWeight: FontWeight.bold, fontSize: 10, color: theme.colorScheme.primary, ), ), Text( slot.authorizedRank.payGrade, style: theme.textTheme.labelSmall?.copyWith( fontSize: 9, color: theme.colorScheme.onSurfaceVariant, ), ), ], ), ); } Color _readinessColor(ReadinessState? state) { switch (state) { case ReadinessState.fullyMissionCapable: return const Color(0xFF4CAF50); case ReadinessState.partiallyMissionCapable: return const Color(0xFFFF9800); case ReadinessState.notMissionCapable: return const Color(0xFFF44336); default: return Colors.grey; } } }