65 lines
2.4 KiB
JavaScript
65 lines
2.4 KiB
JavaScript
import { useNavigate } from 'react-router-dom'
|
|
import LicenseStatus from './LicenseStatus'
|
|
|
|
function fmtDate(dt) {
|
|
if (!dt) return '—'
|
|
return new Date(dt).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' })
|
|
}
|
|
|
|
function fmtAgo(dt) {
|
|
if (!dt) return 'Never'
|
|
const diff = (Date.now() - new Date(dt)) / 1000
|
|
if (diff < 60) return 'Just now'
|
|
if (diff < 3600) return `${Math.floor(diff / 60)}m ago`
|
|
if (diff < 86400) return `${Math.floor(diff / 3600)}h ago`
|
|
return `${Math.floor(diff / 86400)}d ago`
|
|
}
|
|
|
|
export default function SiteCard({ site }) {
|
|
const navigate = useNavigate()
|
|
const expires = new Date(site.license_expires_at)
|
|
const isExpired = expires < new Date()
|
|
const isLocked = site.is_locked
|
|
|
|
const borderColor = isLocked || isExpired
|
|
? 'border-red-800/60 hover:border-red-700'
|
|
: site.last_seen_at && (Date.now() - new Date(site.last_seen_at)) / 3600000 < 12
|
|
? 'border-emerald-800/40 hover:border-emerald-600'
|
|
: 'border-yellow-800/40 hover:border-yellow-600'
|
|
|
|
return (
|
|
<div
|
|
onClick={() => navigate(`/sites/${site.site_id}`)}
|
|
className={`bg-gray-900 border ${borderColor} rounded-xl p-4 cursor-pointer transition-all hover:bg-gray-800`}
|
|
>
|
|
<div className="flex items-start justify-between gap-2 mb-3">
|
|
<div className="min-w-0">
|
|
<h3 className="text-white font-semibold text-sm truncate">{site.name}</h3>
|
|
<p className="text-gray-500 text-xs truncate">{site.owner_name}</p>
|
|
</div>
|
|
<LicenseStatus site={site} />
|
|
</div>
|
|
|
|
<div className="grid grid-cols-2 gap-x-4 gap-y-1 text-xs">
|
|
<div>
|
|
<span className="text-gray-600">Expires</span>
|
|
<p className={`font-medium ${isExpired ? 'text-red-400' : 'text-gray-300'}`}>{fmtDate(site.license_expires_at)}</p>
|
|
</div>
|
|
<div>
|
|
<span className="text-gray-600">Last seen</span>
|
|
<p className="text-gray-300 font-medium">{fmtAgo(site.last_seen_at)}</p>
|
|
</div>
|
|
<div className="col-span-2 mt-1">
|
|
<span className="text-gray-600 font-mono text-[10px]">{site.site_id}</span>
|
|
</div>
|
|
</div>
|
|
|
|
{isLocked && site.lock_reason && (
|
|
<p className="mt-2 text-xs text-red-400 bg-red-900/20 border border-red-800/30 rounded px-2 py-1 truncate">
|
|
Locked: {site.lock_reason}
|
|
</p>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|