CODEX - MAJOR overhaul to the columns and minor changes to the melody detail and form

This commit is contained in:
2026-02-23 09:33:03 +02:00
parent 8b3ec3f6ec
commit fb3bbac245
3 changed files with 338 additions and 107 deletions

View File

@@ -1,4 +1,4 @@
import { useState, useEffect } from "react";
import { useState, useEffect } from "react";
import { useParams, useNavigate } from "react-router-dom";
import api from "../api/client";
import { useAuth } from "../auth/AuthContext";
@@ -47,6 +47,12 @@ function mapPercentageToStepDelay(percent, minSpeed, maxSpeed) {
return Math.round(a * Math.pow(b / a, t));
}
function hueForDepth(index, count) {
const safeCount = Math.max(1, count);
const t = Math.max(0, Math.min(1, index / safeCount));
return 190 + (15 - 190) * t;
}
function Field({ label, children }) {
return (
<div>
@@ -324,31 +330,6 @@ export default function MelodyDetail() {
Melody Information
</h2>
<dl className="grid grid-cols-2 md:grid-cols-3 gap-4">
<Field label="Type">
<span className="capitalize">{melody.type}</span>
</Field>
<Field label="Tone">
<span className="capitalize">{info.melodyTone}</span>
</Field>
<Field label="Steps">{info.steps}</Field>
<Field label="Total Archetype Notes">{info.totalNotes}</Field>
<Field label="Total Active Bells">{info.totalActiveBells ?? "-"}</Field>
<Field label="Min Speed">
{info.minSpeed ? (
<div>
<div>{minBpm} BPM</div>
<div className="text-xs" style={{ color: "var(--text-muted)" }}>{info.minSpeed} ms</div>
</div>
) : "-"}
</Field>
<Field label="Max Speed">
{info.maxSpeed ? (
<div>
<div>{maxBpm} BPM</div>
<div className="text-xs" style={{ color: "var(--text-muted)" }}>{info.maxSpeed} ms</div>
</div>
) : "-"}
</Field>
<Field label="Color">
{info.color ? (
<span className="inline-flex items-center gap-2">
@@ -362,11 +343,25 @@ export default function MelodyDetail() {
"-"
)}
</Field>
<Field label="True Ring">
<span className="px-2 py-0.5 text-xs rounded-full" style={badgeStyle(info.isTrueRing)}>
{info.isTrueRing ? "Yes" : "No"}
</span>
<Field label="Tone">
<span className="capitalize">{info.melodyTone}</span>
</Field>
<Field label="Steps">{info.steps}</Field>
<Field label="Min Speed">
{info.minSpeed ? (
<span>
{minBpm} bpm <span className="text-xs" style={{ color: "var(--text-muted)" }}>· {info.minSpeed} ms</span>
</span>
) : "-"}
</Field>
<Field label="Max Speed">
{info.maxSpeed ? (
<span>
{maxBpm} bpm <span className="text-xs" style={{ color: "var(--text-muted)" }}>· {info.maxSpeed} ms</span>
</span>
) : "-"}
</Field>
<Field label="Unique Bells">{info.totalActiveBells ?? "-"}</Field>
<div className="col-span-2 md:col-span-3">
<Field label="Description">
{getLocalizedValue(info.description, displayLang)}
@@ -428,7 +423,7 @@ export default function MelodyDetail() {
<Field label="Speed">
{settings.speed != null ? (
<span>
{settings.speed}%{speedBpm ? ` · ${speedBpm} BPM` : ""}{speedMs ? ` · ${speedMs} ms` : ""}
{settings.speed}%{speedBpm ? <span className="text-xs" style={{ color: "var(--text-muted)" }}>{` · ${speedBpm} bpm`}</span> : ""}{speedMs ? <span className="text-xs" style={{ color: "var(--text-muted)" }}>{` · ${speedMs} ms`}</span> : ""}
</span>
) : "-"}
</Field>
@@ -452,26 +447,32 @@ export default function MelodyDetail() {
<dd>
{settings.noteAssignments?.length > 0 ? (
<div className="flex flex-wrap gap-1.5">
{settings.noteAssignments.map((assignedBell, noteIdx) => (
<div
key={noteIdx}
className="flex flex-col items-center rounded-md border"
style={{
minWidth: "36px",
padding: "4px 6px",
backgroundColor: "var(--bg-card-hover)",
borderColor: "var(--border-primary)",
}}
>
<span className="text-xs font-bold leading-tight" style={{ color: "var(--text-secondary)" }}>
{String.fromCharCode(65 + noteIdx)}
</span>
<div className="w-full my-0.5" style={{ height: "1px", backgroundColor: "var(--border-primary)" }} />
<span className="text-xs leading-tight" style={{ color: "var(--text-muted)" }}>
{assignedBell > 0 ? assignedBell : "—"}
</span>
</div>
))}
{settings.noteAssignments.map((assignedBell, noteIdx) => {
const noteHue = hueForDepth(noteIdx, settings.noteAssignments.length - 1);
const bellDepthIdx = Math.max(0, Math.min(15, (assignedBell || 1) - 1));
const bellHue = hueForDepth(bellDepthIdx, 15);
return (
<div
key={noteIdx}
className="flex flex-col items-center rounded-md border"
style={{
minWidth: "36px",
padding: "4px 6px",
backgroundColor: "var(--bg-card-hover)",
borderColor: `hsla(${noteHue}, 65%, 55%, 0.45)`,
boxShadow: `0 0 6px hsla(${noteHue}, 75%, 55%, 0.25) inset`,
}}
>
<span className="text-xs font-bold leading-tight" style={{ color: `hsl(${noteHue}, 80%, 72%)` }}>
{String.fromCharCode(65 + noteIdx)}
</span>
<div className="w-full my-0.5" style={{ height: "1px", backgroundColor: "var(--border-primary)" }} />
<span className="text-xs leading-tight" style={{ color: assignedBell > 0 ? `hsl(${bellHue}, 80%, 70%)` : "var(--text-muted)" }}>
{assignedBell > 0 ? assignedBell : "—"}
</span>
</div>
);
})}
</div>
) : (
<span style={{ color: "var(--text-muted)" }}>-</span>
@@ -566,6 +567,9 @@ export default function MelodyDetail() {
</a>
</span>
)}
<span className="text-xs" style={{ color: "var(--text-muted)" }}>
{info.totalNotes ?? 0} active notes
</span>
</span>
);
})()}
@@ -725,3 +729,7 @@ export default function MelodyDetail() {
</div>
);
}