using zustand for localStorage data, fixed socketio on login

This commit is contained in:
Domingo Dirutigliano
2025-07-28 16:01:41 +02:00
parent 699060ae0a
commit 97b3d97753
3 changed files with 89 additions and 11 deletions

View File

@@ -13,6 +13,7 @@ import { Firewall } from './pages/Firewall';
import { useQueryClient } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query';
import NFProxy from './pages/NFProxy'; import NFProxy from './pages/NFProxy';
import ServiceDetailsNFProxy from './pages/NFProxy/ServiceDetails'; import ServiceDetailsNFProxy from './pages/NFProxy/ServiceDetails';
import { useAuth } from './js/store';
function App() { function App() {
@@ -22,16 +23,19 @@ function App() {
const [error, setError] = useState<string|null>() const [error, setError] = useState<string|null>()
const [loadinBtn, setLoadingBtn] = useState(false); const [loadinBtn, setLoadingBtn] = useState(false);
const queryClient = useQueryClient() const queryClient = useQueryClient()
const { isAuthenticated, access_token } = useAuth()
useEffect(()=>{ useEffect(()=>{
socketio.auth = { token: localStorage.getItem("access_token") } socketio.auth = { token: access_token || "" }
socketio.connect() socketio.connect()
getStatus() getStatus()
socketio.on("update", (data) => { socketio.on("update", (data) => {
queryClient.invalidateQueries({ queryKey: data }) queryClient.invalidateQueries({ queryKey: data })
}) })
socketio.on("connect_error", (err) => { socketio.on("connect_error", (err) => {
errorNotify("Socket.Io connection failed! ",`Error message: [${err.message}]`) if (access_token){
errorNotify("Socket.Io connection failed! ",`Error message: [${err.message}]`)
}
getStatus() getStatus()
}); });
return () => { return () => {
@@ -39,7 +43,7 @@ function App() {
socketio.off("connect_error") socketio.off("connect_error")
socketio.disconnect() socketio.disconnect()
} }
},[]) },[isAuthenticated])
const getStatus = () =>{ const getStatus = () =>{
getstatus().then( res =>{ getstatus().then( res =>{

View File

@@ -1,4 +1,5 @@
import { create } from 'zustand' import { create } from 'zustand'
import { persist, createJSONStorage } from 'zustand/middleware';
type NavbarStore = { type NavbarStore = {
navOpened: boolean, navOpened: boolean,
@@ -15,3 +16,75 @@ export const useNavbarStore = create<NavbarStore>()((set) => ({
openNav: () => set({ navOpened: true }), openNav: () => set({ navOpened: true }),
toggleNav: () => set((state) => ({ navOpened: !state.navOpened })), toggleNav: () => set((state) => ({ navOpened: !state.navOpened })),
})) }))
interface AuthState {
access_token: string | null;
setAccessToken: (token: string | null) => void;
clearAccessToken: () => void;
getAccessToken: () => string | null;
}
export const useAuthStore = create<AuthState>()(
persist(
(set, get) => ({
access_token: null,
setAccessToken: (token) => set({ access_token: token }),
clearAccessToken: () => set({ access_token: null }),
getAccessToken: () => get().access_token,
}),
{
name: 'auth-storage',
storage: createJSONStorage(() => localStorage),
partialize: (state) => ({ access_token: state.access_token }),
}
)
);
// Hook personalizzati per un uso più facile nei componenti
export const useAuth = () => {
const { access_token, setAccessToken, clearAccessToken, getAccessToken } = useAuthStore();
const isAuthenticated = !!access_token;
return {
access_token,
isAuthenticated,
setAccessToken,
clearAccessToken,
getAccessToken,
};
};
interface SessionState {
home_section: string | null;
setHomeSection: (section: string | null) => void;
getHomeSection: () => string | null;
}
export const useSessionStore = create<SessionState>()(
persist(
(set, get) => ({
home_section: null,
setHomeSection: (section) => set({ home_section: section }),
getHomeSection: () => get().home_section,
}),
{
name: 'session-storage',
storage: createJSONStorage(() => sessionStorage),
partialize: (state) => ({ home_section: state.home_section }),
}
)
);
export const useSession = () => {
const { home_section, setHomeSection, getHomeSection } = useSessionStore();
return {
home_section,
setHomeSection,
getHomeSection,
};
};

View File

@@ -7,6 +7,7 @@ import { Buffer } from "buffer"
import { QueryClient, useQuery } from "@tanstack/react-query"; import { QueryClient, useQuery } from "@tanstack/react-query";
import { useMediaQuery } from "@mantine/hooks"; import { useMediaQuery } from "@mantine/hooks";
import { io } from "socket.io-client"; import { io } from "socket.io-client";
import { useAuthStore, useSessionStore } from "./store";
export const IS_DEV = import.meta.env.DEV export const IS_DEV = import.meta.env.DEV
@@ -32,14 +33,14 @@ export const socketio = import.meta.env.DEV?
path:"/sock/socket.io", path:"/sock/socket.io",
transports: ['websocket'], transports: ['websocket'],
auth: { auth: {
token: localStorage.getItem("access_token") token: useAuthStore.getState().getAccessToken()
} }
}): }):
io({ io({
path:"/sock/socket.io", path:"/sock/socket.io",
transports: ['websocket'], transports: ['websocket'],
auth: { auth: {
token: localStorage.getItem("access_token") token: useAuthStore.getState().getAccessToken()
} }
}) })
@@ -86,7 +87,7 @@ export async function genericapi(method:string,path:string,data:any = undefined,
cache: 'no-cache', cache: 'no-cache',
headers: { headers: {
...(data?{'Content-Type': is_form ? 'application/x-www-form-urlencoded' : 'application/json'}:{}), ...(data?{'Content-Type': is_form ? 'application/x-www-form-urlencoded' : 'application/json'}:{}),
"Authorization" : "Bearer " + window.localStorage.getItem("access_token") "Authorization" : "Bearer " + useAuthStore.getState().getAccessToken()
}, },
body: data? (is_form ? (new URLSearchParams(data)).toString() : JSON.stringify(data)) : undefined body: data? (is_form ? (new URLSearchParams(data)).toString() : JSON.stringify(data)) : undefined
}).then(res => { }).then(res => {
@@ -132,7 +133,7 @@ export function getMainPath(){
} }
export function HomeRedirector(){ export function HomeRedirector(){
const section = sessionStorage.getItem("home_section") const section = useSessionStore.getState().getHomeSection();
const path = section?`/${section}`:`/nfregex` const path = section?`/${section}`:`/nfregex`
return <Navigate to={path} replace/> return <Navigate to={path} replace/>
} }
@@ -153,27 +154,27 @@ export async function getstatus(){
} }
export async function logout(){ export async function logout(){
window.localStorage.removeItem("access_token") useAuthStore.getState().clearAccessToken();
} }
export async function setpassword(data:PasswordSend) { export async function setpassword(data:PasswordSend) {
const { status, access_token } = await postapi("set-password",data) as ServerResponseToken; const { status, access_token } = await postapi("set-password",data) as ServerResponseToken;
if (access_token) if (access_token)
window.localStorage.setItem("access_token", access_token); useAuthStore.getState().setAccessToken(access_token);
return status === "ok"?undefined:status return status === "ok"?undefined:status
} }
export async function changepassword(data:ChangePassword) { export async function changepassword(data:ChangePassword) {
const { status, access_token } = await postapi("change-password",data) as ServerResponseToken; const { status, access_token } = await postapi("change-password",data) as ServerResponseToken;
if (access_token) if (access_token)
window.localStorage.setItem("access_token", access_token); useAuthStore.getState().setAccessToken(access_token);
return status === "ok"?undefined:status return status === "ok"?undefined:status
} }
export async function login(data:PasswordSend) { export async function login(data:PasswordSend) {
const from = {username: "login", password: data.password}; const from = {username: "login", password: data.password};
const { status, access_token } = await postapi("login",from,true) as LoginResponse; const { status, access_token } = await postapi("login",from,true) as LoginResponse;
window.localStorage.setItem("access_token", access_token); useAuthStore.getState().setAccessToken(access_token);
return status; return status;
} }