init: Init React Application

This commit is contained in:
2025-05-29 13:21:33 +03:00
parent 9444939507
commit 17de7e495f
66 changed files with 10425 additions and 0 deletions

View File

@ -0,0 +1,96 @@
import { API_URL, decodeJWT } from "@shared";
import { makeAutoObservable } from "mobx";
import axios, { AxiosError } from "axios";
type LoginResponse = {
token: string;
user: {
id: number;
name: string;
email: string;
is_admin: boolean;
};
};
class AuthStore {
payload: LoginResponse | null = null;
isLoading = false;
error: string | null = null;
constructor() {
makeAutoObservable(this);
this.initialize();
}
private initialize() {
const storedToken = localStorage.getItem("token") || undefined;
const decoded = decodeJWT(storedToken);
if (decoded) {
this.payload = decoded;
// Set the token in axios defaults for future requests
if (storedToken) {
axios.defaults.headers.common[
"Authorization"
] = `Bearer ${storedToken}`;
}
} else {
// If token is invalid or missing, clear it
this.logout();
}
}
private setAuthToken(token: string) {
localStorage.setItem("token", token);
axios.defaults.headers.common["Authorization"] = `Bearer ${token}`;
}
login = async (email: string, password: string) => {
this.isLoading = true;
this.error = null;
try {
const response = await axios.post<LoginResponse>(
`${API_URL}/auth/login`,
{
email,
password,
}
);
const { token } = response.data;
// Update auth token and store state
this.setAuthToken(token);
this.payload = response.data;
this.error = null;
} catch (error) {
if (error instanceof AxiosError) {
this.error =
error.response?.data?.message || "Ошибка при входе в систему";
} else {
this.error = "Неизвестная ошибка при входе в систему";
}
throw new Error(this.error ?? "Неизвестная ошибка при входе в систему");
} finally {
this.isLoading = false;
}
};
logout = () => {
localStorage.removeItem("token");
this.payload = null;
this.error = null;
};
get isAuthenticated() {
return !!this.payload?.token;
}
get user() {
return this.payload?.user;
}
}
export const authStore = new AuthStore();

View File

@ -0,0 +1,28 @@
import { API_URL, authInstance } from "@shared";
import { makeAutoObservable } from "mobx";
class DevicesStore {
devices: any[] = [];
uuid: string | null = null;
sendSnapshotModalOpen = false;
constructor() {
makeAutoObservable(this);
}
getDevices = async () => {
const response = await authInstance.get(`${API_URL}/devices/connected`);
console.log(response.data);
this.devices = response.data;
};
setSelectedDevice = (uuid: string) => {
this.uuid = uuid;
};
toggleSendSnapshotModal = () => {
this.sendSnapshotModalOpen = !this.sendSnapshotModalOpen;
};
}
export const devicesStore = new DevicesStore();

View File

@ -0,0 +1,15 @@
import { makeAutoObservable } from "mobx";
class LanguageStore {
language: string = "ru";
constructor() {
makeAutoObservable(this);
}
setLanguage = (language: string) => {
this.language = language;
};
}
export const languageStore = new LanguageStore();

View File

@ -0,0 +1,18 @@
import { authInstance } from "@shared";
import { API_URL } from "@shared";
import { makeAutoObservable } from "mobx";
class SnapshotStore {
snapshots: any[] = [];
constructor() {
makeAutoObservable(this);
}
getSnapshots = async () => {
const response = await authInstance.get(`${API_URL}/snapshots`);
this.snapshots = response.data;
};
}
export const snapshotStore = new SnapshotStore();

View File

@ -0,0 +1,17 @@
import { API_URL, authInstance } from "@shared";
import { makeAutoObservable } from "mobx";
class VehicleStore {
vehicles: any[] = [];
constructor() {
makeAutoObservable(this);
}
getVehicles = async () => {
const response = await authInstance.get(`${API_URL}/vehicle`);
this.vehicles = response.data;
};
}
export const vehicleStore = new VehicleStore();

View File

@ -0,0 +1,5 @@
export * from "./AuthStore";
export * from "./LanguageStore";
export * from "./DevicesStore";
export * from "./VehicleStore";
export * from "./SnapshotStore";