feat: optimizaciones responsive en AdminPanel y traducciones i18n en BusinessDetailsView

This commit is contained in:
2026-03-05 09:27:36 -05:00
parent 1488af32ae
commit 4cdd903b8a
5 changed files with 80 additions and 18 deletions

View File

@ -177,6 +177,34 @@ const handleLogout = () => {
gap: 12px; gap: 12px;
} }
.admin-badge, .driver-badge {
padding: 4px 8px;
border-radius: 6px;
font-size: 10px;
font-weight: 800;
text-transform: uppercase;
letter-spacing: 1px;
white-space: nowrap;
}
.admin-badge {
background: rgba(254, 231, 21, 0.15);
color: var(--active-color);
border: 1px solid rgba(254, 231, 21, 0.3);
}
.driver-badge {
background: rgba(74, 222, 128, 0.15);
color: #4ade80;
border: 1px solid rgba(74, 222, 128, 0.3);
}
@media (max-width: 600px) {
.admin-badge, .driver-badge {
display: none;
}
}
.header-title { .header-title {
font-size: 24px; font-size: 24px;
font-weight: 800; font-weight: 800;

View File

@ -267,7 +267,19 @@
"socialMedia": "Social Media", "socialMedia": "Social Media",
"availableOffers": "Available Offers", "availableOffers": "Available Offers",
"viewBusiness": "View Business", "viewBusiness": "View Business",
"loadingPremium": "Loading premium experience..." "loadingPremium": "Loading premium experience...",
"loading": "Loading business...",
"offlineTitle": "Offline",
"offlineDesc": "We couldn't load the data. Check your internet connection and try again.",
"website": "Website",
"gallery": "📸 Gallery",
"about": "About the place",
"contactUs": "Contact us",
"offers": "🎁 Available Offers",
"viewMap": "View on Map",
"call": "Call",
"previous": "Previous",
"next": "Next"
}, },
"profile": { "profile": {
"title": "Profile", "title": "Profile",

View File

@ -271,7 +271,19 @@
"availableOffers": "Ofertas Disponibles", "availableOffers": "Ofertas Disponibles",
"viewBusiness": "Ver Negocio", "viewBusiness": "Ver Negocio",
"getDirections": "Cómo llegar", "getDirections": "Cómo llegar",
"loadingPremium": "Cargando experiencia premium..." "loadingPremium": "Cargando experiencia premium...",
"loading": "Cargando negocio...",
"offlineTitle": "Sin conexión",
"offlineDesc": "No pudimos cargar los datos. Revisa tu internet e intenta de nuevo.",
"website": "Sitio Web",
"gallery": "📸 Galería",
"about": "Sobre el lugar",
"contactUs": "Contáctanos",
"offers": "🎁 Ofertas Disponibles",
"viewMap": "Ver en el Mapa",
"call": "Llamar",
"previous": "Anterior",
"next": "Siguiente"
}, },
"profile": { "profile": {
"title": "Perfil", "title": "Perfil",

View File

@ -268,7 +268,14 @@ h1 {
@media (max-width: 600px) { @media (max-width: 600px) {
.admin-panel { padding: 30px 16px 120px; } .admin-panel { padding: 30px 16px 120px; }
.category-grid { grid-template-columns: 1fr; } .category-grid {
flex-direction: column;
align-items: center;
}
.action-card {
width: 100%;
max-width: 340px;
}
.header-section { text-align: center; padding: 0; } .header-section { text-align: center; padding: 0; }
} }
</style> </style>

View File

@ -9,6 +9,9 @@ import { getImageUrl as utilGetImageUrl } from '@/utils/imageUrl'
import { analyticsService } from '@/services/analyticsService' import { analyticsService } from '@/services/analyticsService'
import LoadingBranded from '@/components/common/LoadingBranded.vue' import LoadingBranded from '@/components/common/LoadingBranded.vue'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
const business = ref<Business | null>(null) const business = ref<Business | null>(null)
@ -122,7 +125,7 @@ const quickInfoPills = computed(() => {
if (business.value.area) pills.push({ icon: 'location_on', text: business.value.area }) if (business.value.area) pills.push({ icon: 'location_on', text: business.value.area })
if (business.value.schedule) pills.push({ icon: 'schedule', text: business.value.schedule }) if (business.value.schedule) pills.push({ icon: 'schedule', text: business.value.schedule })
if (business.value.phone) pills.push({ icon: 'phone', text: business.value.phone }) if (business.value.phone) pills.push({ icon: 'phone', text: business.value.phone })
if (business.value.website) pills.push({ icon: 'language', text: 'Sitio Web', href: business.value.website }) if (business.value.website) pills.push({ icon: 'language', text: t('business.website'), href: business.value.website })
return pills return pills
}) })
@ -135,17 +138,17 @@ const hasSocials = computed(() =>
<template> <template>
<!-- LOADING --> <!-- LOADING -->
<div v-if="isLoading" class="state-full"> <div v-if="isLoading" class="state-full">
<LoadingBranded :message="'Cargando negocio...'" icon="storefront" /> <LoadingBranded :message="t('business.loading')" icon="storefront" />
</div> </div>
<!-- ERROR --> <!-- ERROR -->
<div v-else-if="fetchError" class="state-full"> <div v-else-if="fetchError" class="state-full">
<span class="material-icons state-icon">wifi_off</span> <span class="material-icons state-icon">wifi_off</span>
<h3 class="state-title">Sin conexión</h3> <h3 class="state-title">{{ t('business.offlineTitle') }}</h3>
<p class="state-sub">No pudimos cargar los datos. Revisa tu internet e intenta de nuevo.</p> <p class="state-sub">{{ t('business.offlineDesc') }}</p>
<button class="btn-retry" @click="fetchData"> <button class="btn-retry" @click="fetchData">
<span class="material-icons">refresh</span> <span class="material-icons">refresh</span>
Reintentar {{ t('common.retry') }}
</button> </button>
</div> </div>
@ -165,7 +168,7 @@ const hasSocials = computed(() =>
<div class="hero-gradient"></div> <div class="hero-gradient"></div>
<!-- Top controls --> <!-- Top controls -->
<button class="hero-btn hero-back" @click="goBack" aria-label="Volver"> <button class="hero-btn hero-back" @click="goBack" :aria-label="t('common.back')">
<span class="material-icons">arrow_back</span> <span class="material-icons">arrow_back</span>
</button> </button>
<div class="hero-fav"> <div class="hero-fav">
@ -212,7 +215,7 @@ const hasSocials = computed(() =>
<section v-if="galleryImages.length > 0" class="biz-section"> <section v-if="galleryImages.length > 0" class="biz-section">
<div class="section-header"> <div class="section-header">
<span class="section-accent"></span> <span class="section-accent"></span>
<h2 class="section-title">📸 Galería</h2> <h2 class="section-title">{{ t('business.gallery') }}</h2>
</div> </div>
<div class="carousel-wrap"> <div class="carousel-wrap">
@ -235,10 +238,10 @@ const hasSocials = computed(() =>
<!-- Nav arrows (only if >1 image) --> <!-- Nav arrows (only if >1 image) -->
<template v-if="galleryImages.length > 1"> <template v-if="galleryImages.length > 1">
<button class="car-arrow car-arrow-left" @click="prevSlide" aria-label="Anterior"> <button class="car-arrow car-arrow-left" @click="prevSlide" :aria-label="t('business.previous')">
<span class="material-icons">chevron_left</span> <span class="material-icons">chevron_left</span>
</button> </button>
<button class="car-arrow car-arrow-right" @click="nextSlide" aria-label="Siguiente"> <button class="car-arrow car-arrow-right" @click="nextSlide" :aria-label="t('business.next')">
<span class="material-icons">chevron_right</span> <span class="material-icons">chevron_right</span>
</button> </button>
@ -262,7 +265,7 @@ const hasSocials = computed(() =>
<section v-if="business.description" class="biz-section"> <section v-if="business.description" class="biz-section">
<div class="section-header"> <div class="section-header">
<span class="section-accent"></span> <span class="section-accent"></span>
<h2 class="section-title">Sobre el lugar</h2> <h2 class="section-title">{{ t('business.about') }}</h2>
</div> </div>
<p class="about-text">{{ business.description }}</p> <p class="about-text">{{ business.description }}</p>
</section> </section>
@ -273,7 +276,7 @@ const hasSocials = computed(() =>
<section v-if="hasSocials" class="biz-section"> <section v-if="hasSocials" class="biz-section">
<div class="section-header"> <div class="section-header">
<span class="section-accent"></span> <span class="section-accent"></span>
<h2 class="section-title">Contáctanos</h2> <h2 class="section-title">{{ t('business.contactUs') }}</h2>
</div> </div>
<div class="socials-grid"> <div class="socials-grid">
@ -332,7 +335,7 @@ const hasSocials = computed(() =>
<section v-if="coupons.length > 0" class="biz-section"> <section v-if="coupons.length > 0" class="biz-section">
<div class="section-header"> <div class="section-header">
<span class="section-accent"></span> <span class="section-accent"></span>
<h2 class="section-title">🎁 Ofertas Disponibles</h2> <h2 class="section-title">{{ t('business.offers') }}</h2>
</div> </div>
<div class="coupons-grid"> <div class="coupons-grid">
<div v-for="coupon in coupons" :key="coupon.id" class="coupon-card"> <div v-for="coupon in coupons" :key="coupon.id" class="coupon-card">
@ -348,7 +351,7 @@ const hasSocials = computed(() =>
<div class="coupon-divider"></div> <div class="coupon-divider"></div>
<h3 class="coupon-title">{{ coupon.title }}</h3> <h3 class="coupon-title">{{ coupon.title }}</h3>
<p class="coupon-desc">{{ coupon.description }}</p> <p class="coupon-desc">{{ coupon.description }}</p>
<span class="coupon-off">OFF</span> <span class="coupon-off">{{ t('coupons.off') }}</span>
</div> </div>
</div> </div>
</section> </section>
@ -366,7 +369,7 @@ const hasSocials = computed(() =>
@click="openMaps" @click="openMaps"
> >
<span class="material-icons">near_me</span> <span class="material-icons">near_me</span>
Ver en el Mapa {{ t('business.viewMap') }}
</button> </button>
<button <button
v-if="business.phone" v-if="business.phone"
@ -374,7 +377,7 @@ const hasSocials = computed(() =>
@click="callPhone" @click="callPhone"
> >
<span class="material-icons">phone</span> <span class="material-icons">phone</span>
Llamar {{ t('business.call') }}
</button> </button>
</div> </div>