Change to the Contents of some Sections

This commit is contained in:
2026-02-18 21:26:12 +02:00
parent 7cf54c3f1f
commit 7c26f0971a

View File

@@ -459,69 +459,93 @@ export default function DeviceDetail() {
const deviceInfoSection = ( const deviceInfoSection = (
<section className="rounded-lg border p-6" style={{ backgroundColor: "var(--bg-card)", borderColor: "var(--border-primary)" }}> <section className="rounded-lg border p-6" style={{ backgroundColor: "var(--bg-card)", borderColor: "var(--border-primary)" }}>
<h2 className="text-lg font-semibold mb-4" style={{ color: "var(--text-heading)" }}>Device Information</h2> <h2 className="text-lg font-semibold mb-4" style={{ color: "var(--text-heading)" }}>Device Information</h2>
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gridTemplateRows: "auto auto", gap: "1rem", alignItems: "start" }}> <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: "1rem", alignItems: "start" }}>
{/* Row 1, Col 1: Status */} {/* Col 1: Status — fancy card filling vertical space */}
<div style={{ gridColumn: 1, gridRow: 1, display: "flex", alignItems: "center", gap: "0.75rem" }}> <div
<div className="relative rounded-md border overflow-hidden"
className="w-10 h-10 rounded-full flex items-center justify-center shrink-0" style={{
style={{ backgroundColor: isOnline ? "var(--success-bg)" : "var(--bg-card-hover)" }} borderColor: isOnline ? "rgba(116, 184, 22, 0.3)" : "var(--border-primary)",
backgroundColor: isOnline ? "rgba(116, 184, 22, 0.05)" : "var(--bg-primary)",
padding: "1.25rem",
height: "100%",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
textAlign: "center",
}}
>
<span
className="absolute inset-0 flex items-center justify-center font-bold pointer-events-none select-none"
style={{ fontSize: "4.5rem", color: isOnline ? "var(--success-text)" : "var(--text-muted)", opacity: 0.06 }}
> >
<span {isOnline ? "ON" : "OFF"}
className="w-3 h-3 rounded-full inline-block" </span>
style={{ backgroundColor: isOnline ? "var(--success-text)" : "var(--text-muted)" }} <div className="relative">
/> <div
className="w-12 h-12 rounded-full flex items-center justify-center mx-auto mb-2"
style={{ backgroundColor: isOnline ? "var(--success-bg)" : "var(--bg-card-hover)" }}
>
<span
className="w-4 h-4 rounded-full inline-block"
style={{ backgroundColor: isOnline ? "var(--success-text)" : "var(--text-muted)" }}
/>
</div>
<div className="text-xs font-medium uppercase tracking-wide" style={{ color: "var(--text-muted)" }}>Status</div>
<div className="text-sm font-semibold mt-0.5" style={{ color: isOnline ? "var(--success-text)" : "var(--text-muted)" }}>
{isOnline ? "Online" : "Offline"}
</div>
{mqttStatus && (
<div className="text-xs mt-1" style={{ color: "var(--text-muted)" }}>
{mqttStatus.seconds_since_heartbeat}s ago
</div>
)}
</div>
</div>
{/* Col 2: Serial Number, Hardware Variant, Document ID */}
<div style={{ display: "flex", flexDirection: "column", gap: "0.75rem" }}>
<div>
<div className="text-xs font-medium uppercase tracking-wide" style={{ color: "var(--text-muted)" }}>Serial Number</div>
<div className="text-sm font-mono mt-0.5" style={{ color: "var(--text-primary)" }}>{device.device_id}</div>
</div> </div>
<div> <div>
<div className="text-xs font-medium uppercase tracking-wide" style={{ color: "var(--text-muted)" }}>Status</div> <div className="text-xs font-medium uppercase tracking-wide" style={{ color: "var(--text-muted)" }}>Hardware Variant</div>
<div className="text-sm font-semibold" style={{ color: isOnline ? "var(--success-text)" : "var(--text-muted)" }}> <div className="text-sm mt-0.5" style={{ color: "var(--text-primary)" }}>VesperCore</div>
{isOnline ? "Online" : "Offline"} </div>
{mqttStatus && ( <div>
<span className="ml-2 text-xs font-normal" style={{ color: "var(--text-muted)" }}> <div className="text-xs font-medium uppercase tracking-wide" style={{ color: "var(--text-muted)" }}>Document ID</div>
{mqttStatus.seconds_since_heartbeat}s ago <div className="text-xs font-mono mt-0.5" style={{ color: "var(--text-muted)" }}>{device.id}</div>
</span>
)}
</div>
</div> </div>
</div> </div>
{/* Row 1, Col 2: Hardware Variant */} {/* Col 3: Admin Notes */}
<div style={{ gridColumn: 2, gridRow: 1 }}> <div>
<div className="text-xs font-medium uppercase tracking-wide" style={{ color: "var(--text-muted)" }}>Hardware Variant</div>
<div className="text-sm mt-0.5" style={{ color: "var(--text-primary)" }}>VesperCore</div>
</div>
{/* Row 1-2, Col 3: Admin Notes (spans 2 rows, far right) */}
<div style={{ gridColumn: 3, gridRow: "1 / 3" }}>
<div className="text-xs font-medium uppercase tracking-wide" style={{ color: "var(--text-muted)" }}>Admin Notes</div> <div className="text-xs font-medium uppercase tracking-wide" style={{ color: "var(--text-muted)" }}>Admin Notes</div>
<div className="text-sm mt-0.5" style={{ color: "var(--text-muted)" }}>-</div> <div className="text-sm mt-0.5" style={{ color: "var(--text-muted)" }}>-</div>
</div> </div>
{/* Row 2, Col 1: Serial Number */}
<div style={{ gridColumn: 1, gridRow: 2 }}>
<div className="text-xs font-medium uppercase tracking-wide" style={{ color: "var(--text-muted)" }}>Serial Number</div>
<div className="text-sm font-mono mt-0.5" style={{ color: "var(--text-primary)" }}>{device.device_id}</div>
</div>
{/* Row 2, Col 2: Document ID */}
<div style={{ gridColumn: 2, gridRow: 2 }}>
<div className="text-xs font-medium uppercase tracking-wide" style={{ color: "var(--text-muted)" }}>Document ID</div>
<div className="text-xs font-mono mt-0.5" style={{ color: "var(--text-muted)" }}>{device.id}</div>
</div>
</div> </div>
</section> </section>
); );
const subscriptionSection = ( const subscriptionSection = (
<SectionCard title="Subscription"> <SectionCard title="Subscription">
<dl className="grid gap-4" style={{ gridTemplateColumns: "repeat(auto-fill, minmax(200px, 1fr))" }}> {/* Row 1: Tier | Last Payment On */}
<FieldRow columns={2}>
<Field label="Tier"> <Field label="Tier">
<span className="px-2 py-0.5 text-xs rounded-full capitalize" style={{ backgroundColor: "var(--badge-blue-bg)", color: "var(--badge-blue-text)" }}> <span className="px-2 py-0.5 text-xs rounded-full capitalize" style={{ backgroundColor: "var(--badge-blue-bg)", color: "var(--badge-blue-text)" }}>
{sub.subscrTier} {sub.subscrTier}
</span> </span>
</Field> </Field>
<Field label="Last Payment On">
<span className="text-sm" style={{ color: "var(--text-primary)" }}>3 months ago</span>
</Field>
</FieldRow>
{/* Row 2: Start Date | Expiration Date | Duration | Time Left */}
<FieldRow columns={4}>
<Field label="Start Date">{formatDate(sub.subscrStart)}</Field> <Field label="Start Date">{formatDate(sub.subscrStart)}</Field>
<Field label="Duration">{sub.subscrDuration ? daysToDisplay(sub.subscrDuration) : "-"}</Field>
<Field label="Expiration Date">{subscrEnd ? formatDateNice(subscrEnd) : "-"}</Field> <Field label="Expiration Date">{subscrEnd ? formatDateNice(subscrEnd) : "-"}</Field>
<Field label="Duration">{sub.subscrDuration ? daysToDisplay(sub.subscrDuration) : "-"}</Field>
<Field label="Time Left"> <Field label="Time Left">
{subscrDaysLeft === null ? "-" : subscrDaysLeft <= 0 ? ( {subscrDaysLeft === null ? "-" : subscrDaysLeft <= 0 ? (
<span className="px-2 py-0.5 text-xs rounded-full" style={{ backgroundColor: "var(--danger-bg)", color: "var(--danger-text)" }}> <span className="px-2 py-0.5 text-xs rounded-full" style={{ backgroundColor: "var(--danger-bg)", color: "var(--danger-text)" }}>
@@ -533,9 +557,22 @@ export default function DeviceDetail() {
</span> </span>
)} )}
</Field> </Field>
</FieldRow>
{/* Row 3: Max Users | Max Outputs | Extra Info */}
<FieldRow columns={3}>
<Field label="Max Users">{sub.maxUsers}</Field> <Field label="Max Users">{sub.maxUsers}</Field>
<Field label="Max Outputs">{sub.maxOutputs}</Field> <Field label="Max Outputs">{sub.maxOutputs}</Field>
</dl> <Field label="Extra Info">
<a
href="#"
className="text-xs"
style={{ color: "var(--text-link)" }}
onClick={(e) => e.preventDefault()}
>
View subscription details
</a>
</Field>
</FieldRow>
</SectionCard> </SectionCard>
); );
@@ -715,7 +752,8 @@ export default function DeviceDetail() {
const warrantySection = ( const warrantySection = (
<SectionCard title="Warranty, Maintenance & Statistics"> <SectionCard title="Warranty, Maintenance & Statistics">
<Subsection title="Warranty Information" isFirst> <Subsection title="Warranty Information" isFirst>
<dl className="grid gap-4" style={{ gridTemplateColumns: "repeat(auto-fill, minmax(150px, 1fr))" }}> {/* Row 1: Status | Time Remaining */}
<FieldRow columns={2}>
<Field label="Warranty Status"> <Field label="Warranty Status">
{warrantyDaysLeft !== null ? ( {warrantyDaysLeft !== null ? (
warrantyDaysLeft > 0 ? ( warrantyDaysLeft > 0 ? (
@@ -727,20 +765,24 @@ export default function DeviceDetail() {
<BoolBadge value={stats.warrantyActive} yesLabel="Active" noLabel="Expired" /> <BoolBadge value={stats.warrantyActive} yesLabel="Active" noLabel="Expired" />
)} )}
</Field> </Field>
<Field label="Start Date">{formatDate(stats.warrantyStart)}</Field> <Field label="Time Remaining">
<Field label="Warranty Period">{stats.warrantyPeriod ? daysToDisplay(stats.warrantyPeriod) : "-"}</Field>
<Field label="Expiration Date">{warrantyEnd ? formatDateNice(warrantyEnd) : "-"}</Field>
<Field label="Remaining">
{warrantyDaysLeft === null ? "-" : warrantyDaysLeft <= 0 ? ( {warrantyDaysLeft === null ? "-" : warrantyDaysLeft <= 0 ? (
<span style={{ color: "var(--danger-text)" }}>Expired</span> <span style={{ color: "var(--danger-text)" }}>Expired</span>
) : ( ) : (
`${warrantyDaysLeft} days` `${warrantyDaysLeft} days`
)} )}
</Field> </Field>
</dl> </FieldRow>
{/* Row 2: Start Date | Expiry Date | Period */}
<FieldRow columns={3}>
<Field label="Start Date">{formatDate(stats.warrantyStart)}</Field>
<Field label="Expiry Date">{warrantyEnd ? formatDateNice(warrantyEnd) : "-"}</Field>
<Field label="Period">{stats.warrantyPeriod ? daysToDisplay(stats.warrantyPeriod) : "-"}</Field>
</FieldRow>
</Subsection> </Subsection>
<Subsection title="Maintenance"> <Subsection title="Maintenance">
<dl className="grid gap-4" style={{ gridTemplateColumns: "repeat(auto-fill, minmax(150px, 1fr))" }}> {/* Single row: all 3 fields */}
<FieldRow columns={3}>
<Field label="Last Maintained On">{formatDate(stats.maintainedOn)}</Field> <Field label="Last Maintained On">{formatDate(stats.maintainedOn)}</Field>
<Field label="Maintenance Period">{stats.maintainancePeriod ? daysToDisplay(stats.maintainancePeriod) : "-"}</Field> <Field label="Maintenance Period">{stats.maintainancePeriod ? daysToDisplay(stats.maintainancePeriod) : "-"}</Field>
<Field label="Next Scheduled"> <Field label="Next Scheduled">
@@ -755,29 +797,34 @@ export default function DeviceDetail() {
</span> </span>
) : "-"} ) : "-"}
</Field> </Field>
</dl> </FieldRow>
</Subsection> </Subsection>
<Subsection title="Statistics"> <Subsection title="Statistics">
<dl className="grid gap-4" style={{ gridTemplateColumns: "repeat(auto-fill, minmax(150px, 1fr))" }}> {/* Row 1: Playbacks | Hammer Strikes | Warnings */}
<FieldRow columns={3}>
<Field label="Total Playbacks">{stats.totalPlaybacks}</Field> <Field label="Total Playbacks">{stats.totalPlaybacks}</Field>
<Field label="Total Hammer Strikes">{stats.totalHammerStrikes}</Field> <Field label="Total Hammer Strikes">{stats.totalHammerStrikes}</Field>
<Field label="Total Warnings Given">{stats.totalWarningsGiven}</Field> <Field label="Total Warnings Given">{stats.totalWarningsGiven}</Field>
</FieldRow>
{/* Row 2: Melodies | Favorites */}
<FieldRow columns={3}>
<Field label="Total Melodies">{device.device_melodies_all?.length ?? 0}</Field> <Field label="Total Melodies">{device.device_melodies_all?.length ?? 0}</Field>
<Field label="Favorite Melodies">{device.device_melodies_favorites?.length ?? 0}</Field> <Field label="Favorite Melodies">{device.device_melodies_favorites?.length ?? 0}</Field>
{stats.perBellStrikes?.length > 0 && ( <div />
<div style={{ gridColumn: "1 / -1" }}> </FieldRow>
<Field label="Per Bell Strikes"> {stats.perBellStrikes?.length > 0 && (
<div className="flex flex-wrap gap-2 mt-1"> <div className="mt-2">
{stats.perBellStrikes.slice(0, attr.totalBells || stats.perBellStrikes.length).map((count, i) => ( <Field label="Per Bell Strikes">
<span key={i} className="px-2 py-1 text-xs rounded-md border" style={{ borderColor: "var(--border-primary)", color: "var(--text-primary)" }}> <div className="flex flex-wrap gap-2 mt-1">
Bell {i + 1}: {count} {stats.perBellStrikes.slice(0, attr.totalBells || stats.perBellStrikes.length).map((count, i) => (
</span> <span key={i} className="px-2 py-1 text-xs rounded-md border" style={{ borderColor: "var(--border-primary)", color: "var(--text-primary)" }}>
))} Bell {i + 1}: {count}
</div> </span>
</Field> ))}
</div> </div>
)} </Field>
</dl> </div>
)}
</Subsection> </Subsection>
</SectionCard> </SectionCard>
); );