Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 166 additions & 0 deletions app.css
Original file line number Diff line number Diff line change
Expand Up @@ -3891,3 +3891,169 @@ footer a:hover { color: var(--accent-2); }
.ticket-number { transform: none; margin-bottom: 0; }
.ticket-admit { border-top: none; border-left: 1px solid #e0e0e0; padding-top: 0; padding-left: .5rem; width: auto; }
}

/* ── ORDER (confirmation email card) ── */
.card.order-card {
background: var(--card);
border-radius: var(--radius);
}
.card.order-card .hd.hidden { display: none; }

.order-conf-header {
text-align: center;
padding: 2rem 1.5rem 1.2rem;
}

.order-check {
display: inline-flex;
align-items: center;
justify-content: center;
width: 56px;
height: 56px;
border-radius: 50%;
background: #16a34a;
color: #fff;
font-size: 1.6rem;
font-weight: 700;
line-height: 1;
margin-bottom: .8rem;
box-shadow: 0 0 0 6px rgba(22,163,74,.15);
animation: order-pop .4s ease-out;
}
@keyframes order-pop {
0% { transform: scale(0); opacity: 0; }
60% { transform: scale(1.15); }
100% { transform: scale(1); opacity: 1; }
}

.order-conf-label {
font-size: 1.35rem;
font-weight: 700;
color: var(--ink);
letter-spacing: -.01em;
margin-bottom: .25rem;
}

.order-conf-name {
font-size: .9rem;
color: var(--muted);
font-weight: 500;
}

.order-number-chip {
text-align: center;
margin: .8rem auto;
display: inline-block;
font-family: var(--mono);
font-size: .82rem;
background: var(--surface);
border: 1px solid var(--line);
padding: .35rem .9rem;
border-radius: 6px;
color: var(--ink-2);
letter-spacing: .02em;
width: 100%;
box-sizing: border-box;
display: block;
}

.order-status-pill {
text-align: center;
margin: .6rem 0 1rem;
}
.order-status-pill span,
.order-status-pill {
display: inline-block;
font-size: .75rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: .04em;
padding: .3rem .85rem;
border-radius: 100px;
line-height: 1.4;
}
.order-status-amber {
background: #fef3c7;
color: #92400e;
}
.order-status-green {
background: #dcfce7;
color: #166534;
}
.order-status-red {
background: #fee2e2;
color: #991b1b;
}

.order-summary-box {
background: var(--surface);
border: 1px solid var(--line);
border-radius: var(--radius-sm);
padding: 1rem 1.2rem;
margin: .4rem 0;
}

.order-summary-row {
display: flex;
justify-content: space-between;
align-items: baseline;
padding: .45rem 0;
}
.order-summary-row + .order-summary-row {
border-top: 1px solid var(--line-2);
}

.order-summary-label {
font-size: .82rem;
color: var(--muted);
font-weight: 500;
}

.order-summary-value {
font-size: .88rem;
color: var(--ink);
font-weight: 600;
}

.order-note {
font-size: .85rem;
color: var(--muted);
line-height: 1.55;
padding: .8rem 0;
border-top: 1px solid var(--line-2);
margin-top: .6rem;
}

.order-cta {
display: flex;
align-items: center;
justify-content: center;
gap: .4rem;
margin-top: 1.2rem;
padding: .75rem 1.5rem;
background: var(--accent);
color: #fff;
font-weight: 600;
font-size: .92rem;
border-radius: 10px;
text-decoration: none;
transition: background .15s, transform .1s;
}
.order-cta:hover {
filter: brightness(1.08);
transform: translateY(-1px);
}
.order-cta-arrow {
font-size: 1.1em;
transition: transform .15s;
}
.order-cta:hover .order-cta-arrow {
transform: translateX(3px);
}

