Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
Binary file added Recruit-Training/.DS_Store
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,24 +1,283 @@
import React, {
useCallback,
useMemo,
useReducer,
useRef,
useState,
} from "react";

import BatteryInput from "~/components/batteryInput";
import Header from "~/components/header";
import SpeedInput from "~/components/speedInput";
import WeatherInput from "~/components/weatherInput";

const App = () => {
const calculateRange = () => {
return;
// 1. Define the State interface
interface State {
speed: number | string;
battery: number | string;
weather: number | string;
changed: {
speed: boolean;
battery: boolean;
weather: boolean;
};
}

type ActionType =
| {
type: "UPDATE_SPEED_AND_CHANGED"; // New combined action type
payload: {
speed: number | string; // Speed value
altered: boolean; // Indicates if the input was changed
};
}
| {
type: "UPDATE_BATTERY_AND_CHANGED"; // New combined action type
payload: {
battery: number | string; // battery value
altered: boolean; // Indicates if the input was changed
};
}
| {
type: "UPDATE_WEATHER_AND_CHANGED"; // New combined action type
payload: {
weather: number | string; // battery value
altered: boolean; // Indicates if the input was changed
};
};

const initialState: State = {
speed: "",
battery: "",
weather: 0,
changed: {
speed: false,
battery: false,
weather: false,
},
};

const reducer = (state: State, action: ActionType): State => {
switch (action.type) {
case "UPDATE_SPEED_AND_CHANGED":
return {
...state,
speed: action.payload.speed,
changed: {
...state.changed,
speed: action.payload.altered,
},
};
case "UPDATE_BATTERY_AND_CHANGED":
return {
...state,
battery: action.payload.battery,
changed: {
...state.changed,
battery: action.payload.altered,
},
};
case "UPDATE_WEATHER_AND_CHANGED":
return {
...state,
weather: action.payload.weather,
changed: {
...state.changed,
weather: action.payload.altered,
},
};
default:
return state;
}
};
const App = () => {
const [displayRange, setSD] = useState(false);
const [state, dispatch] = useReducer(reducer, initialState);
const { speed, battery, weather } = state; //initialize the state

//to avoid the type errors:
const handleSpeedChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
dispatch({
type: "UPDATE_SPEED_AND_CHANGED",
payload: {
speed: value === "" ? "" : Number(value), //empty input is allowed or the input is converted to a number
altered: true, //the input changed so we chnage it to true
},
});
setSD(false);
console.log("Speed:", value); // Add this line
},
[],
);

const handleBatteryChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
dispatch({
type: "UPDATE_BATTERY_AND_CHANGED",
payload: {
battery: value === "" ? "" : Number(value), //empty input is allowed or the input is converted to a number
altered: true, //the input changed so we chnage it to true
},
});
setSD(false);
},
[],
);

const handleWeatherChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
// Allow empty input, or convert to a number
dispatch({
type: "UPDATE_WEATHER_AND_CHANGED",
payload: {
weather: value === "" ? "" : Number(value), //empty input is allowed or the input is converted to a number
altered: true, //the input changed so we chnage it to true
},
});
setSD(false);
},
[],
);

const validInputs = useMemo(() => {
//reset battery and speed
let speedError = "";
let batteryError = "";
let isValid = true;

//check the changed fields
if (state.changed.speed) {
if (state.speed === "") {
isValid = false;
speedError = "Speed is required";
} else if (Number(state.speed) < 0 || Number(state.speed) > 90) {
isValid = false;
speedError = "The speed should be within the range of 0 to 90";
}
} else if (state.speed === "") {
//when nothing has been entered yet
isValid = false;
}

if (state.changed.battery) {
if (state.battery === "") {
isValid = false;
batteryError = "Battery is required";
} else if (
typeof state.battery === "number" &&
(state.battery < 0 || state.battery > 100)
) {
isValid = false;
batteryError =
"The battery percentage should be within the range of 0 to 100";
}
} else if (state.battery === "") {
//when nothing has been entered yet
isValid = false;
}

return { speedError, batteryError, isValid };
}, [state.changed, state.speed, state.battery]); //recompute the answer if speed or battery change

/*const calculateRange = useMemo(() => {
const { speedError, batteryError, isValid } = validInputs;

if (!isValid) {
console.error(speedError, batteryError);
return null;
}
return (
-(
(Number(state.speed) * Number(state.speed) * Number(state.battery)) /
2500
) +
4 * Number(state.battery) +
Number(state.weather)
);
}, [validInputs.isValid, state.battery, state.speed, state.weather]);

const handleClick = () => {
const range = calculateRange; // Get the calculated range
rangeRef.current = range; // Set the calculated range to the ref
console.log(rangeRef.current);
console.log(typeof rangeRef.current);
console.log(rangeRef.current !== null);
};*/

const calculatedRange = useMemo(() => {
const { isValid } = validInputs;
if (isValid)
return (
-(
(Number(state.speed) * Number(state.speed) * Number(state.battery)) /
2500
) +
4 * Number(state.battery) +
Number(state.weather)
);
return null;
}, [
validInputs.isValid,
state.speed,
state.battery,
state.weather,
displayRange,
]);

const handleClick = () => {
if (validInputs.isValid) {
setSD(true); // Show the range if inputs are valid
} else {
setSD(false); // Hide or show an error message if inputs are invalid
}
};

return (
<div className="h-screen w-screen bg-[#212121]">
<div className="flex h-full flex-col items-center pt-36 text-white">
<Header />
<form name="simulator" className="flex w-full flex-col items-center">
<div className="mb-4 flex w-full flex-col items-center gap-y-4">
<SpeedInput />
<BatteryInput />
<SpeedInput value={speed} onChange={handleSpeedChange} />
{validInputs.speedError && (
<div className="text-red-500">{validInputs.speedError}</div>
)}
{/* speed error message */}
<BatteryInput value={battery} onChange={handleBatteryChange} />
{validInputs.batteryError && (
<div className="text-red-500">{validInputs.batteryError}</div>
)}
{/* Battery error message */}
</div>
<div className="flex w-full flex-row justify-center gap-4">
<WeatherInput />
<WeatherInput value={weather} onChange={handleWeatherChange} />
</div>

{/*make the button*/}
<div className="mt-8 text-center">
{" "}
{/* Add text-center here */}
<button
type="button"
onClick={handleClick}
className="w-48 rounded bg-blue-500 px-4 py-2 font-bold text-white"
>
Calculate
</button>
<div id="range-output" className="mt-4">
{displayRange && calculatedRange !== null ? (
<p>
The predicted range of the Eylsia is{" "}
{calculatedRange.toFixed(2)} km.
</p>
) : (
<p></p>
)}
</div>
</div>
</form>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Define the props type
export interface InputProps {
value: number | string; // Expecting a string for the input value
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void; // Function to handle changes
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const BatteryInput = () => {
import type { InputProps } from "~/InputProps";

const BatteryInput: React.FC<InputProps> = ({ value, onChange }) => {
return (
<div className="flex w-full flex-col items-center gap-2">
<label>Battery Percentage (%):</label>
Expand All @@ -8,6 +10,9 @@ const BatteryInput = () => {
name="battery"
type="number"
placeholder="Battery"
value={value}
onChange={onChange}
required
/>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const SpeedInput = () => {
import type { InputProps } from "~/InputProps";

const SpeedInput: React.FC<InputProps> = ({ value, onChange }) => {
return (
<>
<div className="flex w-full flex-col items-center gap-2">
Expand All @@ -9,6 +11,9 @@ const SpeedInput = () => {
name="speed"
type="number"
placeholder="Speed"
value={value}
onChange={onChange}
required
/>
</div>
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
const WeatherInput = () => {
import React from "react";

import type { InputProps } from "~/InputProps";

const WeatherInput: React.FC<InputProps> = ({ value, onChange }) => {
return (
<>
<img src="/Cloud.png" height="66px" width="66px" alt="Cloud" />
Expand All @@ -8,7 +12,8 @@ const WeatherInput = () => {
type="range"
min="0"
max="100"
value="50"
value={value}
onChange={onChange}
/>
<img src="/Sun.png" height="66px" width="66px" alt="Sun" />
</>
Expand Down