summaryrefslogtreecommitdiff
path: root/frontend/src/components/Sidebar.tsx
diff options
context:
space:
mode:
authorArne Rief <riearn@proton.me>2025-12-22 12:56:20 +0100
committerArne Rief <riearn@proton.me>2025-12-22 13:02:01 +0100
commitd1b64ddd78d8b8dc3eca76038a75071ab2a575d9 (patch)
tree6213650195cdddb0ec4938380735ebd70847a758 /frontend/src/components/Sidebar.tsx
parent3818739c5901cc3f1d4596b24cfe1b827a2eca23 (diff)
Sidebar split into smaller components
Diffstat (limited to 'frontend/src/components/Sidebar.tsx')
-rw-r--r--frontend/src/components/Sidebar.tsx234
1 files changed, 26 insertions, 208 deletions
diff --git a/frontend/src/components/Sidebar.tsx b/frontend/src/components/Sidebar.tsx
index 2e66865..8bd795b 100644
--- a/frontend/src/components/Sidebar.tsx
+++ b/frontend/src/components/Sidebar.tsx
@@ -1,116 +1,27 @@
-import {
- useState,
- type ChangeEvent,
- type Dispatch,
- type SetStateAction,
-} from "react";
-import "../styles/Button.css";
-import "../styles/Sidebar.css";
-import type { ErrorResponse } from "../types/error";
-import type { CreateRobotResponse, Robot } from "../types/robot";
-
-type ExpandedRobotsState = Record<number, boolean>;
+import { useState, type Dispatch, type SetStateAction } from "react";
+import API_URL from "../config";
+import "../styles/button.css";
+import "../styles/sidebar.css";
+import type { Robot } from "../types/robot";
+import AddRobotForm from "./AddRobotForm";
+import RobotList from "./RobotList";
+import SimulationActions from "./SimulationActions";
type Props = {
- activeSimulation: boolean;
errorMessage: string;
- setErrorMessage: Dispatch<SetStateAction<string>>;
- token: string | null;
robots: Robot[];
- onStartAllRobots: () => Promise<void>;
- onStopAllRobots: () => Promise<void>;
+ token: string | null;
+ setErrorMessage: Dispatch<SetStateAction<string>>;
};
-const API_URL = import.meta.env.VITE_API_URL;
-
-function Sidebar({
- activeSimulation,
- errorMessage,
- setErrorMessage,
- token,
- robots,
- onStartAllRobots,
- onStopAllRobots,
-}: Props) {
- const [expandedRobots, setExpandedRobots] = useState<ExpandedRobotsState>(
- {}
- );
+function Sidebar({ errorMessage, robots, token, setErrorMessage }: Props) {
const [isAddingRobot, setIsAddingRobot] = useState(false);
- const [newRobotName, setNewRobotName] = useState("");
- const [isSubmitting, setIsSubmitting] = useState(false);
-
- function toggleRobotHistory(robotId: number) {
- setExpandedRobots((prev) => ({
- ...prev,
- [robotId]: !prev[robotId],
- }));
- }
function handleAddClick() {
setIsAddingRobot(true);
- setNewRobotName("");
setErrorMessage("");
}
- function handleCancel() {
- setIsAddingRobot(false);
- setNewRobotName("");
- setErrorMessage("");
- }
-
- async function handleSubmit() {
- if (!newRobotName.trim()) {
- setErrorMessage("Please enter a name for the robot.");
- return;
- }
-
- setIsSubmitting(true);
- setErrorMessage("");
-
- try {
- const response = await fetch(`${API_URL}/robots`, {
- method: "POST",
- headers: {
- Authorization: `Bearer ${token}`,
- "Content-Type": "application/json",
- },
- body: JSON.stringify({ name: newRobotName.trim() }),
- });
-
- if (!response.ok) {
- const errorData: ErrorResponse = await response.json();
- throw new Error(
- errorData.message ||
- `Error creating the new robot: ${response.status}`
- );
- }
-
- const data: CreateRobotResponse = await response.json();
- console.log("Robot created successfully: ", data);
-
- // Reset form and close input field
- setNewRobotName("");
- setIsAddingRobot(false);
- } catch (error) {
- console.error("Error creating the new robot:", error);
-
- if (error instanceof Error) {
- setErrorMessage(error.message);
- } else {
- setErrorMessage("Error creating the new robot.");
- }
- } finally {
- setIsSubmitting(false);
- }
- }
-
- function handleInputChange(event: ChangeEvent<HTMLInputElement>) {
- setNewRobotName(event.target.value);
- if (errorMessage) {
- setErrorMessage("");
- }
- }
-
return (
<div className="sidebar">
<div className="sidebar-robots-header">
@@ -120,124 +31,31 @@ function Sidebar({
onClick={handleAddClick}
disabled={isAddingRobot}
>
- + Neu
+ + Add
</button>
</div>
- {isAddingRobot && (
- <div className="add-robot-form">
- <input
- type="text"
- placeholder="Robot name..."
- value={newRobotName}
- onChange={handleInputChange}
- disabled={isSubmitting}
- autoFocus
- />
- <div className="add-robot-actions">
- <button
- className="btn btn-start"
- onClick={handleSubmit}
- disabled={isSubmitting}
- >
- {isSubmitting ? "Creating..." : "Create"}
- </button>
- <button
- className="btn btn-stop"
- onClick={handleCancel}
- disabled={isSubmitting}
- >
- Cancel
- </button>
- </div>
- </div>
+ {isAddingRobot && (
+ <AddRobotForm
+ apiUrl={API_URL}
+ errorMessage={errorMessage}
+ token={token}
+ setErrorMessage={setErrorMessage}
+ setIsAddingRobot={setIsAddingRobot}
+ />
)}
{errorMessage && (
<div className="error-message">{errorMessage}</div>
)}
- <div className="simulation-actions">
- <button
- className="btn btn-start"
- onClick={onStartAllRobots}
- disabled={activeSimulation}
- >
- Start simulation
- </button>
-
- <button
- className="btn btn-stop"
- onClick={onStopAllRobots}
- disabled={!activeSimulation}
- >
- Stop simulation
- </button>
- </div>
-
- <ul className="sidebar-robot-list">
- {robots.map((robot) => {
- const isExpanded = expandedRobots[robot.id];
-
- return (
- <li key={robot.id}>
- <p className="robot-name">{robot.name}</p>
-
- <p>
- Status:{" "}
- <span
- className={`robot-status-${robot.status}`}
- >
- {robot.status}
- </span>
- </p>
-
- <p className="robot-coordinates-label">Position:</p>
- <ul className="robot-coordinates">
- <li>Lat: {robot.lat}</li>
- <li>Lon: {robot.lon}</li>
- </ul>
-
- <button
- className="btn btn-robot-history-toggle"
- onClick={() => toggleRobotHistory(robot.id)}
- aria-expanded={isExpanded}
- >
- Position history
- <span
- className={`arrow ${
- isExpanded ? "open" : ""
- }`}
- >
- ▾
- </span>
- </button>
+ <SimulationActions
+ apiUrl={API_URL}
+ token={token}
+ setErrorMessage={setErrorMessage}
+ />
- <div
- className={`robot-history ${
- isExpanded ? "expanded" : ""
- }`}
- >
- <ul>
- {robot.robot_positions?.length ? (
- robot.robot_positions.map(
- (pos, index) => (
- <li key={index}>
- {`Lat: ${pos.lat}, Lon: ${pos.lon}`}
- </li>
- )
- )
- ) : (
- <li className="robot-history-empty">
- No previous positions.
- </li>
- )}
- </ul>
- </div>
- </li>
- );
- })}
- </ul>
+ <RobotList robots={robots} />
</div>
);
}