2d664795ad
This commit introduces a new "Calls" section to the main sidebar navigation to provide users with access to call logs. - Adds a new collapsible "Calls" menu item to the sidebar configuration. - Includes sub-links for "All Calls", "Incoming", "Outgoing", and "Missed" calls. - Creates new custom icons (GlobeSearch, CallIncome, CallMade, CallMissed, CallReceived) to support the new menu items. - Updates `apexcharts` and `react-apexcharts` dependencies to newer versions.
106 lines
2.9 KiB
TypeScript
106 lines
2.9 KiB
TypeScript
"use client";
|
|
|
|
import Cookies from "js-cookie";
|
|
import React, {
|
|
createContext,
|
|
Dispatch,
|
|
ReactNode,
|
|
SetStateAction,
|
|
useCallback,
|
|
useContext,
|
|
useEffect,
|
|
useMemo,
|
|
useState,
|
|
} from "react";
|
|
|
|
import { useRouter } from "next/navigation";
|
|
import { ILoginResponse, IUser, UserSchema } from "../lib/api/types";
|
|
import { COOKIE_KEYS } from "../lib/shared/cookies";
|
|
|
|
interface UserContextType {
|
|
user: IUser | null;
|
|
accessToken: string | null;
|
|
isAuthenticated: boolean;
|
|
isLoading: boolean;
|
|
setAuthState: (data: ILoginResponse) => void;
|
|
logout: () => void;
|
|
setUser: Dispatch<SetStateAction<IUser | null>>;
|
|
}
|
|
|
|
const UserContext = createContext<UserContextType | undefined>(undefined);
|
|
|
|
interface UserProviderProps {
|
|
children: ReactNode;
|
|
}
|
|
|
|
export const UserProvider: React.FC<UserProviderProps> = ({ children }) => {
|
|
const [user, setUser] = useState<IUser | null>(null);
|
|
const [accessToken, setAccessToken] = useState<string | null>(null);
|
|
const [isLoading, setIsLoading] = useState<boolean>(true);
|
|
const router = useRouter();
|
|
|
|
const logout = useCallback(() => {
|
|
setUser(null);
|
|
setAccessToken(null);
|
|
Cookies.remove(COOKIE_KEYS.access_token);
|
|
Cookies.remove(COOKIE_KEYS.refresh_token);
|
|
Cookies.remove(COOKIE_KEYS.user);
|
|
window.location.href = "/auth/sign-in";
|
|
}, [router]);
|
|
useEffect(() => {
|
|
try {
|
|
const tokenFromCookie = Cookies.get(COOKIE_KEYS.access_token);
|
|
const userJson = Cookies.get(COOKIE_KEYS.user);
|
|
|
|
if (tokenFromCookie && userJson) {
|
|
const userFromCookie = JSON.parse(userJson);
|
|
const validation = UserSchema.safeParse(userFromCookie);
|
|
if (validation.success) {
|
|
setUser(validation.data);
|
|
setAccessToken(tokenFromCookie);
|
|
} else {
|
|
console.warn("Invalid user data in cookie:", validation.error);
|
|
logout();
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.error("Failed to parse user data from cookies", e);
|
|
logout();
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
}, [logout]);
|
|
|
|
const setAuthState = useCallback((data: ILoginResponse) => {
|
|
setAccessToken(data.access_token);
|
|
setUser(data.user);
|
|
|
|
Cookies.set(COOKIE_KEYS.access_token, data.access_token);
|
|
Cookies.set(COOKIE_KEYS.refresh_token, data.refresh_token);
|
|
Cookies.set(COOKIE_KEYS.user, JSON.stringify(data.user));
|
|
}, []);
|
|
|
|
const value = useMemo(
|
|
() => ({
|
|
user,
|
|
accessToken,
|
|
isAuthenticated: !!accessToken,
|
|
isLoading,
|
|
setAuthState,
|
|
logout,
|
|
setUser,
|
|
}),
|
|
[user, accessToken, isLoading, setAuthState, logout, setUser],
|
|
);
|
|
|
|
return <UserContext.Provider value={value}>{children}</UserContext.Provider>;
|
|
};
|
|
|
|
export const useUser = (): UserContextType => {
|
|
const context = useContext(UserContext);
|
|
if (context === undefined) {
|
|
throw new Error("useUser must be used within a UserProvider");
|
|
}
|
|
return context;
|
|
};
|