From 45c9de40131339bd5044b3c0d96598da664586b4 Mon Sep 17 00:00:00 2001 From: Matt-Hurd Date: Mon, 25 Sep 2023 03:11:03 -0500 Subject: [PATCH] Allow users to upload routes --- src/App.tsx | 1 + .../RouteSelection/RouteSelection.tsx | 29 ++++++++++++++++++- src/components/RunMosaic/RunMosaic.tsx | 2 +- src/store/routeSlice.ts | 9 +++++- 4 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index e9a3723..ad1eb2a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -12,6 +12,7 @@ const App: React.FC = () => ( } /> } /> + } /> } /> } /> diff --git a/src/components/RouteSelection/RouteSelection.tsx b/src/components/RouteSelection/RouteSelection.tsx index c77d73e..441126d 100644 --- a/src/components/RouteSelection/RouteSelection.tsx +++ b/src/components/RouteSelection/RouteSelection.tsx @@ -1,5 +1,8 @@ import { useState, useEffect } from "react"; -import { Link } from "react-router-dom"; +import { uploadRoute } from "../../store/routeSlice"; +import { Link, useNavigate } from "react-router-dom"; +import { Route } from "../../models"; +import { useDispatch } from "react-redux"; interface RouteOption { name: string; @@ -13,6 +16,8 @@ interface GameOption { } function RouteSelection() { + const dispatch = useDispatch(); + const navigate = useNavigate(); const [gameOptions, setGameOptions] = useState([]); const [customRouteUrl, setCustomRouteUrl] = useState(""); @@ -29,6 +34,26 @@ function RouteSelection() { const handleCustomRouteInput = (event: React.ChangeEvent) => { setCustomRouteUrl(event.target.value); }; + const handleFileUpload = (event: React.ChangeEvent) => { + const file = event.target.files?.[0]; + if (file) { + const reader = new FileReader(); + reader.onload = (e) => { + try { + const content = e.target?.result; + if (typeof content === "string") { + const parsedRoute: Route = JSON.parse(content); + dispatch(uploadRoute(parsedRoute)); + navigate("/uploaded"); + } + } catch (error) { + console.error("Failed to parse route:", error); + // Handle the error. Maybe update the state to show an error message. + } + }; + reader.readAsText(file); + } + }; return (
@@ -54,6 +79,8 @@ function RouteSelection() { placeholder="Input remote route URL" /> {customRouteUrl && Go} +

.. Or upload a route file

+
); } diff --git a/src/components/RunMosaic/RunMosaic.tsx b/src/components/RunMosaic/RunMosaic.tsx index e015422..c1be78b 100644 --- a/src/components/RunMosaic/RunMosaic.tsx +++ b/src/components/RunMosaic/RunMosaic.tsx @@ -41,7 +41,7 @@ import { useKeyBindings } from "./useKeyBindings"; import { useLivesplit } from "./useLiveSplit"; type RunParams = { - routeUrl: string; + routeUrl?: string; user?: string; repo?: string; path?: string; diff --git a/src/store/routeSlice.ts b/src/store/routeSlice.ts index db8c4f6..fc62a02 100644 --- a/src/store/routeSlice.ts +++ b/src/store/routeSlice.ts @@ -35,7 +35,12 @@ export const loadRoute = createAsyncThunk) => { + state.data = action.payload; + state.status = "succeeded"; + }, + }, extraReducers: (builder) => { builder .addCase(loadRoute.pending, (state) => { @@ -57,4 +62,6 @@ export const selectRouteStatus = (state: RootState) => state.route.status; export const selectRouteData = (state: RootState) => state.route.data; export const selectRouteError = (state: RootState) => state.route.error; +export const { uploadRoute } = routeSlice.actions; + export default routeSlice.reducer;