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 { fetchProfile, 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'; 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 { data: profileData, loading: isLoading, error: fetchError, } = useApi(fetchProfile, { immediate: true }); const { data: terminateData, loading: isTerminating, execute: executeTerminateAll, } = useApi(deleteSessions); useEffect(() => { if (profileData?.success && profileData.activeSessions) { 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); } }, [profileData, i18n.language, t]); useEffect(() => { if (terminateData?.success) { setDevices((prev) => prev.filter((d) => d.current)); } }, [terminateData]); const handleDeleteDevice = async (id: string) => { if (loadingDeleteIds.includes(id)) return; setLoadingDeleteIds((prev) => [...prev, id]); try { const { data } = await deleteSessions({ keys: [id] }); 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', }); } } catch (error: unknown) { showToast({ message: t('active.deleteFailed'), severity: 'error', }); } finally { setLoadingDeleteIds((prev) => prev.filter((loadingId) => loadingId !== id), ); } }; const handleTerminateAllOtherSessions = () => { const otherSessionKeys = devices.filter((d) => !d.current).map((d) => d.id); if (otherSessionKeys.length > 0) { executeTerminateAll({ keys: otherSessionKeys }); } }; const getErrorMessage = (error: unknown): string | null => { if (!error) return null; if (error instanceof Error) return error.message; return String(error); }; return ( {isTerminating ? t('active.deleting') : t('active.deleteDevicesButton')} } > {isLoading ? ( ) : fetchError ? ( {getErrorMessage(fetchError)} ) : ( {devices.map((device) => ( {device.timeAndDate} {device.deviceModel} {device.ip} {device.current && ( )} {isXsup && ( )} ))} )} ); }