From 6e26d9e27b0e7a34d610f555a53674e0500ae220 Mon Sep 17 00:00:00 2001 From: Hanzo_dev <2002samudiojohan@gmail.com> Date: Mon, 23 Feb 2026 15:21:13 -0500 Subject: [PATCH] feat: redesign offers button and carousel as clean FAB + bottom sheet - Offers FAB: clean circular yellow button (52px) replaces OffersBadge with energy rings - Badge: red numbered badge top-right of FAB showing coupon count - FAB flips to X/gray when panel is open (no confusing state) - Carousel panel: bottom sheet anchored above navbar (not floating center modal) - Sheet handle bar at top, drag-friendly feel - Sheet header: star icon + 'Ofertas SIBU' title + count badge + close X - Promo card: horizontal layout (88px square image + discount badge + info column) - Business name in yellow, promo title bold, 2-line desc, yellow CTA pill button - Chevron arrows inside the sheet on both sides, disabled when only 1 coupon - Animated dot indicators: wide pill for active, small circle for rest - Smooth slide-up/down transition on open/close - Removed unused OffersBadge component import --- frontend/src/views/MapView.vue | 619 +++++++++++++++++---------------- 1 file changed, 314 insertions(+), 305 deletions(-) diff --git a/frontend/src/views/MapView.vue b/frontend/src/views/MapView.vue index b35fbe7..36d87c1 100644 --- a/frontend/src/views/MapView.vue +++ b/frontend/src/views/MapView.vue @@ -12,7 +12,6 @@ import { telemetryService } from "@/services/telemetryService"; import { analyticsService } from "@/services/analyticsService"; import BusStopInfoModal from "@/components/BusStopInfoModal.vue"; -import OffersBadge from "@/components/common/OffersBadge.vue"; import type { BusStop } from '@/types' const router = useRouter(); @@ -922,16 +921,19 @@ function clearNavigation() {
- -
+
+ + {{ showPromos ? 'close' : 'local_offer' }} + + {{ couponStore.coupons.length }} +
- - -
-
@@ -1227,236 +1238,282 @@ function clearNavigation() { height: 100%; } -/* Premium Carousel Styles */ -.carousel-container { - padding: 24px; - height: auto; - display: flex; - flex-direction: column; - gap: 20px; - border-radius: 28px; - box-shadow: 0 20px 50px rgba(0,0,0,0.3); -} - -.glass-morphism { - background: var(--card-bg); - backdrop-filter: blur(20px); - -webkit-backdrop-filter: blur(20px); - border: 1px solid var(--border-color); -} - -.carousel-header { - display: flex; - align-items: center; - gap: 12px; - color: var(--active-color); +/* ═══════════════════════════════════════ + OFFERS FAB BUTTON +═══════════════════════════════════════ */ +.offers-fab { position: relative; - padding-left: 48px; /* Space for the absolute close button */ -} - -.carousel-header h2 { - font-size: 1.6rem; /* Slightly smaller for better fit */ - font-weight: 800; - margin: 0; - flex: 1; -} - -.close-promos-btn { - position: absolute; - top: 50%; - left: 0; - transform: translateY(-50%); - background: var(--bg-secondary); + width: 52px; + height: 52px; + border-radius: 50%; + background: var(--active-color); + color: #101820; border: none; - width: 40px; - height: 40px; - border-radius: 12px; display: flex; align-items: center; justify-content: center; cursor: pointer; + box-shadow: 0 4px 20px rgba(254, 231, 21, 0.45); + transition: transform 0.2s, box-shadow 0.2s; + flex-shrink: 0; +} + +.offers-fab:hover { transform: scale(1.08); } +.offers-fab:active { transform: scale(0.96); } + +.offers-fab--open { + background: var(--bg-secondary); color: var(--text-primary); - transition: all 0.2s; + box-shadow: 0 4px 16px rgba(0,0,0,0.25); + border: 1px solid var(--border-color); } -.close-promos-btn:hover { - background: var(--hover-bg); - color: #f44336; -} +.offers-fab-icon { font-size: 1.5rem; transition: color 0.2s; } -.carousel-viewport { - flex: 1; - position: relative; - overflow: hidden; -} - -.carousel-track { - width: 100%; - height: 440px; - position: relative; -} - -.promo-card-premium { +.offers-fab-badge { position: absolute; - width: 100%; - height: 100%; /* Fill the carousel viewport */ - background: var(--card-bg); - border-radius: 24px; - overflow: hidden; - box-shadow: 0 15px 35px rgba(0,0,0,0.15); + top: -4px; + right: -4px; + min-width: 18px; + height: 18px; + padding: 0 4px; + background: #ef4444; + color: #ffffff; + font-size: 0.625rem; + font-weight: 800; + border-radius: 99px; + border: 2px solid var(--bg-primary); display: flex; - flex-direction: column; + align-items: center; + justify-content: center; + line-height: 1; } -.promo-image-wrapper { +/* ═══════════════════════════════════════ + OFFERS BOTTOM SHEET +═══════════════════════════════════════ */ +.offers-sheet { + position: fixed; + bottom: 64px; /* above bottom nav */ + left: 0; + right: 0; + background: var(--bg-secondary); + border-top: 1px solid var(--border-color); + border-radius: 20px 20px 0 0; + z-index: 1300; + padding: 0 0 1rem; + box-shadow: 0 -8px 32px rgba(0,0,0,0.25); +} + +.sheet-handle { + width: 40px; + height: 4px; + border-radius: 99px; + background: var(--border-color); + margin: 10px auto 8px; +} + +.sheet-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0.5rem 1rem 0.75rem; + border-bottom: 1px solid var(--border-color); +} + +.sheet-header-left { + display: flex; + align-items: center; + gap: 0.5rem; +} + +.sheet-star { color: var(--active-color); font-size: 1.125rem; } + +.sheet-title { + font-size: 1rem; + font-weight: 800; + color: var(--text-primary); +} + +.sheet-count-badge { + background: var(--active-color); + color: #101820; + font-size: 0.6875rem; + font-weight: 800; + padding: 0.15rem 0.5rem; + border-radius: 99px; +} + +.sheet-close { + background: var(--bg-primary); + border: 1px solid var(--border-color); + border-radius: 50%; + width: 32px; + height: 32px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + color: var(--text-secondary); + transition: color 0.2s; +} +.sheet-close:hover { color: var(--text-primary); } +.sheet-close .material-icons { font-size: 1.125rem; } + +/* Card area */ +.sheet-card-area { + display: flex; + align-items: center; + gap: 0.25rem; + padding: 0.75rem 0.5rem 0.375rem; + min-height: 110px; +} + +.sheet-nav { + flex-shrink: 0; + width: 32px; + height: 32px; + border-radius: 50%; + border: 1px solid var(--border-color); + background: var(--bg-primary); + color: var(--text-secondary); + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: all 0.18s; +} +.sheet-nav:disabled { opacity: 0.3; cursor: default; } +.sheet-nav:not(:disabled):hover { background: var(--active-color); color: #101820; border-color: var(--active-color); } +.sheet-nav .material-icons { font-size: 1.25rem; } + +.sheet-card { + flex: 1; + display: flex; + gap: 0.75rem; + align-items: flex-start; + min-width: 0; +} + +.sheet-img-wrap { position: relative; - height: 180px; /* Reduced from 280px to save space */ - min-height: 180px; + flex-shrink: 0; + width: 88px; + height: 88px; + border-radius: 12px; + overflow: hidden; + background: var(--bg-primary); } -.promo-img-full { +.sheet-img { width: 100%; height: 100%; object-fit: cover; } -.promo-brand-badge { +.sheet-discount { position: absolute; - top: 12px; - left: 12px; - background: rgba(255,255,255,0.9); - color: #101820; - padding: 4px 10px; - border-radius: 8px; + top: 6px; + left: 6px; + background: #ef4444; + color: #ffffff; + font-size: 0.6875rem; font-weight: 800; - font-size: 0.75rem; - backdrop-filter: blur(5px); + padding: 0.15rem 0.4rem; + border-radius: 6px; + line-height: 1.2; } -.promo-discount-tag { - position: absolute; - bottom: -15px; - right: 16px; - background: #E91E63; - color: white; - padding: 6px 14px; - border-radius: 10px; - font-weight: 800; - font-size: 1.1rem; - box-shadow: 0 5px 15px rgba(233, 30, 99, 0.4); - z-index: 2; -} - -.promo-info-premium { - padding: 24px 20px 20px; /* Reduced padding */ +.sheet-info { + flex: 1; + min-width: 0; display: flex; flex-direction: column; - flex: 1; + gap: 0.2rem; } -.promo-title-premium { - font-size: 1.2rem; /* Reduced from 1.5rem */ - font-weight: 800; - margin-bottom: 8px; - color: var(--text-primary); - display: -webkit-box; - -webkit-line-clamp: 1; - -webkit-box-orient: vertical; - line-clamp: 1; - overflow: hidden; -} - -.promo-desc-premium { - color: var(--text-secondary); - line-height: 1.4; - font-size: 0.9rem; - margin-bottom: 16px; - display: -webkit-box; - -webkit-line-clamp: 3; /* Limit description to 3 lines */ - -webkit-box-orient: vertical; - line-clamp: 3; - overflow: hidden; - flex: 1; /* Push the button to the bottom */ -} - -.promo-btn-premium { - width: 100%; - background: var(--text-primary); - color: var(--bg-primary); - border: none; - padding: 12px; - border-radius: 12px; +.sheet-biz-name { + margin: 0; + font-size: 0.6875rem; font-weight: 700; - cursor: pointer; - transition: transform 0.2s; - margin-top: auto; /* Ensure button stays at bottom */ + color: var(--active-color); + text-transform: uppercase; + letter-spacing: 0.04em; } -.promo-btn-premium:hover { - transform: translateY(-3px); +.sheet-promo-title { + margin: 0; + font-size: 0.9375rem; + font-weight: 800; + color: var(--text-primary); + line-height: 1.2; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.sheet-promo-desc { + margin: 0; + font-size: 0.8rem; + color: var(--text-secondary); + line-height: 1.35; + display: -webkit-box; + -webkit-line-clamp: 2; + line-clamp: 2; + overflow: hidden; +} + +.sheet-cta { + display: inline-flex; + align-items: center; + gap: 0.25rem; + margin-top: 0.375rem; + padding: 0.4rem 0.875rem; background: var(--active-color); - color: white; + color: #101820; + border: none; + border-radius: 99px; + font-size: 0.8125rem; + font-weight: 800; + font-family: inherit; + cursor: pointer; + transition: transform 0.15s; + align-self: flex-start; } +.sheet-cta:active { transform: scale(0.97); } -/* Dots and Nav */ -.carousel-dots { +/* Dots */ +.sheet-dots { display: flex; justify-content: center; - gap: 8px; - margin-top: 24px; + gap: 6px; + padding: 0.25rem 0 0.25rem; } -.dot { +.sheet-dot { width: 8px; height: 8px; border-radius: 50%; - background: var(--border-color); border: none; + background: var(--border-color); cursor: pointer; - transition: all 0.3s; + transition: all 0.25s; + padding: 0; } -.dot.active { - width: 24px; +.sheet-dot--active { + width: 20px; border-radius: 4px; background: var(--active-color); } -.carousel-nav { - position: absolute; - top: 50%; - transform: translateY(-50%); - background: rgba(255,255,255,0.8); - border: none; - width: 44px; - height: 44px; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - box-shadow: 0 4px 10px rgba(0,0,0,0.1); - z-index: 5; -} - -.carousel-nav.prev { left: -25px; } -.carousel-nav.next { right: -25px; } - /* Carousel Slide Animation */ .carousel-slide-enter-active, .carousel-slide-leave-active { - transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1); -} - -.carousel-slide-enter-from { - opacity: 0; - transform: translateX(100px); -} - -.carousel-slide-leave-to { - opacity: 0; - transform: translateX(-100px); + transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1); } +.carousel-slide-enter-from { opacity: 0; transform: translateX(32px); } +.carousel-slide-leave-to { opacity: 0; transform: translateX(-32px); } /* Uber-like Search Interface Styles */ .uber-search-container { @@ -1902,78 +1959,30 @@ function clearNavigation() { 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(254, 231, 21, 0); } } -.floating-promos-container { - position: fixed; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - width: 400px; - max-width: calc(100vw - 40px); - z-index: 1300; +/* Bottom sheet transition */ +.sheet-slide-enter-active, +.sheet-slide-leave-active { + transition: transform 0.35s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.35s; } - -/* Transitions */ -.promo-slide-enter-active, -.promo-slide-leave-active { - transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); -} - -.promo-slide-enter-from, -.promo-slide-leave-to { +.sheet-slide-enter-from, +.sheet-slide-leave-to { + transform: translateY(100%); opacity: 0; - transform: translateY(20px) scale(0.95); } .location-button .material-icons { font-size: 24px; } /* Responsive */ @media (max-width: 900px) { - .uber-search-container { - top: 80px; - } - - .floating-promos-container { - width: 92%; - left: 50%; - top: 50%; - transform: translate(-50%, -50%); - } + .uber-search-container { top: 80px; } - /* Reposition floating controls for mobile thumb reach */ .map-floating-controls { - bottom: 120px; /* Más espacio para pulgares en móvil */ - right: 15px; - align-items: center; - z-index: 1100; + bottom: 130px; + right: 14px; } - /* Adjust carousel height for smaller screens if needed */ - /* Adjust carousel size for mobile */ - .carousel-track { - height: 350px; - } - - .promo-image-wrapper { - height: 120px; - min-height: 120px; - } - - .carousel-header h2 { - font-size: 1.2rem; - } - - .promo-title-premium { - font-size: 1rem; - } - - .promo-desc-premium { - font-size: 0.8rem; - -webkit-line-clamp: 2; - line-clamp: 2; - } - - .promo-info-premium { - padding: 16px 15px; + .offers-sheet { + bottom: 60px; } }