diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 000000000..bc785bb2a Binary files /dev/null and b/.DS_Store differ diff --git a/gs/backend/api/backend_setup.py b/gs/backend/api/backend_setup.py index b6ba6080e..14c2bdbfe 100644 --- a/gs/backend/api/backend_setup.py +++ b/gs/backend/api/backend_setup.py @@ -5,11 +5,15 @@ from gs.backend.api.middleware.logger_middleware import LoggerMiddleware from gs.backend.api.v1.aro.endpoints.picture_requests import picture_requests_router from gs.backend.api.v1.aro.endpoints.user import aro_user_router -from gs.backend.api.v1.mcc.endpoints.aro_requests import aro_requests_router from gs.backend.api.v1.mcc.endpoints.commands import commands_router -from gs.backend.api.v1.mcc.endpoints.main_commands import main_commands_router +from gs.backend.api.v1.mcc.endpoints.mission_commands import mission_commands_router from gs.backend.api.v1.mcc.endpoints.telemetry import telemetry_router +# Imports for test endpoints for MCC +# from gs.backend.api.v1.mcc.endpoints.main_commands import main_commands_router +# from gs.backend.api.v1.mcc.endpoints.mcc_logs import logs_router +# from gs.backend.api.v1.mcc.endpoints.aro_requests import aro_requests_router + def setup_routes(app: FastAPI) -> None: """Adds the routes to the app""" @@ -24,8 +28,12 @@ def setup_routes(app: FastAPI) -> None: mcc_prefix = f"{version_1}/mcc" app.include_router(commands_router, prefix=f"{mcc_prefix}/commands") app.include_router(telemetry_router, prefix=f"{mcc_prefix}/telemetry") - app.include_router(aro_requests_router, prefix=f"{mcc_prefix}/requests") - app.include_router(main_commands_router, prefix=f"{mcc_prefix}/main-commands") + app.include_router(mission_commands_router, prefix=f"{mcc_prefix}/mission-commands") + + # Routes for MCC test endpoints + # app.include_router(aro_requests_router, prefix=f"{mcc_prefix}/requests") + # app.include_router(main_commands_router, prefix=f"{mcc_prefix}/main-commands") + # app.include_router(logs_router, prefix=f"{mcc_prefix}/logs") def setup_middlewares(app: FastAPI) -> None: diff --git a/gs/backend/api/middleware/cors_middleware.py b/gs/backend/api/middleware/cors_middleware.py index 9fcde730c..d539ae4ff 100644 --- a/gs/backend/api/middleware/cors_middleware.py +++ b/gs/backend/api/middleware/cors_middleware.py @@ -10,7 +10,10 @@ def add_cors_middleware(app: FastAPI) -> None: """ app.add_middleware( CORSMiddleware, - allow_origins=["http://localhost:5173"], + allow_origins=[ + "http://localhost:5173", + "http://localhost:5174", + ], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], diff --git a/gs/backend/api/v1/mcc/endpoints/aro_requests.py b/gs/backend/api/v1/mcc/endpoints/aro_requests.py deleted file mode 100644 index 77b8a622c..000000000 --- a/gs/backend/api/v1/mcc/endpoints/aro_requests.py +++ /dev/null @@ -1,3 +0,0 @@ -from fastapi import APIRouter - -aro_requests_router = APIRouter(tags=["MCC", "ARO Requests"]) diff --git a/gs/backend/api/v1/mcc/endpoints/main_commands.py b/gs/backend/api/v1/mcc/endpoints/main_commands.py deleted file mode 100644 index 0cd0f185b..000000000 --- a/gs/backend/api/v1/mcc/endpoints/main_commands.py +++ /dev/null @@ -1,17 +0,0 @@ -from fastapi import APIRouter - -from gs.backend.api.v1.mcc.models.responses import MainCommandsResponse -from gs.backend.data.data_wrappers.mcc_wrappers.main_command_wrapper import get_all_main_commands - -main_commands_router = APIRouter(tags=["MCC", "Main Commands"]) - - -@main_commands_router.get("/") -async def get_main_commands() -> MainCommandsResponse: - """ - Gets the main commands that are available for the MCC - - :return: list of all commands - """ - items = get_all_main_commands() - return MainCommandsResponse(data=items) diff --git a/gs/backend/api/v1/mcc/endpoints/mission_commands.py b/gs/backend/api/v1/mcc/endpoints/mission_commands.py new file mode 100644 index 000000000..cd6ac242e --- /dev/null +++ b/gs/backend/api/v1/mcc/endpoints/mission_commands.py @@ -0,0 +1,36 @@ +from fastapi import APIRouter +from pydantic import BaseModel + +mission_commands_router = APIRouter(tags=["Mission Control"]) + + +class MissionCommandRequest(BaseModel): + """ + Represents a body for a mission command request + + Attributes: + command (str): Title of the command request. + """ + + command: str + + +class MissionCommandResponse(BaseModel): + """ + Represents a body for a mission command response + + Attributes: + response (str): Response message. + """ + + response: str + + +@mission_commands_router.post("/", response_model=MissionCommandResponse) +async def execute_mission_command(cmd: MissionCommandRequest) -> MissionCommandResponse: + """ + Gets the hardcoded mission command response for MCC frontend testing + + :return: mission command respone + """ + return MissionCommandResponse(response=f"Executed command: {cmd.command}") diff --git a/gs/backend/config/config.py b/gs/backend/config/config.py index 6df17d795..5b8295c10 100644 --- a/gs/backend/config/config.py +++ b/gs/backend/config/config.py @@ -6,7 +6,6 @@ load_dotenv() - # TODO: Make these throw an exception if they are None GS_DATABASE_USER = environ.get("GS_DATABASE_USER") GS_DATABASE_PASSWORD = environ.get("GS_DATABASE_PASSWORD") diff --git a/gs/frontend/archive/aro/src/requests/requests.tsx b/gs/frontend/archive/aro/src/requests/requests.tsx index a89db15e9..c60ef3759 100644 --- a/gs/frontend/archive/aro/src/requests/requests.tsx +++ b/gs/frontend/archive/aro/src/requests/requests.tsx @@ -1,31 +1,46 @@ -import { type MouseEvent, useEffect, useState } from "react"; +import { type MouseEvent} from "react"; import type { RequestItemData } from "./request-item-data.ts"; import RequestItem from "./request-item.tsx"; import { getRequestItems } from "./requests-api.ts"; +import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; const Requests = () => { - // TODO: Switch to using react-query - const [data, setData] = useState([]); - useEffect(() => { - const getRequestItemsRegular = async () => { - const response = await getRequestItems(); - setData(response); - }; - getRequestItemsRegular(); - }, []); + + const { + data = [], + isLoading, + } = useQuery({ + queryKey: ["requests"], + queryFn: getRequestItems, + }); + + const queryClient = useQueryClient(); // Removes the request with the given id from the list of data // TODO: Cancel request on the backend + const cancelRequestMutation = useMutation({ + mutationFn: async (id: number) => { + return id; + }, + onSuccess: (id: number) => { + queryClient.setQueryData(["requests"], (old) => + old ? old.filter((item) => item.id !== id) : [] + ); + }, + }); + const cancelRequest = (id: number) => { return async (a: MouseEvent) => { a.preventDefault(); - setData((prev: RequestItemData[]) => - prev.filter((item) => item.id != id) - ); + await cancelRequestMutation.mutateAsync(id); }; }; - if (data.length === 0) { + if (isLoading) { + return
Loading requests...
; + } + + if (!data || data.length === 0) { return
You do not have any request created.
; } @@ -46,13 +61,12 @@ const Requests = () => { - {data.map((item: RequestItemData, key: number) => { + {data.map((item: RequestItemData) => { console.log(item); return ( - - {" "} - - + + + ); })} diff --git a/gs/frontend/archive/mcc/src/aro-requests/aro-requests.tsx b/gs/frontend/archive/mcc/src/aro-requests/aro-requests.tsx index a3887d106..44d485783 100644 --- a/gs/frontend/archive/mcc/src/aro-requests/aro-requests.tsx +++ b/gs/frontend/archive/mcc/src/aro-requests/aro-requests.tsx @@ -1,5 +1,5 @@ import Table from "react-bootstrap/Table"; -import { useEffect, useState } from "react"; +import { useQuery } from '@tanstack/react-query'; type AROItemProps = { id: number; @@ -7,6 +7,7 @@ type AROItemProps = { longitude: number; status: string; }; + function AROItem({ id, latitude, longitude, status }: AROItemProps) { return ( <> @@ -21,17 +22,14 @@ function AROItem({ id, latitude, longitude, status }: AROItemProps) { } function ARORequests() { - const [loading, setLoading] = useState(true); - const [aroRequests, setARORequests] = useState([]); - - useEffect(() => { - fetch("http://localhost:5000/aro-request") - .then((response) => response.json()) - .then((data) => { - setARORequests(data); - setLoading(false); - }); - }, []); + const { data, isLoading} = useQuery({ + queryKey: ["aro-requests"], + queryFn: async () => { + const response = await fetch("http://localhost:8000/api/v1/mcc/requests/"); + if(!response.ok) throw new Error("Network response was not ok"); + return response.json(); + }, + }); return (
@@ -45,14 +43,14 @@ function ARORequests() { - {loading + {isLoading || !data ? ( Loading... ) - : ( - aroRequests.map((item) => { + :( + data.map((item) => { return ( { - const response = await fetch(`http://localhost:5000/recent-logs/`); - const data = await response.json(); - setDate(data.date); - setLog(data.log); - setLoading(false); - }; - - useEffect(() => { - fetchLogData(); - const interval = setInterval(fetchLogData, 10000); - return () => clearInterval(interval); - }, []); +import { useQuery } from '@tanstack/react-query'; +function LogItem({ log }: { log: any }) { return ( - {loading ? Loading... : ( - <> - {date} - {log} - {" "} - - )} + {log.date} + {log.log} ); } function Logs() { - const count = 5; + const { data, isLoading} = useQuery({ + queryKey: ["logData"], + queryFn: async () => { + const response = await fetch("http://localhost:8000/api/v1/mcc/logs/"); + if (!response.ok) { + throw new Error("Network response was not ok"); + } + return response.json(); + }, + }); + return (
@@ -45,7 +32,11 @@ function Logs() { - {[...Array(count).keys()].map((key) => )} + {isLoading ? ( + + ) : ( + data?.map((log: any, idx: number) => ) + )}
Loading...
diff --git a/gs/frontend/archive/mcc/src/mission-commands/mission-commands.tsx b/gs/frontend/archive/mcc/src/mission-commands/mission-commands.tsx index 813201bde..db18992ee 100644 --- a/gs/frontend/archive/mcc/src/mission-commands/mission-commands.tsx +++ b/gs/frontend/archive/mcc/src/mission-commands/mission-commands.tsx @@ -1,52 +1,52 @@ import InputGroup from "react-bootstrap/InputGroup"; import Form from "react-bootstrap/Form"; import Table from "react-bootstrap/Table"; -import { useEffect, useRef, useState } from "react"; +import { useRef, useState } from "react"; +import { useQuery, useMutation } from '@tanstack/react-query'; const MISSON_COMMAND_PREFIX = "MCC_"; function MissionCommands() { - const [commands, setCommands] = useState(""); - const [commandResponse, setCommandResponse] = useState(""); const inputRef = useRef(null); - useEffect(() => { - try { - const command = localStorage.getItem(MISSON_COMMAND_PREFIX + "command"); - const response = localStorage.getItem(MISSON_COMMAND_PREFIX + "response"); - if (!command) return; - if (!response) return; - setCommands(command); - setCommandResponse(response); - } catch (error) { - console.error(error); - } - }, []); + const { data: savedData } = useQuery({ + queryKey: ["missionCommand"], + queryFn: () => { + const command = localStorage.getItem(MISSON_COMMAND_PREFIX + "command") || ""; + const response = localStorage.getItem(MISSON_COMMAND_PREFIX + "response") || ""; + return { command, response }; + }, + initialData: { + command: localStorage.getItem(MISSON_COMMAND_PREFIX + "command") || "", + response: localStorage.getItem(MISSON_COMMAND_PREFIX + "response") || "", + }, +}); - // const handleChange = (event) => { - // setCommands(event.target.value); - // localStorage.setItem(MISSON_COMMAND_PREFIX + "command", event.target.value); - // } + const [commands, setCommands] = useState(savedData.command); - const handleCommand = () => { - try { - const requestOptions = { + const mutation = useMutation({ + mutationFn: async (command: string) => { + const response = await fetch("http://localhost:8000/api/v1/mcc/mission-commands/", { method: "POST", headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ command: commands }), - }; - fetch("http://localhost:5000/mission-control", requestOptions) - .then((response) => response.json()) - .then((data) => { - setCommandResponse(data.response); - localStorage.setItem( - MISSON_COMMAND_PREFIX + "response", - data.response, - ); - }); - } catch (error) { - console.error(error); - } + body: JSON.stringify({ command }), + }); + if (!response.ok) { + throw new Error(`Server error: ${response.status}`); + } + return response.json(); + }, + onSuccess: (data) => { + localStorage.setItem( + MISSON_COMMAND_PREFIX + "response", + data.response + ); + }, + }); + + const handleCommand = () => { + localStorage.setItem(MISSON_COMMAND_PREFIX + "command", commands); + mutation.mutate(commands); }; const clear = () => { @@ -56,8 +56,7 @@ function MissionCommands() { console.error(error); } setCommands(""); - setCommandResponse(""); - // inputRef.current.value = '' + mutation.reset(); }; return ( @@ -69,7 +68,7 @@ function MissionCommands() { setCommands(e.target.value)} ref={inputRef} /> @@ -80,7 +79,13 @@ function MissionCommands() { - {commandResponse && {commandResponse}} + + + {mutation.status === "pending" && "Loading..."} + {mutation.status === "error" && `Error: ${(mutation.error as Error).message}`} + {mutation.status === "success" && mutation.data.response} + + diff --git a/gs/frontend/aro/package-lock.json b/gs/frontend/aro/package-lock.json index 5280bbdec..8caa64420 100644 --- a/gs/frontend/aro/package-lock.json +++ b/gs/frontend/aro/package-lock.json @@ -9,6 +9,8 @@ "version": "0.0.0", "dependencies": { "@tailwindcss/vite": "^4.1.13", + "@tanstack/react-query": "^5.90.2", + "@types/react-router-dom": "^5.3.3", "react": "^19.1.1", "react-dom": "^19.1.1", "react-router-dom": "^7.9.2", @@ -1798,11 +1800,10 @@ "vite": "^5.2.0 || ^6 || ^7" } }, - "node_modules/@testing-library/dom": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", - "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", - "dev": true, + "node_modules/@tanstack/query-core": { + "version": "5.90.2", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.2.tgz", + "integrity": "sha512-k/TcR3YalnzibscALLwxeiLUub6jN5EDLwKDiO7q5f4ICEoptJ+n9+7vcEFy5/x/i6Q+Lb/tXrsKCggf5uQJXQ==", "license": "MIT", "dependencies": { "@babel/code-frame": "^7.10.4", @@ -1818,19 +1819,13 @@ "node": ">=18" } }, - "node_modules/@testing-library/jest-dom": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.8.0.tgz", - "integrity": "sha512-WgXcWzVM6idy5JaftTVC8Vs83NKRmGJz4Hqs4oyOuO2J4r/y79vvKZsb+CaGyCSEbUPI6OsewfPd0G1A0/TUZQ==", - "dev": true, + "node_modules/@tanstack/react-query": { + "version": "5.90.2", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.2.tgz", + "integrity": "sha512-CLABiR+h5PYfOWr/z+vWFt5VsOA2ekQeRQBFSKlcoW6Ndx/f8rfyVmq4LbgOM4GG2qtxAxjLYLOpCNTYm4uKzw==", "license": "MIT", "dependencies": { - "@adobe/css-tools": "^4.4.0", - "aria-query": "^5.0.0", - "css.escape": "^1.5.1", - "dom-accessibility-api": "^0.6.3", - "picocolors": "^1.1.1", - "redent": "^3.0.0" + "@tanstack/query-core": "5.90.2" }, "engines": { "node": ">=14", diff --git a/gs/frontend/aro/package.json b/gs/frontend/aro/package.json index e09f5b9e4..04f4da758 100644 --- a/gs/frontend/aro/package.json +++ b/gs/frontend/aro/package.json @@ -12,6 +12,8 @@ }, "dependencies": { "@tailwindcss/vite": "^4.1.13", + "@tanstack/react-query": "^5.90.2", + "@types/react-router-dom": "^5.3.3", "react": "^19.1.1", "react-dom": "^19.1.1", "react-router-dom": "^7.9.2", diff --git a/gs/frontend/aro/src/main.tsx b/gs/frontend/aro/src/main.tsx index 7ac0034c5..f5c8a616d 100644 --- a/gs/frontend/aro/src/main.tsx +++ b/gs/frontend/aro/src/main.tsx @@ -13,11 +13,17 @@ Object.entries(CSS_VARIABLES).forEach(([property, value]) => { /** * @brief Main component displaying the main application, which is linked to the index.html file * @return tsx element of Main component - */ + */import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; + +const queryClient = new QueryClient(); + ReactDOM.createRoot(document.getElementById("root")!).render( + + ); + diff --git a/gs/frontend/mcc/package-lock.json b/gs/frontend/mcc/package-lock.json index 52ac1ce35..b2c1b2538 100644 --- a/gs/frontend/mcc/package-lock.json +++ b/gs/frontend/mcc/package-lock.json @@ -9,6 +9,8 @@ "version": "0.0.0", "dependencies": { "@tailwindcss/vite": "^4.1.13", + "@tanstack/react-query": "^5.90.2", + "bootstrap": "^5.3.8", "react": "^19.1.1", "react-dom": "^19.1.1", "react-router-dom": "^7.8.2", @@ -1798,102 +1800,32 @@ "vite": "^5.2.0 || ^6 || ^7" } }, - "node_modules/@testing-library/dom": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", - "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "5.3.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "picocolors": "1.1.1", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@testing-library/jest-dom": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.8.0.tgz", - "integrity": "sha512-WgXcWzVM6idy5JaftTVC8Vs83NKRmGJz4Hqs4oyOuO2J4r/y79vvKZsb+CaGyCSEbUPI6OsewfPd0G1A0/TUZQ==", - "dev": true, + "node_modules/@tanstack/query-core": { + "version": "5.90.2", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.2.tgz", + "integrity": "sha512-k/TcR3YalnzibscALLwxeiLUub6jN5EDLwKDiO7q5f4ICEoptJ+n9+7vcEFy5/x/i6Q+Lb/tXrsKCggf5uQJXQ==", "license": "MIT", - "dependencies": { - "@adobe/css-tools": "^4.4.0", - "aria-query": "^5.0.0", - "css.escape": "^1.5.1", - "dom-accessibility-api": "^0.6.3", - "picocolors": "^1.1.1", - "redent": "^3.0.0" - }, - "engines": { - "node": ">=14", - "npm": ">=6", - "yarn": ">=1" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" } }, - "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", - "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@testing-library/react": { - "version": "16.3.0", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.0.tgz", - "integrity": "sha512-kFSyxiEDwv1WLl2fgsq6pPBbw5aWKrsY2/noi1Id0TK0UParSF62oFQFGHXIyaG4pp2tEub/Zlel+fjjZILDsw==", - "dev": true, + "node_modules/@tanstack/react-query": { + "version": "5.90.2", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.2.tgz", + "integrity": "sha512-CLABiR+h5PYfOWr/z+vWFt5VsOA2ekQeRQBFSKlcoW6Ndx/f8rfyVmq4LbgOM4GG2qtxAxjLYLOpCNTYm4uKzw==", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.12.5" + "@tanstack/query-core": "5.90.2" }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@testing-library/dom": "^10.0.0", - "@types/react": "^18.0.0 || ^19.0.0", - "@types/react-dom": "^18.0.0 || ^19.0.0", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@testing-library/user-event": { - "version": "14.6.1", - "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.6.1.tgz", - "integrity": "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12", - "npm": ">=6" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" }, "peerDependencies": { - "@testing-library/dom": ">=7.21.4" + "react": "^18 || ^19" } }, - "node_modules/@types/aria-query": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", - "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", diff --git a/gs/frontend/mcc/package.json b/gs/frontend/mcc/package.json index 9b85fa3be..f75722d2b 100644 --- a/gs/frontend/mcc/package.json +++ b/gs/frontend/mcc/package.json @@ -12,6 +12,8 @@ }, "dependencies": { "@tailwindcss/vite": "^4.1.13", + "@tanstack/react-query": "^5.90.2", + "bootstrap": "^5.3.8", "react": "^19.1.1", "react-dom": "^19.1.1", "react-router-dom": "^7.8.2", diff --git a/gs/frontend/mcc/src/main.tsx b/gs/frontend/mcc/src/main.tsx index 7ac0034c5..6903e7c88 100644 --- a/gs/frontend/mcc/src/main.tsx +++ b/gs/frontend/mcc/src/main.tsx @@ -1,6 +1,10 @@ import React from "react"; import ReactDOM from "react-dom/client"; import App from "./App.tsx"; +import "./index.css"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; + +const queryClient = new QueryClient(); import "./index.css"; // default styles are applied here import { BrowserRouter } from "react-router-dom"; import { CSS_VARIABLES } from "./utils/themes.ts"; @@ -16,8 +20,8 @@ Object.entries(CSS_VARIABLES).forEach(([property, value]) => { */ ReactDOM.createRoot(document.getElementById("root")!).render( - - - + + + );