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
114 changes: 114 additions & 0 deletions app.css
Original file line number Diff line number Diff line change
Expand Up @@ -3489,6 +3489,120 @@ footer a:hover { color: var(--accent-2); }
.bp-desc { color: #666; }
}


/* ── Per-type bespoke: ParcelDelivery — tracking card ── */

.card.tracking-card { background: #fff; border-color: rgba(0,0,0,.08); }
.card.tracking-card .hd.hidden { display: none; }
.card.tracking-card .bd { padding: 0; background: #fff; }
.card.tracking-card .bd::before { display: none; }

/* Tracking number header */
.trk-head {
padding: 1.2rem 1.4rem;
background: #111;
color: #fff;
text-align: center;
}
.trk-label { font-size: .65rem; text-transform: uppercase; letter-spacing: .08em; color: #999; margin-bottom: .2rem; }
.trk-number { font-family: "SF Mono", "Fira Code", "Courier New", monospace; font-size: 1.6rem; font-weight: 700; letter-spacing: .06em; }
.trk-courier { font-size: .75rem; color: #aaa; margin-top: .25rem; }

/* Expected delivery */
.trk-expected {
text-align: center;
padding: 1rem 1.4rem .8rem;
}
.trk-exp-label { display: block; font-size: .65rem; text-transform: uppercase; letter-spacing: .06em; color: #999; margin-bottom: .2rem; }
.trk-exp-date { display: block; font-size: 1.3rem; font-weight: 700; color: #111; }
.trk-exp-time { display: block; font-size: .8rem; color: #888; margin-top: .1rem; }

/* Timeline */
.trk-timeline {
padding: .6rem 1.4rem 1rem;
}
.trk-step {
display: flex;
align-items: flex-start;
position: relative;
}
.trk-dot {
width: 32px;
height: 32px;
border-radius: 50%;
background: #f0f0f0;
color: #999;
display: flex;
align-items: center;
justify-content: center;
font-size: .75rem;
font-weight: 700;
flex-shrink: 0;
position: relative;
z-index: 1;
}
.trk-step.trk-done .trk-dot { background: #dcfce7; color: #15803d; font-size: .9rem; }
.trk-step.trk-current .trk-dot { background: #ea580c; color: #fff; font-size: .9rem; box-shadow: 0 0 0 3px rgba(234,88,12,.2); }

.trk-step-content {
flex: 1;
margin-left: .7rem;
padding-top: .3rem;
}
.trk-step-label { font-size: .85rem; font-weight: 600; color: #333; }
.trk-step.trk-current .trk-step-label { color: #ea580c; }
.trk-step:not(.trk-done):not(.trk-current) .trk-step-label { color: #bbb; }
.trk-step-detail { font-size: .72rem; color: #999; margin-top: .1rem; }

.trk-line {
position: absolute;
left: 15px;
top: 32px;
width: 2px;
height: calc(100% - 28px);
background: #e5e5e5;
}
.trk-line.trk-line-done { background: #15803d; }

/* Info rows */
.trk-info {
padding: .8rem 1.4rem 1.2rem;
border-top: 1px solid #eee;
}
.trk-info-row {
display: flex;
justify-content: space-between;
align-items: baseline;
font-size: .8rem;
color: #555;
padding: .25rem 0;
}
.trk-info-label { font-weight: 600; color: #888; font-size: .72rem; }
.trk-info-row span:last-child { text-align: right; max-width: 65%; }

/* Dark mode tracking */
@media (prefers-color-scheme: dark) {
.card.tracking-card { background: #1c1c1e; border-color: rgba(255,255,255,.06); }
.card.tracking-card .bd { background: #1c1c1e; }
.trk-head { background: #f5f5f5; color: #111; }
.trk-label { color: #666; }
.trk-courier { color: #555; }
.trk-exp-date { color: #f5f5f5; }
.trk-exp-time { color: #666; }
.trk-dot { background: #333; color: #666; }
.trk-step.trk-done .trk-dot { background: #064e3b; color: #6ee7b7; }
.trk-step.trk-current .trk-dot { background: #ea580c; box-shadow: 0 0 0 3px rgba(234,88,12,.3); }
.trk-step-label { color: #ccc; }
.trk-step.trk-current .trk-step-label { color: #fb923c; }
.trk-step:not(.trk-done):not(.trk-current) .trk-step-label { color: #444; }
.trk-step-detail { color: #555; }
.trk-line { background: #333; }
.trk-line.trk-line-done { background: #064e3b; }
.trk-info { border-top-color: #333; }
.trk-info-row { color: #aaa; }
.trk-info-label { color: #666; }
}

/* ──────────────────────────────────────────────
Responsive / Mobile — small-screen polish.
Stacks label/value grid, scales header,
Expand Down
76 changes: 76 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -2350,6 +2350,82 @@
handled.add("departureTime"); handled.add("arrivalTime");
}

// ── PARCEL DELIVERY (tracking card) ──
if (cfg.type === "ParcelDelivery") {
const card = document.querySelector(".card");
if (card) card.classList.add("tracking-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();

// Tracking number header
const trackHead = document.createElement("div"); trackHead.className = "trk-head";
const trackNum = data["trackingNumber"] || "";
const courier = data["provider"] || "";
trackHead.innerHTML = "<div class=\"trk-label\">Tracking Number</div><div class=\"trk-number\">" + trackNum + "</div><div class=\"trk-courier\">" + courier + "</div>";
view.appendChild(trackHead);

// Expected arrival — big date
const expected = data["expectedArrivalUntil"];
if (expected) {
const d = new Date(expected);
const formatted = isNaN(d.getTime()) ? expected : d.toLocaleDateString("en-GB", { weekday: "short", day: "numeric", month: "short", year: "numeric" });
const timeStr = isNaN(d.getTime()) ? "" : d.toLocaleTimeString("en-GB", { hour: "2-digit", minute: "2-digit" });
const expEl = document.createElement("div"); expEl.className = "trk-expected";
expEl.innerHTML = "<span class=\"trk-exp-label\">Estimated Delivery</span><span class=\"trk-exp-date\">" + formatted + "</span><span class=\"trk-exp-time\">by " + timeStr + "</span>";
view.appendChild(expEl);
}

// Vertical progress timeline
const timeline = document.createElement("div"); timeline.className = "trk-timeline";
const steps = [
{ label: "Dispatched", icon: "\u{1F4E6}", detail: "Alza.cz, Jirny" },
{ label: "In Transit", icon: "\u{1F69A}", detail: "Sorting hub, Plze\u0148" },
{ label: "Out for Delivery", icon: "\u{1F4EC}", detail: "Prague 2" },
{ label: "Delivered", icon: "\u2705", detail: "" }
];
const currentStep = 2; // "Out for delivery"
steps.forEach((step, i) => {
const row = document.createElement("div"); row.className = "trk-step";
if (i <= currentStep) row.classList.add("trk-done");
if (i === currentStep) row.classList.add("trk-current");
// Dot / check
const dot = document.createElement("div"); dot.className = "trk-dot";
if (i < currentStep) dot.innerHTML = "\u2705";
else if (i === currentStep) dot.innerHTML = step.icon;
else dot.textContent = (i + 1);
// Content
const content = document.createElement("div"); content.className = "trk-step-content";
content.innerHTML = "<div class=\"trk-step-label\">" + step.label + "</div>" + (step.detail ? "<div class=\"trk-step-detail\">" + step.detail + "</div>" : "");
// Line connector (not on last)
row.append(dot, content);
if (i < steps.length - 1) {
const line = document.createElement("div"); line.className = "trk-line";
if (i < currentStep) line.classList.add("trk-line-done");
row.appendChild(line);
}
timeline.appendChild(row);
});
view.appendChild(timeline);

// Bottom info: item + destination
const info = document.createElement("div"); info.className = "trk-info";
const item = data["itemShipped"] || "";
const addr = data["deliveryAddress"] || "";
if (item) info.innerHTML += "<div class=\"trk-info-row\"><span class=\"trk-info-label\">Item</span><span>" + item + "</span></div>";
if (addr) info.innerHTML += "<div class=\"trk-info-row\"><span class=\"trk-info-label\">Deliver to</span><span>" + addr + "</span></div>";
view.appendChild(info);

handled.add("name"); handled.add("image"); handled.add("description");
handled.add("trackingNumber"); handled.add("provider");
handled.add("expectedArrivalUntil"); handled.add("itemShipped"); handled.add("deliveryAddress");
}

return handled;
}

Expand Down
Loading