diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/css/styles.css b/css/styles.css new file mode 100644 index 0000000..1664c46 --- /dev/null +++ b/css/styles.css @@ -0,0 +1,334 @@ +:root{ + --bg:#f5f5f5; + --card:#ffffff; + --ink:#191b1d; + --muted:#8c9197; + --line:#ededed; + --green:#33c75e; + --green-strong:#2ecf71; + --green-text:#5c7d65; + --orange:#f87171; + --red:#f15a4f; + --navy:#04252b; + --ink2:#0a1112; + --track:#cdeac2; + --chip-border:#e4e4e4; +} + +*{box-sizing:border-box;-webkit-tap-highlight-color:transparent;} +html,body{margin:0;padding:0;height:100%;} +body{ + font-family:'Poppins',system-ui,-apple-system,Segoe UI,Roboto,sans-serif; + background:#e9e9ec; + color:var(--ink); + overflow:hidden; +} + +.app{ + position:relative; + width:100%; + max-width:440px; + height:100vh; + height:100dvh; + margin:0 auto; + background:var(--bg); + overflow:hidden; + box-shadow:0 0 40px rgba(0,0,0,.08); +} + +/* ---------- screens ---------- */ +.screen{ + position:absolute; + inset:0; + display:flex; + flex-direction:column; + opacity:0; + visibility:hidden; + transform:translateX(24px); + transition:opacity .42s ease, transform .42s ease, visibility .42s; + padding-top:env(safe-area-inset-top); +} +.screen.is-active{opacity:1;visibility:visible;transform:translateX(0);} +.screen.is-leaving{opacity:0;transform:translateX(-24px);} + +.page-head{padding:16px 20px 4px;} +.page-title{font-size:26px;font-weight:700;margin:0;letter-spacing:-.02rem;color:var(--ink2);} + +.content{flex:1;overflow-y:auto;padding:12px 16px 14px;} + +/* ---------- info card ---------- */ +.info-card{ + background:var(--card); + border-radius:16px; + padding:16px 14px 16px 18px; + display:flex; + align-items:center; + justify-content:space-between; + gap:10px; +} +.info-card__text{max-width:160px;} +.info-card__title{margin:0;font-weight:600;font-size:14px;line-height:1.25;color:var(--ink2);letter-spacing:-.02rem;} +.info-card__sub{margin:4px 0 0;font-size:12px;font-weight:500;color:var(--ink2);letter-spacing:-.02rem;} +.chip-btn{ + border:1px solid var(--chip-border); + background:#fff; + border-radius:13px; + padding:12px 22px; + font-family:inherit; + font-size:14px; + font-weight:500; + color:var(--ink2); + cursor:pointer; + white-space:nowrap; + letter-spacing:-.02rem; + transition:background .18s ease; +} +.chip-btn:active{background:#f4f4f4;} + +/* ---------- product list ---------- */ +.product-list{list-style:none;margin:14px 0 0;padding:0;display:flex;flex-direction:column;gap:10px;} +.product{ + background:var(--card); + border:1px solid #eaeaea; + border-radius:15px; + padding:10px 16px 10px 10px; + display:flex; + align-items:center; + gap:12px; + cursor:pointer; + transition:border-color .25s ease, box-shadow .25s ease, transform .25s ease; + animation:itemIn .45s cubic-bezier(.22,1,.36,1) both; + overflow:hidden; +} +@keyframes itemIn{0%{opacity:0;transform:translateY(14px) scale(.97);}100%{opacity:1;transform:translateY(0) scale(1);}} +.product:active{transform:scale(.99);} +.product.is-selected{ + border-color:#1b1d1f; + border-width:1.5px; +} + +/* product image */ +.product__img-wrap{ + width:64px;height:64px;flex:0 0 64px; + border-radius:10px; + overflow:hidden; + background:#f0f0f0; +} +.product__img{width:100%;height:100%;object-fit:cover;display:block;} + +/* product icon fallback (SVG) */ +.product__icon-wrap{ + width:64px;height:64px;flex:0 0 64px; + border-radius:10px; + background:#f6f6f6; + display:flex;align-items:center;justify-content:center; +} +.product.is-selected .product__img-wrap, +.product.is-selected .product__icon-wrap{animation:pickPop .45s cubic-bezier(.34,1.56,.64,1);} +@keyframes pickPop{ + 0%{transform:scale(1) rotate(0);} + 35%{transform:scale(1.22) rotate(-8deg);} + 70%{transform:scale(.95) rotate(4deg);} + 100%{transform:scale(1) rotate(0);} +} + +/* product info */ +.product__info{flex:1;min-width:0;} +.product__name{ + margin:0; + font-weight:800; + font-size:16px; + color:var(--ink2); + letter-spacing:-.02rem; + white-space:nowrap; + overflow:hidden; + text-overflow:ellipsis; +} + +/* product radio */ +.product__radio{flex:0 0 auto;} +.product__radio input[type="checkbox"]{ + position:absolute;opacity:0;width:0;height:0;pointer-events:none; +} +.product__radio span{ + display:block; + width:24px;height:24px; + border-radius:50%; + border:2px solid #d2d6db; + background:#fff; + transition:background .2s ease, border-color .2s ease, box-shadow .2s ease; +} +.product.is-selected .product__radio span{ + background:var(--ink2); + border-color:var(--ink2); + box-shadow:0 0 0 2px rgba(10,17,18,.12); +} + +/* ---------- action bar ---------- */ +.action-bar{ + display:flex;align-items:center;gap:14px; + padding:14px 16px; + background:#f0f0f0; + border-top:1px solid #e2e2e2; +} +.action-bar__count{ + font-weight:700;font-size:18px; + color:var(--ink2); + min-width:100px; + letter-spacing:-.02rem; +} +.confirm-btn{ + flex:1; + border:none; + border-radius:24px; + padding:14px 18px; + font-family:inherit; + font-size:18px; + font-weight:500; + letter-spacing:-.02rem; + color:rgba(10,17,18,.45); + background:#dde0e5; + cursor:not-allowed; + transition:background .3s ease, color .3s ease, transform .15s ease; +} +.confirm-btn:not([disabled]){ + background:var(--green); + color:#fff; + cursor:pointer; +} +.confirm-btn:not([disabled]):active{transform:scale(.98);} + +/* ---------- bottom nav ---------- */ +.bottom-nav{ + display:flex;align-items:stretch; + padding-bottom:env(safe-area-inset-bottom); + background:#fff; + border-top:1px solid #eee; + min-height:60px; +} +.nav-inner{ + display:flex; + justify-content:space-around; + align-items:center; + width:100%; + padding:8px 0; +} +.nav-item{ + background:none;border:none; + padding:4px 12px; + cursor:pointer; + display:flex;align-items:center;justify-content:center; + flex:1; +} +.nav-icon-wrap{ + color:#1b1d1f; + display:flex;align-items:center;justify-content:center; + padding:4px; + border-radius:10px; + transition:background .15s ease; +} +.nav-item:active .nav-icon-wrap{background:#f0f0f0;} +.nav-icon-wrap--active{color:var(--green);} + +/* ================= RETIRO ================= */ +.screen--retiro{background:var(--orange);letter-spacing:-.02rem;} +.screen--retiro .page-title{color:var(--ink2);} +.alert-banner{ + background:var(--red); + color:#f2f2f2; + font-weight:700; + font-size:18px; + text-align:center; + padding:16px 16px; + border-radius:15px; + margin-top:4px; +} +.ticket-card{ + background:#fff; + border-radius:18px; + padding:18px 18px 22px; + margin-top:16px; + min-height:260px; +} +.ticket-card__head{display:flex;align-items:center;gap:12px;} +.avatar{ + width:50px;height:50px;border-radius:50%;flex:0 0 auto; + overflow:hidden; + display:flex;align-items:center;justify-content:center; +} +.avatar__img{width:50px;height:50px;object-fit:cover;border-radius:50%;display:block;} +.avatar__fallback{display:none;} +.ticket-card__who{flex:1;min-width:0;} +.ticket-card__name{margin:0;font-weight:700;font-size:18px;line-height:1.15;color:var(--ink2);} +.ticket-card__meta{margin:2px 0 0;font-size:12px;font-weight:500;color:var(--ink2);} +.ticket-card__hour{font-size:16px;font-weight:800;color:#425052;white-space:nowrap;align-self:flex-start;} +.ticket-card__rule{border:none;border-top:1px solid #e0e0e0;margin:8px 0;} +.ticket-card__row{display:flex;justify-content:space-between;align-items:baseline;padding:10px 8px;} +.ticket-card__label{font-weight:700;font-size:18px;color:var(--ink2);} +.ticket-card__total{font-size:18px;font-weight:700;color:var(--ink2);} +.ticket-card__total .t-label{font-size:16px;font-weight:500;} +.ticket-card__item{display:flex;gap:16px;align-items:center;margin-top:6px;padding:0 8px;font-size:18px;font-weight:700;color:var(--ink2);} +.ticket-card__qty{font-weight:700;} + +/* swipe */ +.swipe-wrap{padding:0 20px calc(22px + env(safe-area-inset-bottom));} +.swipe{ + position:relative; + height:60px; + border-radius:30px; + background:var(--track); + display:flex;align-items:center;justify-content:center; + overflow:hidden; + user-select:none; + touch-action:none; +} +.swipe__fill{ + position:absolute;left:0;top:0;height:100%; + width:54px; + background:var(--navy); + border-radius:30px; + z-index:1; +} +.swipe__label{ + position:relative;z-index:0; + font-weight:600;font-size:16px;color:var(--green-text);pointer-events:none; +} +.swipe__knob{ + position:absolute;left:6px;top:6px;z-index:2; + width:48px;height:48px;border-radius:50%; + background:#fdfdfd; + display:flex;align-items:center;justify-content:center; + cursor:grab; + box-shadow:0 2px 6px rgba(0,0,0,.2); + touch-action:none; +} +.swipe__knob:active{cursor:grabbing;} +.swipe__hint{text-align:center;font-size:14px;color:var(--ink2);margin:13px 0 0;font-weight:500;letter-spacing:-.02rem;} + +/* ================= LOADING ================= */ +.screen--loading{background:var(--bg);align-items:center;justify-content:center;} +.loader-card{ + background:#fff; + width:198px;height:198px; + border-radius:28px; + box-shadow:0 18px 44px rgba(0,0,0,.13); + display:flex;flex-direction:column;align-items:center;justify-content:center;gap:28px; +} +.brand{display:flex;align-items:center;justify-content:center;} +.brand__logo{display:block;width:158px;height:auto;} +.spinner{animation:spin .85s linear infinite;} +@keyframes spin{to{transform:rotate(360deg);}} + +/* ================= SUCCESS ================= */ +.screen--success{background:var(--orange);} +.success-body{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:18px;transform:translateY(-4%);} +.success-circle{ + width:116px;height:116px;border-radius:50%; + background:#ededed; + display:flex;align-items:center;justify-content:center; + animation:popIn .5s cubic-bezier(.34,1.56,.64,1); +} +.success-text{font-weight:700;font-size:20px;color:#191b1d;margin:0;} +@keyframes popIn{0%{transform:scale(.4);opacity:0;}100%{transform:scale(1);opacity:1;}} +.success-tick path{stroke-dasharray:80;stroke-dashoffset:80;animation:drawTick .5s ease .3s forwards;} +@keyframes drawTick{to{stroke-dashoffset:0;}} diff --git a/images/trago-gintonic.jpeg b/images/trago-gintonic.jpeg new file mode 100644 index 0000000..22f7047 Binary files /dev/null and b/images/trago-gintonic.jpeg differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..7791ce6 --- /dev/null +++ b/index.html @@ -0,0 +1,177 @@ + + + + + + + skipit · Mis productos + + + + + + + +
+ + +
+
+

Mis productos

+
+ +
+
+
+

Seleccioná tus productos.

+

Retiralos por el mostrador.

+
+ +
+ +
    +
    + +
    + 0 Productos + +
    + + +
    + + +
    +
    +

    Retiro

    +
    + +
    +
    ¡NO hagas swipe antes de retirar!
    + +
    +
    + + + + +
    +

    Rabieta Palermo

    +

    Ingreso - .

    +
    + Hora 00:00:00 +
    +
    +
    + Estas retirando + Total:1 +
    +
    +
    +
    + +
    +
    +
    + Retirado +
    + +
    +
    +

    Deslizá para confirmar que retiraste tus productos

    +
    +
    + + +
    +
    +
    + +
    + +
    +
    + + +
    +
    +

    Retiro

    +
    +
    +
    + +
    +

    ¡Retiraste tus productos!

    +
    +
    + +
    + + + + diff --git a/js/app.js b/js/app.js new file mode 100644 index 0000000..2550ae3 --- /dev/null +++ b/js/app.js @@ -0,0 +1,225 @@ +(function () { + "use strict"; + + /* ---------- live clock (real current time, HH:MM:SS) ---------- */ + var hora = document.getElementById("hora-time"); + function pad(n) { return n < 10 ? "0" + n : "" + n; } + function tick() { + var d = new Date(); + hora.textContent = "Hora " + pad(d.getHours()) + ":" + pad(d.getMinutes()) + ":" + pad(d.getSeconds()); + } + tick(); + setInterval(tick, 1000); + + /* ---------- product icon fallbacks (SVG) ---------- */ + var ICONS = { + beer: + '', + trago: + '' + }; + + /* ---------- product datasets ---------- */ + var SETS = [ + [ + { name: "Pinta ingreso", img: "https://assets.skipit.com.ar/60/cropped_1768234365786.webp" }, + { name: "Pinta ingreso", img: "https://assets.skipit.com.ar/60/cropped_1768234365786.webp" } + ], + [ + { name: "Trago ingreso", img: "images/trago-gintonic.jpeg" } + ] + ]; + var setIndex = 0; + + var listEl = document.getElementById("product-list"); + var countLabel = document.getElementById("count-label"); + var confirmBtn = document.getElementById("confirm-btn"); + + function refresh() { + var n = listEl.querySelectorAll(".product.is-selected").length; + countLabel.textContent = n + (n === 1 ? " Producto" : " Productos"); + confirmBtn.disabled = n === 0; + } + + function buildProduct(item, i) { + var li = document.createElement("li"); + li.className = "product"; + li.style.animationDelay = (i * 0.07) + "s"; + + var mediaHtml; + if (item.img) { + mediaHtml = + '
    ' + + '' + item.name + '' + + '
    '; + } else { + mediaHtml = + '
    ' + ICONS[item.icon] + '
    '; + } + + li.innerHTML = + mediaHtml + + '
    ' + + '

    ' + item.name + '

    ' + + '
    ' + + '
    ' + + '' + + '' + + '
    '; + + var radioInput = li.querySelector('.product__radio input'); + + function toggle() { + var sel = li.classList.toggle("is-selected"); + radioInput.checked = sel; + refresh(); + } + li.addEventListener("click", toggle); + li.addEventListener("keydown", function (e) { + if (e.key === "Enter" || e.key === " ") { e.preventDefault(); toggle(); } + }); + li.setAttribute("tabindex", "0"); + li.setAttribute("role", "checkbox"); + li.setAttribute("aria-checked", "false"); + + var origToggle = toggle; + toggle = function () { + var sel = li.classList.toggle("is-selected"); + radioInput.checked = sel; + li.setAttribute("aria-checked", sel ? "true" : "false"); + refresh(); + }; + li.removeEventListener("click", origToggle); + li.addEventListener("click", toggle); + li.addEventListener("keydown", function (e) { + if (e.key === "Enter" || e.key === " ") { e.preventDefault(); toggle(); } + }); + + return li; + } + + function renderProducts() { + listEl.innerHTML = ""; + SETS[setIndex].forEach(function (item, i) { + listEl.appendChild(buildProduct(item, i)); + }); + refresh(); + } + + document.querySelector(".chip-btn").addEventListener("click", function () { + setIndex = (setIndex + 1) % SETS.length; + renderProducts(); + }); + + renderProducts(); + + /* ---------- screen navigation ---------- */ + function show(id) { + document.querySelectorAll(".screen").forEach(function (s) { + if (s.id === id) { + s.classList.remove("is-leaving"); + s.classList.add("is-active"); + } else if (s.classList.contains("is-active")) { + s.classList.remove("is-active"); + s.classList.add("is-leaving"); + setTimeout(function () { s.classList.remove("is-leaving"); }, 450); + } + }); + } + + /* ---------- confirm -> build Retiro ticket ---------- */ + var retiroItems = document.getElementById("retiro-items"); + var retiroTotal = document.getElementById("retiro-total"); + + confirmBtn.addEventListener("click", function () { + if (confirmBtn.disabled) return; + var sels = listEl.querySelectorAll(".product.is-selected"); + retiroItems.innerHTML = ""; + sels.forEach(function (li) { + var name = li.querySelector(".product__name").textContent; + var row = document.createElement("div"); + row.className = "ticket-card__item"; + row.innerHTML = '1' + name + ""; + retiroItems.appendChild(row); + }); + retiroTotal.textContent = sels.length; + show("screen-retiro"); + resetSwipe(); + }); + + /* ---------- swipe to confirm ---------- */ + var swipe = document.getElementById("swipe"); + var knob = document.getElementById("swipe-knob"); + var fill = document.getElementById("swipe-fill"); + var dragging = false, startX = 0, currentX = 0, maxX = 0, done = false; + + function paint(x, anim) { + knob.style.transition = anim ? "left .25s ease" : "none"; + fill.style.transition = anim ? "width .25s ease" : "none"; + knob.style.left = (6 + x) + "px"; + fill.style.width = (x <= 0 ? 0 : 6 + x + knob.offsetWidth / 2) + "px"; + } + + function resetSwipe() { + done = false; + currentX = 0; + paint(0, true); + } + + function knobX(px) { + maxX = swipe.clientWidth - knob.offsetWidth - 12; + var x = Math.max(0, Math.min(px, maxX)); + paint(x, false); + return x; + } + + function pointerDown(e) { + if (done) return; + dragging = true; + knob.style.transition = "none"; + startX = (e.touches ? e.touches[0].clientX : e.clientX) - currentX; + } + function pointerMove(e) { + if (!dragging) return; + var px = (e.touches ? e.touches[0].clientX : e.clientX) - startX; + currentX = knobX(px); + if (e.cancelable) e.preventDefault(); + } + function pointerUp() { + if (!dragging) return; + dragging = false; + if (currentX >= maxX * 0.82) { + done = true; + currentX = maxX; + paint(maxX, true); + finish(); + } else { + currentX = 0; + paint(0, true); + } + } + + knob.addEventListener("mousedown", pointerDown); + window.addEventListener("mousemove", pointerMove); + window.addEventListener("mouseup", pointerUp); + knob.addEventListener("touchstart", pointerDown, { passive: true }); + window.addEventListener("touchmove", pointerMove, { passive: false }); + window.addEventListener("touchend", pointerUp); + + function finish() { + show("screen-loading"); + setTimeout(function () { show("screen-success"); }, 2200); + } +})();