select
This commit is contained in:
@@ -872,7 +872,7 @@ function renderKeys(keys) {
|
|||||||
</div>
|
</div>
|
||||||
<button type="button" class="btn btn-ghost btn-sm"
|
<button type="button" class="btn btn-ghost btn-sm"
|
||||||
style="align-self:center"
|
style="align-self:center"
|
||||||
onclick="buyCredits('${escAttr(k.name)}', this)">
|
onclick="buyCredits('${escAttr(k.name)}')">
|
||||||
Buy Credits
|
Buy Credits
|
||||||
</button>
|
</button>
|
||||||
</div>`;
|
</div>`;
|
||||||
@@ -880,9 +880,31 @@ function renderKeys(keys) {
|
|||||||
.join("");
|
.join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
function buyCredits(keyName, btn) {
|
function buyCredits(keyName) {
|
||||||
btnLoad(btn, "Redirecting\u2026");
|
const backdrop = document.getElementById("credits-backdrop");
|
||||||
|
backdrop._keyName = keyName;
|
||||||
|
document.getElementById("credits-key-name").textContent = keyName;
|
||||||
|
// default to first option
|
||||||
|
const radios = backdrop.querySelectorAll('input[name="credits-amount"]');
|
||||||
|
radios.forEach((r, i) => (r.checked = i === 0));
|
||||||
|
backdrop.classList.add("open");
|
||||||
|
}
|
||||||
|
|
||||||
|
function buyCreditsClose() {
|
||||||
|
document.getElementById("credits-backdrop").classList.remove("open");
|
||||||
|
}
|
||||||
|
|
||||||
|
function buyCreditsSubmit() {
|
||||||
|
const backdrop = document.getElementById("credits-backdrop");
|
||||||
|
const selected = backdrop.querySelector(
|
||||||
|
'input[name="credits-amount"]:checked',
|
||||||
|
);
|
||||||
|
if (!selected) {
|
||||||
|
toast("Please select an amount.", "warning");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const keyName = backdrop._keyName;
|
||||||
const params = new URLSearchParams(window.location.search);
|
const params = new URLSearchParams(window.location.search);
|
||||||
const activeAgent = agents.find((a) => a.UUID === activeUUID);
|
const activeAgent = agents.find((a) => a.UUID === activeUUID);
|
||||||
const couponInput = document.getElementById("coupon-input");
|
const couponInput = document.getElementById("coupon-input");
|
||||||
@@ -891,6 +913,7 @@ function buyCredits(keyName, btn) {
|
|||||||
const fields = {
|
const fields = {
|
||||||
product: "prod_Ufj2wCf4rhemT8",
|
product: "prod_Ufj2wCf4rhemT8",
|
||||||
key: keyName || "",
|
key: keyName || "",
|
||||||
|
value: selected.value,
|
||||||
agent: activeUUID || "",
|
agent: activeUUID || "",
|
||||||
period: "",
|
period: "",
|
||||||
location: activeAgent?.server || "",
|
location: activeAgent?.server || "",
|
||||||
@@ -908,11 +931,11 @@ function buyCredits(keyName, btn) {
|
|||||||
form.action = CREDITS_URL;
|
form.action = CREDITS_URL;
|
||||||
form.target = "_self";
|
form.target = "_self";
|
||||||
|
|
||||||
for (const [name, value] of Object.entries(fields)) {
|
for (const [name, val] of Object.entries(fields)) {
|
||||||
const inp = document.createElement("input");
|
const inp = document.createElement("input");
|
||||||
inp.type = "hidden";
|
inp.type = "hidden";
|
||||||
inp.name = name;
|
inp.name = name;
|
||||||
inp.value = value;
|
inp.value = val;
|
||||||
form.appendChild(inp);
|
form.appendChild(inp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+75
@@ -875,6 +875,81 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- /app-shell -->
|
<!-- /app-shell -->
|
||||||
|
|
||||||
|
<!-- ═══════════════════════════════════════════════════════════
|
||||||
|
BUY CREDITS MODAL
|
||||||
|
════════════════════════════════════════════════════════════════ -->
|
||||||
|
<div id="credits-backdrop" class="modal-backdrop">
|
||||||
|
<div class="modal" style="max-width: 460px">
|
||||||
|
<div class="modal-header">
|
||||||
|
<span class="modal-title">Buy Credits</span>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p class="credits-key-label">
|
||||||
|
Credits will be assigned to key:
|
||||||
|
<span id="credits-key-name"></span>
|
||||||
|
</p>
|
||||||
|
<div class="credits-options">
|
||||||
|
<label class="credits-option">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="credits-amount"
|
||||||
|
value="5.50"
|
||||||
|
/>
|
||||||
|
<span class="credits-option-label"
|
||||||
|
>€ 5.50</span
|
||||||
|
>
|
||||||
|
</label>
|
||||||
|
<label class="credits-option">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="credits-amount"
|
||||||
|
value="11.00"
|
||||||
|
/>
|
||||||
|
<span class="credits-option-label"
|
||||||
|
>€ 11.00</span
|
||||||
|
>
|
||||||
|
</label>
|
||||||
|
<label class="credits-option">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="credits-amount"
|
||||||
|
value="22.00"
|
||||||
|
/>
|
||||||
|
<span class="credits-option-label"
|
||||||
|
>€ 22.00</span
|
||||||
|
>
|
||||||
|
</label>
|
||||||
|
<label class="credits-option">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="credits-amount"
|
||||||
|
value="55.00"
|
||||||
|
/>
|
||||||
|
<span class="credits-option-label"
|
||||||
|
>€ 55.00</span
|
||||||
|
>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<p class="credits-fee-note">
|
||||||
|
A 10% handling fee is added on top of the OpenRouter
|
||||||
|
credits value.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="btn btn-ghost" onclick="buyCreditsClose()">
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
id="credits-buy-btn"
|
||||||
|
class="btn btn-primary"
|
||||||
|
onclick="buyCreditsSubmit()"
|
||||||
|
>
|
||||||
|
Buy Credits
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- ═══════════════════════════════════════════════════════════
|
<!-- ═══════════════════════════════════════════════════════════
|
||||||
CONFIRM DIALOG
|
CONFIRM DIALOG
|
||||||
════════════════════════════════════════════════════════════════ -->
|
════════════════════════════════════════════════════════════════ -->
|
||||||
|
|||||||
+65
@@ -1438,6 +1438,71 @@ body::after {
|
|||||||
gap: 10px;
|
gap: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ─── Credits Modal ────────────────────────────────────────── */
|
||||||
|
.credits-key-label {
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--text-muted);
|
||||||
|
margin: 0 0 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.credits-key-label span {
|
||||||
|
color: var(--accent);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.credits-options {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.credits-option {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 11px 14px;
|
||||||
|
background: var(--bg-inner);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
cursor: pointer;
|
||||||
|
transition:
|
||||||
|
border-color 0.15s,
|
||||||
|
background 0.15s;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.credits-option:has(input:checked) {
|
||||||
|
border-color: var(--accent);
|
||||||
|
background: var(--accent-dim);
|
||||||
|
}
|
||||||
|
|
||||||
|
.credits-option input[type="radio"] {
|
||||||
|
accent-color: var(--accent);
|
||||||
|
width: 15px;
|
||||||
|
height: 15px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.credits-option-label {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text);
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.credits-fee-note {
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--text-muted);
|
||||||
|
line-height: 1.55;
|
||||||
|
background: var(--bg-inner);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
padding: 10px 12px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* ─── Utility ───────────────────────────────────────────────── */
|
/* ─── Utility ───────────────────────────────────────────────── */
|
||||||
.text-muted {
|
.text-muted {
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
|
|||||||
Reference in New Issue
Block a user