Add files via upload

This commit is contained in:
James 2025-10-06 01:07:06 -07:00 committed by GitHub
parent b1a8bd7d6d
commit 4a49e7e18b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 209 additions and 331 deletions

View File

@ -338,10 +338,7 @@
<div class="wrap">
<div class="row">
<h1>BESTWCOAST Shop</h1>
<a class="cart-btn"
href="#"
id="loginDiscord"
data-client-id="1423370765578797126">Login to our Discord</a>
<a class="cart-btn" href="https://discord.gg/kQrAQSSrez" id="loginDiscord">Login to our Discord</a>
<span id="whoami" class="muted"></span>
<div class="spacer"></div>
<nav class="links" aria-label="Primary">
@ -375,64 +372,6 @@
<section id="grid" class="grid"></section>
</div>
</main>
<script>
const API = "https://affiliated-lets-automatic-oak.trycloudflare.com"; // unchanged
// ---- whoami banner (unchanged logic) ----
async function getWhoAmI() {
try {
const r = await fetch(`${API}/api/inventory`, { credentials: 'include' });
if (!r.ok) return null;
const j = await r.json();
const u = j?.user ?? j;
const label = u?.global_name ?? u?.username ?? (u?.id ? `User ${u.id}` : null);
return label ? { label, raw: u } : null;
} catch { return null; }
}
(async () => {
const who = await getWhoAmI();
document.getElementById('whoami').textContent =
who ? `Signed in as ${who.label}` : 'Not signed in';
})();
// ---- FIXED Discord login button ----
document.getElementById('loginDiscord').addEventListener('click', async (e) => {
e.preventDefault();
const backTo = encodeURIComponent(location.href);
const clientId = document.getElementById('loginDiscord').dataset.clientId;
const backendStart = `${API}/api/auth/discord?redirect=${backTo}`;
const callback = encodeURIComponent(`${API}/api/auth/discord/callback`);
const direct = `https://discord.com/oauth2/authorize?client_id=${clientId}&redirect_uri=${callback}&response_type=code&scope=identify`;
try {
// If backend is reachable, use the backend start route
const ping = await fetch(`${API}/healthz`, { mode: 'no-cors' }).catch(() => null);
// no-cors fetch wont throw on 200, but if DNS/route fails we hit catch above
location.href = backendStart;
} catch {
// Fallback: go straight to Discords authorize page
location.href = direct;
}
});
</script>
<script>
document.getElementById('checkoutBtn').addEventListener('click', async (e) => {
e.preventDefault();
const entries = Object.entries(state.cart || {});
if (!entries.length) return alert('Your cart is empty.');
alert("⚠️ IMPORTANT: After checkout, you must contact a team member to receive your order.\n\nPlease open a ticket in Discord once payment is complete.");
const items = entries.map(([id, qty]) => {
const p = products.find(p => p.id === id);
return { id, name: p?.name || id, qty: Number(qty || 1), price: p?.price || 0 };
});
await checkout(items);
});
</script>
<!-- Drawer (Cart) -->
<aside id="drawer" aria-hidden="true">
@ -528,45 +467,18 @@
let remaining = 12;
/* ===== Login banner (whoami) ===== */
/* ===== Login banner (whoami) + Discord OAuth ===== */
async function getWhoAmI() {
try {
// inventory endpoint should set/return session if already logged in
const r = await fetch(`${API}/api/inventory`, { credentials: 'include' });
const r = await fetch(`${API}/api/inventory`, { credentials: 'include' })
if (!r.ok) return null;
const j = await r.json();
// Some backends return user data nested (e.g., { user: {...} })
const u = j?.user ?? j;
// Prefer global_name, fall back to username, then to Discord ID
const label =
u?.global_name ??
u?.username ??
(u?.id ? `User ${u.id}` : null);
return label ? { label, raw: u } : null;
} catch {
return null;
return await r.json();
} catch { return null; }
}
}
// Show status next to the button
(async () => {
const who = await getWhoAmI();
document.getElementById('whoami').textContent =
who ? `Signed in as ${who.label}` : 'Not signed in';
})();
// Clicking the button should start Discord OAuth on your server.
// Adjust the path if your backend uses a different route.
document.getElementById('loginDiscord').addEventListener('click', (e) => {
e.preventDefault();
const redirect = encodeURIComponent(location.href);
location.href = `${API}/api/auth/discord?redirect=${redirect}`;
getWhoAmI().then(u => {
if (u) document.getElementById('whoami').textContent =
`Signed in as ${u.global_name || u.username}`;
});
/* ===== Products (unique IDs) ===== */
const products = [
{ id: 'server1', name: 'Server Class 1', price: 25.00, category: 'servers', tag: 'Server monthly', img: 'img/PrivateServerCLASS01.png'},
@ -768,68 +680,34 @@
async function checkout(cart) {
let user = null;
try {
const r = await fetch(`${API}/api/inventory`, { credentials: 'include' });
if (r.ok) user = await r.json();
} catch { }
// reserve
// 1) reserve
const r1 = await fetch(`${API}/api/reserve`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ items: cart, user })
body: JSON.stringify({ items: cart })
});
const j1 = await r1.json();
if (!j1.ok) { alert(j1.error || 'reserve failed'); return; }
// create checkout with Discord user
// 2) create checkout
const r2 = await fetch(`${API}/api/create-checkout`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
resKey: j1.resKey,
items: [],
discordUser: user, // <— this flows to metadata
success_url: location.origin + location.pathname + '?ok=1',
cancel_url: location.origin + location.pathname + '?cancel=1'
})
});
const j2 = await r2.json();
if (!j2.url) { alert(j2.error || 'create-checkout failed'); return; }
location.href = j2.url;
location.href = j2.url; // redirect to Stripe
}
// Single, unified checkout click handler (shows warning, then proceeds)
document.getElementById('checkoutBtn').addEventListener('click', async (e) => {
e.preventDefault();
const entries = Object.entries(state.cart || {});
if (!entries.length) return alert('Your cart is empty.');
alert("⚠️ IMPORTANT: After checkout, you must contact a team member to receive your order.\n\nPlease open a ticket in Discord once payment is complete.");
const items = entries.map(([id, qty]) => {
const p = products.find(p => p.id === id);
return { id, name: p?.name || id, qty: Number(qty || 1), price: p?.price || 0 };
});
await checkout(items);
});
// === Checkout warning ===
document.getElementById('checkoutBtn').addEventListener('click', (e) => {
e.preventDefault();
alert("⚠️ IMPORTANT: After checkout, you must contact a team member to receive your order.\n\nPlease open a ticket in Discord once payment is complete.");
});
document.getElementById('checkoutBtn').addEventListener('click', async () => {
const entries = Object.entries(state.cart || {});
if (!entries.length) return alert('Your cart is empty.');
alert("⚠️ IMPORTANT: After checkout, you must contact a team member to receive your order.\n\nPlease open a ticket in Discord once payment is complete.");
const items = entries.map(([id, qty]) => {
const p = products.find(p => p.id === id);
return { id, name: p?.name || id, qty: Number(qty || 1), price: p?.price || 0 };