UX polish — duration, preview button, Select state, dropdown current, switch action
Pure UX bundle from the testing batch. None individually changes behavior; together they remove a half-dozen sharp edges. 1. Policy-list duration column: human-readable `31536000s` / `604800s` / `0s` are now `1 year` / `1 week` / `perpetual`. New `fmtDuration()` helper handles common cadences (1 day, 1 week, 1 month, 3 months, 6 months, 1 year, 2 years) with arithmetic fallbacks for non-canonical values. Grace column gets the same treatment with "none" for 0. 2. "Preview buy page" button per product header The Policies tab's per-product card now has a "Preview buy page" button on the right side of the header (when ≥ 1 public+active policy exists). Opens /buy/<slug> in a new tab. tableCard() helper grew an optional headerAction param. 3. Buy page tier card: "Select" → "Selected" When a tier becomes the active selection, its button label flips to "Selected" while other tiers' buttons stay "Select". Combined with the existing .selected card-border styling gives buyers an unambiguous "yes, this tier is what's tied to the price card below" cue. 4. Licenses page POLICY column shows display name Was showing slug (`recurring`, `core`, `creator`); now shows the operator-set display name (Recurring Pro, Core, Creator) primary, with the slug as a smaller mono-font line below. Operators see what the buyer sees while keeping the slug visible for SDK reference. (Subscriptions tab already handled this pattern; this brings Licenses in line.) 5. Change Tier dropdown: "(current)" annotation Current tier now appears in the dropdown but with " · current" appended and `disabled` attribute set. Operator sees what they're starting from but can't pick the no-op. Auto-selects the first SELECTABLE option so the modal opens with a valid target ready. formSelect() helper grew per-option `disabled` support. 6. Single "Switch active payment provider" StartOS action The two old "Activate BTCPay" / "Activate Zaprite" actions collapsed into one dropdown-driven action. Operators saw the pair as confusing — both appeared alongside Connect / Disconnect / Status, and operators couldn't tell at a glance which one was currently active. New action pre-fills the dropdown with the currently-active provider so opening it is immediately informative. Old action ids retained as visibility:'hidden' shims for back-compat with any operator scripts pointing at them. Test count unchanged; UI-only changes don't touch any test fixtures.
This commit is contained in:
@@ -603,10 +603,16 @@ footer.kfooter a:hover {{ color:var(--navy-900); }}
|
||||
function selectTier(slug) {{
|
||||
if (!TIERS[slug]) return;
|
||||
selectedPolicy = slug;
|
||||
// Visual update.
|
||||
// Visual update — toggle .selected on cards AND swap the button
|
||||
// label so the chosen tier reads "Selected" while the others
|
||||
// stay "Select". Buyer gets a clear "yes, this is what's tied
|
||||
// to the price card below" signal.
|
||||
document.querySelectorAll('.tier').forEach(function(c) {{
|
||||
if (c.getAttribute('data-policy-slug') === slug) c.classList.add('selected');
|
||||
const isMatch = c.getAttribute('data-policy-slug') === slug;
|
||||
if (isMatch) c.classList.add('selected');
|
||||
else c.classList.remove('selected');
|
||||
const btn = c.querySelector('.tier-select-btn');
|
||||
if (btn) btn.textContent = isMatch ? 'Selected' : 'Select';
|
||||
}});
|
||||
// Reset any active discount apply state — a different tier may not
|
||||
// honor the same code (server validates again on the next Apply).
|
||||
|
||||
Reference in New Issue
Block a user