front-hub/src/stores/user.ts

126 lines
4.0 KiB
TypeScript
Raw Normal View History

2023-05-30 18:34:41 +00:00
import { PatchUserRequest, UserSettings, UserSettingsField, UserWithFields } from "@root/model/user";
import { produce } from "immer";
2023-05-17 11:20:11 +00:00
import { create } from "zustand";
import { createJSONStorage, devtools, persist } from "zustand/middleware";
2023-05-30 18:34:41 +00:00
import { StringSchema, string } from "yup";
import { patchUser } from "@root/api/user";
2023-05-17 11:20:11 +00:00
interface UserStore {
userId: string | null;
2023-05-30 18:34:41 +00:00
user: UserWithFields | null;
settingsFields: UserSettings | null;
2023-05-17 11:20:11 +00:00
}
2023-05-30 18:34:41 +00:00
const defaultFieldValues = {
value: "",
error: null,
touched: false,
};
const defaultFields = {
name: { ...defaultFieldValues },
surname: { ...defaultFieldValues },
middleName: { ...defaultFieldValues },
companyName: { ...defaultFieldValues },
email: { ...defaultFieldValues },
phoneNumber: { ...defaultFieldValues },
password: { ...defaultFieldValues },
};
2023-05-17 11:20:11 +00:00
const initialState: UserStore = {
userId: null,
user: null,
2023-05-30 18:34:41 +00:00
settingsFields: { ...defaultFields },
2023-05-17 11:20:11 +00:00
};
export const useUserStore = create<UserStore>()(
persist(
devtools(
(set, get) => initialState,
{
name: "User store",
2023-05-30 18:34:41 +00:00
enabled: process.env.NODE_ENV === "development",
2023-05-17 11:20:11 +00:00
}
),
{
name: "user",
storage: createJSONStorage(() => localStorage),
2023-05-30 18:34:41 +00:00
partialize: state => ({
userId: state.userId,
user: state.user,
})
2023-05-17 11:20:11 +00:00
}
)
);
export const setUserId = (userId: string | null) => useUserStore.setState({ userId });
2023-05-30 18:34:41 +00:00
export const setUser = (user: UserWithFields | null) => useUserStore.setState(
produce<UserStore>(state => {
state.user = user;
if (!user) {
state.settingsFields = null;
return;
}
if (!state.settingsFields) state.settingsFields = { ...defaultFields };
state.settingsFields.name.value = user.name || "";
state.settingsFields.surname.value = user.surname || "";
state.settingsFields.middleName.value = user.middleName || "";
state.settingsFields.companyName.value = user.companyName || "";
state.settingsFields.email.value = user.email;
state.settingsFields.phoneNumber.value = user.phoneNumber;
state.settingsFields.password.value = "";
})
);
export const clearUser = () => useUserStore.setState({ ...initialState });
export const setSettingsField = async (
fieldName: UserSettingsField,
value: string,
) => {
const state = useUserStore.getState();
let errorMessage: string | null = null;
try {
validators[fieldName].validateSync(value);
} catch (error: any) {
errorMessage = error.message;
}
useUserStore.setState(produce<UserStore>(state, state => {
if (!state.settingsFields) return;
state.settingsFields[fieldName].value = value || "";
state.settingsFields[fieldName].touched = true;
state.settingsFields[fieldName].error = errorMessage;
}));
};
export const sendUserData = async () => {
const state = useUserStore.getState();
if (!state.settingsFields) return;
const payload: PatchUserRequest = {};
for (const [fieldName, fieldValue] of Object.entries(state.settingsFields)) {
if (
fieldValue.value !== (state.user?.[fieldName as UserSettingsField] ?? "")
) payload[fieldName as UserSettingsField] = fieldValue.value;
}
const user = await patchUser(payload);
setUser(user);
};
2023-05-17 11:20:11 +00:00
2023-05-30 18:34:41 +00:00
const validators: Record<UserSettingsField, StringSchema> = {
name: string(),
email: string().email("Неверный email"),
surname: string(),
phoneNumber: string().matches(/^[+\d|\d]*$/, "Неверный номер телефона").min(6, "Номер телефона должен содержать минимум 6 символов"),
middleName: string(),
password: string().min(8, "Минимум 8 символов").matches(/^[.,:;-_+\d\w]+$/, "Некорректные символы в пароле"),
companyName: string(),
};