;
export const SimulatorChairRideStatus: FC<
ComponentProps<"div"> & {
diff --git a/frontend/app/components/modules/simulator-display/simulator-chair-display.tsx b/frontend/app/components/modules/simulator-display/simulator-chair-display.tsx
index 06fc40b8..bee65f4e 100644
--- a/frontend/app/components/modules/simulator-display/simulator-chair-display.tsx
+++ b/frontend/app/components/modules/simulator-display/simulator-chair-display.tsx
@@ -99,37 +99,37 @@ const ChairProgress: FC<{
return rideStatus !== undefined ? getSimulatorStartCoordinate() : null;
}, [rideStatus]);
- const pickupProgress: number = useMemo(() => {
+ const progressToPickup: number = useMemo(() => {
if (!rideStatus || !pickupLoc || !startLoc || !currentLoc) {
return 0;
}
switch (rideStatus) {
case "MATCHING":
+ case "COMPLETED":
return 0;
case "PICKUP":
case "ARRIVED":
case "CARRYING":
- case "COMPLETED":
return 100;
default:
return progress(startLoc, currentLoc, pickupLoc);
}
}, [rideStatus, pickupLoc, startLoc, currentLoc]);
- const distanceProgress: number = useMemo(() => {
+ const progressToDestination: number = useMemo(() => {
if (!rideStatus || !destLoc || !pickupLoc || !currentLoc) {
return 0;
}
switch (rideStatus) {
case "MATCHING":
+ case "COMPLETED":
case "PICKUP":
case "ENROUTE":
return 0;
case "ARRIVED":
- case "COMPLETED":
return 100;
default:
- return progress(destLoc, currentLoc, pickupLoc);
+ return progress(pickupLoc, currentLoc, destLoc);
}
}, [rideStatus, destLoc, pickupLoc, currentLoc]);
@@ -140,13 +140,11 @@ const ChairProgress: FC<{
{rideStatus &&
- ["PICKUP", "CARRYING", "ARRIVED", "COMPLETED"].includes(
- rideStatus,
- ) && (
+ ["PICKUP", "CARRYING", "ARRIVED"].includes(rideStatus) && (
)}
@@ -154,16 +152,17 @@ const ChairProgress: FC<{
- {rideStatus && ["MATCHING", "ENROUTE"].includes(rideStatus) && (
-
- )}
+ {rideStatus &&
+ ["MATCHING", "COMPLETED", "ENROUTE"].includes(rideStatus) && (
+
+ )}
diff --git a/frontend/app/contexts/client-context.tsx b/frontend/app/contexts/client-context.tsx
index 9050dbc9..8b213123 100644
--- a/frontend/app/contexts/client-context.tsx
+++ b/frontend/app/contexts/client-context.tsx
@@ -13,7 +13,7 @@ import {
} from "~/api/api-components";
import { isClientApiError } from "~/types";
import { getCookieValue } from "~/utils/get-cookie-value";
-import { getUserAccessToken, getUserId } from "~/utils/storage";
+import { getUserId } from "~/utils/storage";
function jsonFromSSEResponse(value: string) {
const data = value.slice("data:".length).trim();
@@ -140,13 +140,11 @@ export const useNotification = ():
type ClientContextProps = {
data?: AppGetNotificationResponse["data"];
userId?: string | null;
- accessToken?: string | null;
};
const ClientContext = createContext({});
-export const UserProvider = ({ children }: { children: ReactNode }) => {
- const [accessToken] = useState(() => getUserAccessToken());
+export const ClientProvider = ({ children }: { children: ReactNode }) => {
const [userId] = useState(() => getUserId());
const navigate = useNavigate();
const data = useNotification();
@@ -160,7 +158,7 @@ export const UserProvider = ({ children }: { children: ReactNode }) => {
}, [navigate]);
return (
-
+
{children}
);
diff --git a/frontend/app/contexts/simulator-context.tsx b/frontend/app/contexts/simulator-context.tsx
index 45063871..0161d013 100644
--- a/frontend/app/contexts/simulator-context.tsx
+++ b/frontend/app/contexts/simulator-context.tsx
@@ -3,10 +3,14 @@ import {
createContext,
useContext,
useEffect,
+ useMemo,
useState,
} from "react";
import type { Coordinate } from "~/api/api-schemas";
-import { getSimulateChair } from "~/utils/get-initial-data";
+import {
+ getSimulateChair,
+ getSimulateChairFromToken,
+} from "~/utils/get-initial-data";
import { apiBaseURL } from "~/api/api-base-url";
import {
@@ -15,11 +19,13 @@ import {
} from "~/api/api-components";
import { SimulatorChair } from "~/types";
import { getSimulatorCurrentCoordinate } from "~/utils/storage";
+import { getCookieValue } from "~/utils/get-cookie-value";
type SimulatorContextProps = {
chair?: SimulatorChair;
data?: ChairGetNotificationResponse["data"];
setCoordinate?: (coordinate: Coordinate) => void;
+ setToken?: (token: string) => void;
};
const SimulatorContext = createContext({});
@@ -29,8 +35,6 @@ function jsonFromSseResult(value: string) {
return JSON.parse(data) as T;
}
-const simulateChair = getSimulateChair();
-
const useNotification = (): ChairGetNotificationResponse["data"] => {
const [isSse, setIsSse] = useState(false);
const [notification, setNotification] =
@@ -61,6 +65,9 @@ const useNotification = (): ChairGetNotificationResponse["data"] => {
| undefined;
setNotification(json);
} catch (error) {
+ if (error instanceof DOMException && error.name === "AbortError") {
+ return;
+ }
console.error(error);
}
};
@@ -134,6 +141,9 @@ const useNotification = (): ChairGetNotificationResponse["data"] => {
});
timeoutId = setTimeout(() => void polling(), retryAfterMs);
} catch (error) {
+ if (error instanceof DOMException && error.name === "AbortError") {
+ return;
+ }
console.error(error);
}
};
@@ -149,8 +159,30 @@ const useNotification = (): ChairGetNotificationResponse["data"] => {
return notification?.data;
};
+
+
export const SimulatorProvider = ({ children }: { children: ReactNode }) => {
+
+ const [token, setToken] = useState();
+
+ const simulateChair = useMemo(() => {
+ return token ? getSimulateChairFromToken(token) : getSimulateChair();
+ }, [token]);
+
+ useEffect(() => {
+ const token = getCookieValue(document.cookie, "chair_session");
+ if (token) {
+ setToken(token);
+ return;
+ }
+ // TODO: tokenがなければUI上で選択させるようにする
+ if (simulateChair?.token) {
+ document.cookie = `chair_session=${simulateChair.token}; path=/`;
+ }
+ }, [simulateChair]);
+
const data = useNotification();
+
const [coordinate, setCoordinate] = useState(() => {
const coordinate = getSimulatorCurrentCoordinate();
return coordinate ?? { latitude: 0, longitude: 0 };
@@ -168,6 +200,7 @@ export const SimulatorProvider = ({ children }: { children: ReactNode }) => {
data,
chair: simulateChair ? { ...simulateChair, coordinate } : undefined,
setCoordinate,
+ setToken
}}
>
{children}
diff --git a/frontend/app/globals.d.ts b/frontend/app/globals.d.ts
index 8996cfc8..3ef9d6fa 100644
--- a/frontend/app/globals.d.ts
+++ b/frontend/app/globals.d.ts
@@ -3,19 +3,4 @@
*/
declare const __API_BASE_URL__: string;
-declare const __INITIAL_OWNER_DATA__:
- | {
- owners: {
- id: string;
- name: string;
- token: string;
- }[];
- targetSimulatorChair: {
- id: string;
- owner_id: string;
- name: string;
- model: string;
- token: string;
- };
- }
- | undefined;
+declare const __INITIAL_DATA__: object;
diff --git a/frontend/app/routes/client._index/driving-state/arrived.tsx b/frontend/app/routes/client._index/driving-state/arrived.tsx
index ea4a57c6..a39664cc 100644
--- a/frontend/app/routes/client._index/driving-state/arrived.tsx
+++ b/frontend/app/routes/client._index/driving-state/arrived.tsx
@@ -12,7 +12,7 @@ import { useClientContext } from "~/contexts/client-context";
import confetti from "canvas-confetti";
export const Arrived = ({ onEvaluated }: { onEvaluated: () => void }) => {
- const { accessToken, data } = useClientContext();
+ const { data } = useClientContext();
const [rating, setRating] = useState(0);
const onClick: MouseEventHandler = useCallback(
@@ -20,9 +20,6 @@ export const Arrived = ({ onEvaluated }: { onEvaluated: () => void }) => {
e.preventDefault();
try {
void fetchAppPostRideEvaluation({
- headers: {
- Authorization: `Bearer ${accessToken}`,
- },
pathParams: {
rideId: data?.ride_id ?? "",
},
@@ -35,7 +32,7 @@ export const Arrived = ({ onEvaluated }: { onEvaluated: () => void }) => {
}
onEvaluated();
},
- [onEvaluated, accessToken, data?.ride_id, rating],
+ [onEvaluated, data?.ride_id, rating],
);
useEffect(() => {
diff --git a/frontend/app/routes/client._index/route.tsx b/frontend/app/routes/client._index/route.tsx
index 1f5a46ed..b3212836 100644
--- a/frontend/app/routes/client._index/route.tsx
+++ b/frontend/app/routes/client._index/route.tsx
@@ -89,26 +89,19 @@ export default function Index() {
if (!currentLocation || !destLocation) {
return;
}
- const abortController = new AbortController();
- fetchAppPostRidesEstimatedFare(
- {
- body: {
- pickup_coordinate: currentLocation,
- destination_coordinate: destLocation,
- },
+ fetchAppPostRidesEstimatedFare({
+ body: {
+ pickup_coordinate: currentLocation,
+ destination_coordinate: destLocation,
},
- abortController.signal,
- )
+ })
.then((res) =>
setEstimatePrice({ fare: res.fare, discount: res.discount }),
)
- .catch((err) => {
- console.error(err);
+ .catch((error) => {
+ console.error(error);
setEstimatePrice(undefined);
});
- return () => {
- abortController.abort();
- };
}, [currentLocation, destLocation]);
const handleRideRequest = useCallback(async () => {
@@ -150,6 +143,9 @@ export default function Index() {
});
setDisplayedChairs(chairs);
} catch (error) {
+ if (error instanceof DOMException && error.name === "AbortError") {
+ return;
+ }
console.error(error);
}
};
@@ -282,6 +278,7 @@ export default function Index() {
statusModalRef.current?.close();
setCurrentLocation(destLocation);
setDestLocation(undefined);
+ setEstimatePrice(undefined);
}}
/>
)}
diff --git a/frontend/app/routes/client.history/route.tsx b/frontend/app/routes/client.history/route.tsx
index 878a9722..467a30b9 100644
--- a/frontend/app/routes/client.history/route.tsx
+++ b/frontend/app/routes/client.history/route.tsx
@@ -22,18 +22,14 @@ export default function Index() {
const [rides, setRides] = useState([]);
useEffect(() => {
- const abortController = new AbortController();
void (async () => {
try {
- const res = await fetchAppGetRides({}, abortController.signal);
+ const res = await fetchAppGetRides({});
setRides(res.rides);
} catch (error) {
console.error(error);
}
})();
- return () => {
- abortController.abort();
- };
}, []);
return (
diff --git a/frontend/app/routes/client/route.tsx b/frontend/app/routes/client/route.tsx
index 92d4f0c8..4be79069 100644
--- a/frontend/app/routes/client/route.tsx
+++ b/frontend/app/routes/client/route.tsx
@@ -1,14 +1,14 @@
import { Outlet } from "@remix-run/react";
import { FooterNavigation } from "~/components/modules/footer-navigation/footer-navigation";
import { MainFrame } from "~/components/primitives/frame/frame";
-import { UserProvider } from "../../contexts/client-context";
+import { ClientProvider } from "../../contexts/client-context";
export default function ClientLayout() {
return (
-
+
-
+
);
diff --git a/frontend/app/routes/owner.sales/route.tsx b/frontend/app/routes/owner.sales/route.tsx
index f44a1f36..6beef6f3 100644
--- a/frontend/app/routes/owner.sales/route.tsx
+++ b/frontend/app/routes/owner.sales/route.tsx
@@ -45,27 +45,20 @@ export default function Index() {
const since = salesDate?.since;
const until = salesDate?.until;
if (!since || !until) return;
- let abortController: AbortController | undefined;
void (async () => {
try {
- abortController = new AbortController();
setSales(
- await fetchOwnerGetSales(
- {
- queryParams: {
- until: timestamp(until),
- since: timestamp(since),
- },
+ await fetchOwnerGetSales({
+ queryParams: {
+ until: timestamp(until),
+ since: timestamp(since),
},
- abortController.signal,
- ),
+ }),
);
} catch (error) {
console.error(error);
}
})();
-
- return () => abortController?.abort();
}, [salesDate, setSales]);
const chairModelMap = useMemo(
diff --git a/frontend/app/utils/get-initial-data.ts b/frontend/app/utils/get-initial-data.ts
index 10087ec6..62bc31dd 100644
--- a/frontend/app/utils/get-initial-data.ts
+++ b/frontend/app/utils/get-initial-data.ts
@@ -12,16 +12,41 @@ type InitialOwner = {
token: string;
};
-const initialOwnerData = __INITIAL_OWNER_DATA__;
+type initialDataType =
+ | {
+ owners: {
+ id: string;
+ name: string;
+ token: string;
+ }[];
+ simulatorChairs: {
+ id: string;
+ owner_id: string;
+ name: string;
+ model: string;
+ token: string;
+ }[];
+ }
+ | undefined;
+
+const initialData = __INITIAL_DATA__ as initialDataType;
export const getOwners = (): InitialOwner[] => {
return (
- initialOwnerData?.owners?.map((owner) => ({
+ initialData?.owners?.map((owner) => ({
...owner,
})) ?? []
);
};
-export const getSimulateChair = (): InitialChair | undefined => {
- return initialOwnerData?.targetSimulatorChair;
+export const getSimulateChair = (index?: number): InitialChair | undefined => {
+ return index
+ ? initialData?.simulatorChairs[index]
+ : initialData?.simulatorChairs[0];
+};
+
+export const getSimulateChairFromToken = (
+ token: string,
+): InitialChair | undefined => {
+ return initialData?.simulatorChairs.find((c) => c.token === token);
};
diff --git a/frontend/app/utils/storage.ts b/frontend/app/utils/storage.ts
index 240211af..8e337412 100644
--- a/frontend/app/utils/storage.ts
+++ b/frontend/app/utils/storage.ts
@@ -64,11 +64,3 @@ export const setUserId = (id: string) => {
export const getUserId = (): string | null => {
return getStorage("user.id", sessionStorage);
};
-
-export const setUserAccessToken = (id: string) => {
- return setStorage("user.accessToken", id, sessionStorage);
-};
-
-export const getUserAccessToken = (): string | null => {
- return getStorage("user.accessToken", sessionStorage);
-};
diff --git a/frontend/initial-owner-data.json b/frontend/initial-data.json
similarity index 51%
rename from frontend/initial-owner-data.json
rename to frontend/initial-data.json
index 4d02bb34..6f7ef303 100644
--- a/frontend/initial-owner-data.json
+++ b/frontend/initial-data.json
@@ -26,11 +26,27 @@
"token": "3585ccc78c507660a4802973d269849e"
}
],
- "targetSimulatorChair": {
- "id": "01JDFEF7MGXXCJKW1MNJXPA77A",
- "owner_id": "01JDFEDF008NTA922W12FS7800",
- "name": "QC-L13-8361",
- "model": "クエストチェア Lite",
- "token": "3013d5ec84e1b230f913a17d71ef27c8"
- }
+ "simulatorChairs": [
+ {
+ "id": "01JDFEF7MGXXCJKW1MNJXPA77A",
+ "owner_id": "01JDFEDF008NTA922W12FS7800",
+ "name": "QC-L13-8361",
+ "model": "クエストチェア Lite",
+ "token": "3013d5ec84e1b230f913a17d71ef27c8"
+ },
+ {
+ "id": "01JDFEXJM006PH4C1EVHJ31QMV",
+ "owner_id": "01JDFEDF008NTA922W12FS7800",
+ "name": "LC-48-2566",
+ "model": "Legacy Chair",
+ "token": "b63d4c58ded093013ea5a483e2184d91"
+ },
+ {
+ "id": "01JDFGTKR0586QH1QGXRACGB80",
+ "owner_id": "01JDFEDF008NTA922W12FS7800",
+ "name": "IS-33-8740",
+ "model": "Infinity Seat",
+ "token": "091cd034ce1ac4a9dd9fb1b5ec52c3dc"
+ }
+ ]
}
diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts
index b63e50cf..8d2e6c96 100644
--- a/frontend/vite.config.ts
+++ b/frontend/vite.config.ts
@@ -20,10 +20,8 @@ const DEFAULT_URL = `http://${DEFAULT_HOSTNAME}:${DEFAULT_PORT}`;
type APIResponse = Record;
-const intialOwnerData = existsSync("./initial-owner-data.json")
- ? (JSON.parse(
- readFileSync("./initial-owner-data.json").toString(),
- ) as unknown)
+const intialOwnerData = existsSync("./initial-data.json")
+ ? (JSON.parse(readFileSync("./initial-data.json").toString()) as unknown)
: undefined;
const getLoggedInURLForClient = async () => {
@@ -253,7 +251,7 @@ export const config = {
],
define: {
[alternativeURLExpression]: `"${process.env["API_BASE_URL"] ?? "."}"`,
- __INITIAL_OWNER_DATA__: intialOwnerData,
+ __INITIAL_DATA__: intialOwnerData,
},
server: {
proxy: {
diff --git a/webapp/go/app_handlers.go b/webapp/go/app_handlers.go
index 20882df0..ccacee3f 100644
--- a/webapp/go/app_handlers.go
+++ b/webapp/go/app_handlers.go
@@ -857,17 +857,14 @@ func appGetNearbyChairs(w http.ResponseWriter, r *http.Request) {
continue
}
- ride := &Ride{}
- if err := tx.Get(
- ride,
- `SELECT * FROM rides WHERE chair_id = ? ORDER BY created_at DESC LIMIT 1`,
- chair.ID,
- ); err != nil {
- if !errors.Is(err, sql.ErrNoRows) {
- writeError(w, http.StatusInternalServerError, err)
- return
- }
- } else {
+ rides := []*Ride{}
+ if err := tx.Select(&rides, `SELECT * FROM rides WHERE chair_id = ? ORDER BY created_at DESC`, chair.ID); err != nil {
+ writeError(w, http.StatusInternalServerError, err)
+ return
+ }
+
+ skip := false
+ for _, ride := range rides {
// 過去にライドが存在し、かつ、それが完了していない場合はスキップ
status, err := getLatestRideStatus(tx, ride.ID)
if err != nil {
@@ -875,9 +872,13 @@ func appGetNearbyChairs(w http.ResponseWriter, r *http.Request) {
return
}
if status != "COMPLETED" {
- continue
+ skip = true
+ break
}
}
+ if skip {
+ continue
+ }
// 最新の位置情報を取得
chairLocation := &ChairLocation{}