Initial Commit. Split cloud service from the combined project
This commit is contained in:
64
sysadmin_panel/src/components/SiteCard.jsx
Normal file
64
sysadmin_panel/src/components/SiteCard.jsx
Normal file
@@ -0,0 +1,64 @@
|
||||
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>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user