import { useState } from 'react' import { Head, useForm } from '@inertiajs/react' import Layout from '../Layout' import SuccessMessage from '../../components/SuccessMessage' import ErrorMessage from '../../components/ErrorMessage' export default function SessionsIndex({ auth, sessions, flash }) { const { delete: destroy, processing } = useForm() const [confirmingSessionId, setConfirmingSessionId] = useState(null) const handleTerminateSession = (id) => { destroy(`/sessions/${id}`, { preserveScroll: true, onSuccess: () => setConfirmingSessionId(null), }) } const formatLastActiveTime = (time) => { const date = new Date(time) return new Intl.DateTimeFormat('default', { dateStyle: 'medium', timeStyle: 'short', }).format(date) } const isCurrentSession = (session) => { return session.is_current } return ( <Layout user={auth}> <Head title="Active Sessions" /> <div className="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8"> <div className="px-4 py-6 sm:px-0"> <div className="bg-white shadow overflow-hidden sm:rounded-lg"> <div className="px-4 py-5 sm:px-6"> <h1 className="text-lg leading-6 font-medium text-gray-900">Active Sessions</h1> <p className="mt-1 max-w-2xl text-sm text-gray-500"> View and manage your currently active sessions across different devices. </p> </div> {flash.success && ( <div className="px-4 sm:px-6"> <SuccessMessage message={flash.success} /> </div> )} {flash.error && ( <div className="px-4 sm:px-6"> <ErrorMessage message={flash.error} /> </div> )} <div className="border-t border-gray-200"> <ul className="divide-y divide-gray-200"> {sessions.map((session) => ( <li key={session.id} className="px-4 py-4 sm:px-6"> <div className="flex items-center justify-between"> <div className="flex items-center"> <div className="flex-shrink-0"> {isCurrentSession(session) ? ( <span className="inline-flex items-center justify-center h-10 w-10 rounded-full bg-green-100"> <svg className="h-6 w-6 text-green-600" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" /> </svg> </span> ) : ( <span className="inline-flex items-center justify-center h-10 w-10 rounded-full bg-gray-100"> <svg className="h-6 w-6 text-gray-600" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" /> </svg> </span> )} </div> <div className="ml-4"> <div className="flex items-center"> <h3 className="text-sm font-medium text-gray-900"> {session.user_agent || 'Unknown Device'} </h3> {isCurrentSession(session) && ( <span className="ml-2 inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800"> Current Session </span> )} </div> <div className="mt-1 text-sm text-gray-500"> <div>IP: {session.ip_address || 'Unknown'}</div> <div>Last active: {formatLastActiveTime(session.updated_at)}</div> </div> </div> </div> <div> {!isCurrentSession(session) ? ( confirmingSessionId === session.id ? ( <div className="flex space-x-2"> <button type="button" className="inline-flex items-center px-2.5 py-1.5 border border-transparent text-xs font-medium rounded text-white bg-red-600 hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500" onClick={() => handleTerminateSession(session.id)} disabled={processing} > {processing ? 'Terminating...' : 'Confirm'} </button> <button type="button" className="inline-flex items-center px-2.5 py-1.5 border border-gray-300 shadow-sm text-xs font-medium rounded text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" onClick={() => setConfirmingSessionId(null)} > Cancel </button> </div> ) : ( <button type="button" className="inline-flex items-center px-2.5 py-1.5 border border-gray-300 shadow-sm text-xs font-medium rounded text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" onClick={() => setConfirmingSessionId(session.id)} > Terminate </button> ) ) : ( <span className="text-xs text-gray-500">Active</span> )} </div> </div> </li> ))} {sessions.length === 0 && ( <li className="px-4 py-6 sm:px-6 text-center text-gray-500"> No active sessions found. </li> )} </ul> </div> <div className="px-4 py-4 sm:px-6 bg-gray-50 border-t border-gray-200"> <div className="text-sm"> <p className="font-medium text-gray-700">About sessions</p> <p className="mt-1 text-gray-500"> Sessions are created when you log in to your account. You can terminate any session except your current one. If you notice any suspicious activity, terminate the session and change your password immediately. </p> </div> </div> </div> </div> </div> </Layout> ) }