feat: Select article list in sight

This commit is contained in:
2025-05-31 06:35:05 +03:00
parent 5ef61bcef4
commit 2e6917406e
21 changed files with 899 additions and 498 deletions

View File

@ -0,0 +1,36 @@
import { authInstance } from "@shared";
import { makeAutoObservable, runInAction } from "mobx";
export type Article = {
id: string;
heading: string;
body: string;
service_name: string;
};
class ArticlesStore {
constructor() {
makeAutoObservable(this);
}
articles: Article[] = [];
articleData: Article | null = null;
getArticles = async () => {
const response = await authInstance.get("/article");
runInAction(() => {
this.articles = response.data;
});
};
getArticle = async (id: string) => {
const response = await authInstance.get(`/article/${id}`);
runInAction(() => {
this.articleData = response.data;
});
};
}
export const articlesStore = new ArticlesStore();

View File

@ -1,5 +1,5 @@
import { API_URL, decodeJWT } from "@shared";
import { makeAutoObservable } from "mobx";
import { makeAutoObservable, runInAction } from "mobx";
import axios, { AxiosError } from "axios";
type LoginResponse = {
@ -14,6 +14,7 @@ type LoginResponse = {
class AuthStore {
payload: LoginResponse | null = null;
token: string | null = null;
isLoading = false;
error: string | null = null;
@ -28,21 +29,13 @@ class AuthStore {
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) => {
@ -58,12 +51,13 @@ class AuthStore {
}
);
const { token } = response.data;
const data = response.data;
// Update auth token and store state
this.setAuthToken(token);
this.payload = response.data;
this.error = null;
runInAction(() => {
this.setAuthToken(data.token);
this.payload = response.data;
this.error = null;
});
} catch (error) {
if (error instanceof AxiosError) {
this.error =
@ -85,7 +79,7 @@ class AuthStore {
};
get isAuthenticated() {
return !!this.payload?.token;
return this.payload?.token !== null;
}
get user() {

View File

@ -1,5 +1,5 @@
import { authInstance } from "@shared";
import { makeAutoObservable } from "mobx";
import { makeAutoObservable, runInAction } from "mobx";
type City = {
id: number;
@ -18,7 +18,9 @@ class CityStore {
getCities = async () => {
const response = await authInstance.get("/city");
this.cities = response.data;
runInAction(() => {
this.cities = response.data;
});
};
}

View File

@ -1,5 +1,5 @@
import { API_URL, authInstance } from "@shared";
import { makeAutoObservable } from "mobx";
import { makeAutoObservable, runInAction } from "mobx";
class DevicesStore {
devices: string[] = [];
@ -12,7 +12,9 @@ class DevicesStore {
getDevices = async () => {
const response = await authInstance.get(`${API_URL}/devices/connected`);
this.devices = response.data;
runInAction(() => {
this.devices = response.data;
});
};
setSelectedDevice = (uuid: string) => {

View File

@ -1,13 +1,14 @@
import { makeAutoObservable } from "mobx";
import { Language } from "../SightsStore";
class LanguageStore {
language: string = "ru";
language: Language = "ru";
constructor() {
makeAutoObservable(this);
}
setLanguage = (language: string) => {
setLanguage = (language: Language) => {
this.language = language;
};
}

View File

@ -1,4 +1,4 @@
import { authInstance } from "@shared";
import { authInstance, languageInstance, languageStore } from "@shared";
import { makeAutoObservable, runInAction } from "mobx";
export type Language = "ru" | "en" | "zh";
@ -8,7 +8,6 @@ export type MultilingualContent = {
name: string;
description: string;
address: string;
// Add other fields that need to be multilingual
};
};
@ -28,10 +27,22 @@ export type Sight = {
video_preview: string | null;
};
export type CreateSight = {
[key in Language]: {
name: string;
description: string;
address: string;
};
};
class SightsStore {
sights: Sight[] = [];
sight: Sight | null = null;
cachedMultilingualContent: MultilingualContent | null = null;
createSight: CreateSight = {
ru: { name: "", description: "", address: "" },
en: { name: "", description: "", address: "" },
zh: { name: "", description: "", address: "" },
};
constructor() {
makeAutoObservable(this);
@ -52,34 +63,96 @@ class SightsStore {
});
};
setCachedMultilingualContent = (content: MultilingualContent) => {
createSightAction = async (
city: number,
coordinates: { latitude: number; longitude: number }
) => {
const id = (
await authInstance.post("/sight", {
name: this.createSight[languageStore.language].name,
description: this.createSight[languageStore.language].description,
address: this.createSight[languageStore.language].address,
city_id: city,
latitude: coordinates.latitude,
longitude: coordinates.longitude,
})
).data.id;
const anotherLanguages = ["ru", "en", "zh"].filter(
(language) => language !== languageStore.language
);
await languageInstance(anotherLanguages[0] as Language).patch(
`/sight/${id}`,
{
name: this.createSight[anotherLanguages[0] as Language].name,
description:
this.createSight[anotherLanguages[0] as Language].description,
address: this.createSight[anotherLanguages[0] as Language].address,
city_id: city,
latitude: coordinates.latitude,
longitude: coordinates.longitude,
}
);
await languageInstance(anotherLanguages[1] as Language).patch(
`/sight/${id}`,
{
name: this.createSight[anotherLanguages[1] as Language].name,
description:
this.createSight[anotherLanguages[1] as Language].description,
address: this.createSight[anotherLanguages[1] as Language].address,
city_id: city,
latitude: coordinates.latitude,
longitude: coordinates.longitude,
}
);
runInAction(() => {
this.cachedMultilingualContent = content;
this.createSight = {
ru: { name: "", description: "", address: "" },
en: { name: "", description: "", address: "" },
zh: { name: "", description: "", address: "" },
};
});
};
setCreateSight = (content: CreateSight) => {
runInAction(() => {
this.createSight = content;
});
};
updateCachedLanguageContent = (
updateCreateSight = (
language: Language,
content: Partial<MultilingualContent[Language]>
content: Partial<CreateSight[Language]>
) => {
runInAction(() => {
if (!this.cachedMultilingualContent) {
this.cachedMultilingualContent = {
ru: { name: "", description: "", address: "" },
en: { name: "", description: "", address: "" },
zh: { name: "", description: "", address: "" },
};
}
this.cachedMultilingualContent[language] = {
...this.cachedMultilingualContent[language],
this.createSight[language] = {
...this.createSight[language],
...content,
};
});
};
clearCachedMultilingualContent = () => {
clearCreateSight = () => {
runInAction(() => {
this.cachedMultilingualContent = null;
this.createSight = {
ru: {
name: "",
description: "",
address: "",
},
en: {
name: "",
description: "",
address: "",
},
zh: {
name: "",
description: "",
address: "",
},
};
});
};
}

View File

@ -5,3 +5,4 @@ export * from "./VehicleStore";
export * from "./SnapshotStore";
export * from "./SightsStore";
export * from "./CityStore";
export * from "./ArticlesStore";