fix: connect header and layout user info to api, fix setting api and lazy load
This commit is contained in:
@@ -1,13 +1,14 @@
|
|||||||
import { Box, IconButton, Typography } from '@mui/material';
|
import { Box, IconButton, Skeleton, Typography } from '@mui/material';
|
||||||
import { Icon } from '@rkheftan/harmony-ui';
|
import { Icon } from '@rkheftan/harmony-ui';
|
||||||
import { More } from 'iconsax-react';
|
import { More } from 'iconsax-react';
|
||||||
import type { User } from './type';
|
import type { User } from './type';
|
||||||
|
|
||||||
interface HeaderProps {
|
interface HeaderProps {
|
||||||
user: User;
|
user: User;
|
||||||
|
loading: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Header: React.FC<HeaderProps> = ({ user }) => {
|
export const Header: React.FC<HeaderProps> = ({ user, loading }) => {
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
@@ -20,10 +21,14 @@ export const Header: React.FC<HeaderProps> = ({ user }) => {
|
|||||||
>
|
>
|
||||||
<Box>
|
<Box>
|
||||||
<Typography variant="body1">
|
<Typography variant="body1">
|
||||||
{user.firstName + ' ' + user.lastName}
|
{loading ? (
|
||||||
|
<Skeleton variant="text" />
|
||||||
|
) : (
|
||||||
|
user.firstName + ' ' + user.lastName
|
||||||
|
)}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2" color="textSecondary">
|
<Typography variant="body2" color="textSecondary">
|
||||||
{user.phoneNumber}
|
{loading ? <Skeleton variant="text" /> : user.phoneNumber}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { Box, useMediaQuery, useTheme } from '@mui/material';
|
|||||||
import { Header } from './Header';
|
import { Header } from './Header';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Toolbar } from './Toolbar';
|
import { Toolbar } from './Toolbar';
|
||||||
|
import { useApi } from '@/hooks/useApi';
|
||||||
|
import { fetchProfile } from '@/features/profile/api/settingsApi';
|
||||||
import type { User } from './type';
|
import type { User } from './type';
|
||||||
|
|
||||||
export const Layout = () => {
|
export const Layout = () => {
|
||||||
@@ -14,11 +16,7 @@ export const Layout = () => {
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
||||||
const [sideNavOpen, setSideNavOpen] = useState(false);
|
const [sideNavOpen, setSideNavOpen] = useState(false);
|
||||||
const [user] = useState<User>({
|
const { data, loading } = useApi(fetchProfile, { immediate: true });
|
||||||
firstName: 'محمد حسین',
|
|
||||||
lastName: 'برزه گر',
|
|
||||||
phoneNumber: '09123456789',
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
@@ -46,16 +44,48 @@ export const Layout = () => {
|
|||||||
isMobile={isMobile}
|
isMobile={isMobile}
|
||||||
sideNavOpen={sideNavOpen}
|
sideNavOpen={sideNavOpen}
|
||||||
setSideNavOpen={setSideNavOpen}
|
setSideNavOpen={setSideNavOpen}
|
||||||
user={user}
|
loading={loading}
|
||||||
|
user={{
|
||||||
|
firstName: data?.firstName || '',
|
||||||
|
lastName: data?.lastName || '',
|
||||||
|
phoneNumber: data?.phoneNumber || '',
|
||||||
|
profileUrl: data?.profileImageUrl,
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<Outlet />
|
<Box sx={{ flex: 1, overflowY: 'auto' }}>
|
||||||
|
<Outlet />
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<SideNav
|
<SideNav
|
||||||
open={sideNavOpen}
|
open={sideNavOpen}
|
||||||
onClose={() => setSideNavOpen(false)}
|
onClose={() => setSideNavOpen(false)}
|
||||||
header={isMobile ? undefined : <Header user={user} />}
|
header={
|
||||||
footer={isMobile ? <Header user={user} /> : undefined}
|
isMobile ? undefined : (
|
||||||
|
<Header
|
||||||
|
loading={loading}
|
||||||
|
user={{
|
||||||
|
firstName: data?.firstName || '',
|
||||||
|
lastName: data?.lastName || '',
|
||||||
|
phoneNumber: data?.phoneNumber || '',
|
||||||
|
profileUrl: data?.profileImageUrl,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
footer={
|
||||||
|
isMobile ? (
|
||||||
|
<Header
|
||||||
|
loading={loading}
|
||||||
|
user={{
|
||||||
|
firstName: data?.firstName || '',
|
||||||
|
lastName: data?.lastName || '',
|
||||||
|
phoneNumber: data?.phoneNumber || '',
|
||||||
|
profileUrl: data?.profileImageUrl,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : undefined
|
||||||
|
}
|
||||||
navConfig={navItemConfigs}
|
navConfig={navItemConfigs}
|
||||||
activePath={location.pathname + location.hash}
|
activePath={location.pathname + location.hash}
|
||||||
selectedVariant="textOnly"
|
selectedVariant="textOnly"
|
||||||
|
|||||||
@@ -3,18 +3,20 @@ import {
|
|||||||
Box,
|
Box,
|
||||||
IconButton,
|
IconButton,
|
||||||
Toolbar as MuiToolbar,
|
Toolbar as MuiToolbar,
|
||||||
Typography,
|
Skeleton,
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import { Icon } from '@rkheftan/harmony-ui';
|
import { Icon } from '@rkheftan/harmony-ui';
|
||||||
import { HambergerMenu, Menu } from 'iconsax-react';
|
import { HambergerMenu, Menu } from 'iconsax-react';
|
||||||
import type { Dispatch, SetStateAction } from 'react';
|
import type { Dispatch, SetStateAction } from 'react';
|
||||||
import type { User } from './type';
|
import type { User } from './type';
|
||||||
|
import Logo from '../Logo';
|
||||||
|
|
||||||
interface ToolbarProps {
|
interface ToolbarProps {
|
||||||
sideNavOpen: boolean;
|
sideNavOpen: boolean;
|
||||||
setSideNavOpen: Dispatch<SetStateAction<boolean>>;
|
setSideNavOpen: Dispatch<SetStateAction<boolean>>;
|
||||||
isMobile: boolean;
|
isMobile: boolean;
|
||||||
user: User;
|
user: User;
|
||||||
|
loading: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Toolbar: React.FC<ToolbarProps> = ({
|
export const Toolbar: React.FC<ToolbarProps> = ({
|
||||||
@@ -22,6 +24,7 @@ export const Toolbar: React.FC<ToolbarProps> = ({
|
|||||||
setSideNavOpen,
|
setSideNavOpen,
|
||||||
isMobile,
|
isMobile,
|
||||||
user,
|
user,
|
||||||
|
loading,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<MuiToolbar
|
<MuiToolbar
|
||||||
@@ -52,20 +55,22 @@ export const Toolbar: React.FC<ToolbarProps> = ({
|
|||||||
<Icon Component={HambergerMenu} />
|
<Icon Component={HambergerMenu} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
)}
|
)}
|
||||||
{/* <Logo /> */}
|
<Logo />
|
||||||
<Typography variant="h6">LOGO placeholder</Typography>
|
|
||||||
</Box>
|
</Box>
|
||||||
<Box
|
<Box
|
||||||
sx={{ display: 'flex', height: '100%', alignItems: 'center', gap: 1 }}
|
sx={{ display: 'flex', height: '100%', alignItems: 'center', gap: 1 }}
|
||||||
>
|
>
|
||||||
{isMobile && (
|
{isMobile &&
|
||||||
<Avatar
|
(loading ? (
|
||||||
sx={{ width: 32, height: 32, fontSize: '14px' }}
|
<Skeleton variant="circular" />
|
||||||
src={user.profileUrl}
|
) : (
|
||||||
>
|
<Avatar
|
||||||
{user.firstName.charAt(0) + ' ' + user.lastName.charAt(0)}
|
sx={{ width: 32, height: 32, fontSize: '14px' }}
|
||||||
</Avatar>
|
src={user.profileUrl}
|
||||||
)}
|
>
|
||||||
|
{user.firstName.charAt(0) + ' ' + user.lastName.charAt(0)}
|
||||||
|
</Avatar>
|
||||||
|
))}
|
||||||
<IconButton>
|
<IconButton>
|
||||||
<Icon Component={Menu} variant="Bold" />
|
<Icon Component={Menu} variant="Bold" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import {
|
|||||||
import { type InfoRowData } from '../types/settingsType';
|
import { type InfoRowData } from '../types/settingsType';
|
||||||
|
|
||||||
export async function fetchProfile() {
|
export async function fetchProfile() {
|
||||||
return apiClient.post<GetProfileApiResponse>('/Profile/GetProfile');
|
return apiClient.post<GetProfileApiResponse>('/Profile/GetProfile', {});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function saveProfile(payload: {
|
export async function saveProfile(payload: {
|
||||||
|
|||||||
@@ -1,15 +1,4 @@
|
|||||||
import { Layout } from '@/components';
|
import { Layout } from '@/components';
|
||||||
import {
|
|
||||||
AuthenticationPage,
|
|
||||||
ForgetPasswordPage,
|
|
||||||
UserCompletionPage,
|
|
||||||
} from '@/features/authorization';
|
|
||||||
import {
|
|
||||||
ActiveDevicesPage,
|
|
||||||
SecurityPage,
|
|
||||||
SettingPage,
|
|
||||||
UserInformationPage,
|
|
||||||
} from '@/features/profile';
|
|
||||||
import {
|
import {
|
||||||
Calendar,
|
Calendar,
|
||||||
Devices,
|
Devices,
|
||||||
@@ -23,9 +12,45 @@ import {
|
|||||||
Sms,
|
Sms,
|
||||||
type Icon,
|
type Icon,
|
||||||
} from 'iconsax-react';
|
} from 'iconsax-react';
|
||||||
import { type ReactNode } from 'react';
|
import { lazy, type ReactNode } from 'react';
|
||||||
import { Navigate } from 'react-router-dom';
|
import { Navigate } from 'react-router-dom';
|
||||||
|
|
||||||
|
const AuthenticationPage = lazy(() =>
|
||||||
|
import('@/features/authorization').then((module) => ({
|
||||||
|
default: module.AuthenticationPage,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
const UserCompletionPage = lazy(() =>
|
||||||
|
import('@/features/authorization').then((module) => ({
|
||||||
|
default: module.UserCompletionPage,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
const ForgetPasswordPage = lazy(() =>
|
||||||
|
import('@/features/authorization').then((module) => ({
|
||||||
|
default: module.ForgetPasswordPage,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
const UserInformationPage = lazy(() =>
|
||||||
|
import('@/features/profile').then((module) => ({
|
||||||
|
default: module.UserInformationPage,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
const SecurityPage = lazy(() =>
|
||||||
|
import('@/features/profile').then((module) => ({
|
||||||
|
default: module.SecurityPage,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
const ActiveDevicesPage = lazy(() =>
|
||||||
|
import('@/features/profile').then((module) => ({
|
||||||
|
default: module.ActiveDevicesPage,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
const SettingPage = lazy(() =>
|
||||||
|
import('@/features/profile').then((module) => ({
|
||||||
|
default: module.SettingPage,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
export interface RouteConfig {
|
export interface RouteConfig {
|
||||||
path: string;
|
path: string;
|
||||||
element?: ReactNode;
|
element?: ReactNode;
|
||||||
|
|||||||
Reference in New Issue
Block a user