mirror of
https://github.com/wanderer-industries/wanderer
synced 2025-12-12 10:45:54 +00:00
This reverts commit b29e57b3a4.
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import { SystemKillsContent } from '../../../mapInterface/widgets/SystemKills/SystemKillsContent/SystemKillsContent';
|
import { SystemKillsContent } from '../../../mapInterface/widgets/SystemKills/SystemKillsContent/SystemKillsContent';
|
||||||
import { useKillsCounter } from '../../hooks/useKillsCounter';
|
import { useKillsCounter } from '../../hooks/useKillsCounter';
|
||||||
import { WdTooltipWrapper } from '@/hooks/Mapper/components/ui-kit/WdTooltipWrapper';
|
import { WdTooltipWrapper } from '@/hooks/Mapper/components/ui-kit/WdTooltipWrapper';
|
||||||
import { WithChildren, WithClassName } from '@/hooks/Mapper/types/common';
|
import { WithChildren, WithClassName } from '@/hooks/Mapper/types/common.ts';
|
||||||
|
|
||||||
type TooltipSize = 'xs' | 'sm' | 'md' | 'lg';
|
type TooltipSize = 'xs' | 'sm' | 'md' | 'lg';
|
||||||
|
|
||||||
@@ -11,32 +11,16 @@ type KillsBookmarkTooltipProps = {
|
|||||||
systemId: string;
|
systemId: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
size?: TooltipSize;
|
size?: TooltipSize;
|
||||||
timeRange?: number;
|
|
||||||
} & WithChildren &
|
} & WithChildren &
|
||||||
WithClassName;
|
WithClassName;
|
||||||
|
|
||||||
export const KillsCounter = ({
|
export const KillsCounter = ({ killsCount, systemId, className, children, size = 'xs' }: KillsBookmarkTooltipProps) => {
|
||||||
killsCount,
|
|
||||||
systemId,
|
|
||||||
className,
|
|
||||||
children,
|
|
||||||
size = 'xs',
|
|
||||||
timeRange = 1,
|
|
||||||
}: KillsBookmarkTooltipProps) => {
|
|
||||||
const { isLoading, kills: detailedKills, systemNameMap } = useKillsCounter({ realSystemId: systemId });
|
const { isLoading, kills: detailedKills, systemNameMap } = useKillsCounter({ realSystemId: systemId });
|
||||||
|
|
||||||
if (!killsCount || detailedKills.length === 0 || !systemId || isLoading) return null;
|
if (!killsCount || detailedKills.length === 0 || !systemId || isLoading) return null;
|
||||||
|
|
||||||
const tooltipContent = (
|
const tooltipContent = (
|
||||||
<SystemKillsContent
|
<SystemKillsContent kills={detailedKills} systemNameMap={systemNameMap} compact={true} onlyOneSystem={true} />
|
||||||
kills={detailedKills}
|
|
||||||
systemNameMap={systemNameMap}
|
|
||||||
compact={true}
|
|
||||||
onlyOneSystem={true}
|
|
||||||
autoSize={true}
|
|
||||||
timeRange={timeRange}
|
|
||||||
limit={killsCount}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -7,9 +7,8 @@ import { useKillsWidgetSettings } from './hooks/useKillsWidgetSettings';
|
|||||||
import { useSystemKills } from './hooks/useSystemKills';
|
import { useSystemKills } from './hooks/useSystemKills';
|
||||||
import { KillsSettingsDialog } from './components/SystemKillsSettingsDialog';
|
import { KillsSettingsDialog } from './components/SystemKillsSettingsDialog';
|
||||||
import { isWormholeSpace } from '@/hooks/Mapper/components/map/helpers/isWormholeSpace';
|
import { isWormholeSpace } from '@/hooks/Mapper/components/map/helpers/isWormholeSpace';
|
||||||
import { SolarSystemRawType } from '@/hooks/Mapper/types';
|
|
||||||
|
|
||||||
export const SystemKills: React.FC = React.memo(() => {
|
export const SystemKills: React.FC = () => {
|
||||||
const {
|
const {
|
||||||
data: { selectedSystems, systems, isSubscriptionActive },
|
data: { selectedSystems, systems, isSubscriptionActive },
|
||||||
outCommand,
|
outCommand,
|
||||||
@@ -26,16 +25,6 @@ export const SystemKills: React.FC = React.memo(() => {
|
|||||||
return map;
|
return map;
|
||||||
}, [systems]);
|
}, [systems]);
|
||||||
|
|
||||||
const systemBySolarSystemId = useMemo(() => {
|
|
||||||
const map: Record<number, SolarSystemRawType> = {};
|
|
||||||
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 [settings] = useKillsWidgetSettings();
|
||||||
const visible = settings.showAll;
|
const visible = settings.showAll;
|
||||||
|
|
||||||
@@ -51,61 +40,78 @@ export const SystemKills: React.FC = React.memo(() => {
|
|||||||
const filteredKills = useMemo(() => {
|
const filteredKills = useMemo(() => {
|
||||||
if (!settings.whOnly || !visible) return kills;
|
if (!settings.whOnly || !visible) return kills;
|
||||||
return kills.filter(kill => {
|
return kills.filter(kill => {
|
||||||
const system = systemBySolarSystemId[kill.solar_system_id];
|
const system = systems.find(
|
||||||
|
sys => sys.system_static_info.solar_system_id === kill.solar_system_id
|
||||||
|
);
|
||||||
if (!system) {
|
if (!system) {
|
||||||
console.warn(`System with id ${kill.solar_system_id} not found.`);
|
console.warn(`System with id ${kill.solar_system_id} not found.`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return isWormholeSpace(system.system_static_info.system_class);
|
return isWormholeSpace(system.system_static_info.system_class);
|
||||||
});
|
});
|
||||||
}, [kills, settings.whOnly, systemBySolarSystemId, visible]);
|
}, [kills, settings.whOnly, systems]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-full flex flex-col min-h-0">
|
<div className="h-full flex flex-col min-h-0">
|
||||||
<div className="flex flex-col flex-1 min-h-0">
|
<div className="flex flex-col flex-1 min-h-0">
|
||||||
<Widget label={<KillsHeader systemId={systemId} onOpenSettings={() => setSettingsDialogVisible(true)} />}>
|
<Widget
|
||||||
{!isSubscriptionActive ? (
|
label={
|
||||||
<div className="w-full h-full flex items-center justify-center">
|
<KillsHeader
|
||||||
<span className="select-none text-center text-stone-400/80 text-sm">
|
systemId={systemId}
|
||||||
Kills available with 'Active' map subscription only (contact map administrators)
|
onOpenSettings={() => setSettingsDialogVisible(true)}
|
||||||
</span>
|
/>
|
||||||
</div>
|
}
|
||||||
) : isNothingSelected ? (
|
>
|
||||||
<div className="w-full h-full flex items-center justify-center">
|
<div className="relative h-full">
|
||||||
<span className="select-none text-center text-stone-400/80 text-sm">
|
{!isSubscriptionActive ? (
|
||||||
No system selected (or toggle “Show all systems”)
|
<div className="absolute inset-0 flex items-center justify-center">
|
||||||
</span>
|
<span className="select-none text-center text-stone-400/80 text-sm">
|
||||||
</div>
|
Kills available with 'Active' map subscription only (contact map administrators)
|
||||||
) : showLoading ? (
|
</span>
|
||||||
<div className="w-full h-full flex items-center justify-center">
|
</div>
|
||||||
<span className="select-none text-center text-stone-400/80 text-sm">Loading Kills...</span>
|
) : isNothingSelected ? (
|
||||||
</div>
|
<div className="absolute inset-0 flex items-center justify-center">
|
||||||
) : error ? (
|
<span className="select-none text-center text-stone-400/80 text-sm">
|
||||||
<div className="w-full h-full flex items-center justify-center">
|
No system selected (or toggle “Show all systems”)
|
||||||
<span className="select-none text-center text-red-400 text-sm">{error}</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
) : !filteredKills || filteredKills.length === 0 ? (
|
) : showLoading ? (
|
||||||
<div className="w-full h-full flex items-center justify-center">
|
<div className="absolute inset-0 flex items-center justify-center">
|
||||||
<span className="select-none text-center text-stone-400/80 text-sm">No kills found</span>
|
<span className="select-none text-center text-stone-400/80 text-sm">
|
||||||
</div>
|
Loading Kills...
|
||||||
) : (
|
</span>
|
||||||
<div className="w-full h-full" style={{ height: '100%' }}>
|
</div>
|
||||||
<SystemKillsContent
|
) : error ? (
|
||||||
key={settings.compact ? 'compact' : 'normal'}
|
<div className="absolute inset-0 flex items-center justify-center">
|
||||||
kills={filteredKills}
|
<span className="select-none text-center text-red-400 text-sm">
|
||||||
systemNameMap={systemNameMap}
|
{error}
|
||||||
compact={settings.compact}
|
</span>
|
||||||
onlyOneSystem={!visible}
|
</div>
|
||||||
timeRange={settings.timeRange}
|
) : !filteredKills || filteredKills.length === 0 ? (
|
||||||
/>
|
<div className="absolute inset-0 flex items-center justify-center">
|
||||||
</div>
|
<span className="select-none text-center text-stone-400/80 text-sm">
|
||||||
)}
|
No kills found
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="h-full overflow-y-auto">
|
||||||
|
<SystemKillsContent
|
||||||
|
key={settings.compact ? 'compact' : 'normal'}
|
||||||
|
kills={filteredKills}
|
||||||
|
systemNameMap={systemNameMap}
|
||||||
|
compact={settings.compact}
|
||||||
|
onlyOneSystem={!visible}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</Widget>
|
</Widget>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{settingsDialogVisible && <KillsSettingsDialog visible setVisible={setSettingsDialogVisible} />}
|
<KillsSettingsDialog
|
||||||
|
visible={settingsDialogVisible}
|
||||||
|
setVisible={setSettingsDialogVisible}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
};
|
||||||
|
|
||||||
SystemKills.displayName = 'SystemKills';
|
|
||||||
|
|||||||
@@ -14,7 +14,3 @@
|
|||||||
white-space: pre-line;
|
white-space: pre-line;
|
||||||
line-height: 1.2rem;
|
line-height: 1.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.VirtualScroller {
|
|
||||||
height: 100% !important;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,17 +1,13 @@
|
|||||||
import React, { useMemo, useRef, useEffect, useState } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { DetailedKill } from '@/hooks/Mapper/types/kills';
|
import { DetailedKill } from '@/hooks/Mapper/types/kills';
|
||||||
import { VirtualScroller } from 'primereact/virtualscroller';
|
import { KillRow } from '../components/SystemKillsRow';
|
||||||
import { useSystemKillsItemTemplate } from '../hooks/useSystemKillsTemplate';
|
|
||||||
|
|
||||||
export interface SystemKillsContentProps {
|
interface SystemKillsContentProps {
|
||||||
kills: DetailedKill[];
|
kills: DetailedKill[];
|
||||||
systemNameMap: Record<string, string>;
|
systemNameMap: Record<string, string>;
|
||||||
compact?: boolean;
|
compact?: boolean;
|
||||||
onlyOneSystem?: boolean;
|
onlyOneSystem?: boolean;
|
||||||
autoSize?: boolean;
|
|
||||||
timeRange: number;
|
|
||||||
limit?: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SystemKillsContent: React.FC<SystemKillsContentProps> = ({
|
export const SystemKillsContent: React.FC<SystemKillsContentProps> = ({
|
||||||
@@ -19,73 +15,36 @@ export const SystemKillsContent: React.FC<SystemKillsContentProps> = ({
|
|||||||
systemNameMap,
|
systemNameMap,
|
||||||
compact = false,
|
compact = false,
|
||||||
onlyOneSystem = false,
|
onlyOneSystem = false,
|
||||||
autoSize = false,
|
|
||||||
timeRange = 1,
|
|
||||||
limit,
|
|
||||||
}) => {
|
}) => {
|
||||||
const processedKills = useMemo(() => {
|
const sortedKills = useMemo(() => {
|
||||||
const validKills = kills.filter(kill => kill.kill_time);
|
return [...kills].sort((a, b) => {
|
||||||
|
|
||||||
const sortedKills = validKills.sort((a, b) => {
|
|
||||||
const timeA = a.kill_time ? new Date(a.kill_time).getTime() : 0;
|
const timeA = a.kill_time ? new Date(a.kill_time).getTime() : 0;
|
||||||
const timeB = b.kill_time ? new Date(b.kill_time).getTime() : 0;
|
const timeB = b.kill_time ? new Date(b.kill_time).getTime() : 0;
|
||||||
return timeB - timeA;
|
return timeB - timeA;
|
||||||
});
|
});
|
||||||
|
}, [kills]);
|
||||||
if (limit != null) {
|
|
||||||
return sortedKills.slice(0, limit);
|
|
||||||
} else {
|
|
||||||
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, limit]);
|
|
||||||
|
|
||||||
const itemSize = compact ? 35 : 50;
|
|
||||||
const computedHeight = autoSize ? Math.max(processedKills.length, 1) * itemSize + 5 : undefined;
|
|
||||||
|
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
const scrollerRef = useRef<any>(null);
|
|
||||||
const [containerHeight, setContainerHeight] = useState<number>(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 (
|
return (
|
||||||
<div ref={autoSize ? undefined : containerRef} className="w-full h-full">
|
<div
|
||||||
<VirtualScroller
|
className={clsx(
|
||||||
ref={autoSize ? undefined : scrollerRef}
|
'flex flex-col w-full text-stone-200 text-xs transition-all duration-300',
|
||||||
items={processedKills}
|
compact ? 'p-1' : 'p-1'
|
||||||
itemSize={itemSize}
|
)}
|
||||||
itemTemplate={itemTemplate}
|
>
|
||||||
autoSize={autoSize}
|
{sortedKills.map(kill => {
|
||||||
style={{ height: autoSize ? `${computedHeight}px` : containerHeight ? `${containerHeight}px` : '100%' }}
|
const systemIdStr = String(kill.solar_system_id);
|
||||||
className={clsx('w-full h-full overflow-x-hidden overflow-y-auto custom-scrollbar select-none')}
|
const systemName = systemNameMap[systemIdStr] || `System ${systemIdStr}`;
|
||||||
/>
|
|
||||||
|
return (
|
||||||
|
<KillRow
|
||||||
|
key={kill.killmail_id}
|
||||||
|
killDetails={kill}
|
||||||
|
systemName={systemName}
|
||||||
|
isCompact={compact}
|
||||||
|
onlyOneSystem={onlyOneSystem}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,9 +21,14 @@ export interface CompactKillRowProps {
|
|||||||
onlyOneSystem: boolean;
|
onlyOneSystem: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CompactKillRow: React.FC<CompactKillRowProps> = ({ killDetails, systemName, onlyOneSystem }) => {
|
export const CompactKillRow: React.FC<CompactKillRowProps> = ({
|
||||||
|
killDetails,
|
||||||
|
systemName,
|
||||||
|
onlyOneSystem,
|
||||||
|
}) => {
|
||||||
const {
|
const {
|
||||||
killmail_id = 0,
|
killmail_id = 0,
|
||||||
|
|
||||||
// Victim
|
// Victim
|
||||||
victim_char_name = 'Unknown Pilot',
|
victim_char_name = 'Unknown Pilot',
|
||||||
victim_alliance_ticker = '',
|
victim_alliance_ticker = '',
|
||||||
@@ -35,6 +40,7 @@ export const CompactKillRow: React.FC<CompactKillRowProps> = ({ killDetails, sys
|
|||||||
victim_corp_id = 0,
|
victim_corp_id = 0,
|
||||||
victim_alliance_id = 0,
|
victim_alliance_id = 0,
|
||||||
victim_ship_type_id = 0,
|
victim_ship_type_id = 0,
|
||||||
|
|
||||||
// Attacker
|
// Attacker
|
||||||
final_blow_char_id = 0,
|
final_blow_char_id = 0,
|
||||||
final_blow_char_name = '',
|
final_blow_char_name = '',
|
||||||
@@ -45,54 +51,70 @@ export const CompactKillRow: React.FC<CompactKillRowProps> = ({ killDetails, sys
|
|||||||
final_blow_corp_id = 0,
|
final_blow_corp_id = 0,
|
||||||
final_blow_corp_name = '',
|
final_blow_corp_name = '',
|
||||||
final_blow_ship_type_id = 0,
|
final_blow_ship_type_id = 0,
|
||||||
|
|
||||||
kill_time = '',
|
kill_time = '',
|
||||||
total_value = 0,
|
total_value = 0,
|
||||||
} = killDetails || {};
|
} = killDetails || {};
|
||||||
|
|
||||||
const attackerIsNpc = final_blow_char_id === 0;
|
const attackerIsNpc = final_blow_char_id === 0;
|
||||||
|
|
||||||
const victimAffiliationTicker = victim_alliance_ticker || victim_corp_ticker || 'No Ticker';
|
// Tickers & strings
|
||||||
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 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 killTimeAgo = kill_time ? formatTimeMixed(kill_time) : '0h ago';
|
||||||
const attackerSubscript = getAttackerSubscript(killDetails);
|
const attackerSubscript = getAttackerSubscript(killDetails);
|
||||||
|
|
||||||
const { victimCorpLogoUrl, victimAllianceLogoUrl, victimShipUrl } = buildVictimImageUrls({
|
// Victim images, including the ship
|
||||||
|
const {
|
||||||
|
victimCorpLogoUrl,
|
||||||
|
victimAllianceLogoUrl,
|
||||||
|
victimShipUrl,
|
||||||
|
} = buildVictimImageUrls({
|
||||||
victim_char_id,
|
victim_char_id,
|
||||||
victim_ship_type_id,
|
victim_ship_type_id,
|
||||||
victim_corp_id,
|
victim_corp_id,
|
||||||
victim_alliance_id,
|
victim_alliance_id,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Attacker corp/alliance
|
||||||
const { attackerCorpLogoUrl, attackerAllianceLogoUrl } = buildAttackerImageUrls({
|
const { attackerCorpLogoUrl, attackerAllianceLogoUrl } = buildAttackerImageUrls({
|
||||||
final_blow_char_id,
|
final_blow_char_id,
|
||||||
final_blow_corp_id,
|
final_blow_corp_id,
|
||||||
final_blow_alliance_id,
|
final_blow_alliance_id,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { url: victimPrimaryLogoUrl, tooltip: victimPrimaryTooltip } = getPrimaryLogoAndTooltip(
|
// Victim corp/alliance logo
|
||||||
victimAllianceLogoUrl,
|
const { url: victimPrimaryLogoUrl, tooltip: victimPrimaryTooltip } =
|
||||||
victimCorpLogoUrl,
|
getPrimaryLogoAndTooltip(
|
||||||
victim_alliance_name,
|
victimAllianceLogoUrl,
|
||||||
victim_corp_name,
|
victimCorpLogoUrl,
|
||||||
'Victim',
|
victim_alliance_name,
|
||||||
);
|
victim_corp_name,
|
||||||
|
'Victim'
|
||||||
|
);
|
||||||
|
|
||||||
const { url: attackerPrimaryImageUrl, tooltip: attackerPrimaryTooltip } = getAttackerPrimaryImageAndTooltip(
|
// Attacker corp/alliance or NPC ship
|
||||||
attackerIsNpc,
|
const { url: attackerPrimaryImageUrl, tooltip: attackerPrimaryTooltip } =
|
||||||
attackerAllianceLogoUrl,
|
getAttackerPrimaryImageAndTooltip(
|
||||||
attackerCorpLogoUrl,
|
attackerIsNpc,
|
||||||
final_blow_alliance_name,
|
attackerAllianceLogoUrl,
|
||||||
final_blow_corp_name,
|
attackerCorpLogoUrl,
|
||||||
final_blow_ship_type_id,
|
final_blow_alliance_name,
|
||||||
);
|
final_blow_corp_name,
|
||||||
|
final_blow_ship_type_id
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'h-10 flex items-center border-b border-stone-800',
|
'h-10 flex items-center border-b border-stone-800',
|
||||||
'text-xs whitespace-nowrap overflow-hidden leading-none',
|
'text-xs whitespace-nowrap overflow-hidden leading-none'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
@@ -107,13 +129,19 @@ export const CompactKillRow: React.FC<CompactKillRowProps> = ({ killDetails, sys
|
|||||||
<img
|
<img
|
||||||
src={victimShipUrl}
|
src={victimShipUrl}
|
||||||
alt="VictimShip"
|
alt="VictimShip"
|
||||||
className={clsx(classes.killRowImage, 'w-full h-full object-contain')}
|
className={clsx(
|
||||||
|
classes.killRowImage,
|
||||||
|
'w-full h-full object-contain'
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{victimPrimaryLogoUrl && (
|
{victimPrimaryLogoUrl && (
|
||||||
<WdTooltipWrapper content={victimPrimaryTooltip} position={TooltipPosition.top}>
|
<WdTooltipWrapper
|
||||||
|
content={victimPrimaryTooltip}
|
||||||
|
position={TooltipPosition.top}
|
||||||
|
>
|
||||||
<a
|
<a
|
||||||
href={zkillLink('kill', killmail_id)}
|
href={zkillLink('kill', killmail_id)}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
@@ -123,13 +151,16 @@ export const CompactKillRow: React.FC<CompactKillRowProps> = ({ killDetails, sys
|
|||||||
<img
|
<img
|
||||||
src={victimPrimaryLogoUrl}
|
src={victimPrimaryLogoUrl}
|
||||||
alt="VictimPrimaryLogo"
|
alt="VictimPrimaryLogo"
|
||||||
className={clsx(classes.killRowImage, 'w-full h-full object-contain')}
|
className={clsx(
|
||||||
|
classes.killRowImage,
|
||||||
|
'w-full h-full object-contain'
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</WdTooltipWrapper>
|
</WdTooltipWrapper>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col ml-2 flex-1 min-w-0 overflow-hidden leading-[1rem]">
|
<div className="flex flex-col ml-2 min-w-0 overflow-hidden leading-[1rem]">
|
||||||
<div className="truncate text-stone-200">
|
<div className="truncate text-stone-200">
|
||||||
{victim_char_name}
|
{victim_char_name}
|
||||||
<span className="text-stone-400"> / {victimAffiliationTicker}</span>
|
<span className="text-stone-400"> / {victimAffiliationTicker}</span>
|
||||||
@@ -145,17 +176,20 @@ export const CompactKillRow: React.FC<CompactKillRowProps> = ({ killDetails, sys
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center ml-auto gap-2">
|
<div className="flex items-center ml-auto gap-2">
|
||||||
<div className="flex flex-col items-end flex-1 min-w-0 overflow-hidden text-right leading-[1rem]">
|
<div className="flex flex-col items-end min-w-0 overflow-hidden text-right leading-[1rem]">
|
||||||
{!attackerIsNpc && (attackerName || attackerTicker) && (
|
{!attackerIsNpc && (attackerName || attackerTicker) && (
|
||||||
<div className="truncate text-stone-200">
|
<div className="truncate text-stone-200">
|
||||||
{attackerName}
|
{attackerName}
|
||||||
{attackerTicker && <span className="ml-1 text-stone-400">/ {attackerTicker}</span>}
|
{attackerTicker && (
|
||||||
|
<span className="ml-1 text-stone-400">/ {attackerTicker}</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="truncate text-stone-400">
|
<div className="truncate text-stone-400">
|
||||||
{!onlyOneSystem && systemName ? (
|
{!onlyOneSystem && systemName ? (
|
||||||
<>
|
<>
|
||||||
{systemName} / <span className="ml-1 text-red-400">{killTimeAgo}</span>
|
{systemName} /{' '}
|
||||||
|
<span className="ml-1 text-red-400">{killTimeAgo}</span>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<span className="text-red-400">{killTimeAgo}</span>
|
<span className="text-red-400">{killTimeAgo}</span>
|
||||||
@@ -163,7 +197,10 @@ export const CompactKillRow: React.FC<CompactKillRowProps> = ({ killDetails, sys
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{attackerPrimaryImageUrl && (
|
{attackerPrimaryImageUrl && (
|
||||||
<WdTooltipWrapper content={attackerPrimaryTooltip} position={TooltipPosition.top}>
|
<WdTooltipWrapper
|
||||||
|
content={attackerPrimaryTooltip}
|
||||||
|
position={TooltipPosition.top}
|
||||||
|
>
|
||||||
<a
|
<a
|
||||||
href={zkillLink('kill', killmail_id)}
|
href={zkillLink('kill', killmail_id)}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
@@ -173,14 +210,17 @@ export const CompactKillRow: React.FC<CompactKillRowProps> = ({ killDetails, sys
|
|||||||
<img
|
<img
|
||||||
src={attackerPrimaryImageUrl}
|
src={attackerPrimaryImageUrl}
|
||||||
alt={attackerIsNpc ? 'NpcShip' : 'AttackerPrimaryLogo'}
|
alt={attackerIsNpc ? 'NpcShip' : 'AttackerPrimaryLogo'}
|
||||||
className={clsx(classes.killRowImage, 'w-full h-full object-contain')}
|
className={clsx(
|
||||||
|
classes.killRowImage,
|
||||||
|
'w-full h-full object-contain'
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
{attackerSubscript && (
|
{attackerSubscript && (
|
||||||
<span
|
<span
|
||||||
className={clsx(
|
className={clsx(
|
||||||
classes.attackerCountLabel,
|
classes.attackerCountLabel,
|
||||||
attackerSubscript.cssClass,
|
attackerSubscript.cssClass,
|
||||||
'text-[0.6rem] leading-none px-[2px]',
|
'text-[0.6rem] leading-none px-[2px]'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{attackerSubscript.label}
|
{attackerSubscript.label}
|
||||||
|
|||||||
@@ -22,7 +22,11 @@ export interface FullKillRowProps {
|
|||||||
onlyOneSystem: boolean;
|
onlyOneSystem: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FullKillRow: React.FC<FullKillRowProps> = ({ killDetails, systemName, onlyOneSystem }) => {
|
export const FullKillRow: React.FC<FullKillRowProps> = ({
|
||||||
|
killDetails,
|
||||||
|
systemName,
|
||||||
|
onlyOneSystem,
|
||||||
|
}) => {
|
||||||
const {
|
const {
|
||||||
killmail_id = 0,
|
killmail_id = 0,
|
||||||
// Victim data
|
// Victim data
|
||||||
@@ -53,13 +57,21 @@ export const FullKillRow: React.FC<FullKillRowProps> = ({ killDetails, systemNam
|
|||||||
|
|
||||||
const attackerIsNpc = final_blow_char_id === 0;
|
const attackerIsNpc = final_blow_char_id === 0;
|
||||||
const victimAffiliation = victim_alliance_ticker || victim_corp_ticker || null;
|
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';
|
const killTimeAgo = kill_time ? formatTimeMixed(kill_time) : '0h ago';
|
||||||
|
|
||||||
// Build victim images
|
// Build victim images
|
||||||
const { victimPortraitUrl, victimCorpLogoUrl, victimAllianceLogoUrl, victimShipUrl } = buildVictimImageUrls({
|
const {
|
||||||
|
victimPortraitUrl,
|
||||||
|
victimCorpLogoUrl,
|
||||||
|
victimAllianceLogoUrl,
|
||||||
|
victimShipUrl,
|
||||||
|
} = buildVictimImageUrls({
|
||||||
victim_char_id,
|
victim_char_id,
|
||||||
victim_ship_type_id,
|
victim_ship_type_id,
|
||||||
victim_corp_id,
|
victim_corp_id,
|
||||||
@@ -67,35 +79,47 @@ export const FullKillRow: React.FC<FullKillRowProps> = ({ killDetails, systemNam
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Build attacker images
|
// Build attacker images
|
||||||
const { attackerPortraitUrl, attackerCorpLogoUrl, attackerAllianceLogoUrl } = buildAttackerImageUrls({
|
const {
|
||||||
|
attackerPortraitUrl,
|
||||||
|
attackerCorpLogoUrl,
|
||||||
|
attackerAllianceLogoUrl,
|
||||||
|
} = buildAttackerImageUrls({
|
||||||
final_blow_char_id,
|
final_blow_char_id,
|
||||||
final_blow_corp_id,
|
final_blow_corp_id,
|
||||||
final_blow_alliance_id,
|
final_blow_alliance_id,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Primary image for victim
|
// Primary image for victim
|
||||||
const { url: victimPrimaryImageUrl, tooltip: victimPrimaryTooltip } = getPrimaryLogoAndTooltip(
|
const { url: victimPrimaryImageUrl, tooltip: victimPrimaryTooltip } =
|
||||||
victimAllianceLogoUrl,
|
getPrimaryLogoAndTooltip(
|
||||||
victimCorpLogoUrl,
|
victimAllianceLogoUrl,
|
||||||
victim_alliance_name,
|
victimCorpLogoUrl,
|
||||||
victim_corp_name,
|
victim_alliance_name,
|
||||||
'Victim',
|
victim_corp_name,
|
||||||
);
|
'Victim'
|
||||||
|
);
|
||||||
|
|
||||||
// Primary image for attacker
|
// Primary image for attacker
|
||||||
const { url: attackerPrimaryImageUrl, tooltip: attackerPrimaryTooltip } = getAttackerPrimaryImageAndTooltip(
|
const { url: attackerPrimaryImageUrl, tooltip: attackerPrimaryTooltip } =
|
||||||
attackerIsNpc,
|
getAttackerPrimaryImageAndTooltip(
|
||||||
attackerAllianceLogoUrl,
|
attackerIsNpc,
|
||||||
attackerCorpLogoUrl,
|
attackerAllianceLogoUrl,
|
||||||
final_blow_alliance_name,
|
attackerCorpLogoUrl,
|
||||||
final_blow_corp_name,
|
final_blow_alliance_name,
|
||||||
final_blow_ship_type_id,
|
final_blow_corp_name,
|
||||||
);
|
final_blow_ship_type_id
|
||||||
|
);
|
||||||
|
|
||||||
const attackerSubscript = getAttackerSubscript(killDetails);
|
const attackerSubscript = getAttackerSubscript(killDetails);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={clsx(classes.killRowContainer, 'w-full text-sm py-1 px-2', 'flex flex-col sm:flex-row')}>
|
<div
|
||||||
|
className={clsx(
|
||||||
|
classes.killRowContainer,
|
||||||
|
'w-full text-sm py-1 px-2',
|
||||||
|
'flex flex-col sm:flex-row'
|
||||||
|
)}
|
||||||
|
>
|
||||||
<div className="w-full flex flex-col sm:flex-row items-start gap-2">
|
<div className="w-full flex flex-col sm:flex-row items-start gap-2">
|
||||||
{/* Victim Section */}
|
{/* Victim Section */}
|
||||||
<div className="flex items-start gap-1 min-w-0">
|
<div className="flex items-start gap-1 min-w-0">
|
||||||
@@ -110,13 +134,19 @@ export const FullKillRow: React.FC<FullKillRowProps> = ({ killDetails, systemNam
|
|||||||
<img
|
<img
|
||||||
src={victimShipUrl}
|
src={victimShipUrl}
|
||||||
alt="VictimShip"
|
alt="VictimShip"
|
||||||
className={clsx(classes.killRowImage, 'w-full h-full object-contain')}
|
className={clsx(
|
||||||
|
classes.killRowImage,
|
||||||
|
'w-full h-full object-contain'
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{victimPrimaryImageUrl && (
|
{victimPrimaryImageUrl && (
|
||||||
<WdTooltipWrapper content={victimPrimaryTooltip} position={TooltipPosition.top}>
|
<WdTooltipWrapper
|
||||||
|
content={victimPrimaryTooltip}
|
||||||
|
position={TooltipPosition.top}
|
||||||
|
>
|
||||||
<div className="relative shrink-0 w-12 h-12 sm:w-14 sm:h-14 overflow-hidden">
|
<div className="relative shrink-0 w-12 h-12 sm:w-14 sm:h-14 overflow-hidden">
|
||||||
<a
|
<a
|
||||||
href={zkillLink('kill', killmail_id)}
|
href={zkillLink('kill', killmail_id)}
|
||||||
@@ -127,7 +157,10 @@ export const FullKillRow: React.FC<FullKillRowProps> = ({ killDetails, systemNam
|
|||||||
<img
|
<img
|
||||||
src={victimPrimaryImageUrl}
|
src={victimPrimaryImageUrl}
|
||||||
alt="VictimPrimaryLogo"
|
alt="VictimPrimaryLogo"
|
||||||
className={clsx(classes.killRowImage, 'w-full h-full object-contain')}
|
className={clsx(
|
||||||
|
classes.killRowImage,
|
||||||
|
'w-full h-full object-contain'
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -138,10 +171,12 @@ export const FullKillRow: React.FC<FullKillRowProps> = ({ killDetails, systemNam
|
|||||||
victimCharacterId={victim_char_id}
|
victimCharacterId={victim_char_id}
|
||||||
victimPortraitUrl={victimPortraitUrl}
|
victimPortraitUrl={victimPortraitUrl}
|
||||||
/>
|
/>
|
||||||
<div className="flex flex-col flex-1 text-stone-200 leading-4 min-w-0 overflow-hidden">
|
<div className="flex flex-col text-stone-200 leading-4 min-w-0 overflow-hidden">
|
||||||
<div className="truncate font-semibold">
|
<div className="truncate font-semibold">
|
||||||
{victim_char_name}
|
{victim_char_name}
|
||||||
{victimAffiliation && <span className="ml-1 text-stone-400">/ {victimAffiliation}</span>}
|
{victimAffiliation && (
|
||||||
|
<span className="ml-1 text-stone-400">/ {victimAffiliation}</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="truncate text-stone-300">
|
<div className="truncate text-stone-300">
|
||||||
{victim_ship_name}
|
{victim_ship_name}
|
||||||
@@ -152,15 +187,20 @@ export const FullKillRow: React.FC<FullKillRowProps> = ({ killDetails, systemNam
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="truncate text-stone-400">{!onlyOneSystem && systemName && <span>{systemName}</span>}</div>
|
<div className="truncate text-stone-400">
|
||||||
|
{!onlyOneSystem && systemName && <span>{systemName}</span>}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{/* Attacker Section */}
|
||||||
<div className="flex items-start gap-1 min-w-0 sm:ml-auto">
|
<div className="flex items-start gap-1 min-w-0 sm:ml-auto">
|
||||||
<div className="flex flex-col flex-1 items-end leading-4 min-w-0 overflow-hidden text-right">
|
<div className="flex flex-col items-end leading-4 min-w-0 overflow-hidden text-right">
|
||||||
{!attackerIsNpc && (
|
{!attackerIsNpc && (
|
||||||
<div className="truncate font-semibold">
|
<div className="truncate font-semibold">
|
||||||
{final_blow_char_name}
|
{final_blow_char_name}
|
||||||
{attackerAffiliation && <span className="ml-1 text-stone-400">/ {attackerAffiliation}</span>}
|
{attackerAffiliation && (
|
||||||
|
<span className="ml-1 text-stone-400">/ {attackerAffiliation}</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{!attackerIsNpc && final_blow_ship_name && (
|
{!attackerIsNpc && final_blow_ship_name && (
|
||||||
@@ -168,7 +208,7 @@ export const FullKillRow: React.FC<FullKillRowProps> = ({ killDetails, systemNam
|
|||||||
)}
|
)}
|
||||||
<div className="truncate text-red-400">{killTimeAgo}</div>
|
<div className="truncate text-red-400">{killTimeAgo}</div>
|
||||||
</div>
|
</div>
|
||||||
{!attackerIsNpc && attackerPortraitUrl && final_blow_char_id &&final_blow_char_id > 0 && (
|
{(!attackerIsNpc && attackerPortraitUrl && final_blow_char_id > 0) && (
|
||||||
<div className="relative shrink-0 w-12 h-12 sm:w-14 sm:h-14 overflow-hidden">
|
<div className="relative shrink-0 w-12 h-12 sm:w-14 sm:h-14 overflow-hidden">
|
||||||
<a
|
<a
|
||||||
href={zkillLink('character', final_blow_char_id)}
|
href={zkillLink('character', final_blow_char_id)}
|
||||||
@@ -179,13 +219,19 @@ export const FullKillRow: React.FC<FullKillRowProps> = ({ killDetails, systemNam
|
|||||||
<img
|
<img
|
||||||
src={attackerPortraitUrl}
|
src={attackerPortraitUrl}
|
||||||
alt="AttackerPortrait"
|
alt="AttackerPortrait"
|
||||||
className={clsx(classes.killRowImage, 'w-full h-full object-contain')}
|
className={clsx(
|
||||||
|
classes.killRowImage,
|
||||||
|
'w-full h-full object-contain'
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{attackerPrimaryImageUrl && (
|
{attackerPrimaryImageUrl && (
|
||||||
<WdTooltipWrapper content={attackerPrimaryTooltip} position={TooltipPosition.top}>
|
<WdTooltipWrapper
|
||||||
|
content={attackerPrimaryTooltip}
|
||||||
|
position={TooltipPosition.top}
|
||||||
|
>
|
||||||
<div className="relative shrink-0 w-12 h-12 sm:w-14 sm:h-14 overflow-hidden">
|
<div className="relative shrink-0 w-12 h-12 sm:w-14 sm:h-14 overflow-hidden">
|
||||||
<a
|
<a
|
||||||
href={zkillLink('kill', killmail_id)}
|
href={zkillLink('kill', killmail_id)}
|
||||||
@@ -196,10 +242,18 @@ export const FullKillRow: React.FC<FullKillRowProps> = ({ killDetails, systemNam
|
|||||||
<img
|
<img
|
||||||
src={attackerPrimaryImageUrl}
|
src={attackerPrimaryImageUrl}
|
||||||
alt={attackerIsNpc ? 'NpcShip' : 'AttackerPrimaryLogo'}
|
alt={attackerIsNpc ? 'NpcShip' : 'AttackerPrimaryLogo'}
|
||||||
className={clsx(classes.killRowImage, 'w-full h-full object-contain')}
|
className={clsx(
|
||||||
|
classes.killRowImage,
|
||||||
|
'w-full h-full object-contain'
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
{attackerSubscript && (
|
{attackerSubscript && (
|
||||||
<span className={clsx(attackerSubscript.cssClass, classes.attackerCountLabel)}>
|
<span
|
||||||
|
className={clsx(
|
||||||
|
attackerSubscript.cssClass,
|
||||||
|
classes.attackerCountLabel
|
||||||
|
)}
|
||||||
|
>
|
||||||
{attackerSubscript.label}
|
{attackerSubscript.label}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
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<string, string>,
|
|
||||||
compact: boolean,
|
|
||||||
onlyOneSystem: boolean,
|
|
||||||
kill: DetailedKill,
|
|
||||||
options: VirtualScrollerTemplateOptions,
|
|
||||||
) {
|
|
||||||
const systemIdStr = String(kill.solar_system_id);
|
|
||||||
const systemName = systemNameMap[systemIdStr] || `System ${systemIdStr}`;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div style={{ height: `${options.props.itemSize}px` }} className={clsx({ 'bg-gray-900': options.odd })}>
|
|
||||||
<KillRow killDetails={kill} systemName={systemName} isCompact={compact} onlyOneSystem={onlyOneSystem} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -10,7 +10,7 @@ export interface KillRowProps {
|
|||||||
onlyOneSystem?: boolean;
|
onlyOneSystem?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const KillRowComponent: React.FC<KillRowProps> = ({
|
export const KillRow: React.FC<KillRowProps> = ({
|
||||||
killDetails,
|
killDetails,
|
||||||
systemName,
|
systemName,
|
||||||
isCompact = false,
|
isCompact = false,
|
||||||
@@ -19,7 +19,6 @@ const KillRowComponent: React.FC<KillRowProps> = ({
|
|||||||
if (isCompact) {
|
if (isCompact) {
|
||||||
return <CompactKillRow killDetails={killDetails} systemName={systemName} onlyOneSystem={onlyOneSystem} />;
|
return <CompactKillRow killDetails={killDetails} systemName={systemName} onlyOneSystem={onlyOneSystem} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <FullKillRow killDetails={killDetails} systemName={systemName} onlyOneSystem={onlyOneSystem} />;
|
return <FullKillRow killDetails={killDetails} systemName={systemName} onlyOneSystem={onlyOneSystem} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const KillRow = React.memo(KillRowComponent);
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { Dialog } from 'primereact/dialog';
|
import { Dialog } from 'primereact/dialog';
|
||||||
import { Button } from 'primereact/button';
|
import { Button } from 'primereact/button';
|
||||||
import { InputSwitch } from 'primereact/inputswitch';
|
|
||||||
import { WdImgButton, SystemView, TooltipPosition } from '@/hooks/Mapper/components/ui-kit';
|
import { WdImgButton, SystemView, TooltipPosition } from '@/hooks/Mapper/components/ui-kit';
|
||||||
import { PrimeIcons } from 'primereact/api';
|
import { PrimeIcons } from 'primereact/api';
|
||||||
import { useKillsWidgetSettings } from '../hooks/useKillsWidgetSettings';
|
import { useKillsWidgetSettings } from '../hooks/useKillsWidgetSettings';
|
||||||
@@ -22,10 +21,10 @@ export const KillsSettingsDialog: React.FC<KillsSettingsDialogProps> = ({ visibl
|
|||||||
showAll: globalSettings.showAll,
|
showAll: globalSettings.showAll,
|
||||||
whOnly: globalSettings.whOnly,
|
whOnly: globalSettings.whOnly,
|
||||||
excludedSystems: globalSettings.excludedSystems || [],
|
excludedSystems: globalSettings.excludedSystems || [],
|
||||||
timeRange: globalSettings.timeRange,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const [, forceRender] = useState(0);
|
const [, forceRender] = useState(0);
|
||||||
|
|
||||||
const [addSystemDialogVisible, setAddSystemDialogVisible] = useState(false);
|
const [addSystemDialogVisible, setAddSystemDialogVisible] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -35,7 +34,6 @@ export const KillsSettingsDialog: React.FC<KillsSettingsDialogProps> = ({ visibl
|
|||||||
showAll: globalSettings.showAll,
|
showAll: globalSettings.showAll,
|
||||||
whOnly: globalSettings.whOnly,
|
whOnly: globalSettings.whOnly,
|
||||||
excludedSystems: globalSettings.excludedSystems || [],
|
excludedSystems: globalSettings.excludedSystems || [],
|
||||||
timeRange: globalSettings.timeRange,
|
|
||||||
};
|
};
|
||||||
forceRender(n => n + 1);
|
forceRender(n => n + 1);
|
||||||
}
|
}
|
||||||
@@ -57,15 +55,6 @@ export const KillsSettingsDialog: React.FC<KillsSettingsDialogProps> = ({ visibl
|
|||||||
forceRender(n => n + 1);
|
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) => {
|
const handleRemoveSystem = useCallback((sysId: number) => {
|
||||||
localRef.current = {
|
localRef.current = {
|
||||||
...localRef.current,
|
...localRef.current,
|
||||||
@@ -122,18 +111,11 @@ export const KillsSettingsDialog: React.FC<KillsSettingsDialogProps> = ({ visibl
|
|||||||
checked={localData.whOnly}
|
checked={localData.whOnly}
|
||||||
onChange={e => handleWHChange(e.target.checked)}
|
onChange={e => handleWHChange(e.target.checked)}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="kills-wormhole-only-mode" className="cursor-pointer">
|
<label htmlFor="kills-wh-only-mode" className="cursor-pointer">
|
||||||
Only show wormhole kills
|
Only show wormhole kills
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Time Range Toggle using InputSwitch */}
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<span className="text-sm">Time Range:</span>
|
|
||||||
<InputSwitch checked={localData.timeRange === 24} onChange={e => handleTimeRangeChange(e.value ? 24 : 1)} />
|
|
||||||
<span className="text-sm">{localData.timeRange === 24 ? '24 Hours' : '1 Hour'}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<label className="text-sm text-stone-400">Excluded Systems</label>
|
<label className="text-sm text-stone-400">Excluded Systems</label>
|
||||||
@@ -146,7 +128,7 @@ export const KillsSettingsDialog: React.FC<KillsSettingsDialogProps> = ({ visibl
|
|||||||
{excluded.length === 0 && <div className="text-stone-500 text-xs italic">No systems excluded.</div>}
|
{excluded.length === 0 && <div className="text-stone-500 text-xs italic">No systems excluded.</div>}
|
||||||
{excluded.map(sysId => (
|
{excluded.map(sysId => (
|
||||||
<div key={sysId} className="flex items-center justify-between border-b border-stone-600 py-1 px-1 text-xs">
|
<div key={sysId} className="flex items-center justify-between border-b border-stone-600 py-1 px-1 text-xs">
|
||||||
<SystemView systemId={sysId.toString()} hideRegion compact />
|
<SystemView systemId={sysId.toString()} hideRegion compact/>
|
||||||
|
|
||||||
<WdImgButton
|
<WdImgButton
|
||||||
className={PrimeIcons.TRASH}
|
className={PrimeIcons.TRASH}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ export interface KillsWidgetSettings {
|
|||||||
whOnly: boolean;
|
whOnly: boolean;
|
||||||
excludedSystems: number[];
|
excludedSystems: number[];
|
||||||
version: number;
|
version: number;
|
||||||
timeRange: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DEFAULT_KILLS_WIDGET_SETTINGS: KillsWidgetSettings = {
|
export const DEFAULT_KILLS_WIDGET_SETTINGS: KillsWidgetSettings = {
|
||||||
@@ -15,8 +14,7 @@ export const DEFAULT_KILLS_WIDGET_SETTINGS: KillsWidgetSettings = {
|
|||||||
showAll: false,
|
showAll: false,
|
||||||
whOnly: true,
|
whOnly: true,
|
||||||
excludedSystems: [],
|
excludedSystems: [],
|
||||||
version: 1,
|
version: 0,
|
||||||
timeRange: 1,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function mergeWithDefaults(settings?: Partial<KillsWidgetSettings>): KillsWidgetSettings {
|
function mergeWithDefaults(settings?: Partial<KillsWidgetSettings>): KillsWidgetSettings {
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
// 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<string, string>,
|
|
||||||
compact: boolean,
|
|
||||||
onlyOneSystem: boolean,
|
|
||||||
) {
|
|
||||||
return useCallback(
|
|
||||||
(kill: DetailedKill, options: VirtualScrollerTemplateOptions) =>
|
|
||||||
KillItemTemplate(systemNameMap, compact, onlyOneSystem, kill, options),
|
|
||||||
[systemNameMap, compact, onlyOneSystem],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user