Skip to content

Commit

Permalink
[Add] Settings page, [Add] Settings options like LBS by default, etc.…
Browse files Browse the repository at this point in the history
….., [Fix] minor fixes
  • Loading branch information
ZeroxyDev committed Feb 15, 2024
1 parent 13ce414 commit d3ee030
Show file tree
Hide file tree
Showing 20 changed files with 23,704 additions and 22,740 deletions.
45,669 changes: 22,954 additions & 22,715 deletions package-lock.json

Large diffs are not rendered by default.

361 changes: 358 additions & 3 deletions package.json

Large diffs are not rendered by default.

Binary file added public/images/user/placeholder.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "flightmetrics"
version = "1.2.0"
version = "1.3.0"
description = "FlightMetrics is a tool for aircraft simulation"
authors = ["you"]
license = ""
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
},
"package": {
"productName": "FlightMetrics",
"version": "1.2.0"
"version": "1.3.0"
},
"tauri": {
"allowlist": {
Expand Down
66 changes: 66 additions & 0 deletions src/app/UI/switch/accordion.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React, { FC } from 'react';
import * as RadixAccordion from '@radix-ui/react-accordion';
import { ChevronDownIcon } from '@radix-ui/react-icons';

interface AccordionProps {
items: { title: string; content: React.ReactNode }[];
}

const Accordion: FC<AccordionProps> = ({ items }) => (
<RadixAccordion.Root
className="-mt-3 w-full "
type="single"
defaultValue="item-1"
collapsible
>
{items.map((item, index) => (
<AccordionItem key={index} className="last:mb-2 " value={`item-${index + 1}`}>
<AccordionTrigger><span className="text-primary opacity-75 text-[20px] -ml-2">{item.title}</span></AccordionTrigger>
<AccordionContent>{item.content}</AccordionContent>
</AccordionItem>
))}
</RadixAccordion.Root>
);

const AccordionItem: FC<React.ComponentProps<typeof RadixAccordion.Item>> = React.forwardRef(({ children, ...props }, forwardedRef) => (
<RadixAccordion.Item
className="overflow-hidden"
{...props}
ref={forwardedRef}
>
{children}
</RadixAccordion.Item>
));

const AccordionTrigger: FC<React.ComponentProps<typeof RadixAccordion.Trigger>> = React.forwardRef(({ children, ...props }, forwardedRef) => (
<RadixAccordion.Header className="flex">
<RadixAccordion.Trigger
className=" group flex h-[45px] flex-1 cursor-default items-center justify-between px-5 text-[15px] leading-none outline-none"
{...props}
ref={forwardedRef}
>
{children}
<ChevronDownIcon
className="ease-[cubic-bezier(0.87,_0,_0.13,_1)] text-primary transition-transform duration-300 group-data-[state=open]:rotate-180 "
aria-hidden
/>
</RadixAccordion.Trigger>
</RadixAccordion.Header>
));

const AccordionContent: FC<React.ComponentProps<typeof RadixAccordion.Content>> = React.forwardRef(({ children, ...props }, forwardedRef) => (
<RadixAccordion.Content
className="data-[state=open]:animate-slideDown data-[state=closed]:animate-slideUp overflow-hidden "
{...props}
ref={forwardedRef}
>
<div className="">{children}</div>
</RadixAccordion.Content>
));

Accordion.displayName = 'Accordion';
AccordionItem.displayName = 'AccordionItem';
AccordionTrigger.displayName = 'AccordionTrigger';
AccordionContent.displayName = 'AccordionContent';

export default Accordion;
46 changes: 46 additions & 0 deletions src/app/UI/switch/switch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import * as Switch from "@radix-ui/react-switch";
import { ReactElement, JSXElementConstructor, ReactNode, ReactPortal, PromiseLikeOfReactNode, useState, useEffect } from "react";
import Tooltip from "../tooltip/tooltip";
import { getSetting } from "@/app/utils/states";

export const CreateSwitch = (id: string | undefined, label: string | number | boolean | ReactElement<any, string | JSXElementConstructor<any>> | Iterable<ReactNode> | ReactPortal | PromiseLikeOfReactNode | null | undefined, tooltipLabel: any, handleChange: (arg0: boolean) => void) => {
const [defaultChecked, setDefaultChecked] = useState(false);
const [isLoaded, setIsLoaded] = useState(false);

useEffect(() => {
if (typeof window === 'object') {
const storedValue = getSetting(id as string);
if (storedValue !== null) {
setDefaultChecked(storedValue === 'true');
}
setIsLoaded(true);
}
}, [id]);

return (
<>
{isLoaded ? (
<div className="flex w-full px-5 pb-5 last:pb-2 justify-between items-center">
<Tooltip followCursor={true} text={tooltipLabel}>
<label className="text-primary opacity-40 font-main text-[13px] text-start leading-none pr-[15px] truncate" htmlFor={id}>
{label}
</label>
</Tooltip>
<Switch.Root
className="w-[36px] cursor-pointer h-[20px] bg-secondary rounded-full relative focus:shadow-[0_0_0_2px] focus:shadow-black data-[state=checked]:bg-tertiary outline-none "
id={id}
onCheckedChange={(e) => handleChange(e)}
defaultChecked={defaultChecked}
>
<Switch.Thumb className="block w-[18px] h-[18px] bg-primary opacity-40 outline-none data-[state=checked]:opacity-100 border-tertiary data-[state=checked]:brightness-100 rounded-full transition-transform duration-100 will-change-transform data-[state=checked]:translate-x-[18px]" />
</Switch.Root>
</div>
) : (
<div role="status" className="flex w-full first:mt-4 px-5 pb-5 last:pb-2 justify-between items-center animate-pulse">
<div className="h-4 bg-secondary rounded-full w-full "></div>
<span className="sr-only">Loading...</span>
</div>
)}
</>
);
};
24 changes: 24 additions & 0 deletions src/app/UI/tooltip/tooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from 'react';
import * as Tooltips from '@radix-ui/react-tooltip';

const Tooltip = ({ text, children, followCursor } : { text: string, children: React.ReactNode, followCursor: boolean }) => {
return (
<Tooltips.Provider delayDuration={100}>
<Tooltips.Root>
<Tooltips.Trigger asChild>
{children}
</Tooltips.Trigger>
<Tooltips.Portal>
<Tooltips.Content
className="z-50 shadow-background border-2 italic text-start text-quinary border-tertiary backdrop-blur-md bg-hover ml-4 max-w-[200px] data-[state=delayed-open]:data-[side=top]:animate-slideDownAndFade data-[state=delayed-open]:data-[side=right]:animate-slideLeftAndFade data-[state=delayed-open]:data-[side=left]:animate-slideRightAndFade data-[state=delayed-open]:data-[side=bottom]:animate-slideUpAndFade text-violet11 select-none rounded-[12px] px-[15px] py-[10px] text-[13px] leading-none shadow-[hsl(206_22%_7%_/_35%)_0px_0px_100px_0px,_hsl(206_22%_7%_/_20%)_0px_10px_20px_-15px] will-change-[transform,opacity]"
sideOffset={5}
>
{text}
</Tooltips.Content>
</Tooltips.Portal>
</Tooltips.Root>
</Tooltips.Provider>
);
};

export default Tooltip;
50 changes: 42 additions & 8 deletions src/app/choose/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ import { IoIosArrowBack } from "react-icons/io";
import Button from '../UI/buttons/button';
import InProgress from '../UI/progress/in-progress';
import { colourStyles } from '../UI/style/select-styles';
import { convertAircraftModel, transformAirportObject } from '../utils/convert';
import { convertAircraftModel, lbsToKg, transformAirportObject } from '../utils/convert';
import { calculateTrim } from '../utils/aircraftV';
import generalSettings from '@/config/general';
import { useSimbrief } from '../context/simbriefContext';
import { getSetting, getSettings } from '../utils/states';
import Loading from '../loading';

export default function Calculate() {
const [selectedAirport, setSelectedAirport] = useState<SelectType | null>(null);
Expand Down Expand Up @@ -58,6 +60,31 @@ export default function Calculate() {
{ value: 'wet', label: 'Wet' }
]);

// Settings variables
const [defaultSimbrief, setDefaultSimbrief] = useState(false);
const [defaultSimbriefInfo, setDefaultSimbriefInfo] = useState(false);
const [defaultLBS, setDefaultLBS] = useState(false);
const [defaultMetar, setDefaultMetar] = useState(false);
const [isLoaded, setIsLoaded] = useState(false);

useEffect(() => {
if (typeof window === 'object') {
const storedValue = getSettings();

if (storedValue !== null) {
setDefaultSimbrief(storedValue['useSimBriefSwitch'] === 'true');
setDefaultSimbriefInfo(storedValue['useInfoViewerSwitch'] === 'true');
setDefaultLBS(storedValue['useLBSwitch'] === 'true');
setDefaultMetar(storedValue['useMetarSwitch'] === 'true');
console.log(storedValue);
if (storedValue['useSimBriefSwitch'] === 'true') {
setActualStep(-1);
}
}
setIsLoaded(true);
}
}, []);

useEffect(() => {
async function fetchData() {
try {
Expand Down Expand Up @@ -139,7 +166,7 @@ export default function Calculate() {
})));
setLoading(false);
// Setear las variables del METAR si está activo
if (responseExternal && generalSettings.metarAPI) {
if (responseExternal && generalSettings.metarAPI && defaultMetar) {
const metar = await fetchMetar(icao ? icao : airportICAO.toUpperCase());
if (metar) {
setSelectedQNH(metar.barometer.mb);
Expand Down Expand Up @@ -271,7 +298,7 @@ export default function Calculate() {
...aircraftDetails
},
flightDetails: {
grossWeight: selectedGW,
grossWeight: (!defaultLBS ? selectedGW : lbsToKg(parseInt(selectedGW.toFixed(0)))) ,
centerOfGravity: selectedCG,
QNH: selectedQNH,
temperature: selectedTemperature,
Expand Down Expand Up @@ -325,7 +352,12 @@ export default function Calculate() {
updateMCDUSettings(performance);

if (useSimbriefUser !== "") {
router.push('/simbrief');
if (!defaultSimbriefInfo) {
router.push('/result');
}else {
router.push('/simbrief');
}

}else {
router.push('/dashboard');
}
Expand Down Expand Up @@ -467,7 +499,7 @@ useEffect(() => {
case 8:
return noise !== null;
case 9:
return selectedGW >= parseInt(aircraftDetails?.info.weight.empty) * 1000 && selectedGW <= parseInt(aircraftDetails?.info.weight.maxTakeoff) * 1000;
return (!defaultLBS ? selectedGW : lbsToKg(parseInt(selectedGW.toFixed(0)))) >= parseInt(aircraftDetails?.info.weight.empty) * 1000 && (!defaultLBS ? selectedGW : lbsToKg(parseInt(selectedGW.toFixed(0)))) <= parseInt(aircraftDetails?.info.weight.maxTakeoff) * 1000;
case 10:
return selectedCG >= 8.0 && selectedCG <= 50.0;
case 11:
Expand Down Expand Up @@ -508,7 +540,7 @@ useEffect(() => {
case 8:
return createSelect('Is noise reduction required?', noise, noiseOptions, setNoise, false, true, "Are you requiring noise reduction on your flight?");
case 9:
return createInputOption('Select your Gross Weight', selectedGW, setSelectedGW, 'gw', true, "Enter the Gross Weight of your aircraft in kg.");
return createInputOption('Select your Gross Weight', selectedGW, setSelectedGW, 'gw', true, `Enter the Gross Weight of your aircraft in ${defaultLBS ? "lbs" : "kg"}.`);
case 10:
return createInputOption('Select your Center of Gravity', selectedCG, setSelectedCG, 'cg', true, "Enter the Center of Gravity of your aircraft.");
case 11:
Expand All @@ -525,7 +557,8 @@ useEffect(() => {
};

return (
<div className="container flex justify-center items-center flex-col w-screen h-screen mx-auto p-8">
<>
{isLoaded ? <div className="container flex justify-center items-center flex-col w-screen h-screen mx-auto p-8">
{actualStep >= -1 && <div className="flex-col flex justify-center items-center grid-cols-2 max-w-[500px] w-full gap-4">
<InProgress actualStep={actualStep}></InProgress>
<div className='z-[100] w-full '>
Expand All @@ -548,6 +581,7 @@ useEffect(() => {
<Button loading={loading} text="Automatic" handleFunction={() => handleNextStep(1)}></Button>
<Button loading={loading} text="Manual" handleFunction={() => handleNextStep(2)}></Button>
</div>}
</div>
</div> : <Loading></Loading>}
</>
);
}
2 changes: 1 addition & 1 deletion src/app/components/layout/titlebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default function Titlebar() {
{ actualPage != "/" ? <Link href={"/"} className="inline-flex justify-center items-center w-[30px] h-[30px] cursor-pointer text-primary"><IoIosArrowBack/></Link> : <div className="flex items-center justify-center">
<Link href={"/settings"} className="inline-flex justify-center items-center w-[30px] h-[30px] cursor-pointer text-primary"><IoMdSettings/></Link>
</div> }
<h1 data-tauri-drag-region className="font-bold text-primary text-sm">Flight Metrics</h1>
<h1 data-tauri-drag-region className="font-bold text-primary text-sm">FlightMetrics</h1>
<div className="inline-flex justify-center text-primary items-center w-[30px] h-[30px] cursor-pointer" onClick={onClose} id="titlebar-close">
<IoMdClose />
</div>
Expand Down
3 changes: 3 additions & 0 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { MCDUContextProvider } from "./context/mcduContext";
import { useEffect, useState } from "react";
import Footer from "./components/layout/footer";
import { SimbriefContextProvider } from "./context/simbriefContext";
import Link from "next/link";
import { IoMdSettings } from "react-icons/io";

const inter = Inter({ subsets: ["latin"] });

Expand Down Expand Up @@ -39,6 +41,7 @@ export default function RootLayout({
<body className={`rounded-[40px] m-0 ${isTauri ? 'bg-transparent' : 'bg-[#000000] bg-[radial-gradient(#ffffff33_1px,#ffffff10_1px)] bg-[size:20px_20px]'} overflow-hidden`}>
<div style={{ height: isTauri ? '700px' : '100vh' }} className={`bg-[#000000] bg-[radial-gradient(#ffffff20_1px,#ffffff10_1px)] bg-[size:20px_20px] w-full ${isTauri ? 'h-[600px]' : 'h-screen'} flex justify-center items-center bordernone border-tertiary rounded-big`}>
{isTauri && <div className='h-12 mb-8 block z-20'><Titlebar /></div>}
{!isTauri &&<Link href={"/settings"} className="inline-flex z-50 fixed top-[20px] right-[20px] justify-center items-center w-[30px] h-[30px] cursor-pointer text-primary"><IoMdSettings/></Link>}
<div className='w-full z-10 flex justify-center items-center h-full '>
<SimbriefContextProvider>
<MCDUContextProvider>
Expand Down
7 changes: 7 additions & 0 deletions src/app/loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export default function Loading() {
// You can add any UI inside Loading, including a Skeleton.
return <div
className="inline-block h-12 w-12 animate-spin rounded-full border-[8px] border-solid border-current border-r-transparent align-[-0.125em] motion-reduce:animate-[spin_1.5s_linear_infinite]" role="status">
<span className="!absolute !-m-px !h-px !w-px !overflow-hidden !whitespace-nowrap !border-0 !p-0 ![clip:rect(0,0,0,0)]">Loading...</span>
</div>;
}
47 changes: 47 additions & 0 deletions src/app/settings/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"use client";
import React from "react";
import { CreateSwitch } from "../UI/switch/switch";
import Accordion from "../UI/switch/accordion";
import { useSwitchState } from "../utils/states";
import { IoIosArrowBack } from "react-icons/io";
import { useRouter } from "next/navigation";

export default function Settings() {
const [useSimBriefSwitch, handleUseSimBriefSwitch] = useSwitchState('useSimBriefSwitch', false);
const [useLBSwitch, handleUseLBSwitch] = useSwitchState('useLBSwitch', false);
const [useInfoViewerSwitch, handleUseInfoViewerSwitch] = useSwitchState('useInfoViewerSwitch', true);
const [useMetarSwitch, handleUseMetarSwitch] = useSwitchState('useMetarSwitch', true);

const accordionItems = [
{
title: 'General Settings',
content: (
<form>
{CreateSwitch('useSimBriefSwitch', 'Use SimBrief Integration automatically', 'Enable integration with SimBrief for flight metrics', handleUseSimBriefSwitch)}
{CreateSwitch('useInfoViewerSwitch', 'View Simbrief information before takeoff calculation', 'View Simbrief information before takeoff calculation', handleUseInfoViewerSwitch)}
{CreateSwitch('useLBSwitch', 'Use LBS by default', 'Use LBS instead of KG by default', handleUseLBSwitch)}
{CreateSwitch('useMetarSwitch', 'Use metar API', 'Use metar API by default', handleUseMetarSwitch)}
</form>
),
}
// Puedes agregar más secciones y ajustes aquí según sea necesario
];


const router = useRouter();
return (
<div className="w-screen max-w-[1200px] overflow-hidden max-h-[100vh] flex justify-between items-center h-screen">

<div style={{ filter: 'drop-shadow(0 0px 40px rgba(255, 255, 255, 0.1))' }} className="w-full px-[50px] border-secondary h-full max-h-[calc(100vh-100px)] backdrop-blur-[2px] rounded-[30px]">

<div className="flex items-center justify-start">
<button className='transition h-fit mr-4 duration-300 border border-tertiary bg-button hover:bg-buttonHover text-white py-2 px-2 rounded-[20px] text-center' onClick={() => router.back()}><IoIosArrowBack /></button>
<h1 className="text-primary opacity-90 text-start py-4 border-tertiary font-main text-[30px] rounded-[20px] ">Settings</h1>
</div>
<section className='text-primary w-full pt-5 cursor-pointer max-h-[calc(100vh-100px)]'>
<Accordion items={accordionItems} />
</section>
</div>
</div>
);
}
Loading

0 comments on commit d3ee030

Please # to comment.