diff --git a/src/components/settings/SessionSecuritySection.tsx b/src/components/settings/SessionSecuritySection.tsx new file mode 100644 index 00000000..bc9cf8b7 --- /dev/null +++ b/src/components/settings/SessionSecuritySection.tsx @@ -0,0 +1,310 @@ +import { useState } from 'react'; +import { + Laptop, + Smartphone, + Monitor, + ShieldCheck, + Trash2, + LogOut, +} from 'lucide-react'; +import { Button } from '@/components/ui/button'; +import { AsyncButton } from '@/components/ui/async-button'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { cn } from '@/lib/utils'; +import type { Session } from '@/services/session.service'; +import { formatTimestampTooltip } from '@/utils/time.utils'; + +export interface SessionSecuritySectionProps { + sessions: Session[]; + isLoading?: boolean; + isError?: boolean; + isRevoking?: boolean; + onRevokeSession: (sessionId: string) => void; + onRevokeAllOtherSessions: () => void; + className?: string; +} + +function DeviceIcon({ device }: { device: string }) { + const label = device.toLowerCase(); + const className = 'size-5 text-white/60'; + if (label.includes('iphone') || label.includes('android') || label.includes('phone')) { + return