@media (max-width: 480px) {
.order-conf-header { padding: 1.4rem 1rem .8rem; }
.order-check { width: 46px; height: 46px; font-size: 1.3rem; }
.order-conf-label { font-size: 1.15rem; }
.order-summary-box { padding: .8rem; }
}
100 changes: 100 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -2426,6 +2426,106 @@
handled.add("expectedArrivalUntil"); handled.add("itemShipped"); handled.add("deliveryAddress");
}

// ── ORDER (confirmation email card) ──
if (cfg.type === "Order") {
const card = document.querySelector(".card");
if (card) card.classList.add("order-card");

// Hide normal header
const hd = document.querySelector(".hd");
if (hd) hd.classList.add("hidden");

// Remove generic hero if present
const heroMount = document.getElementById("hero-mount");
if (heroMount) heroMount.querySelector('.hero')?.remove();

// ── Confirmation header: big checkmark + title ──
const confHeader = document.createElement("div"); confHeader.className = "order-conf-header";

// Animated checkmark circle
const checkCircle = document.createElement("div"); checkCircle.className = "order-check";
checkCircle.innerHTML = "\u2713";
confHeader.appendChild(checkCircle);

// "Order Confirmed" label
const confLabel = document.createElement("div"); confLabel.className = "order-conf-label";
confLabel.textContent = "Order Confirmed";
confHeader.appendChild(confLabel);

// Order name as subtitle
const orderName = data["name"];
if (orderName) {
const nameEl = document.createElement("div"); nameEl.className = "order-conf-name";
nameEl.textContent = orderName;
confHeader.appendChild(nameEl);
}

view.appendChild(confHeader);

// ── Order number chip (monospace) ──
const orderNum = data["orderNumber"];
if (orderNum) {
const chip = document.createElement("div"); chip.className = "order-number-chip";
chip.textContent = orderNum;
view.appendChild(chip);
}

// ── Status pill ──
const status = data["orderStatus"];
if (status) {
const pill = document.createElement("div"); pill.className = "order-status-pill";
// Extract short label from URL like https://schema.org/OrderProcessing
const shortStatus = status.split("/").pop().replace("Order", "");
pill.textContent = shortStatus;
// Color by status
if (status.includes("Delivered") || status.includes("Complete")) pill.classList.add("order-status-green");
else if (status.includes("Cancelled")) pill.classList.add("order-status-red");
else pill.classList.add("order-status-amber");
view.appendChild(pill);
}

// ── Summary box: seller + date ──
const summaryBox = document.createElement("div"); summaryBox.className = "order-summary-box";

const seller = data["seller"];
if (seller) {
const row = document.createElement("div"); row.className = "order-summary-row";
row.innerHTML = "<span class=\"order-summary-label\">Seller</span><span class=\"order-summary-value\">" + seller + "</span>";
summaryBox.appendChild(row);
}

const orderDate = data["orderDate"];
if (orderDate) {
const d = formatDate(orderDate);
const row = document.createElement("div"); row.className = "order-summary-row";
row.innerHTML = "<span class=\"order-summary-label\">Date</span><span class=\"order-summary-value\">" + (d || orderDate) + "</span>";
summaryBox.appendChild(row);
}

if (summaryBox.children.length) view.appendChild(summaryBox);

// Description as a note
const desc = data["description"];
if (desc) {
const note = document.createElement("div"); note.className = "order-note";
note.textContent = desc;
view.appendChild(note);
}

// Track Order CTA
const url = data["url"];
if (url) {
const cta = document.createElement("a"); cta.className = "order-cta";
cta.href = url; cta.target = "_blank"; cta.rel = "noopener";
cta.innerHTML = "<span class=\"order-cta-text\">Track Order</span><span class=\"order-cta-arrow\">\u2192</span>";
view.appendChild(cta);
}

handled.add("name"); handled.add("image"); handled.add("description");
handled.add("orderNumber"); handled.add("orderStatus"); handled.add("orderDate");
handled.add("seller"); handled.add("url");
}

// ── QUESTION (Stack Overflow Q&A card) ──
if (cfg.type === "Question") {
const card = document.querySelector(".card");
Expand Down
Loading