diff --git a/assets/js/hooks/Mapper/components/map/components/SolarSystemNode/SolarSystemKillsCounter.tsx b/assets/js/hooks/Mapper/components/map/components/SolarSystemNode/SolarSystemKillsCounter.tsx index 7f319a38..340f746f 100644 --- a/assets/js/hooks/Mapper/components/map/components/SolarSystemNode/SolarSystemKillsCounter.tsx +++ b/assets/js/hooks/Mapper/components/map/components/SolarSystemNode/SolarSystemKillsCounter.tsx @@ -1,7 +1,7 @@ import { SystemKillsContent } from '../../../mapInterface/widgets/SystemKills/SystemKillsContent/SystemKillsContent'; import { useKillsCounter } from '../../hooks/useKillsCounter'; import { WdTooltipWrapper } from '@/hooks/Mapper/components/ui-kit/WdTooltipWrapper'; -import { WithChildren, WithClassName } from '@/hooks/Mapper/types/common.ts'; +import { WithChildren, WithClassName } from '@/hooks/Mapper/types/common'; type TooltipSize = 'xs' | 'sm' | 'md' | 'lg'; @@ -11,16 +11,31 @@ type KillsBookmarkTooltipProps = { systemId: string; className?: string; size?: TooltipSize; + timeRange?: number; } & WithChildren & WithClassName; -export const KillsCounter = ({ killsCount, systemId, className, children, size = 'xs' }: KillsBookmarkTooltipProps) => { +export const KillsCounter = ({ + killsCount, + systemId, + className, + children, + size = 'xs', + timeRange = 1, +}: KillsBookmarkTooltipProps) => { const { isLoading, kills: detailedKills, systemNameMap } = useKillsCounter({ realSystemId: systemId }); if (!killsCount || detailedKills.length === 0 || !systemId || isLoading) return null; const tooltipContent = ( - + ); return ( diff --git a/assets/js/hooks/Mapper/components/map/components/SolarSystemNode/SolarSystemNodeDefault.tsx b/assets/js/hooks/Mapper/components/map/components/SolarSystemNode/SolarSystemNodeDefault.tsx index e5cbcffa..298f178f 100644 --- a/assets/js/hooks/Mapper/components/map/components/SolarSystemNode/SolarSystemNodeDefault.tsx +++ b/assets/js/hooks/Mapper/components/map/components/SolarSystemNode/SolarSystemNodeDefault.tsx @@ -4,7 +4,7 @@ import { Handle, NodeProps, Position } from 'reactflow'; import clsx from 'clsx'; import classes from './SolarSystemNodeDefault.module.scss'; import { PrimeIcons } from 'primereact/api'; -import { useLocalCounter, useSolarSystemNode } from '../../hooks/useSolarSystemLogic'; +import { useLocalCounter, useSolarSystemNode, useNodeKillsCount } from '../../hooks/useSolarSystemLogic'; import { EFFECT_BACKGROUND_STYLES, MARKER_BOOKMARK_BG_STYLES, @@ -18,6 +18,7 @@ import { KillsCounter } from './SolarSystemKillsCounter'; export const SolarSystemNodeDefault = memo((props: NodeProps) => { const nodeVars = useSolarSystemNode(props); const { localCounterCharacters } = useLocalCounter(nodeVars); + const localKillsCount = useNodeKillsCount(nodeVars.solarSystemId, nodeVars.killsCount); return ( <> @@ -35,9 +36,9 @@ export const SolarSystemNodeDefault = memo((props: NodeProps )} - {nodeVars.killsCount && nodeVars.killsCount > 0 && nodeVars.solarSystemId && ( + {localKillsCount && localKillsCount > 0 && nodeVars.solarSystemId && ( ) => { const nodeVars = useSolarSystemNode(props); const { localCounterCharacters } = useLocalCounter(nodeVars); + const localKillsCount = useNodeKillsCount(nodeVars.solarSystemId, nodeVars.killsCount); return ( <> @@ -35,9 +36,9 @@ export const SolarSystemNodeTheme = memo((props: NodeProps) )} - {nodeVars.killsCount && nodeVars.killsCount > 0 && nodeVars.solarSystemId && ( + {localKillsCount && localKillsCount > 0 && nodeVars.solarSystemId && ( ): SolarS kind: s.kind, name: s.name, group: s.group, - sig_id: s.eve_id, // Add a unique key property })) as UnsplashedSignatureType[], ); }, [isShowUnsplashedSignatures, systemSigs]); @@ -281,3 +281,25 @@ export interface SolarSystemNodeVars { classTitle: string | null; temporaryName?: string | null; } + +export function useNodeKillsCount(systemId: number | string, initialKillsCount: number | null): number | null { + const [killsCount, setKillsCount] = useState(initialKillsCount); + + useEffect(() => { + setKillsCount(initialKillsCount); + }, [initialKillsCount]); + + useMapEventListener(event => { + if (event.name === Commands.killsUpdated && event.data?.toString() === systemId.toString()) { + //@ts-ignore + if (event.payload && typeof event.payload.kills === 'number') { + // @ts-ignore + setKillsCount(event.payload.kills); + } + return true; + } + return false; + }); + + return killsCount; +} diff --git a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/SystemKills.tsx b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/SystemKills.tsx index a4e7c9f8..9e2e4ce0 100644 --- a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/SystemKills.tsx +++ b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/SystemKills.tsx @@ -7,8 +7,9 @@ import { useKillsWidgetSettings } from './hooks/useKillsWidgetSettings'; import { useSystemKills } from './hooks/useSystemKills'; import { KillsSettingsDialog } from './components/SystemKillsSettingsDialog'; import { isWormholeSpace } from '@/hooks/Mapper/components/map/helpers/isWormholeSpace'; +import { SolarSystemRawType } from '@/hooks/Mapper/types'; -export const SystemKills: React.FC = () => { +export const SystemKills: React.FC = React.memo(() => { const { data: { selectedSystems, systems, isSubscriptionActive }, outCommand, @@ -25,6 +26,16 @@ export const SystemKills: React.FC = () => { return map; }, [systems]); + const systemBySolarSystemId = useMemo(() => { + const map: Record = {}; + systems.forEach(sys => { + if (sys.system_static_info?.solar_system_id != null) { + map[sys.system_static_info.solar_system_id] = sys; + } + }); + return map; + }, [systems]); + const [settings] = useKillsWidgetSettings(); const visible = settings.showAll; @@ -40,78 +51,61 @@ export const SystemKills: React.FC = () => { const filteredKills = useMemo(() => { if (!settings.whOnly || !visible) return kills; return kills.filter(kill => { - const system = systems.find( - sys => sys.system_static_info.solar_system_id === kill.solar_system_id - ); + const system = systemBySolarSystemId[kill.solar_system_id]; if (!system) { console.warn(`System with id ${kill.solar_system_id} not found.`); return false; } return isWormholeSpace(system.system_static_info.system_class); }); - }, [kills, settings.whOnly, systems]); + }, [kills, settings.whOnly, systemBySolarSystemId, visible]); return (
- setSettingsDialogVisible(true)} - /> - } - > -
- {!isSubscriptionActive ? ( -
- - Kills available with 'Active' map subscription only (contact map administrators) - -
- ) : isNothingSelected ? ( -
- - No system selected (or toggle “Show all systems”) - -
- ) : showLoading ? ( -
- - Loading Kills... - -
- ) : error ? ( -
- - {error} - -
- ) : !filteredKills || filteredKills.length === 0 ? ( -
- - No kills found - -
- ) : ( -
- -
- )} -
+ setSettingsDialogVisible(true)} />}> + {!isSubscriptionActive ? ( +
+ + Kills available with 'Active' map subscription only (contact map administrators) + +
+ ) : isNothingSelected ? ( +
+ + No system selected (or toggle “Show all systems”) + +
+ ) : showLoading ? ( +
+ Loading Kills... +
+ ) : error ? ( +
+ {error} +
+ ) : !filteredKills || filteredKills.length === 0 ? ( +
+ No kills found +
+ ) : ( +
+ +
+ )}
- + {settingsDialogVisible && }
); -}; +}); + +SystemKills.displayName = 'SystemKills'; diff --git a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/SystemKillsContent/SystemKillsContent.module.scss b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/SystemKillsContent/SystemKillsContent.module.scss index 8f882e96..0b6d72c3 100644 --- a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/SystemKillsContent/SystemKillsContent.module.scss +++ b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/SystemKillsContent/SystemKillsContent.module.scss @@ -14,3 +14,7 @@ white-space: pre-line; line-height: 1.2rem; } + +.VirtualScroller { + height: 100% !important; +} diff --git a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/SystemKillsContent/SystemKillsContent.tsx b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/SystemKillsContent/SystemKillsContent.tsx index 8dc1d7db..3b7909ac 100644 --- a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/SystemKillsContent/SystemKillsContent.tsx +++ b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/SystemKillsContent/SystemKillsContent.tsx @@ -1,13 +1,16 @@ -import React, { useMemo } from 'react'; +import React, { useMemo, useRef, useEffect, useState } from 'react'; import clsx from 'clsx'; import { DetailedKill } from '@/hooks/Mapper/types/kills'; -import { KillRow } from '../components/SystemKillsRow'; +import { VirtualScroller } from 'primereact/virtualscroller'; +import { useSystemKillsItemTemplate } from '../hooks/useSystemKillsTemplate'; -interface SystemKillsContentProps { +export interface SystemKillsContentProps { kills: DetailedKill[]; systemNameMap: Record; compact?: boolean; onlyOneSystem?: boolean; + autoSize?: boolean; + timeRange: number; } export const SystemKillsContent: React.FC = ({ @@ -15,36 +18,68 @@ export const SystemKillsContent: React.FC = ({ systemNameMap, compact = false, onlyOneSystem = false, + autoSize = false, + timeRange = 1, }) => { - const sortedKills = useMemo(() => { - return [...kills].sort((a, b) => { + const processedKills = useMemo(() => { + const validKills = kills.filter(kill => kill.kill_time); + + const sortedKills = validKills.sort((a, b) => { const timeA = a.kill_time ? new Date(a.kill_time).getTime() : 0; const timeB = b.kill_time ? new Date(b.kill_time).getTime() : 0; return timeB - timeA; }); - }, [kills]); + + const now = Date.now(); + const cutoff = now - timeRange * 60 * 60 * 1000; + return sortedKills.filter(kill => { + if (!kill.kill_time) return false; + const killTime = new Date(kill.kill_time).getTime(); + return killTime >= cutoff; + }); + }, [kills, timeRange]); + + const itemSize = compact ? 35 : 50; + const computedHeight = autoSize ? Math.max(processedKills.length, 1) * itemSize + 5 : undefined; + + const containerRef = useRef(null); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const scrollerRef = useRef(null); + const [containerHeight, setContainerHeight] = useState(0); + + useEffect(() => { + if (!autoSize && containerRef.current) { + const measure = () => { + const newHeight = containerRef.current?.clientHeight ?? 0; + setContainerHeight(newHeight); + scrollerRef.current?.refresh?.(); + }; + + measure(); + const observer = new ResizeObserver(measure); + observer.observe(containerRef.current); + window.addEventListener('resize', measure); + + return () => { + observer.disconnect(); + window.removeEventListener('resize', measure); + }; + } + }, [autoSize]); + + const itemTemplate = useSystemKillsItemTemplate(systemNameMap, compact, onlyOneSystem); return ( -
- {sortedKills.map(kill => { - const systemIdStr = String(kill.solar_system_id); - const systemName = systemNameMap[systemIdStr] || `System ${systemIdStr}`; - - return ( - - ); - })} +
+
); }; diff --git a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/components/CompactKillRow.tsx b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/components/CompactKillRow.tsx index d6e75554..6e94c64c 100644 --- a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/components/CompactKillRow.tsx +++ b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/components/CompactKillRow.tsx @@ -21,14 +21,9 @@ export interface CompactKillRowProps { onlyOneSystem: boolean; } -export const CompactKillRow: React.FC = ({ - killDetails, - systemName, - onlyOneSystem, -}) => { +export const CompactKillRow: React.FC = ({ killDetails, systemName, onlyOneSystem }) => { const { killmail_id = 0, - // Victim victim_char_name = 'Unknown Pilot', victim_alliance_ticker = '', @@ -40,7 +35,6 @@ export const CompactKillRow: React.FC = ({ victim_corp_id = 0, victim_alliance_id = 0, victim_ship_type_id = 0, - // Attacker final_blow_char_id = 0, final_blow_char_name = '', @@ -51,70 +45,54 @@ export const CompactKillRow: React.FC = ({ final_blow_corp_id = 0, final_blow_corp_name = '', final_blow_ship_type_id = 0, - kill_time = '', total_value = 0, } = killDetails || {}; const attackerIsNpc = final_blow_char_id === 0; - // Tickers & strings - const victimAffiliationTicker = - victim_alliance_ticker || victim_corp_ticker || 'No Ticker'; - const killValueFormatted = - total_value != null && total_value > 0 ? `${formatISK(total_value)} ISK` : null; + const victimAffiliationTicker = victim_alliance_ticker || victim_corp_ticker || 'No Ticker'; + const killValueFormatted = total_value != null && total_value > 0 ? `${formatISK(total_value)} ISK` : null; const attackerName = attackerIsNpc ? '' : final_blow_char_name; - const attackerTicker = attackerIsNpc - ? '' - : final_blow_alliance_ticker || final_blow_corp_ticker || ''; + const attackerTicker = attackerIsNpc ? '' : final_blow_alliance_ticker || final_blow_corp_ticker || ''; const killTimeAgo = kill_time ? formatTimeMixed(kill_time) : '0h ago'; const attackerSubscript = getAttackerSubscript(killDetails); - // Victim images, including the ship - const { - victimCorpLogoUrl, - victimAllianceLogoUrl, - victimShipUrl, - } = buildVictimImageUrls({ + const { victimCorpLogoUrl, victimAllianceLogoUrl, victimShipUrl } = buildVictimImageUrls({ victim_char_id, victim_ship_type_id, victim_corp_id, victim_alliance_id, }); - // Attacker corp/alliance const { attackerCorpLogoUrl, attackerAllianceLogoUrl } = buildAttackerImageUrls({ final_blow_char_id, final_blow_corp_id, final_blow_alliance_id, }); - // Victim corp/alliance logo - const { url: victimPrimaryLogoUrl, tooltip: victimPrimaryTooltip } = - getPrimaryLogoAndTooltip( - victimAllianceLogoUrl, - victimCorpLogoUrl, - victim_alliance_name, - victim_corp_name, - 'Victim' - ); + const { url: victimPrimaryLogoUrl, tooltip: victimPrimaryTooltip } = getPrimaryLogoAndTooltip( + victimAllianceLogoUrl, + victimCorpLogoUrl, + victim_alliance_name, + victim_corp_name, + 'Victim', + ); - // Attacker corp/alliance or NPC ship - const { url: attackerPrimaryImageUrl, tooltip: attackerPrimaryTooltip } = - getAttackerPrimaryImageAndTooltip( - attackerIsNpc, - attackerAllianceLogoUrl, - attackerCorpLogoUrl, - final_blow_alliance_name, - final_blow_corp_name, - final_blow_ship_type_id - ); + const { url: attackerPrimaryImageUrl, tooltip: attackerPrimaryTooltip } = getAttackerPrimaryImageAndTooltip( + attackerIsNpc, + attackerAllianceLogoUrl, + attackerCorpLogoUrl, + final_blow_alliance_name, + final_blow_corp_name, + final_blow_ship_type_id, + ); return (
@@ -129,19 +107,13 @@ export const CompactKillRow: React.FC = ({ VictimShip
)} {victimPrimaryLogoUrl && ( - + = ({ VictimPrimaryLogo )}
-
+
{victim_char_name} / {victimAffiliationTicker} @@ -176,20 +145,17 @@ export const CompactKillRow: React.FC = ({
-
+
{!attackerIsNpc && (attackerName || attackerTicker) && (
{attackerName} - {attackerTicker && ( - / {attackerTicker} - )} + {attackerTicker && / {attackerTicker}}
)}
{!onlyOneSystem && systemName ? ( <> - {systemName} /{' '} - {killTimeAgo} + {systemName} / {killTimeAgo} ) : ( {killTimeAgo} @@ -197,10 +163,7 @@ export const CompactKillRow: React.FC = ({
{attackerPrimaryImageUrl && ( - + = ({ {attackerIsNpc {attackerSubscript && ( {attackerSubscript.label} diff --git a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/components/FullKillRow.tsx b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/components/FullKillRow.tsx index 40ee237b..060acba7 100644 --- a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/components/FullKillRow.tsx +++ b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/components/FullKillRow.tsx @@ -22,11 +22,7 @@ export interface FullKillRowProps { onlyOneSystem: boolean; } -export const FullKillRow: React.FC = ({ - killDetails, - systemName, - onlyOneSystem, -}) => { +export const FullKillRow: React.FC = ({ killDetails, systemName, onlyOneSystem }) => { const { killmail_id = 0, // Victim data @@ -57,21 +53,13 @@ export const FullKillRow: React.FC = ({ const attackerIsNpc = final_blow_char_id === 0; const victimAffiliation = victim_alliance_ticker || victim_corp_ticker || null; - const attackerAffiliation = attackerIsNpc - ? '' - : final_blow_alliance_ticker || final_blow_corp_ticker || ''; + const attackerAffiliation = attackerIsNpc ? '' : final_blow_alliance_ticker || final_blow_corp_ticker || ''; - const killValueFormatted = - total_value != null && total_value > 0 ? `${formatISK(total_value)} ISK` : null; + const killValueFormatted = total_value != null && total_value > 0 ? `${formatISK(total_value)} ISK` : null; const killTimeAgo = kill_time ? formatTimeMixed(kill_time) : '0h ago'; // Build victim images - const { - victimPortraitUrl, - victimCorpLogoUrl, - victimAllianceLogoUrl, - victimShipUrl, - } = buildVictimImageUrls({ + const { victimPortraitUrl, victimCorpLogoUrl, victimAllianceLogoUrl, victimShipUrl } = buildVictimImageUrls({ victim_char_id, victim_ship_type_id, victim_corp_id, @@ -79,47 +67,35 @@ export const FullKillRow: React.FC = ({ }); // Build attacker images - const { - attackerPortraitUrl, - attackerCorpLogoUrl, - attackerAllianceLogoUrl, - } = buildAttackerImageUrls({ + const { attackerPortraitUrl, attackerCorpLogoUrl, attackerAllianceLogoUrl } = buildAttackerImageUrls({ final_blow_char_id, final_blow_corp_id, final_blow_alliance_id, }); // Primary image for victim - const { url: victimPrimaryImageUrl, tooltip: victimPrimaryTooltip } = - getPrimaryLogoAndTooltip( - victimAllianceLogoUrl, - victimCorpLogoUrl, - victim_alliance_name, - victim_corp_name, - 'Victim' - ); + const { url: victimPrimaryImageUrl, tooltip: victimPrimaryTooltip } = getPrimaryLogoAndTooltip( + victimAllianceLogoUrl, + victimCorpLogoUrl, + victim_alliance_name, + victim_corp_name, + 'Victim', + ); // Primary image for attacker - const { url: attackerPrimaryImageUrl, tooltip: attackerPrimaryTooltip } = - getAttackerPrimaryImageAndTooltip( - attackerIsNpc, - attackerAllianceLogoUrl, - attackerCorpLogoUrl, - final_blow_alliance_name, - final_blow_corp_name, - final_blow_ship_type_id - ); + const { url: attackerPrimaryImageUrl, tooltip: attackerPrimaryTooltip } = getAttackerPrimaryImageAndTooltip( + attackerIsNpc, + attackerAllianceLogoUrl, + attackerCorpLogoUrl, + final_blow_alliance_name, + final_blow_corp_name, + final_blow_ship_type_id, + ); const attackerSubscript = getAttackerSubscript(killDetails); return ( -
+
{/* Victim Section */} )} {victimPrimaryImageUrl && ( - + @@ -171,12 +138,10 @@ export const FullKillRow: React.FC = ({ victimCharacterId={victim_char_id} victimPortraitUrl={victimPortraitUrl} /> -
+
{victim_char_name} - {victimAffiliation && ( - / {victimAffiliation} - )} + {victimAffiliation && / {victimAffiliation}}
{victim_ship_name} @@ -187,20 +152,15 @@ export const FullKillRow: React.FC = ({ )}
-
- {!onlyOneSystem && systemName && {systemName}} -
+
{!onlyOneSystem && systemName && {systemName}}
- {/* Attacker Section */}
-
+
{!attackerIsNpc && (
{final_blow_char_name} - {attackerAffiliation && ( - / {attackerAffiliation} - )} + {attackerAffiliation && / {attackerAffiliation}}
)} {!attackerIsNpc && final_blow_ship_name && ( @@ -208,7 +168,7 @@ export const FullKillRow: React.FC = ({ )}
{killTimeAgo}
- {(!attackerIsNpc && attackerPortraitUrl && final_blow_char_id > 0) && ( + {!attackerIsNpc && attackerPortraitUrl && final_blow_char_id &&final_blow_char_id > 0 && ( )} {attackerPrimaryImageUrl && ( - +
= ({ {attackerIsNpc {attackerSubscript && ( - + {attackerSubscript.label} )} diff --git a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/components/KillItemTemplate.tsx b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/components/KillItemTemplate.tsx new file mode 100644 index 00000000..e495c066 --- /dev/null +++ b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/components/KillItemTemplate.tsx @@ -0,0 +1,21 @@ +import { DetailedKill } from '@/hooks/Mapper/types/kills'; +import { VirtualScrollerTemplateOptions } from 'primereact/virtualscroller'; +import { KillRow } from './SystemKillsRow'; +import clsx from 'clsx'; + +export function KillItemTemplate( + systemNameMap: Record, + compact: boolean, + onlyOneSystem: boolean, + kill: DetailedKill, + options: VirtualScrollerTemplateOptions, +) { + const systemIdStr = String(kill.solar_system_id); + const systemName = systemNameMap[systemIdStr] || `System ${systemIdStr}`; + + return ( +
+ +
+ ); +} diff --git a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/components/SystemKillsRow.tsx b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/components/SystemKillsRow.tsx index 8217adbd..704b96ec 100644 --- a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/components/SystemKillsRow.tsx +++ b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/components/SystemKillsRow.tsx @@ -10,7 +10,7 @@ export interface KillRowProps { onlyOneSystem?: boolean; } -export const KillRow: React.FC = ({ +const KillRowComponent: React.FC = ({ killDetails, systemName, isCompact = false, @@ -19,6 +19,7 @@ export const KillRow: React.FC = ({ if (isCompact) { return ; } - return ; }; + +export const KillRow = React.memo(KillRowComponent); diff --git a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/components/SystemKillsSettingsDialog.tsx b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/components/SystemKillsSettingsDialog.tsx index a2a384af..6cee23cb 100644 --- a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/components/SystemKillsSettingsDialog.tsx +++ b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/components/SystemKillsSettingsDialog.tsx @@ -1,6 +1,7 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'; import { Dialog } from 'primereact/dialog'; import { Button } from 'primereact/button'; +import { InputSwitch } from 'primereact/inputswitch'; import { WdImgButton, SystemView, TooltipPosition } from '@/hooks/Mapper/components/ui-kit'; import { PrimeIcons } from 'primereact/api'; import { useKillsWidgetSettings } from '../hooks/useKillsWidgetSettings'; @@ -21,10 +22,10 @@ export const KillsSettingsDialog: React.FC = ({ visibl showAll: globalSettings.showAll, whOnly: globalSettings.whOnly, excludedSystems: globalSettings.excludedSystems || [], + timeRange: globalSettings.timeRange, }); const [, forceRender] = useState(0); - const [addSystemDialogVisible, setAddSystemDialogVisible] = useState(false); useEffect(() => { @@ -34,6 +35,7 @@ export const KillsSettingsDialog: React.FC = ({ visibl showAll: globalSettings.showAll, whOnly: globalSettings.whOnly, excludedSystems: globalSettings.excludedSystems || [], + timeRange: globalSettings.timeRange, }; forceRender(n => n + 1); } @@ -55,6 +57,15 @@ export const KillsSettingsDialog: React.FC = ({ visibl forceRender(n => n + 1); }, []); + // Updated handler to set time range as a number: 1 or 24 + const handleTimeRangeChange = useCallback((newTimeRange: 1 | 24) => { + localRef.current = { + ...localRef.current, + timeRange: newTimeRange, + }; + forceRender(n => n + 1); + }, []); + const handleRemoveSystem = useCallback((sysId: number) => { localRef.current = { ...localRef.current, @@ -111,11 +122,18 @@ export const KillsSettingsDialog: React.FC = ({ visibl checked={localData.whOnly} onChange={e => handleWHChange(e.target.checked)} /> -
+ {/* Time Range Toggle using InputSwitch */} +
+ Time Range: + handleTimeRangeChange(e.value ? 24 : 1)} /> + {localData.timeRange === 24 ? '24 Hours' : '1 Hour'} +
+
@@ -128,7 +146,7 @@ export const KillsSettingsDialog: React.FC = ({ visibl {excluded.length === 0 &&
No systems excluded.
} {excluded.map(sysId => (
- + ): KillsWidgetSettings { diff --git a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/hooks/useSystemKillsTemplate.tsx b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/hooks/useSystemKillsTemplate.tsx new file mode 100644 index 00000000..a9637d48 --- /dev/null +++ b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/hooks/useSystemKillsTemplate.tsx @@ -0,0 +1,17 @@ +// useSystemKillsItemTemplate.tsx +import { useCallback } from 'react'; +import { VirtualScrollerTemplateOptions } from 'primereact/virtualscroller'; +import { DetailedKill } from '@/hooks/Mapper/types/kills'; +import { KillItemTemplate } from '../components/KillItemTemplate'; + +export function useSystemKillsItemTemplate( + systemNameMap: Record, + compact: boolean, + onlyOneSystem: boolean, +) { + return useCallback( + (kill: DetailedKill, options: VirtualScrollerTemplateOptions) => + KillItemTemplate(systemNameMap, compact, onlyOneSystem, kill, options), + [systemNameMap, compact, onlyOneSystem], + ); +} diff --git a/assets/js/hooks/Mapper/types/kills.ts b/assets/js/hooks/Mapper/types/kills.ts index dac134c7..dd3da266 100644 --- a/assets/js/hooks/Mapper/types/kills.ts +++ b/assets/js/hooks/Mapper/types/kills.ts @@ -21,7 +21,6 @@ export interface DetailedKill { victim_ship_type_id?: number | null; victim_ship_name?: string; - final_blow_char_id?: number | null; final_blow_char_name?: string; final_blow_corp_id?: number | null;