import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useState } from 'react'; import { listBrowserSessionProfiles, deleteBrowserSessionProfile, testBrowserSessionProfile, type BrowserSessionProfile, } from '../../api'; import { AddBrowserSessionDialog } from './AddBrowserSessionDialog'; function StatusPill({ status }: { status: BrowserSessionProfile['status'] }) { const map: Record = { pending: 'bg-slate-200 text-slate-700', active: 'bg-emerald-100 dark:bg-emerald-500/15 text-emerald-700 dark:text-emerald-300', expired: 'bg-amber-100 dark:bg-amber-500/15 text-amber-800 dark:text-amber-300', revoked: 'bg-slate-200 text-slate-500', error: 'bg-rose-100 dark:bg-rose-500/15 text-rose-700 dark:text-rose-300', }; const labels: Record = { pending: '保留中', active: '有効', expired: '期限切れ', revoked: '無効化', error: 'エラー', }; return {labels[status]}; } export function BrowserSessionsPanel() { const qc = useQueryClient(); const { data: profiles = [], isLoading } = useQuery({ queryKey: ['browser-session-profiles'], queryFn: listBrowserSessionProfiles, }); const del = useMutation({ mutationFn: (id: number) => deleteBrowserSessionProfile(id), onSuccess: () => qc.invalidateQueries({ queryKey: ['browser-session-profiles'] }), }); const test = useMutation({ mutationFn: (id: number) => testBrowserSessionProfile(id), onSuccess: () => qc.invalidateQueries({ queryKey: ['browser-session-profiles'] }), }); const [adding, setAdding] = useState(false); const [reLoginProfileId, setReLoginProfileId] = useState(null); return (

ブラウザセッション

ログイン後の cookie / storageState をユーザーごとに暗号化して保存し、ブラウザマクロから{' '} session_profile_id{' '} で参照できるようにします。保存されたセッションは他のユーザーと共有されません。

{isLoading &&
読み込み中…
}
{profiles.length === 0 && !isLoading && (
保存済みセッションはまだありません。
上の「サイトのセッションを追加」ボタンから始めてください。
)} {profiles.map(p => (
{p.label} id={p.id}
{p.startUrl}
{p.lastError &&
{p.lastError}
}
{p.lastSavedAt ? `保存: ${new Date(p.lastSavedAt).toLocaleString('ja-JP')}` : '未保存'} {p.lastUsedAt && ` · 最終使用: ${new Date(p.lastUsedAt).toLocaleString('ja-JP')}`}
))}
{adding && ( p.id === reLoginProfileId) ?? null : null} onClose={() => { setAdding(false); setReLoginProfileId(null); }} /> )}
); }