116 lines
3.4 KiB
TypeScript
116 lines
3.4 KiB
TypeScript
import React, { useState, useEffect } from 'react';
|
|
import {
|
|
Box,
|
|
Typography,
|
|
CircularProgress,
|
|
useTheme,
|
|
useMediaQuery,
|
|
} from '@mui/material';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { CardContainer } from '@/components/CardContainer';
|
|
import { PageWrapper } from '../PageWrapper';
|
|
import type { LoginLog } from '../../types/settingsApiType';
|
|
import { formatDate } from '@/utils/formatSessionDate';
|
|
import { useToast } from '@harmony/kit';
|
|
import { useProfile } from '../../hooks/useProfile';
|
|
|
|
export function RecentLogins() {
|
|
const { t, i18n } = useTranslation('setting');
|
|
const [logs, setLogs] = useState<LoginLog[]>([]);
|
|
const theme = useTheme();
|
|
const isXsup = useMediaQuery(theme.breakpoints.up('xs'));
|
|
const showToast = useToast();
|
|
|
|
const { isLoadingProfile, refetchProfile } = useProfile();
|
|
|
|
// useEffect(() => {
|
|
// if (profileData?.success && Array.isArray(profileData.loginLogs)) {
|
|
// setLogs(profileData.loginLogs);
|
|
// }
|
|
// }, [profileData]);
|
|
|
|
// useEffect(() => {
|
|
// if (fetchError) {
|
|
// showToast({
|
|
// message: getErrorMessage(fetchError) || t('active.errorFetch'),
|
|
// severity: 'error',
|
|
// });
|
|
// }
|
|
// }, [fetchError, t, showToast]);
|
|
|
|
useEffect(() => {
|
|
const loadProfile = async () => {
|
|
const profileData = await refetchProfile();
|
|
|
|
if (!profileData) return;
|
|
|
|
if (profileData.success) {
|
|
if (!Array.isArray(profileData.loginLogs)) return;
|
|
setLogs(profileData.loginLogs);
|
|
} else {
|
|
showToast({
|
|
message: profileData.message || t('active.errorFetch'),
|
|
severity: 'error',
|
|
});
|
|
}
|
|
};
|
|
|
|
loadProfile();
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, []);
|
|
|
|
return (
|
|
<PageWrapper>
|
|
<CardContainer
|
|
title={t('securityForm.recentLogins')}
|
|
subtitle={t('securityForm.description')}
|
|
>
|
|
{isLoadingProfile ? (
|
|
<Box
|
|
sx={{
|
|
display: 'flex',
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
p: 4,
|
|
minHeight: '200px',
|
|
}}
|
|
>
|
|
<CircularProgress />
|
|
</Box>
|
|
) : (
|
|
<Box sx={{ px: 4 }}>
|
|
{logs.map((log, index) => (
|
|
<React.Fragment key={index}>
|
|
<Box
|
|
sx={{
|
|
display: 'flex',
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
minHeight: 50,
|
|
py: 1.5,
|
|
flexWrap: 'wrap',
|
|
gap: 2,
|
|
}}
|
|
>
|
|
<Typography sx={{ flex: 1, minWidth: 160 }}>
|
|
{formatDate(log.loginDateTime, i18n.language, t)}
|
|
</Typography>
|
|
<Typography sx={{ flex: 1, minWidth: 160 }}>
|
|
{`${log.deviceOs} ${log.deviceName}`}
|
|
</Typography>
|
|
<Typography sx={{ flex: 1, minWidth: 120 }}>
|
|
{log.ipAddress}
|
|
</Typography>
|
|
</Box>
|
|
{isXsup && index < logs.length - 1 && (
|
|
<Box sx={{ borderBottom: 1, borderColor: 'divider' }} />
|
|
)}
|
|
</React.Fragment>
|
|
))}
|
|
</Box>
|
|
)}
|
|
</CardContainer>
|
|
</PageWrapper>
|
|
);
|
|
}
|