Add templates/acheivments/achievement_sample1_input.html
This commit is contained in:
parent
6a49256399
commit
d54bd3fa1d
726
templates/acheivments/achievement_sample1_input.html
Normal file
726
templates/acheivments/achievement_sample1_input.html
Normal file
@ -0,0 +1,726 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>Create ETA Achievement Input</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--bg: #050816;
|
||||||
|
--panel: rgba(15, 23, 42, 0.96);
|
||||||
|
--border: rgba(148, 163, 184, 0.65);
|
||||||
|
--accent: #ffb800;
|
||||||
|
--accent-soft: rgba(255, 184, 0, 0.16);
|
||||||
|
--text: #f9fafb;
|
||||||
|
--muted: #9ca3af;
|
||||||
|
--radius: 18px;
|
||||||
|
}
|
||||||
|
* { box-sizing: border-box; }
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding: 24px 12px 32px;
|
||||||
|
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||||
|
background: radial-gradient(circle at top, #111827 0, #050816 55%, #020308 100%);
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
.wrap {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 1120px;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
|
||||||
|
gap: 18px;
|
||||||
|
}
|
||||||
|
@media (max-width: 960px) {
|
||||||
|
.wrap { grid-template-columns: minmax(0, 1fr); }
|
||||||
|
}
|
||||||
|
.panel {
|
||||||
|
background: var(--panel);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
box-shadow: 0 18px 48px rgba(15, 23, 42, 0.9);
|
||||||
|
padding: 14px 16px 16px;
|
||||||
|
}
|
||||||
|
.panel-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.panel-title {
|
||||||
|
font-size: 0.82rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.18em;
|
||||||
|
color: var(--muted);
|
||||||
|
}
|
||||||
|
.panel-subtitle {
|
||||||
|
font-size: 1.08rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.tag {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
padding: 3px 9px;
|
||||||
|
border-radius: 999px;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.15em;
|
||||||
|
color: var(--muted);
|
||||||
|
}
|
||||||
|
form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
font-size: 0.86rem;
|
||||||
|
}
|
||||||
|
.field-group { display: flex; flex-direction: column; gap: 4px; }
|
||||||
|
.field-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
.field-row { grid-template-columns: minmax(0, 1fr); }
|
||||||
|
}
|
||||||
|
label.field-label {
|
||||||
|
font-size: 0.78rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.16em;
|
||||||
|
color: var(--muted);
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.field-label span.hint {
|
||||||
|
font-size: 0.7rem;
|
||||||
|
color: var(--muted);
|
||||||
|
text-transform: none;
|
||||||
|
letter-spacing: normal;
|
||||||
|
}
|
||||||
|
.input,
|
||||||
|
.textarea {
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 999px;
|
||||||
|
border: 1px solid rgba(55, 65, 81, 1);
|
||||||
|
background: rgba(15, 23, 42, 0.96);
|
||||||
|
color: var(--text);
|
||||||
|
padding: 7px 11px;
|
||||||
|
font-size: 0.86rem;
|
||||||
|
outline: none;
|
||||||
|
transition: border-color 0.14s ease-out, box-shadow 0.14s ease-out, background 0.14s ease-out;
|
||||||
|
}
|
||||||
|
.textarea {
|
||||||
|
border-radius: 14px;
|
||||||
|
min-height: 80px;
|
||||||
|
resize: vertical;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
.input:focus,
|
||||||
|
.textarea:focus {
|
||||||
|
border-color: var(--accent);
|
||||||
|
box-shadow: 0 0 0 1px rgba(255, 184, 0, 0.45);
|
||||||
|
background: rgba(15, 23, 42, 0.99);
|
||||||
|
}
|
||||||
|
.input::placeholder,
|
||||||
|
.textarea::placeholder {
|
||||||
|
color: rgba(148, 163, 184, 0.7);
|
||||||
|
}
|
||||||
|
.pill-row { display: flex; flex-wrap: wrap; gap: 6px; }
|
||||||
|
.pill {
|
||||||
|
font-size: 0.74rem;
|
||||||
|
padding: 4px 9px;
|
||||||
|
border-radius: 999px;
|
||||||
|
border: 1px solid rgba(55, 65, 81, 1);
|
||||||
|
background: rgba(15, 23, 42, 0.96);
|
||||||
|
color: var(--muted);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.pill.is-active {
|
||||||
|
border-color: var(--accent);
|
||||||
|
background: var(--accent-soft);
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
.medal-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
.medal-input {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 6px 9px;
|
||||||
|
border-radius: 14px;
|
||||||
|
border: 1px solid rgba(55, 65, 81, 1);
|
||||||
|
background: rgba(15, 23, 42, 0.98);
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
.medal-input span.badge {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 999px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 0.78rem;
|
||||||
|
}
|
||||||
|
.medal-gold span.badge {
|
||||||
|
background: linear-gradient(135deg, #facc15, #f97316);
|
||||||
|
color: #111827;
|
||||||
|
}
|
||||||
|
.medal-silver span.badge {
|
||||||
|
background: linear-gradient(135deg, #e5e7eb, #9ca3af);
|
||||||
|
color: #020617;
|
||||||
|
}
|
||||||
|
.medal-bronze span.badge {
|
||||||
|
background: linear-gradient(135deg, #f97316, #b45309);
|
||||||
|
color: #020617;
|
||||||
|
}
|
||||||
|
.medal-input input {
|
||||||
|
width: 100%;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--text);
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
.medal-input input::-webkit-outer-spin-button,
|
||||||
|
.medal-input input::-webkit-inner-spin-button {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.medal-input input[type="number"] { -moz-appearance: textfield; }
|
||||||
|
|
||||||
|
.chips-input {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 5px 6px;
|
||||||
|
border-radius: 16px;
|
||||||
|
border: 1px dashed rgba(75, 85, 99, 1);
|
||||||
|
background: rgba(15, 23, 42, 0.8);
|
||||||
|
}
|
||||||
|
.chip-token {
|
||||||
|
font-size: 0.74rem;
|
||||||
|
padding: 3px 8px;
|
||||||
|
border-radius: 999px;
|
||||||
|
border: 1px solid rgba(148, 163, 184, 0.8);
|
||||||
|
background: rgba(15, 23, 42, 0.96);
|
||||||
|
}
|
||||||
|
.chip-input-field {
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--text);
|
||||||
|
font-size: 0.82rem;
|
||||||
|
padding: 3px 4px;
|
||||||
|
min-width: 80px;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.athletes-list { display: flex; flex-direction: column; gap: 6px; }
|
||||||
|
.athlete-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 0.35fr 0.65fr;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
.athlete-row .input { border-radius: 12px; padding: 6px 9px; }
|
||||||
|
.field-note {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: var(--muted);
|
||||||
|
}
|
||||||
|
.footer-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
.btn-row { display: flex; align-items: center; gap: 8px; }
|
||||||
|
.btn {
|
||||||
|
border-radius: 999px;
|
||||||
|
font-size: 0.82rem;
|
||||||
|
padding: 7px 14px;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
background: rgba(15, 23, 42, 0.96);
|
||||||
|
color: var(--text);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.btn-primary {
|
||||||
|
background: linear-gradient(135deg, var(--accent), #fb923c);
|
||||||
|
border-color: transparent;
|
||||||
|
color: #111827;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-card {
|
||||||
|
position: relative;
|
||||||
|
border-radius: 18px;
|
||||||
|
padding: 12px 14px;
|
||||||
|
background: radial-gradient(circle at top left, #1e293b, #020617 55%);
|
||||||
|
border: 1px solid rgba(148, 163, 184, 0.4);
|
||||||
|
min-height: 120px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.preview-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 8px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
.preview-eyebrow {
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.18em;
|
||||||
|
color: var(--muted);
|
||||||
|
font-size: 0.72rem;
|
||||||
|
}
|
||||||
|
.preview-medals {
|
||||||
|
font-size: 0.78rem;
|
||||||
|
padding: 2px 10px;
|
||||||
|
border-radius: 999px;
|
||||||
|
border: 1px solid rgba(250, 204, 21, 0.9);
|
||||||
|
background: var(--accent-soft);
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
.preview-title {
|
||||||
|
margin: 0 0 3px;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.preview-meta {
|
||||||
|
margin: 0 0 8px;
|
||||||
|
font-size: 0.78rem;
|
||||||
|
color: var(--muted);
|
||||||
|
}
|
||||||
|
.preview-footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
font-size: 0.76rem;
|
||||||
|
}
|
||||||
|
.preview-avatars { display: flex; }
|
||||||
|
.preview-avatar {
|
||||||
|
width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
border-radius: 999px;
|
||||||
|
border: 2px solid #020617;
|
||||||
|
background: linear-gradient(135deg, #f97316, #ec4899);
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 0.7rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #020617;
|
||||||
|
margin-left: -7px;
|
||||||
|
}
|
||||||
|
.preview-avatar:first-child { margin-left: 0; }
|
||||||
|
.preview-cta {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="wrap">
|
||||||
|
<section class="panel">
|
||||||
|
<header class="panel-header">
|
||||||
|
<div>
|
||||||
|
<div class="panel-title">Achievement input</div>
|
||||||
|
<div class="panel-subtitle">Define card + detail data</div>
|
||||||
|
</div>
|
||||||
|
<span class="tag">JSON Output</span>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<form id="achievement-form">
|
||||||
|
<div class="field-group">
|
||||||
|
<label class="field-label">
|
||||||
|
ID / slug
|
||||||
|
<span class="hint">Used in data-achievement-id</span>
|
||||||
|
</label>
|
||||||
|
<input class="input" id="field-id" placeholder="thailand-2023" required />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field-group">
|
||||||
|
<label class="field-label">
|
||||||
|
Title
|
||||||
|
<span class="hint">Detail title</span>
|
||||||
|
</label>
|
||||||
|
<input class="input" id="field-title" placeholder="Thailand Open Championships 2023" required />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field-row">
|
||||||
|
<div class="field-group">
|
||||||
|
<label class="field-label">
|
||||||
|
Short title
|
||||||
|
<span class="hint">Card title</span>
|
||||||
|
</label>
|
||||||
|
<input class="input" id="field-short-title" placeholder="Thailand Open Championships" />
|
||||||
|
</div>
|
||||||
|
<div class="field-group">
|
||||||
|
<label class="field-label">
|
||||||
|
Type icon
|
||||||
|
<span class="hint">🏆 / 🥋 / ⭐</span>
|
||||||
|
</label>
|
||||||
|
<input class="input" id="field-type-icon" placeholder="🏆" maxlength="4" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field-row">
|
||||||
|
<div class="field-group">
|
||||||
|
<label class="field-label">
|
||||||
|
Location
|
||||||
|
<span class="hint">City, Country</span>
|
||||||
|
</label>
|
||||||
|
<input class="input" id="field-location" placeholder="Bangkok, Thailand" required />
|
||||||
|
</div>
|
||||||
|
<div class="field-group">
|
||||||
|
<label class="field-label">
|
||||||
|
Date label
|
||||||
|
<span class="hint">Card label</span>
|
||||||
|
</label>
|
||||||
|
<input class="input" id="field-date-label" placeholder="Nov 2023" required />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field-group">
|
||||||
|
<label class="field-label">
|
||||||
|
Full date
|
||||||
|
<span class="hint">Detail header</span>
|
||||||
|
</label>
|
||||||
|
<input class="input" id="field-date-full" placeholder="November 2023" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field-group">
|
||||||
|
<label class="field-label">
|
||||||
|
Image URL
|
||||||
|
<span class="hint">Card + detail cover</span>
|
||||||
|
</label>
|
||||||
|
<input class="input" id="field-image" placeholder="https://images.pexels.com/..." />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field-group">
|
||||||
|
<label class="field-label">
|
||||||
|
Medals
|
||||||
|
<span class="hint">Numbers only</span>
|
||||||
|
</label>
|
||||||
|
<div class="medal-row">
|
||||||
|
<div class="medal-input medal-gold">
|
||||||
|
<span class="badge">🥇</span>
|
||||||
|
<input type="number" min="0" id="field-gold" placeholder="1" />
|
||||||
|
</div>
|
||||||
|
<div class="medal-input medal-silver">
|
||||||
|
<span class="badge">🥈</span>
|
||||||
|
<input type="number" min="0" id="field-silver" placeholder="3" />
|
||||||
|
</div>
|
||||||
|
<div class="medal-input medal-bronze">
|
||||||
|
<span class="badge">🥉</span>
|
||||||
|
<input type="number" min="0" id="field-bronze" placeholder="0" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field-row">
|
||||||
|
<div class="field-group">
|
||||||
|
<label class="field-label">
|
||||||
|
Total bouts
|
||||||
|
</label>
|
||||||
|
<input type="number" min="0" class="input" id="field-bouts" placeholder="6" />
|
||||||
|
</div>
|
||||||
|
<div class="field-group">
|
||||||
|
<label class="field-label">
|
||||||
|
Wins
|
||||||
|
</label>
|
||||||
|
<input type="number" min="0" class="input" id="field-wins" placeholder="4" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field-group">
|
||||||
|
<label class="field-label">
|
||||||
|
Category
|
||||||
|
<span class="hint">Detail meta</span>
|
||||||
|
</label>
|
||||||
|
<input class="input" id="field-category" placeholder="World Taekwondo G2 Event" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field-group">
|
||||||
|
<label class="field-label">
|
||||||
|
Story
|
||||||
|
<span class="hint">Detail description</span>
|
||||||
|
</label>
|
||||||
|
<textarea class="textarea" id="field-story" placeholder="Under the leadership of Grand Master Sami Al Manai, ..."></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field-group">
|
||||||
|
<label class="field-label">
|
||||||
|
Chips
|
||||||
|
<span class="hint">Enter + press comma or Enter</span>
|
||||||
|
</label>
|
||||||
|
<div class="chips-input" id="chips-wrapper">
|
||||||
|
<input class="chip-input-field" id="chip-input" placeholder="World Ranking Points" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field-group">
|
||||||
|
<label class="field-label">
|
||||||
|
Athletes
|
||||||
|
<span class="hint">Used for avatars + detail list</span>
|
||||||
|
</label>
|
||||||
|
<div class="athletes-list" id="athletes-list">
|
||||||
|
<div class="athlete-row">
|
||||||
|
<input class="input" id="ath-name-1" placeholder="Hanan" />
|
||||||
|
<input class="input" id="ath-role-1" placeholder="Senior Poomsae • Gold" />
|
||||||
|
</div>
|
||||||
|
<div class="athlete-row">
|
||||||
|
<input class="input" id="ath-name-2" placeholder="Asmahan" />
|
||||||
|
<input class="input" id="ath-role-2" placeholder="Kyorugi -49kg • Silver" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer-row">
|
||||||
|
<span class="field-note">Add up to 4 athletes; initials appear on the card.</span>
|
||||||
|
<div class="btn-row">
|
||||||
|
<button type="button" class="btn" id="btn-add-athlete">+ Athlete</button>
|
||||||
|
<button type="button" class="btn" id="btn-clear-athletes">Clear</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer-row">
|
||||||
|
<span class="field-note">Submit to send this payload to your backend.</span>
|
||||||
|
<div class="btn-row">
|
||||||
|
<button type="reset" class="btn">Reset</button>
|
||||||
|
<button type="submit" class="btn btn-primary">Generate payload</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="panel">
|
||||||
|
<header class="panel-header">
|
||||||
|
<div>
|
||||||
|
<div class="panel-title">Card preview</div>
|
||||||
|
<div class="panel-subtitle">How it will render</div>
|
||||||
|
</div>
|
||||||
|
<span class="tag">Read-only</span>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<article class="preview-card">
|
||||||
|
<div class="preview-header">
|
||||||
|
<span class="preview-eyebrow" id="preview-type">International</span>
|
||||||
|
<span class="preview-medals" id="preview-medals">🥇 0 • 🥈 0 • 🥉 0</span>
|
||||||
|
</div>
|
||||||
|
<h3 class="preview-title" id="preview-title">Achievement title</h3>
|
||||||
|
<p class="preview-meta" id="preview-meta">Location • Date label</p>
|
||||||
|
|
||||||
|
<div class="preview-footer">
|
||||||
|
<div class="preview-avatars" id="preview-avatars"></div>
|
||||||
|
<div class="preview-cta">
|
||||||
|
<span>Tap to view story</span>
|
||||||
|
<span>↗</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<pre id="payload-output" style="margin-top:12px;font-size:0.75rem;background:#020617;border-radius:12px;border:1px solid rgba(55,65,81,1);padding:8px 10px;white-space:pre-wrap;word-break:break-word;"></pre>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const titleEl = document.getElementById("field-title");
|
||||||
|
const shortTitleEl = document.getElementById("field-short-title");
|
||||||
|
const locationEl = document.getElementById("field-location");
|
||||||
|
const dateLabelEl = document.getElementById("field-date-label");
|
||||||
|
const goldEl = document.getElementById("field-gold");
|
||||||
|
const silverEl = document.getElementById("field-silver");
|
||||||
|
const bronzeEl = document.getElementById("field-bronze");
|
||||||
|
const athletesList = document.getElementById("athletes-list");
|
||||||
|
const addAthleteBtn = document.getElementById("btn-add-athlete");
|
||||||
|
const clearAthletesBtn = document.getElementById("btn-clear-athletes");
|
||||||
|
const chipWrapper = document.getElementById("chips-wrapper");
|
||||||
|
const chipInput = document.getElementById("chip-input");
|
||||||
|
const previewType = document.getElementById("preview-type");
|
||||||
|
const previewMedals = document.getElementById("preview-medals");
|
||||||
|
const previewTitle = document.getElementById("preview-title");
|
||||||
|
const previewMeta = document.getElementById("preview-meta");
|
||||||
|
const previewAvatars = document.getElementById("preview-avatars");
|
||||||
|
const payloadOutput = document.getElementById("payload-output");
|
||||||
|
|
||||||
|
function updatePreviewText() {
|
||||||
|
const title = titleEl.value.trim() || "Achievement title";
|
||||||
|
const shortTitle = shortTitleEl.value.trim() || title;
|
||||||
|
const loc = locationEl.value.trim() || "Location";
|
||||||
|
const dateLabel = dateLabelEl.value.trim() || "Date";
|
||||||
|
previewTitle.textContent = shortTitle;
|
||||||
|
previewMeta.textContent = loc + " • " + dateLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updatePreviewMedals() {
|
||||||
|
const g = Number(goldEl.value || 0);
|
||||||
|
const s = Number(silverEl.value || 0);
|
||||||
|
const b = Number(bronzeEl.value || 0);
|
||||||
|
previewMedals.textContent = `🥇 ${g} • 🥈 ${s} • 🥉 ${b}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAthletes() {
|
||||||
|
const rows = athletesList.querySelectorAll(".athlete-row");
|
||||||
|
const result = [];
|
||||||
|
rows.forEach((row) => {
|
||||||
|
const n = row.querySelector("input[id^='ath-name']").value.trim();
|
||||||
|
const r = row.querySelector("input[id^='ath-role']").value.trim();
|
||||||
|
if (n || r) result.push({ name: n, role: r });
|
||||||
|
});
|
||||||
|
return result.slice(0, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
function initials(name) {
|
||||||
|
if (!name) return "?";
|
||||||
|
const parts = name.trim().split(/\s+/);
|
||||||
|
if (parts.length === 1) return parts[0][0]?.toUpperCase() || "?";
|
||||||
|
return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
function updatePreviewAvatars() {
|
||||||
|
const athletes = getAthletes();
|
||||||
|
previewAvatars.innerHTML = "";
|
||||||
|
athletes.forEach((a) => {
|
||||||
|
const span = document.createElement("span");
|
||||||
|
span.className = "preview-avatar";
|
||||||
|
span.textContent = initials(a.name);
|
||||||
|
previewAvatars.appendChild(span);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[titleEl, shortTitleEl, locationEl, dateLabelEl].forEach((el) =>
|
||||||
|
el.addEventListener("input", updatePreviewText)
|
||||||
|
);
|
||||||
|
[goldEl, silverEl, bronzeEl].forEach((el) =>
|
||||||
|
el.addEventListener("input", updatePreviewMedals)
|
||||||
|
);
|
||||||
|
|
||||||
|
function wireAthleteInputs() {
|
||||||
|
const nameInputs = athletesList.querySelectorAll("input[id^='ath-name']");
|
||||||
|
nameInputs.forEach((input) => {
|
||||||
|
input.removeEventListener("input", updatePreviewAvatars);
|
||||||
|
input.addEventListener("input", updatePreviewAvatars);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
addAthleteBtn.addEventListener("click", () => {
|
||||||
|
const rows = athletesList.querySelectorAll(".athlete-row").length;
|
||||||
|
if (rows >= 4) return;
|
||||||
|
const idx = rows + 1;
|
||||||
|
const row = document.createElement("div");
|
||||||
|
row.className = "athlete-row";
|
||||||
|
row.innerHTML = `
|
||||||
|
<input class="input" id="ath-name-${idx}" placeholder="Name" />
|
||||||
|
<input class="input" id="ath-role-${idx}" placeholder="Role • Result" />
|
||||||
|
`;
|
||||||
|
athletesList.appendChild(row);
|
||||||
|
wireAthleteInputs();
|
||||||
|
updatePreviewAvatars();
|
||||||
|
});
|
||||||
|
|
||||||
|
clearAthletesBtn.addEventListener("click", () => {
|
||||||
|
athletesList.innerHTML = "";
|
||||||
|
for (let i = 1; i <= 2; i++) {
|
||||||
|
const row = document.createElement("div");
|
||||||
|
row.className = "athlete-row";
|
||||||
|
row.innerHTML = `
|
||||||
|
<input class="input" id="ath-name-${i}" placeholder="Name" />
|
||||||
|
<input class="input" id="ath-role-${i}" placeholder="Role • Result" />
|
||||||
|
`;
|
||||||
|
athletesList.appendChild(row);
|
||||||
|
}
|
||||||
|
wireAthleteInputs();
|
||||||
|
updatePreviewAvatars();
|
||||||
|
});
|
||||||
|
|
||||||
|
wireAthleteInputs();
|
||||||
|
updatePreviewText();
|
||||||
|
updatePreviewMedals();
|
||||||
|
updatePreviewAvatars();
|
||||||
|
|
||||||
|
function readChips() {
|
||||||
|
const chips = [];
|
||||||
|
chipWrapper.querySelectorAll(".chip-token").forEach((token) => {
|
||||||
|
chips.push(token.dataset.value);
|
||||||
|
});
|
||||||
|
const pending = chipInput.value.trim();
|
||||||
|
if (pending) chips.push(pending);
|
||||||
|
return chips;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addChip(value) {
|
||||||
|
const v = value.trim();
|
||||||
|
if (!v) return;
|
||||||
|
const token = document.createElement("span");
|
||||||
|
token.className = "chip-token";
|
||||||
|
token.dataset.value = v;
|
||||||
|
token.textContent = v;
|
||||||
|
chipWrapper.insertBefore(token, chipInput);
|
||||||
|
}
|
||||||
|
|
||||||
|
chipInput.addEventListener("keydown", (e) => {
|
||||||
|
if (e.key === "Enter" || e.key === ",") {
|
||||||
|
e.preventDefault();
|
||||||
|
addChip(chipInput.value);
|
||||||
|
chipInput.value = "";
|
||||||
|
} else if (e.key === "Backspace" && !chipInput.value) {
|
||||||
|
const last = chipWrapper.querySelector(".chip-token:last-of-type");
|
||||||
|
if (last) chipWrapper.removeChild(last);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const form = document.getElementById("achievement-form");
|
||||||
|
form.addEventListener("submit", (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const id = document.getElementById("field-id").value.trim();
|
||||||
|
const title = titleEl.value.trim();
|
||||||
|
const shortTitle = shortTitleEl.value.trim() || title;
|
||||||
|
const loc = locationEl.value.trim();
|
||||||
|
const dateLabel = dateLabelEl.value.trim();
|
||||||
|
const dateFull = document.getElementById("field-date-full").value.trim() || dateLabel;
|
||||||
|
const image = document.getElementById("field-image").value.trim();
|
||||||
|
const typeIcon = document.getElementById("field-type-icon").value.trim() || "🏆";
|
||||||
|
const bouts = Number(document.getElementById("field-bouts").value || 0);
|
||||||
|
const wins = Number(document.getElementById("field-wins").value || 0);
|
||||||
|
const category = document.getElementById("field-category").value.trim();
|
||||||
|
const story = document.getElementById("field-story").value.trim();
|
||||||
|
const g = Number(goldEl.value || 0);
|
||||||
|
const s = Number(silverEl.value || 0);
|
||||||
|
const b = Number(bronzeEl.value || 0);
|
||||||
|
const medalsText = `${g} Gold • ${s} Silver${b ? ` • ${b} Bronze` : ""}`;
|
||||||
|
const athletes = getAthletes();
|
||||||
|
const chips = readChips();
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
id: id,
|
||||||
|
title: title,
|
||||||
|
short_title: shortTitle,
|
||||||
|
location: loc,
|
||||||
|
date_label: dateLabel,
|
||||||
|
date_full: dateFull,
|
||||||
|
image_url: image,
|
||||||
|
medal_summary: medalsText,
|
||||||
|
type_icon: typeIcon,
|
||||||
|
athletes_count: athletes.length,
|
||||||
|
bouts_count: bouts,
|
||||||
|
bouts_label: bouts && wins ? `${bouts} Bouts • ${wins} Wins` : "",
|
||||||
|
category: category,
|
||||||
|
story: story,
|
||||||
|
chips: chips,
|
||||||
|
athletes: athletes
|
||||||
|
};
|
||||||
|
|
||||||
|
payloadOutput.textContent = JSON.stringify(payload, null, 2);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
x
Reference in New Issue
Block a user