import React from 'react'
import { Head, router } from '@inertiajs/react'
import AdminLayout from '../../Layouts/AdminLayout'
function formatDateTime(value) {
if (!value) return '—'
const date = new Date(value)
if (Number.isNaN(date.getTime())) return '—'
return new Intl.DateTimeFormat('en', { dateStyle: 'medium', timeStyle: 'short' }).format(date)
}
function StatCard({ label, value, tone = 'sky' }) {
const tones = {
sky: 'border-sky-300/15 bg-sky-400/10 text-sky-100',
amber: 'border-amber-300/15 bg-amber-400/10 text-amber-100',
emerald: 'border-emerald-300/15 bg-emerald-400/10 text-emerald-100',
rose: 'border-rose-300/15 bg-rose-400/10 text-rose-100',
}
return (
{label}
{Number(value || 0).toLocaleString()}
)
}
function badgeTone(status) {
if (status === 'approved') return 'border-emerald-300/20 bg-emerald-400/12 text-emerald-100'
if (status === 'rejected') return 'border-rose-300/20 bg-rose-400/12 text-rose-100'
return 'border-amber-300/20 bg-amber-400/12 text-amber-100'
}
async function requestJson(url, body) {
const response = await fetch(url, {
method: 'POST',
credentials: 'same-origin',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || '',
'X-Requested-With': 'XMLHttpRequest',
},
body: JSON.stringify(body || {}),
})
const payload = await response.json().catch(() => ({}))
if (!response.ok) {
throw new Error(payload?.message || 'Request failed.')
}
return payload
}
export default function UsernameQueue({ title, requests, stats, filters, options, endpoints }) {
const [state, setState] = React.useState(filters || { q: '', status: 'pending' })
const [notes, setNotes] = React.useState({})
const [busy, setBusy] = React.useState('')
const [notice, setNotice] = React.useState('')
const [error, setError] = React.useState('')
React.useEffect(() => {
setState(filters || { q: '', status: 'pending' })
}, [filters])
function update(key, value) {
setState((current) => ({ ...current, [key]: value }))
}
function applyFilters(event) {
event.preventDefault()
router.get(endpoints.index, state, { preserveState: true, replace: true, preserveScroll: true })
}
async function moderate(item, action) {
const actionKey = `${action}-${item.id}`
setBusy(actionKey)
setError('')
setNotice('')
try {
const payload = await requestJson(action === 'approve' ? item.approve_url : item.reject_url, {
note: String(notes[item.id] || ''),
})
setNotice(payload.message || `Request ${action}d.`)
router.reload({ only: ['requests', 'stats'], preserveScroll: true })
} catch (requestError) {
setError(requestError.message || 'Request failed.')
} finally {
setBusy('')
}
}
const items = requests?.data || []
return (
Moderation surface
Username Queue
Review pending username requests before they are applied to the account or history trail.
Page {requests?.current_page || 1} / {requests?.last_page || 1}
{Number(requests?.total || 0).toLocaleString()} requests
{notice ? {notice}
: null}
{error ? {error}
: null}
{items.length === 0 ? (
No username requests matched the current filters.
) : items.map((item) => (
{String(item.status || 'pending').replaceAll('_', ' ')}
{item.context ? (
{item.context.replaceAll('_', ' ')}
) : null}
{item.similar_to ? (
Similar to {item.similar_to}
) : null}
{item.requested_username}
{item.current_username ? `Current: @${item.current_username}` : 'No current username'}
{item.current_name ? ` • ${item.current_name}` : ''}
Requested {formatDateTime(item.created_at)}
{item.reviewed_at ? ` • reviewed ${formatDateTime(item.reviewed_at)}` : ''}
))}
{requests?.prev_page_url || requests?.next_page_url ? (
Showing page {requests?.current_page || 1} of {requests?.last_page || 1}
{requests?.prev_page_url ? (
) : null}
{requests?.next_page_url ? (
) : null}
) : null}
)
}