Commit 3a26228b by asranov0003

feat: add data slice

parent f1d34baa
export const API_URL = "https://cabinet.thecybernanny.com/nanny/backend/rpc"; // PROD
// export const API_URL = "https://cabinet.dev.thecybernanny.com/nanny/backend/rpc"; // DEV
export const GOOGLE_MAPS_API_KEY = "AIzaSyABfhzIz1S4kpWvIMtsDD6XIjo2F7r-mTs";
export const TG_USER_ID = window.Telegram.WebApp.initDataUnsafe?.user?.id || 0;
export const TOKEN = localStorage.getItem(`token-${TG_USER_ID}`) || "";
import React from "react";
import React, { useEffect, useState } from "react";
import "./Routes.css";
import SectionHeader from "../../layouts/SectionHeader";
import CButton from "../../components/CButton";
import { useTranslation } from "react-i18next";
import GoogleMapReact from "google-map-react";
import {
useAppDispatch,
useAppSelector,
type RootState,
} from "../../stores/store";
import { getRouteHistory } from "../../stores/slices/dataSlice";
const Routes: React.FC = () => {
const [fromDate, setFromDate] = useState("");
const [fromTime, setFromTime] = useState("");
const [toDate, setToDate] = useState("");
const [toTime, setToTime] = useState("");
const { selectedDevice } = useAppSelector((state: RootState) => state.device);
const { routeHistory, isRouteHistoryLoading } = useAppSelector(
(state: RootState) => state.data
);
const dispatch = useAppDispatch();
const { t } = useTranslation();
useEffect(() => {
if (selectedDevice) {
const now = new Date();
const yesterday = new Date(now);
yesterday.setDate(now.getDate() - 1);
setFromDate(yesterday.toISOString().slice(0, 10));
setFromTime("00:00");
setToDate(now.toISOString().slice(0, 10));
setToTime("23:59");
dispatch(
getRouteHistory({
deviceId: selectedDevice.id,
dateFrom: yesterday,
dateTo: now,
recStart: 0,
recLimit: 1000,
})
);
}
}, [dispatch, selectedDevice]);
const handleSearch = () => {
if (!selectedDevice) return;
const dateFrom = new Date(`${fromDate}T${fromTime}`);
const dateTo = new Date(`${toDate}T${toTime}`);
dispatch(
getRouteHistory({
deviceId: selectedDevice.id,
dateFrom,
dateTo,
recStart: 0,
recLimit: 1000,
})
);
};
useEffect(() => {
console.log("routeHistory", routeHistory);
}, [routeHistory]);
return (
<div className="routes wrapper">
<SectionHeader to="/home" />
......@@ -28,21 +88,45 @@ const Routes: React.FC = () => {
<div className="routes__filter__date">
<label htmlFor="from">{t("common.from")}</label>
<div>
<input type="date" id="from" />
<input type="time" id="from-time" />
<input
type="date"
id="from"
value={fromDate}
onChange={(e) => setFromDate(e.target.value)}
/>
<input
type="time"
id="from-time"
value={fromTime}
onChange={(e) => setFromTime(e.target.value)}
/>
</div>
</div>
<div className="routes__filter__date">
<label htmlFor="to">{t("common.to")}</label>
<div>
<input type="date" id="to" />
<input type="time" id="to-time" />
<input
type="date"
id="to"
value={toDate}
onChange={(e) => setToDate(e.target.value)}
/>
<input
type="time"
id="to-time"
value={toTime}
onChange={(e) => setToTime(e.target.value)}
/>
</div>
</div>
</div>
<CButton title={t("button.search")} />
<CButton
title={t("button.search")}
onClick={handleSearch}
isLoading={isRouteHistoryLoading}
/>
</div>
</div>
</div>
......
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { sendRpcRequest } from "../../services/apiClient";
interface IRouteHistory {
date: string;
location: {
lat: string;
lon: string;
};
}
interface IDataState {
routeHistory: IRouteHistory[];
isRouteHistoryLoading: boolean;
routeHistoryError: string | null;
}
const initialState: IDataState = {
routeHistory: [],
isRouteHistoryLoading: false,
routeHistoryError: null,
};
export const getRouteHistory = createAsyncThunk(
"data/getRouteHistory",
async (
{
deviceId,
dateFrom,
dateTo,
recStart = 0,
recLimit = 1000,
}: {
deviceId: string;
dateFrom: Date;
dateTo: Date;
recStart?: number;
recLimit?: number;
},
{ rejectWithValue }
) => {
try {
const response = await sendRpcRequest<{ list: IRouteHistory[] }>(
"data.getroutehistory",
{
deviceId,
dateFrom,
dateTo,
recStart,
recLimit,
}
);
return response.list;
} catch (error: unknown) {
if (
typeof error === "object" &&
error !== null &&
"message" in error &&
typeof error.message === "string"
) {
return rejectWithValue(error.message);
}
return rejectWithValue("Unknown error occurred");
}
}
);
const dataSlice = createSlice({
name: "data",
initialState,
reducers: {},
extraReducers: (builder) => {
builder
.addCase(getRouteHistory.pending, (state) => {
state.isRouteHistoryLoading = true;
state.routeHistoryError = null;
})
.addCase(getRouteHistory.fulfilled, (state, action) => {
state.isRouteHistoryLoading = false;
state.routeHistory = action.payload;
})
.addCase(getRouteHistory.rejected, (state, action) => {
state.isRouteHistoryLoading = false;
state.routeHistoryError = action.payload as string;
});
},
});
export default dataSlice.reducer;
......@@ -9,6 +9,7 @@ import browserHistorySlice from "./slices/browserHistorySlice";
import callHistorySlice from "./slices/callHistorySlice";
import messengerHistorySlice from "./slices/messengerHistorySlice";
import usageLimitSlice from "./slices/usageLimitSlice";
import dataSlice from "./slices/dataSlice";
import {
useDispatch,
useSelector,
......@@ -27,6 +28,7 @@ export const store = configureStore({
callHistory: callHistorySlice,
messengerHistory: messengerHistorySlice,
usageLimit: usageLimitSlice,
data: dataSlice,
},
});
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment