Files
xkhofmann-tfdidesign-md11-l…/PackageSources/js-bundle/src/components/SBEntry/SBEntryPax.tsx
T
2026-02-13 02:50:43 +01:00

220 lines
7.6 KiB
TypeScript

import { FC, useEffect, useState } from 'react';
import { WASMDataPax } from '../../types/WASMData';
import { LoadingState, SimBrief } from '../../types/general';
import { ImportFlightPlanKH } from '../../utils/TFDISBImport';
import { CoherentCallSBEntryPax, loadAircraft, unloadAircraft } from '../../utils/utils';
import CGSelect from '../CGSelect/CGSelect';
import ActionBar from '../actionbar/ActionBar';
import Input from '../input/Input';
interface SBEntryProps {
WASMData: WASMDataPax;
loadingState: LoadingState;
gsxActive: boolean;
gsxFuelActive: boolean;
setLoadingState: (newState: LoadingState) => void;
}
const SBEntryPax: FC<SBEntryProps> = ({ WASMData, loadingState, gsxActive, gsxFuelActive, setLoadingState }) => {
const [CGTarget, setCGTarget] = useState(WASMData.targetPayload.CGTarget);
const [fuel, setFuel] = useState(Math.round(WASMData.targetPayload.fuel));
const [SBInFlight, setSBInFlight] = useState(false);
// FROM EFB
const simBrief = useSelector((state) => state.simbrief.plan);
const ZFW = () => {
if (loadingState !== 'loaded' && !gsxActive) return Math.round(WASMData.targetPayload.total);
return Math.round(WASMData.livePayload.total);
};
const ZFWValid = () => {
return ZFW() <= WASMData.limits.maxZFW;
};
const GW = () => {
return fuel + ZFW();
};
const GWValid = () => {
return GW() <= WASMData.limits.maxTOW;
};
const handleInput = (input: string, maxValue: number, setter: (value: number) => void) => {
if (!input) {
setter(0);
return;
}
const converted = parseInt(input);
if (converted) {
if (converted < 0) setter(0);
else if (converted > maxValue) setter(maxValue);
else setter(converted);
}
};
const updateData = (SBPlan?: SimBrief, _fuel?: number) => {
CoherentCallSBEntryPax(CGTarget, _fuel ?? fuel, SBPlan);
};
useEffect(() => {
if (!simBrief || gsxActive) return;
setSBInFlight(true);
const SBResponse = ImportFlightPlanKH(
simBrief,
WASMData.limits.maxZFW,
WASMData.limits.maxTOW,
WASMData.limits.maxFuel,
WASMData.userData.isImperial
);
if (SBResponse.type === 'error') {
console.error('TODO: ERROR', SBResponse.message);
setSBInFlight(false);
return;
}
const _fuel = parseFloat((SBResponse.message as SimBrief).fuel as unknown as string) ?? 0;
updateData(SBResponse.message as SimBrief, _fuel);
setFuel(_fuel);
setFuel(parseFloat((SBResponse.message as SimBrief).fuel as unknown as string) ?? 0);
setSBInFlight(false);
}, [simBrief, gsxActive]);
useEffect(() => updateData(), [CGTarget, fuel]);
useEffect(
() =>
setFuel((prev) => {
if (prev > WASMData.limits.maxFuel) return WASMData.limits.maxFuel;
return prev;
}),
[WASMData.userData.isER]
);
return (
<>
<div className="block flex w-full flex-col opacity-100 transition-opacity duration-150 ease-linear mb-4">
<div className="flex w-full items-center justify-between rounded-md bg-zinc-600 p-2 px-4">
<div className="flex w-full items-center justify-between text-xs">
<label>Fuel ({WASMData.userData.isImperial ? 'lbs' : 'kg'})</label>
<Input
type="text"
placeholder=""
className={`w-1/2 rounded-lg border border-white bg-zinc-700 px-3 py-2 text-right`}
value={fuel}
onChange={(value) => handleInput(value, WASMData.limits.maxFuel, setFuel)}
disabled={loadingState !== 'preview' || gsxFuelActive}
/>
</div>
</div>
</div>
<div className="block flex w-full flex-col opacity-100 transition-opacity duration-150 ease-linear mb-4">
<div className="flex w-full items-center justify-between rounded-t-md bg-zinc-600 p-2 px-4">
<div className="flex w-full items-center justify-between text-xs">
<label>Planned ZFW ({WASMData.userData.isImperial ? 'lbs' : 'kg'})</label>
<input
type="text"
placeholder=""
className="w-1/2 rounded-lg border border-white bg-zinc-700 px-3 py-2 text-right focus:border-blue-600 focus:ring-blue-600"
value={WASMData.sbPlanned.ZFW}
disabled
/>
</div>
</div>
<div className="flex w-full items-center justify-between bg-zinc-700 p-2 px-4">
<div className="flex w-full items-center justify-between text-xs">
<label>Planned GW ({WASMData.userData.isImperial ? 'lbs' : 'kg'})</label>
<input
type="text"
placeholder=""
className="w-1/2 rounded-lg border border-white bg-zinc-700 px-3 py-2 text-right focus:border-blue-600 focus:ring-blue-600"
value={WASMData.sbPlanned.GW}
disabled
/>
</div>
</div>
<div className="flex w-full items-center justify-between rounded-b-md bg-zinc-600 p-2 px-4">
<div className="flex w-full items-center justify-between text-xs">
<label>
Target ZFWCG ({WASMData.limits.minCG} - {WASMData.limits.maxCG})
</label>
<CGSelect
minCG={WASMData.limits.minCG}
maxCG={WASMData.limits.maxCG}
value={CGTarget}
disabled={loadingState !== 'preview' || gsxActive}
increase={() =>
setCGTarget((prev) => {
const _new = prev + 0.1;
return _new;
})
}
decrease={() =>
setCGTarget((prev) => {
const _new = prev - 0.1;
return _new;
})
}
/>
</div>
</div>
</div>
<div className="block flex w-full flex-col opacity-100 transition-opacity duration-150 ease-linear mb-4">
<div className="flex w-full items-center justify-between rounded-t-md bg-zinc-600 p-2 px-4">
<div className="flex w-full items-center justify-between text-xs">
<label>
{loadingState !== 'loaded' && !gsxActive ? 'Expected' : 'Actual'} ZFW (
{WASMData.userData.isImperial ? 'lbs' : 'kg'})
</label>
<input
type="text"
placeholder=""
className={`w-1/2 rounded-lg border ${ZFWValid() ? 'border-white' : 'border-red-500 text-red-500'} bg-zinc-700 px-3 py-2 text-right`}
disabled
value={ZFW()}
/>
</div>
</div>
<div className="flex w-full items-center justify-between rounded-b-md bg-zinc-700 p-2 px-4">
<div className="flex w-full items-center justify-between text-xs">
<label>
{loadingState !== 'loaded' && !gsxActive ? 'Expected' : 'Actual'} GW (
{WASMData.userData.isImperial ? 'lbs' : 'kg'})
</label>
<input
type="text"
placeholder=""
className={`w-1/2 rounded-lg border ${GWValid() ? 'border-white' : 'border-red-500 text-red-500'} bg-zinc-700 px-3 py-2 text-right`}
disabled
value={GW()}
/>
</div>
</div>
</div>
<ActionBar
loadingState={loadingState}
loadDisabled={!GWValid() || SBInFlight}
GSXSync={WASMData.options.GSXSync}
load={() => {
setLoadingState('loaded');
loadAircraft();
}}
unload={() => {
setLoadingState('preview');
unloadAircraft();
}}
/>
</>
);
};
export default SBEntryPax;