import React, { useState, useEffect } from 'react'; import { Box, Typography, Button, useTheme, useMediaQuery, CircularProgress, } from '@mui/material'; import { useTranslation } from 'react-i18next'; import { DeviceMessage, Logout } from 'iconsax-react'; import { CardContainer } from '@/components/CardContainer'; import { PageWrapper } from '../components/PageWrapper'; import { Icon } from '@rkheftan/harmony-ui'; import { deleteSessions } from '../api/settingsApi'; import { type ApiSession } from '../types/settingsApiType'; import { useApi } from '@/hooks/useApi'; import { formatDate } from '@/utils/formatSessionDate'; import { type Device } from '../types/settingsType'; import { useToast } from '@rkheftan/harmony-ui'; import { useProfile } from '../hooks/useProfile'; export function ActiveDevicesPage() { const { t, i18n } = useTranslation('setting'); const [devices, setDevices] = useState([]); const [loadingDeleteIds, setLoadingDeleteIds] = useState([]); const theme = useTheme(); const isXsup = useMediaQuery(theme.breakpoints.up('xs')); const showToast = useToast(); const { isLoadingProfile, refetchProfile } = useProfile(); const { loading: isTerminating, execute: executeTerminate } = useApi(deleteSessions); useEffect(() => { const loadProfile = async () => { const profileData = await refetchProfile(); if (!profileData) return; if (profileData.success) { if (!profileData.activeSessions) return; const { sessions, currentKey } = profileData.activeSessions; const formattedDevices = sessions.map((session: ApiSession) => ({ id: session.key, timeAndDate: formatDate(session.created, i18n.language, t), deviceModel: `${session.deviceOs} ${session.deviceName}`, ip: session.ipAddress, current: session.key === currentKey, })); const sortedDevices = formattedDevices.sort((a, b) => { if (a.current && !b.current) return -1; if (!a.current && b.current) return 1; return 0; }); setDevices(sortedDevices); } else { showToast({ message: profileData.message || t('message.serverError'), severity: 'error', }); } }; loadProfile(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const handleDeleteDevice = async (id: string) => { if (loadingDeleteIds.includes(id)) return; setLoadingDeleteIds((prev) => [...prev, id]); try { const data = await executeTerminate({ keys: [id] }); if (!data) return; if (data.success) { setDevices((prevDevices) => prevDevices.filter((d) => d.id !== id)); showToast({ message: t('active.successDelete'), severity: 'success' }); } else { showToast({ message: data.message || t('active.deleteFailed'), severity: 'error', }); } } finally { setLoadingDeleteIds((prev) => prev.filter((loadingId) => loadingId !== id), ); } }; const handleTerminateAllOtherSessions = async () => { const otherSessionKeys = devices.filter((d) => !d.current).map((d) => d.id); if (otherSessionKeys.length > 0) { const terminateData = await executeTerminate({ keys: otherSessionKeys }); if (!terminateData) return; if (terminateData?.success) { setDevices((prev) => prev.filter((d) => d.current)); } else { showToast({ message: terminateData.message || t('active.deleteFailed'), severity: 'error', }); } } }; return ( {isTerminating ? t('active.deleting') : t('active.deleteDevicesButton')} } > {isLoadingProfile ? ( ) : ( {devices.map((device) => ( {device.timeAndDate} {device.deviceModel} {device.ip} {device.current && ( )} {isXsup && ( )} ))} )} ); }