162 lines
6.4 KiB
TypeScript
162 lines
6.4 KiB
TypeScript
'use client';
|
|
|
|
import React from 'react';
|
|
import { OperatorSession } from './types';
|
|
|
|
interface OperationsSessionProps {
|
|
session: OperatorSession;
|
|
onSignOut: () => void;
|
|
signingOut?: boolean;
|
|
}
|
|
|
|
export function OperationsSessionView({
|
|
session,
|
|
onSignOut,
|
|
signingOut = false,
|
|
}: OperationsSessionProps) {
|
|
function formatDate(isoString?: string) {
|
|
if (!isoString) return '--';
|
|
return new Date(isoString).toLocaleString('en-US', {
|
|
year: 'numeric',
|
|
month: 'short',
|
|
day: 'numeric',
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
second: '2-digit',
|
|
timeZoneName: 'short',
|
|
});
|
|
}
|
|
|
|
const isOwner = session.role === 'owner';
|
|
|
|
return (
|
|
<div className="space-y-6 w-full max-w-5xl">
|
|
{/* Header Row */}
|
|
<div className="pb-4 border-b border-outline-variant/30">
|
|
<span className="text-[11px] font-mono text-primary-fixed-dim block font-semibold">
|
|
Session Credentials
|
|
</span>
|
|
<h1 className="font-headline-xl text-2xl sm:text-3xl lg:text-4xl font-extrabold text-on-surface tracking-tight mt-1">
|
|
My Session
|
|
</h1>
|
|
<p className="text-xs sm:text-sm text-outline mt-1.5 max-w-2xl">
|
|
Cryptographic authority and active authentication status for this browser session.
|
|
</p>
|
|
</div>
|
|
|
|
{/* Session Details Card */}
|
|
<div className="p-6 sm:p-8 rounded-2xl bg-surface-container-low border border-outline-variant/30 space-y-6 shadow-sm">
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
|
{/* Verified Identity */}
|
|
<div className="p-3.5 rounded-lg bg-surface-container-lowest border border-outline-variant/20 space-y-1">
|
|
<span className="text-[10px] font-mono text-outline">
|
|
Verified Identity
|
|
</span>
|
|
<div className="text-sm font-semibold text-on-surface break-all">
|
|
{session.identity}
|
|
</div>
|
|
<span className="text-[10px] text-on-surface-variant font-mono">
|
|
ops.operators identity
|
|
</span>
|
|
</div>
|
|
|
|
{/* Operations Role */}
|
|
<div className="p-3.5 rounded-lg bg-surface-container-lowest border border-outline-variant/20 space-y-1">
|
|
<span className="text-[10px] font-mono text-outline">
|
|
Operations Role
|
|
</span>
|
|
<div>
|
|
<span
|
|
className={`inline-flex items-center px-2 py-0.5 rounded text-xs font-mono font-semibold capitalize ${
|
|
isOwner
|
|
? 'bg-primary-container/15 text-primary-container border border-primary-container/40'
|
|
: 'bg-surface-container-high text-on-surface font-semibold border border-outline-variant/40'
|
|
}`}
|
|
>
|
|
{session.role}
|
|
</span>
|
|
</div>
|
|
<span className="text-[10px] text-on-surface-variant font-mono">
|
|
{isOwner ? 'Full platform authority' : 'Standard operator telemetry read'}
|
|
</span>
|
|
</div>
|
|
|
|
{/* Session Status */}
|
|
<div className="p-3.5 rounded-lg bg-surface-container-lowest border border-outline-variant/20 space-y-1">
|
|
<span className="text-[10px] font-mono text-outline">
|
|
Session Status
|
|
</span>
|
|
<div className="flex items-center gap-1.5 text-xs font-mono font-semibold text-secondary-fixed">
|
|
<span className="h-2 w-2 rounded-full bg-secondary-fixed"></span>
|
|
<span className="capitalize">{session.status}</span>
|
|
</div>
|
|
<span className="text-[10px] text-on-surface-variant font-mono">
|
|
Validated on-demand
|
|
</span>
|
|
</div>
|
|
|
|
{/* Environment */}
|
|
<div className="p-3.5 rounded-lg bg-surface-container-lowest border border-outline-variant/20 space-y-1">
|
|
<span className="text-[10px] font-mono text-outline">
|
|
Runtime Environment
|
|
</span>
|
|
<div className="text-xs font-mono font-semibold text-on-surface capitalize">
|
|
{session.environment ?? 'production'}
|
|
</div>
|
|
<span className="text-[10px] text-on-surface-variant font-mono">
|
|
Target API host boundary
|
|
</span>
|
|
</div>
|
|
|
|
{/* Created Timestamp */}
|
|
<div className="p-3.5 rounded-lg bg-surface-container-lowest border border-outline-variant/20 space-y-1">
|
|
<span className="text-[10px] font-mono text-outline">
|
|
Session Created
|
|
</span>
|
|
<div className="text-xs font-mono text-on-surface">
|
|
{formatDate(session.createdAt)}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Last Activity */}
|
|
<div className="p-3.5 rounded-lg bg-surface-container-lowest border border-outline-variant/20 space-y-1">
|
|
<span className="text-[10px] font-mono text-outline">
|
|
Last Activity
|
|
</span>
|
|
<div className="text-xs font-mono text-on-surface">
|
|
{formatDate(session.lastActivityAt)}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Absolute Expiry */}
|
|
<div className="p-3.5 rounded-lg bg-surface-container-lowest border border-outline-variant/20 space-y-1 sm:col-span-2">
|
|
<span className="text-[10px] font-mono text-outline">
|
|
Absolute Expiry
|
|
</span>
|
|
<div className="text-xs font-mono text-on-surface">
|
|
{formatDate(session.expiresAt)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Action Row */}
|
|
<div className="pt-4 border-t border-outline-variant/20 flex items-center justify-between">
|
|
<span className="text-[11px] text-outline font-mono">
|
|
Cookie: __Host-motorsignal_ops (HttpOnly, Secure, SameSite=Strict)
|
|
</span>
|
|
|
|
<button
|
|
type="button"
|
|
onClick={onSignOut}
|
|
disabled={signingOut}
|
|
className="inline-flex items-center gap-1.5 px-4 py-2 rounded-lg bg-surface-container-high hover:bg-surface-bright text-error border border-error/30 text-xs font-bold transition-all focus-visible:ring-2 focus-visible:ring-error focus-visible:outline-none disabled:opacity-50"
|
|
>
|
|
<span className="material-symbols-outlined text-[16px]">logout</span>
|
|
<span>{signingOut ? 'Signing out...' : 'Sign Out'}</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|