Compare commits

..

2 Commits

10 changed files with 235 additions and 53 deletions

View File

@@ -1,11 +1,3 @@
import {
MASS_STATE_NAMES,
MASS_STATE_NAMES_ORDER,
SHIP_SIZES_NAMES,
SHIP_SIZES_NAMES_ORDER,
SHIP_SIZES_NAMES_SHORT,
SHIP_SIZES_SIZE,
} from '@/hooks/Mapper/components/map/constants.ts';
import { ConnectionType, MassState, ShipSizeStatus, SolarSystemConnection, TimeStatus } from '@/hooks/Mapper/types';
import clsx from 'clsx';
import { PrimeIcons } from 'primereact/api';
@@ -14,6 +6,8 @@ import { MenuItem } from 'primereact/menuitem';
import React, { RefObject, useMemo } from 'react';
import { Edge } from 'reactflow';
import { LifetimeActionsWrapper } from '@/hooks/Mapper/components/map/components/ContextMenuConnection/LifetimeActionsWrapper.tsx';
import { MassStatusActionsWrapper } from '@/hooks/Mapper/components/map/components/ContextMenuConnection/MassStatusActionsWrapper.tsx';
import { ShipSizeActionsWrapper } from '@/hooks/Mapper/components/map/components/ContextMenuConnection/ShipSizeActionsWrapper.tsx';
import classes from './ContextMenuConnection.module.scss';
import { getSystemStaticInfo } from '@/hooks/Mapper/mapRootProvider/hooks/useLoadSystemStatic.ts';
import { isNullsecSpace } from '@/hooks/Mapper/components/map/helpers/isKnownSpace.ts';
@@ -86,16 +80,28 @@ export const ContextMenuConnection: React.FC<ContextMenuConnectionProps> = ({
return <LifetimeActionsWrapper lifetime={edge.data?.time_status} onChangeLifetime={onChangeTimeState} />;
},
},
...(!isFrigateSize
? [
{
className: clsx(classes.FastActions, '!h-[54px]'),
template: () => {
return (
<MassStatusActionsWrapper
massStatus={edge.data?.mass_status}
onChangeMassStatus={onChangeMassState}
/>
);
},
},
]
: []),
{
label: `Frigate`,
className: clsx({
[classes.ConnectionFrigate]: isFrigateSize,
}),
icon: PrimeIcons.CLOUD,
command: () =>
onChangeShipSizeStatus(
edge.data?.ship_size_type === ShipSizeStatus.small ? ShipSizeStatus.large : ShipSizeStatus.small,
),
className: clsx(classes.FastActions, '!h-[64px]'),
template: () => {
return (
<ShipSizeActionsWrapper shipSize={edge.data?.ship_size_type} onChangeShipSize={onChangeShipSizeStatus} />
);
},
},
{
label: `Save mass`,
@@ -105,41 +111,6 @@ export const ContextMenuConnection: React.FC<ContextMenuConnectionProps> = ({
icon: PrimeIcons.LOCK,
command: () => onToggleMassSave(!edge.data?.locked),
},
...(!isFrigateSize
? [
{
label: `Mass status`,
icon: PrimeIcons.CHART_PIE,
items: MASS_STATE_NAMES_ORDER.map(x => ({
label: MASS_STATE_NAMES[x],
className: clsx({
[classes.SelectedItem]: edge.data?.mass_status === x,
}),
command: () => onChangeMassState(x),
})),
},
]
: []),
{
label: `Ship Size`,
icon: PrimeIcons.CLOUD,
items: SHIP_SIZES_NAMES_ORDER.map(x => ({
label: (
<div className="grid grid-cols-[20px_120px_1fr_40px] gap-2 items-center">
<div className="text-[12px] font-bold text-stone-400">{SHIP_SIZES_NAMES_SHORT[x]}</div>
<div>{SHIP_SIZES_NAMES[x]}</div>
<div></div>
<div className="flex justify-end whitespace-nowrap text-[12px] font-bold text-stone-500">
{SHIP_SIZES_SIZE[x]} t.
</div>
</div>
) as unknown as string, // TODO my lovely kostyl
className: clsx({
[classes.SelectedItem]: edge.data?.ship_size_type === x,
}),
command: () => onChangeShipSizeStatus(x),
})),
},
...(bothNullsec
? [
{

View File

@@ -0,0 +1,15 @@
import { LayoutEventBlocker } from '@/hooks/Mapper/components/ui-kit';
import {
WdMassStatusSelector,
WdMassStatusSelectorProps,
} from '@/hooks/Mapper/components/ui-kit/WdMassStatusSelector.tsx';
export const MassStatusActionsWrapper = (props: WdMassStatusSelectorProps) => {
return (
<LayoutEventBlocker className="flex flex-col gap-1 w-[100%] h-full px-2 pt-[4px]">
<div className="text-[12px] text-stone-500 font-semibold">Mass status:</div>
<WdMassStatusSelector {...props} />
</LayoutEventBlocker>
);
};

View File

@@ -0,0 +1,12 @@
import { LayoutEventBlocker } from '@/hooks/Mapper/components/ui-kit';
import { WdShipSizeSelector, WdShipSizeSelectorProps } from '@/hooks/Mapper/components/ui-kit/WdShipSizeSelector.tsx';
export const ShipSizeActionsWrapper = (props: WdShipSizeSelectorProps) => {
return (
<LayoutEventBlocker className="flex flex-col gap-1 w-[100%] h-full px-2 pt-[4px]">
<div className="text-[12px] text-stone-500 font-semibold">Ship size:</div>
<WdShipSizeSelector {...props} />
</LayoutEventBlocker>
);
};

View File

@@ -5,7 +5,7 @@ import {
import { SystemsSettingsProvider } from '@/hooks/Mapper/components/mapRootContent/components/SignatureSettings/Provider.tsx';
import { WdButton } from '@/hooks/Mapper/components/ui-kit';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import { OutCommand, SignatureGroup, SystemSignature, TimeStatus } from '@/hooks/Mapper/types';
import { MassState, OutCommand, SignatureGroup, SystemSignature, TimeStatus } from '@/hooks/Mapper/types';
import { Dialog } from 'primereact/dialog';
import { InputText } from 'primereact/inputtext';
import { useCallback, useEffect } from 'react';
@@ -15,6 +15,7 @@ type SystemSignaturePrepared = Omit<SystemSignature, 'linked_system'> & {
linked_system: string;
k162Type: string;
time_status: TimeStatus;
mass_status: MassState;
};
export interface MapSettingsProps {
@@ -59,6 +60,7 @@ export const SignatureSettings = ({ systemId, show, onHide, signatureData }: Map
custom_info: JSON.stringify({
k162Type: values.k162Type,
time_status: values.time_status,
mass_status: values.mass_status,
}),
};
@@ -139,16 +141,19 @@ export const SignatureSettings = ({ systemId, show, onHide, signatureData }: Map
let k162Type = null;
let time_status = TimeStatus._24h;
let mass_status = MassState.normal;
if (custom_info) {
const customInfo = JSON.parse(custom_info);
k162Type = customInfo.k162Type;
time_status = customInfo.time_status;
mass_status = customInfo.mass_status ?? MassState.normal;
}
signatureForm.reset({
linked_system: linked_system?.solar_system_id.toString() ?? undefined,
k162Type: k162Type,
time_status: time_status,
mass_status: mass_status,
...rest,
});
}, [signatureForm, signatureData]);

View File

@@ -5,6 +5,7 @@ import { SignatureK162TypeSelect } from '@/hooks/Mapper/components/mapRootConten
import { SignatureLeadsToSelect } from '@/hooks/Mapper/components/mapRootContent/components/SignatureSettings/components/SignatureLeadsToSelect';
import { SignatureLifetimeSelect } from '@/hooks/Mapper/components/mapRootContent/components/SignatureSettings/components/SignatureLifetimeSelect.tsx';
import { SignatureTempName } from '@/hooks/Mapper/components/mapRootContent/components/SignatureSettings/components/SignatureTempName.tsx';
import { SignatureMassStatusSelect } from '@/hooks/Mapper/components/mapRootContent/components/SignatureSettings/components/SignatureMassStatusSelect.tsx';
export const SignatureGroupContentWormholes = () => {
const { watch } = useFormContext<SystemSignature>();
@@ -34,6 +35,11 @@ export const SignatureGroupContentWormholes = () => {
<SignatureLifetimeSelect name="time_status" />
</div>
<div className="grid grid-cols-[100px_250px_1fr] gap-2 items-center text-[14px]">
<span>Mass status:</span>
<SignatureMassStatusSelect name="mass_status" />
</div>
<label className="grid grid-cols-[100px_250px_1fr] gap-2 items-center text-[14px]">
<span>Temp. Name:</span>
<SignatureTempName />

View File

@@ -0,0 +1,30 @@
import { Controller, useFormContext } from 'react-hook-form';
import { MassState, SystemSignature } from '@/hooks/Mapper/types';
import { WdMassStatusSelector } from '@/hooks/Mapper/components/ui-kit/WdMassStatusSelector.tsx';
export interface SignatureMassStatusSelectProps {
name: string;
defaultValue?: MassState;
}
export const SignatureMassStatusSelect = ({
name,
defaultValue = MassState.normal,
}: SignatureMassStatusSelectProps) => {
const { control } = useFormContext<SystemSignature>();
return (
<div className="my-1">
<Controller
// @ts-ignore
name={name}
control={control}
defaultValue={defaultValue}
render={({ field }) => {
// @ts-ignore
return <WdMassStatusSelector massStatus={field.value} onChangeMassStatus={e => field.onChange(e)} />;
}}
/>
</div>
);
};

View File

@@ -2,3 +2,4 @@ export * from './SignatureGroupSelect';
export * from './SignatureGroupContent';
export * from './SignatureK162TypeSelect';
export * from './SignatureLifetimeSelect';
export * from './SignatureMassStatusSelect';

View File

@@ -0,0 +1,65 @@
import { WdButton } from '@/hooks/Mapper/components/ui-kit/WdButton.tsx';
import { MassState } from '@/hooks/Mapper/types';
import clsx from 'clsx';
import { BUILT_IN_TOOLTIP_OPTIONS } from './constants.ts';
const MASS_STATUS = [
{
id: MassState.verge,
label: 'Verge',
className: 'bg-red-400 hover:!bg-red-400',
inactiveClassName: 'bg-red-400/30',
description: 'Mass status: Verge of collapse',
},
{
id: MassState.half,
label: 'Half',
className: 'bg-orange-300 hover:!bg-orange-300',
inactiveClassName: 'bg-orange-300/30',
description: 'Mass status: Half',
},
{
id: MassState.normal,
label: 'Normal',
className: 'bg-indigo-300 hover:!bg-indigo-300',
inactiveClassName: 'bg-indigo-300/30',
description: 'Mass status: Normal',
},
];
export interface WdMassStatusSelectorProps {
massStatus?: MassState;
onChangeMassStatus(massStatus: MassState): void;
className?: string;
}
export const WdMassStatusSelector = ({
massStatus = MassState.normal,
onChangeMassStatus,
className,
}: WdMassStatusSelectorProps) => {
return (
<form>
<div className={clsx('grid grid-cols-[auto_auto_auto] gap-1', className)}>
{MASS_STATUS.map(x => (
<WdButton
key={x.id}
outlined={false}
value={x.label}
tooltip={x.description}
tooltipOptions={BUILT_IN_TOOLTIP_OPTIONS}
size="small"
className={clsx(
`py-[1px] justify-center min-w-auto w-auto border-0 text-[12px] font-bold leading-[20px]`,
{ [x.inactiveClassName]: massStatus !== x.id },
x.className,
)}
onClick={() => onChangeMassStatus(x.id)}
>
{x.label}
</WdButton>
))}
</div>
</form>
);
};

View File

@@ -0,0 +1,76 @@
import { WdButton } from '@/hooks/Mapper/components/ui-kit/WdButton.tsx';
import { ShipSizeStatus } from '@/hooks/Mapper/types';
import clsx from 'clsx';
import { BUILT_IN_TOOLTIP_OPTIONS } from './constants.ts';
import {
SHIP_SIZES_DESCRIPTION,
SHIP_SIZES_NAMES,
SHIP_SIZES_NAMES_ORDER,
SHIP_SIZES_NAMES_SHORT,
SHIP_SIZES_SIZE,
} from '@/hooks/Mapper/components/map/constants.ts';
const SHIP_SIZE_STYLES: Record<ShipSizeStatus, { className: string; inactiveClassName: string }> = {
[ShipSizeStatus.small]: {
className: 'bg-indigo-400 hover:!bg-indigo-400',
inactiveClassName: 'bg-indigo-400/30',
},
[ShipSizeStatus.medium]: {
className: 'bg-cyan-500 hover:!bg-cyan-500',
inactiveClassName: 'bg-cyan-500/30',
},
[ShipSizeStatus.large]: {
className: 'bg-indigo-300 hover:!bg-indigo-300',
inactiveClassName: 'bg-indigo-300/30',
},
[ShipSizeStatus.freight]: {
className: 'bg-indigo-300 hover:!bg-indigo-300',
inactiveClassName: 'bg-indigo-300/30',
},
[ShipSizeStatus.capital]: {
className: 'bg-indigo-300 hover:!bg-indigo-300',
inactiveClassName: 'bg-indigo-300/30',
},
};
export interface WdShipSizeSelectorProps {
shipSize?: ShipSizeStatus;
onChangeShipSize(shipSize: ShipSizeStatus): void;
className?: string;
}
export const WdShipSizeSelector = ({
shipSize = ShipSizeStatus.large,
onChangeShipSize,
className,
}: WdShipSizeSelectorProps) => {
return (
<form>
<div className={clsx('grid grid-cols-[1fr_1fr_1fr_1fr_1fr] gap-1', className)}>
{SHIP_SIZES_NAMES_ORDER.map(size => {
const style = SHIP_SIZE_STYLES[size];
const tooltip = `${SHIP_SIZES_NAMES[size]}${SHIP_SIZES_SIZE[size]} t. ${SHIP_SIZES_DESCRIPTION[size]}`;
return (
<WdButton
key={size}
outlined={false}
value={SHIP_SIZES_NAMES_SHORT[size]}
tooltip={tooltip}
tooltipOptions={BUILT_IN_TOOLTIP_OPTIONS}
size="small"
className={clsx(
`py-[1px] justify-center min-w-auto w-auto border-0 text-[11px] font-bold leading-[20px]`,
{ [style.inactiveClassName]: shipSize !== size },
style.className,
)}
onClick={() => onChangeShipSize(size)}
>
<span className="text-[11px] font-bold">{SHIP_SIZES_NAMES_SHORT[size]}</span>
</WdButton>
);
})}
</div>
</form>
);
};

View File

@@ -31,6 +31,7 @@ export type SignatureCustomInfo = {
k162Type?: string;
time_status?: number;
isCrit?: boolean;
mass_status?: number;
};
export type SystemSignature = {