// frontend/src/pages/bellcloud/devices/tabs/WarrantyTab.jsx
import Button from '@/components/ui/Button'
import StatusBadge from '@/components/ui/StatusBadge'
import { fmtDateMedium, fmtDateLong } from '@/lib/formatters'
// ─── Helpers ──────────────────────────────────────────────────────────────────
function parseDate(val) {
if (!val) return null
// Firestore Timestamp object
if (typeof val === 'object' && typeof val.seconds === 'number') {
return new Date(val.seconds * 1000)
}
const d = new Date(val)
return isNaN(d.getTime()) ? null : d
}
function addDays(date, days) {
if (!date || !days) return null
const d = new Date(date)
d.setDate(d.getDate() + Number(days))
return d
}
function daysUntil(date) {
if (!date) return null
return Math.ceil((date.getTime() - Date.now()) / 86400000)
}
/** 0–100 how much of the period has ELAPSED */
function calcProgress(start, end) {
if (!start || !end) return null
const total = end.getTime() - start.getTime()
if (total <= 0) return 100
const elapsed = Date.now() - start.getTime()
return Math.min(100, Math.max(0, Math.round((elapsed / total) * 100)))
}
/** Remaining portion (inverse of elapsed) */
function calcRemaining(start, end) {
const p = calcProgress(start, end)
return p === null ? null : 100 - p
}
function daysLabel(days) {
if (days == null || days === 0) return '—'
if (days % 365 === 0) {
const y = days / 365
return `${y} year${y !== 1 ? 's' : ''}`
}
if (days % 30 === 0) {
const m = days / 30
return `${m} month${m !== 1 ? 's' : ''}`
}
return `${days} day${days !== 1 ? 's' : ''}`
}
// ─── Glass surface styles ─────────────────────────────────────────────────────
const GLASS = {
background: 'rgba(28, 32, 38, 0.30)',
backdropFilter: 'var(--blur-modal)',
WebkitBackdropFilter: 'var(--blur-modal)',
border: '1px solid var(--color-border)',
boxShadow: 'var(--shadow-card), var(--shadow-md)',
borderRadius: 'var(--radius-xl)',
}
const GLASS_ELEVATED = {
background: 'rgba(28, 32, 38, 0.40)',
backdropFilter: 'var(--blur-modal)',
WebkitBackdropFilter: 'var(--blur-modal)',
border: '1px solid var(--color-border)',
boxShadow: 'var(--shadow-sm)',
borderRadius: 'var(--radius-lg)',
}
// ─── Primitives ───────────────────────────────────────────────────────────────
function SectionLabel({ children }) {
return (
{children}
)
}
function InfoCell({ label, children }) {
return (
{label}
{children ?? '—'}
)
}
function ProgressBar({ value, color = 'var(--color-primary)', label, showPct = true }) {
const pct = Math.max(0, Math.min(100, value ?? 0))
return (
{(label || showPct) && (
{label && (
{label}
)}
{showPct && (
{pct}%
)}
)}
)
}
function Divider() {
return
}
function DetailRow({ label, value, valueColor }) {
return (
{label}
{value ?? '—'}
)
}
// ─── Subscription Hero ────────────────────────────────────────────────────────
function SubscriptionHero({ sub, canEdit, onEditSubscription, deviceUsers }) {
const subscrStart = parseDate(sub?.subscrStart)
const subscrEnd = addDays(subscrStart, sub?.subscrDuration)
const daysLeft = daysUntil(subscrEnd)
const remaining = calcRemaining(subscrStart, subscrEnd)
const isActive = daysLeft === null || daysLeft > 0
const tier = sub?.subscrTier || null
const progressColor = daysLeft === null
? 'var(--color-primary)'
: daysLeft > 60
? 'var(--color-success)'
: daysLeft > 14
? 'var(--color-warning)'
: 'var(--color-danger)'
// Registered users = actual device users count passed from parent
const regUsers = Array.isArray(deviceUsers) ? deviceUsers.length : null
const maxUsers = sub?.maxUsers ?? null
const hwOutputs = sub?.hw_outputs ?? null
const maxOutputs = sub?.maxOutputs ?? null
return (
{/* Left accent glow */}
{/* Right ambient glow */}
{/* ── Column 1: Tier ── */}
{tier ? `${tier} Tier` : 'No Subscription'}
{isActive ? 'Active License' : 'Expired'}
{/* ── Column 2: Progress bar ── */}
{/* Top label row */}
{daysLeft === null
? 'No expiry set'
: daysLeft <= 0
? 'Subscription expired'
: `${daysLeft} days remaining`}
{daysLabel(sub?.subscrDuration)} plan
{/* Progress bar */}
{/* Bottom: inline Start / Renewal */}
{subscrStart && (
Start:{' '}
{fmtDateMedium(subscrStart.toISOString())}
)}
{subscrEnd && (
Renewal:{' '}
{fmtDateMedium(subscrEnd.toISOString())}
)}
{/* ── Column 3: Users + Outputs + Edit — side by side ── */}
{/* Users block */}
Device Users
Max:{' '}
{maxUsers ?? '—'}
{regUsers !== null && (
<>
{' '}| {' '}
Reg:{' '}
{regUsers}
>
)}
{/* Outputs block */}
Outputs
HW:{' '}
{hwOutputs ?? '—'}
{maxOutputs !== null && (
<>
{' '}| {' '}
Max:{' '}
{maxOutputs}
>
)}
{/* Edit pencil icon button */}
{canEdit && (
{
e.currentTarget.style.background = 'rgba(49,53,60,0.50)'
e.currentTarget.style.color = 'var(--color-text-primary)'
}}
onMouseLeave={e => {
e.currentTarget.style.background = 'transparent'
e.currentTarget.style.color = 'var(--color-text-muted)'
}}
>
)}
)
}
// ─── Warranty Card ────────────────────────────────────────────────────────────
function WarrantyCard({ stats, canEdit, onEditWarranty }) {
const warrantyStart = parseDate(stats?.warrantyStart)
const warrantyEnd = addDays(warrantyStart, stats?.warrantyPeriod)
const daysLeft = daysUntil(warrantyEnd)
const remaining = calcRemaining(warrantyStart, warrantyEnd)
const isVoid = stats?.warrantyActive === false
const isExpired = !isVoid && daysLeft !== null && daysLeft <= 0
const isActive = !isVoid && !isExpired && (daysLeft === null || daysLeft > 0)
const statusLabel = isVoid ? 'Warranty Void' : isExpired ? 'Expired' : isActive ? 'Active' : '—'
const statusVariant = isVoid ? 'warning' : isExpired ? 'danger' : isActive ? 'success' : 'neutral'
const borderAccent = isVoid
? 'var(--color-warning)'
: isExpired
? 'var(--color-danger)'
: 'var(--color-success)'
const progressColor = isVoid || isExpired ? 'var(--color-danger)' : 'var(--color-success)'
return (
{/* Accent side glow */}
{/* Header */}
{statusLabel}
{isVoid
? 'Warranty has been manually voided'
: isExpired
? warrantyEnd
? `Coverage ended on ${fmtDateLong(warrantyEnd.toISOString())}`
: 'Coverage has expired'
: warrantyEnd
? `Active until ${fmtDateMedium(warrantyEnd.toISOString())}`
: 'Warranty is currently active'}
{canEdit && (
Edit Warranty
)}
{/* Progress */}
{/* Detail grid */}
{warrantyStart ? fmtDateMedium(warrantyStart.toISOString()) : '—'}
{warrantyEnd ? fmtDateMedium(warrantyEnd.toISOString()) : '—'}
{daysLabel(stats?.warrantyPeriod)}
{statusLabel}
)
}
// ─── Maintenance Card ─────────────────────────────────────────────────────────
function MaintenanceCard({ stats }) {
const maintainedOn = parseDate(stats?.maintainedOn)
const nextMaint = addDays(maintainedOn, stats?.maintainancePeriod)
const daysLeft = daysUntil(nextMaint)
const remaining = calcRemaining(maintainedOn, nextMaint)
const isOverdue = daysLeft !== null && daysLeft <= 0
const isDueSoon = daysLeft !== null && daysLeft > 0 && daysLeft <= 30
const statusVariant = isOverdue ? 'danger' : isDueSoon ? 'warning' : 'neutral'
const progressColor = isOverdue
? 'var(--color-danger)'
: isDueSoon
? 'var(--color-warning)'
: 'var(--color-info)'
return (
{/* Title */}
Maintenance Schedule
{(isOverdue || isDueSoon) && (
{isOverdue ? 'Overdue' : 'Due Soon'}
)}
{/* Next service highlight */}
{nextMaint ? (
Next Scheduled Service
{fmtDateLong(nextMaint.toISOString())}
{isOverdue ? 'Overdue by' : 'In'}
{daysLeft != null ? `${Math.abs(daysLeft)} day${Math.abs(daysLeft) !== 1 ? 's' : ''}` : '—'}
) : (
No maintenance schedule set
)}
{/* Progress bar */}
{/* Detail rows */}
)
}
// ─── Performance Metrics ──────────────────────────────────────────────────────
function MetricTile({ icon, label, value, accent = 'var(--color-primary)', tag, tagVariant = 'info' }) {
return (
{icon}
{tag != null && (
{tag}
)}
)
}
function PerformanceMetrics({ device, stats }) {
const totalWarnings = Number.isFinite(stats?.totalWarningsGiven) ? stats.totalWarningsGiven : null
const melodiesCount = Array.isArray(device?.device_melodies_all) ? device.device_melodies_all.length : null
return (
{/* System Warnings */}
0 ? 'var(--color-danger)' : 'var(--color-success)'}
tag={totalWarnings !== null ? (totalWarnings === 0 ? 'Clean' : 'Flagged') : null}
tagVariant={totalWarnings === 0 ? 'success' : 'danger'}
value={totalWarnings !== null ? totalWarnings : '—'}
label="System Warnings"
icon={
}
/>
{/* On-board Melodies */}
}
/>
{/* Firmware Version */}
}
/>
{/* Total Melodies (favorites) */}
0 ? 'Saved' : null}
tagVariant="warning"
value={Array.isArray(device?.device_melodies_favorites) ? device.device_melodies_favorites.length : '—'}
label="Favourite Melodies"
icon={
}
/>
)
}
// ─── WarrantyTab ──────────────────────────────────────────────────────────────
export default function WarrantyTab({
device,
canEdit,
sub,
stats,
deviceUsers,
onEditSubscription,
onEditWarranty,
}) {
return (
{/* Subscription hero — no section label above */}
{/* Warranty card — no section label above */}
{/* Masonry: Maintenance + Metrics side by side */}
)
}