wip migration
This commit is contained in:
160
components/BannerCoop.vue
Normal file
160
components/BannerCoop.vue
Normal file
@@ -0,0 +1,160 @@
|
||||
<template>
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="banner-text col-12" align="center">
|
||||
<span>
|
||||
Si quieres formar parte de este gran proyecto
|
||||
<br class="br" />registrate en el siguiente formulario
|
||||
</span>
|
||||
<img
|
||||
class="sep-dots"
|
||||
src="@/assets/img/latienda-dots-blue.svg"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row banner-links justify-content-center" align="center">
|
||||
<NuxtLink class="col-2 link out-div" to="/page/info">
|
||||
<img src="@/assets/img/latienda-info-red.svg" alt="" />
|
||||
<img
|
||||
class="dots"
|
||||
src="@/assets/img/latienda-dots-vertical-red.svg"
|
||||
alt=""
|
||||
/>
|
||||
<span>Saber más</span>
|
||||
</NuxtLink>
|
||||
<NuxtLink class="col-2 link fill-div" to="/registro/cooperativa">
|
||||
<img
|
||||
class="img-form"
|
||||
src="@/assets/img/latienda-formulario.svg"
|
||||
alt=""
|
||||
/>
|
||||
<img
|
||||
class="dots"
|
||||
src="@/assets/img/latienda-dots-vertical-white.svg"
|
||||
alt=""
|
||||
/>
|
||||
<span>¡sí, quiero!</span>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'BannerCoop',
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.container-fluid {
|
||||
padding-top: 80px;
|
||||
padding-bottom: 80px;
|
||||
background-color: $color-lighter-green;
|
||||
background-image: url('../assets/img/latienda-banner-imagen.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
background-position: right;
|
||||
position: relative;
|
||||
|
||||
@include mobile {
|
||||
background: linear-gradient(rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.3)),
|
||||
url('../assets/img/latienda-banner-imagen.png');
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
}
|
||||
.banner-text {
|
||||
@include mobile {
|
||||
padding: 2em;
|
||||
}
|
||||
span {
|
||||
font-size: $m;
|
||||
color: $color-navy;
|
||||
font-weight: $regular;
|
||||
|
||||
@include mobile {
|
||||
font-size: $s;
|
||||
font-weight: $medium;
|
||||
color: $color-light;
|
||||
}
|
||||
}
|
||||
img {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
display: block;
|
||||
width: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
.sep-dots {
|
||||
@include mobile {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.banner-links {
|
||||
.link {
|
||||
border-radius: 40px;
|
||||
padding: 10px;
|
||||
text-decoration: none;
|
||||
min-width: 200px;
|
||||
|
||||
@include mobile {
|
||||
min-width: 160px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 30px;
|
||||
|
||||
@include mobile {
|
||||
width: 25px;
|
||||
}
|
||||
}
|
||||
|
||||
.dots {
|
||||
width: 5px;
|
||||
margin: 0 10px 0 10px;
|
||||
@include mobile {
|
||||
width: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
.img-form {
|
||||
width: 25px;
|
||||
@include mobile {
|
||||
width: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
text-transform: uppercase;
|
||||
font-size: $xs;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.out-div {
|
||||
border: 2px solid $color-orange;
|
||||
color: $color-orange;
|
||||
margin-right: 10px;
|
||||
|
||||
@include mobile {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.fill-div {
|
||||
background-color: $color-orange;
|
||||
color: $color-light;
|
||||
}
|
||||
|
||||
.br {
|
||||
@include mobile {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
82
components/CookieUsageNotification.vue
Normal file
82
components/CookieUsageNotification.vue
Normal file
@@ -0,0 +1,82 @@
|
||||
<template>
|
||||
<ClientOnly>
|
||||
<BAlert class="cookies" :show="show">
|
||||
<div class="cookies-container">
|
||||
<span class="title">Uso de cookies</span>
|
||||
<p>
|
||||
Utilizamos cookies propias y de terceros para mejorar la navegación.
|
||||
Si continúa navegando, consideramos que acepta su uso. Puede obtener
|
||||
más información, o bien conocer cómo cambiar la configuración, en
|
||||
nuestra <NuxtLink to="/page/cookies">Política de cookies</NuxtLink>.
|
||||
</p>
|
||||
<BButton size="sm" variant="success" @click="close">Aceptar</BButton>
|
||||
</div>
|
||||
</BAlert>
|
||||
</ClientOnly>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
import { mapActions } from 'pinia'
|
||||
export default {
|
||||
name: 'CookieUsageNotification',
|
||||
data() {
|
||||
return {
|
||||
show: undefined,
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
const auth = useAuthStore()
|
||||
if (auth.cookiesAccepted === true) {
|
||||
this.show = false
|
||||
} else {
|
||||
this.show = true
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
...mapActions(useAuthStore, ['acceptCookies']),
|
||||
close() {
|
||||
this.show = false
|
||||
this.acceptCookies()
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.cookies {
|
||||
z-index: 999;
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
background-color: $color-navy;
|
||||
border: none;
|
||||
color: $color-light;
|
||||
a {
|
||||
color: $color-light;
|
||||
text-decoration: underline;
|
||||
}
|
||||
span {
|
||||
font-size: $m;
|
||||
font-weight: $bold;
|
||||
}
|
||||
p {
|
||||
font-size: $s;
|
||||
}
|
||||
}
|
||||
.cookies-container {
|
||||
font-weight: $regular;
|
||||
}
|
||||
.btn {
|
||||
background-color: $color-navy;
|
||||
color: $color-light;
|
||||
border: 2px solid $color-orange;
|
||||
padding: 0.5em 1em;
|
||||
margin: auto;
|
||||
|
||||
&:hover {
|
||||
background-color: $color-orange;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
212
components/Footer.vue
Normal file
212
components/Footer.vue
Normal file
@@ -0,0 +1,212 @@
|
||||
<template>
|
||||
<div>
|
||||
<hr />
|
||||
<div>
|
||||
<img class="bolsa" src="@/assets/img/footer-bolsa.svg" alt="" />
|
||||
</div>
|
||||
<hr />
|
||||
<div class="social">
|
||||
<a href="https://www.facebook.com/coceta" target="_blank">
|
||||
<img
|
||||
class="social-logo"
|
||||
src="@/assets/img/footer-facebook.svg"
|
||||
alt=""
|
||||
/>
|
||||
</a>
|
||||
<a href="https://twitter.com/Coopsdetrabajo" target="_blank">
|
||||
<img class="social-logo" src="@/assets/img/footer-twitter.svg" alt="" />
|
||||
</a>
|
||||
</div>
|
||||
<hr />
|
||||
<div class="organization">
|
||||
<div class="organization-image-container">
|
||||
<img
|
||||
class="organization-image"
|
||||
src="@/assets/img/footer-coceta.svg"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<span class="dot"></span>
|
||||
<span class="dot"></span>
|
||||
<span class="dot"></span>
|
||||
<span class="dot"></span>
|
||||
<span class="dot"></span>
|
||||
<span class="dot"></span>
|
||||
<span class="dot"></span>
|
||||
<span class="dot"></span>
|
||||
<span class="dot"></span>
|
||||
<span class="dot"></span>
|
||||
</div>
|
||||
<div class="organization-image-container">
|
||||
<img
|
||||
class="organization-image"
|
||||
src="@/assets/img/footer-ministerio.svg"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="link-list">
|
||||
<li>
|
||||
<small>2021 La Tienda.Coop</small>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="https://coceta.coop/" class="footer-link" target="_blank">
|
||||
<small>Coceta</small>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<NuxtLink to="/page/terminos">
|
||||
<small>Términos y condiciones</small>
|
||||
</NuxtLink>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<NuxtLink to="/page/legal">
|
||||
<small>Política de privacidad</small>
|
||||
</NuxtLink>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<NuxtLink to="/page/cookies">
|
||||
<small>Cookies</small>
|
||||
</NuxtLink>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a
|
||||
href="http://enreda.coop/"
|
||||
class="footer-link enreda"
|
||||
target="_blank"
|
||||
>
|
||||
<small
|
||||
><mark class="highlight">Sitio desarrollado por Enreda</mark></small
|
||||
>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Footer',
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
hr {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.bolsa {
|
||||
width: 50px;
|
||||
height: auto;
|
||||
margin: 4.375rem auto;
|
||||
display: block;
|
||||
@include mobile {
|
||||
width: 35px;
|
||||
margin: 3rem auto;
|
||||
}
|
||||
}
|
||||
.social {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 3.125rem auto;
|
||||
&-logo {
|
||||
height: 1.25rem;
|
||||
margin: auto 1.875rem;
|
||||
}
|
||||
}
|
||||
|
||||
.organization {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
&-image {
|
||||
width: 18rem;
|
||||
margin: 3.125rem;
|
||||
@include mobile {
|
||||
width: 6rem;
|
||||
margin: 0.8rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dot {
|
||||
height: 3px;
|
||||
width: 3px;
|
||||
background-color: #bbb;
|
||||
border-radius: 50%;
|
||||
display: block;
|
||||
margin: 7px;
|
||||
|
||||
@include mobile {
|
||||
height: 2px;
|
||||
width: 2px;
|
||||
margin: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.link-list {
|
||||
font-family: 'Noto Sans';
|
||||
font-size: $xs;
|
||||
color: $color-grey-darker;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-wrap: nowrap;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 3.125rem;
|
||||
text-decoration: none;
|
||||
list-style-type: none;
|
||||
|
||||
@include mobile {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@include tablet {
|
||||
flex-direction: row;
|
||||
font-size: $xxs;
|
||||
}
|
||||
|
||||
& small {
|
||||
margin: auto 1.25rem;
|
||||
text-align: center;
|
||||
color: $color-grey-darker;
|
||||
:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
@include tablet {
|
||||
li:nth-child(1):after,
|
||||
li:nth-child(2):after,
|
||||
li:nth-child(3):after,
|
||||
li:nth-child(4):after,
|
||||
li:nth-child(5):after {
|
||||
color: $color-grey-darker;
|
||||
content: '|';
|
||||
margin: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.footer-link {
|
||||
.enreda {
|
||||
padding: 1.25em;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
background: $color-greylighter;
|
||||
border-radius: 5px;
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
33
components/FormHeader.vue
Normal file
33
components/FormHeader.vue
Normal file
@@ -0,0 +1,33 @@
|
||||
<template>
|
||||
<div class="header">
|
||||
<h1 class="title">{{ title }}</h1>
|
||||
<img src="@/assets/img/latienda-lineapuntos-2.svg" alt="" class="" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
title: { type: String, default: '' },
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-bottom: 40px;
|
||||
|
||||
.title {
|
||||
font-size: $xl;
|
||||
color: $color-navy;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 40px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
89
components/FormInput.vue
Normal file
89
components/FormInput.vue
Normal file
@@ -0,0 +1,89 @@
|
||||
<template>
|
||||
<div class="form-input">
|
||||
<label
|
||||
>{{ labelText + (required ? '*' : '') }}
|
||||
<input
|
||||
v-model="inputValue"
|
||||
:required="required"
|
||||
:type="type"
|
||||
:step="step"
|
||||
:placeholder="placeholder"
|
||||
@input="handleInput"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
labelText: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
required: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
step: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
value: {
|
||||
type: [Number, String],
|
||||
default: '',
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
emits: ['input'],
|
||||
data() {
|
||||
return {
|
||||
inputValue: this.value,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleInput() {
|
||||
this.$emit('input', this.inputValue)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.form-input {
|
||||
// width: 100%; //Utilizar este width para controlar el ancho desde el elemento padre
|
||||
width: 45%;
|
||||
@include mobile {
|
||||
width: 80%;
|
||||
}
|
||||
// @include desktop {
|
||||
// width: 25%;
|
||||
// }
|
||||
}
|
||||
input {
|
||||
width: 100%;
|
||||
background-color: $color-grey-inputs;
|
||||
border: 1px solid $color-grey-inputs-border;
|
||||
border-radius: 4px;
|
||||
padding: 10px 5px;
|
||||
display: block;
|
||||
margin-bottom: 10px;
|
||||
font-weight: $regular;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
label {
|
||||
text-align: left;
|
||||
color: $color-navy;
|
||||
font-weight: $bold;
|
||||
font-size: $xs;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
253
components/GoogleAddress.vue
Normal file
253
components/GoogleAddress.vue
Normal file
@@ -0,0 +1,253 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<label>{{ label }}</label>
|
||||
<p v-if="value && !place">{{ value }}</p>
|
||||
<p v-if="place">{{ place.address }}</p>
|
||||
<p v-show="error" class="error">{{ error }}</p>
|
||||
|
||||
<div class="input-and-btn">
|
||||
<button class="geo-btn" type="button" @click="getGeoLocation">
|
||||
<v-progress-circular
|
||||
v-if="loading"
|
||||
:size="15"
|
||||
:width="2"
|
||||
indeterminate
|
||||
/>
|
||||
<v-icon v-else small class="geo-icon"> mdi-crosshairs-gps </v-icon>
|
||||
</button>
|
||||
<input
|
||||
ref="googleMap"
|
||||
:required="!value"
|
||||
placeholder=""
|
||||
type="search"
|
||||
@focus="clear"
|
||||
/>
|
||||
|
||||
<!-- <button class="add-btn" type="button" @click="logPlace">Añadir</button> -->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Loader } from '@googlemaps/js-api-loader'
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
geo: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
default: 'Dirección',
|
||||
},
|
||||
},
|
||||
emits: ['addedData'],
|
||||
data() {
|
||||
return {
|
||||
google: null,
|
||||
autocomplete: null,
|
||||
geocoder: null,
|
||||
place: null,
|
||||
error: null,
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
|
||||
async mounted() {
|
||||
const config = useRuntimeConfig()
|
||||
const apiKey = config.public.googleMapsApiKey
|
||||
if (!apiKey) {
|
||||
console.error('Google Maps API key is not defined in the runtime config.')
|
||||
return
|
||||
}
|
||||
const googleMapApi = new Loader({
|
||||
libraries: ['places'],
|
||||
apiKey: apiKey,
|
||||
})
|
||||
|
||||
try {
|
||||
await googleMapApi.load()
|
||||
await this.initializeMap()
|
||||
} catch (error) {
|
||||
console.error('Error loading Google Maps API:', error)
|
||||
this.error = 'Error al cargar el mapa de Google'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initializeMap() {
|
||||
const mapContainer = this.$refs.googleMap
|
||||
|
||||
if (!mapContainer || !window.google) {
|
||||
this.error = 'Google Maps no disponible'
|
||||
return
|
||||
}
|
||||
|
||||
this.autocomplete = new window.google.maps.places.PlaceAutocompleteElement(mapContainer)
|
||||
window.google.maps.event.addListener(this.autocomplete, 'place_changed', () => this.logPlace())
|
||||
this.geocoder = new window.google.maps.Geocoder()
|
||||
if (this.geo) {
|
||||
this.getGeoData(this.geo)
|
||||
}
|
||||
},
|
||||
|
||||
async getGeoLocation() {
|
||||
this.place = null
|
||||
this.error = null
|
||||
const geoLocation = () =>
|
||||
new Promise((resolve, reject) => {
|
||||
if (!navigator.geolocation) {
|
||||
reject(new Error('Geolocalización no soportada'))
|
||||
return
|
||||
}
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
(posData) => {
|
||||
resolve(posData)
|
||||
},
|
||||
(error) => {
|
||||
reject(error)
|
||||
}
|
||||
)
|
||||
} )
|
||||
try {
|
||||
this.loading = true
|
||||
const position = await geoLocation()
|
||||
const geo = {
|
||||
lat: position.coords.latitude,
|
||||
lng: position.coords.longitude,
|
||||
}
|
||||
this.getGeoData(geo)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
this.error = 'No se puede obtener la ubicación'
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
|
||||
getGeoData(coordinates) {
|
||||
if (!this.geocoder) {
|
||||
this.error = 'Geocoder no inicializado'
|
||||
this.loading = false
|
||||
return
|
||||
}
|
||||
|
||||
this.geocoder.geocode({ location: coordinates }, (result, status) => {
|
||||
if (status === 'OK') {
|
||||
const data = result[0]
|
||||
const address = data.formatted_address
|
||||
const geo = {
|
||||
latitude: Number(data.geometry.location.lat().toFixed(4)),
|
||||
longitude: Number(data.geometry.location.lng().toFixed(4)),
|
||||
}
|
||||
const city = data.address_components.find(
|
||||
(element) => element.types[0] === 'locality'
|
||||
).long_name || ''
|
||||
this.place = { address, geo, city }
|
||||
if (this.$refs.googleMap) {
|
||||
this.$refs.googleMap.value = this.place.address
|
||||
}
|
||||
this.$emit('addedData', this.place)
|
||||
this.loading = false
|
||||
} else {
|
||||
this.error = 'No se puede obtener la ubicación'
|
||||
this.loading = false
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
clear() {
|
||||
this.place = null
|
||||
this.error = null
|
||||
this.$refs.googleMap.value = null
|
||||
this.$emit('addedData', this.place)
|
||||
},
|
||||
|
||||
async logPlace() {
|
||||
this.place = null
|
||||
this.error = null
|
||||
try {
|
||||
const googlePlace = await this.autocomplete.getPlace()
|
||||
console.log('Google Place:', googlePlace)
|
||||
const address = googlePlace.formatted_address
|
||||
const geo = {
|
||||
latitude: Number(googlePlace.geometry.location.lat().toFixed(4)),
|
||||
longitude: Number(googlePlace.geometry.location.lng().toFixed(4)),
|
||||
}
|
||||
const city =
|
||||
googlePlace.address_components.find(
|
||||
(element) => element.types[0] === 'locality'
|
||||
)?.long_name || ''
|
||||
this.place = { address, geo, city }
|
||||
this.$emit('addedData', this.place)
|
||||
} catch {
|
||||
this.place = null
|
||||
this.error = 'Debe introducir una dirección correcta'
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
label {
|
||||
text-align: left;
|
||||
color: $color-navy;
|
||||
font-weight: $bold;
|
||||
font-size: $xs;
|
||||
display: block;
|
||||
}
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
background-color: $color-grey-inputs;
|
||||
border: 1px solid $color-grey-inputs-border;
|
||||
border-radius: 4px;
|
||||
padding: 9px 5px;
|
||||
display: block;
|
||||
outline: none;
|
||||
font-size: $s;
|
||||
}
|
||||
|
||||
.input-and-btn {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
input {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
button {
|
||||
height: auto;
|
||||
background-color: $color-navy;
|
||||
color: $color-light;
|
||||
border: 1px solid $color-navy;
|
||||
border-radius: 5px;
|
||||
text-transform: uppercase;
|
||||
padding: 5px 5px;
|
||||
font-size: $xxs;
|
||||
|
||||
@include mobile {
|
||||
font-size: $xxs;
|
||||
}
|
||||
}
|
||||
.geo-btn {
|
||||
width: 10%;
|
||||
min-width: 30px;
|
||||
}
|
||||
// .add-btn {
|
||||
// width: 20%;
|
||||
// }
|
||||
}
|
||||
|
||||
.error {
|
||||
color: $color-error;
|
||||
}
|
||||
|
||||
.geo-icon {
|
||||
color: $color-light !important;
|
||||
}
|
||||
</style>
|
||||
204
components/HighlightsCard.vue
Normal file
204
components/HighlightsCard.vue
Normal file
@@ -0,0 +1,204 @@
|
||||
<template>
|
||||
<div class="box">
|
||||
<div class="title">
|
||||
<h5 class="category-title">{{ title }}</h5>
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<NuxtLink :to="`/productos/${products[0] ? products[0].id : 1}`">
|
||||
<div class="item">
|
||||
<BImg
|
||||
class="image"
|
||||
fluid
|
||||
:src="getProductImg(products[0])"
|
||||
alt=""
|
||||
/>
|
||||
<h6 class="product-name">
|
||||
{{
|
||||
products[0]
|
||||
? products[0].name
|
||||
.toLowerCase()
|
||||
.replace(/^[a-zA-ZÀ-ÿ\u00f1\u00d1]/, (c) =>
|
||||
c.toUpperCase()
|
||||
)
|
||||
: ''
|
||||
}}
|
||||
</h6>
|
||||
</div>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<NuxtLink :to="`/productos/${products[1] ? products[1].id : 1}`">
|
||||
<div class="item">
|
||||
<BImg
|
||||
class="image"
|
||||
fluid
|
||||
:src="getProductImg(products[1])"
|
||||
alt=""
|
||||
/>
|
||||
<h6 class="product-name">
|
||||
{{
|
||||
products[1]
|
||||
? products[1].name
|
||||
.toLowerCase()
|
||||
.replace(/^[a-zA-ZÀ-ÿ\u00f1\u00d1]/, (c) =>
|
||||
c.toUpperCase()
|
||||
)
|
||||
: ''
|
||||
}}
|
||||
</h6>
|
||||
</div>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<NuxtLink :to="`/productos/${products[2] ? products[2].id : 1}`">
|
||||
<div class="item">
|
||||
<BImg
|
||||
class="image"
|
||||
fluid
|
||||
:src="getProductImg(products[2])"
|
||||
alt=""
|
||||
/>
|
||||
<h6 class="product-name">
|
||||
{{
|
||||
products[2]
|
||||
? products[2].name
|
||||
.toLowerCase()
|
||||
.replace(/^[a-zA-ZÀ-ÿ\u00f1\u00d1]/, (c) =>
|
||||
c.toUpperCase()
|
||||
)
|
||||
: ''
|
||||
}}
|
||||
</h6>
|
||||
</div>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<NuxtLink :to="`/productos/${products[3] ? products[3].id : 1}`">
|
||||
<div class="item">
|
||||
<BImg
|
||||
class="image"
|
||||
fluid
|
||||
:src="getProductImg(products[3])"
|
||||
alt=""
|
||||
/>
|
||||
<h6 class="product-name">
|
||||
{{
|
||||
products[3]
|
||||
? products[3].name
|
||||
.toLowerCase()
|
||||
.replace(/^[a-zA-ZÀ-ÿ\u00f1\u00d1]/, (c) =>
|
||||
c.toUpperCase()
|
||||
)
|
||||
: ''
|
||||
}}
|
||||
</h6>
|
||||
</div>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<nuxt-link class="link" :to="`/busqueda?category=${category}`"
|
||||
>Ver más →</nuxt-link
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'HighlightsCard',
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
category: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
products: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getProductImg(product) {
|
||||
if (product && product.image) return product.image
|
||||
return `@/assets/img/latienda-product-default.svg`
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.box {
|
||||
border-radius: 7px;
|
||||
border: 1px solid $color-greylighter;
|
||||
position: relative;
|
||||
background-color: $color-light;
|
||||
margin-top: 30px;
|
||||
height: 100%;
|
||||
display: block;
|
||||
overflow: auto;
|
||||
padding: 0.8rem;
|
||||
padding-bottom: 0.4rem;
|
||||
@include mobile {
|
||||
margin-top: 15px;
|
||||
}
|
||||
}
|
||||
.category-title {
|
||||
color: $color-navy;
|
||||
}
|
||||
.link {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-items: center;
|
||||
align-items: center;
|
||||
color: $color-greylink;
|
||||
font-family: $font-primary;
|
||||
font-weight: $bold;
|
||||
font-size: $s;
|
||||
}
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-items: center;
|
||||
align-items: center;
|
||||
|
||||
.product-name {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
font-family: $font-secondary;
|
||||
font-size: $s;
|
||||
font-weight: 400;
|
||||
display: -webkit-box;
|
||||
--webkit-line-clamp: 2;
|
||||
--webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
margin-top: 0.6rem;
|
||||
}
|
||||
}
|
||||
|
||||
.image {
|
||||
width: 100%;
|
||||
max-height: 6rem;
|
||||
max-width: 6rem;
|
||||
object-fit: cover;
|
||||
@include mobile {
|
||||
max-height: 12rem;
|
||||
max-width: 12rem;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
width: 100%;
|
||||
margin: 1.2rem 0 0.5rem;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
157
components/ItemsRow.vue
Normal file
157
components/ItemsRow.vue
Normal file
@@ -0,0 +1,157 @@
|
||||
<template>
|
||||
<div class="row">
|
||||
<ClientOnly placerholder="Loading...">
|
||||
<!-- <div class="arrow-left-wrapper col-2 col-sm-1">
|
||||
<img
|
||||
class="arrow"
|
||||
src="@/assets/img/categories-row-arrow-left.svg"
|
||||
alt=""
|
||||
@click="slideCarousel('prev')"
|
||||
/>
|
||||
</div> -->
|
||||
|
||||
<Carousel
|
||||
ref="productDetails"
|
||||
class="col-8 col-sm-10"
|
||||
:items-to-show="3"
|
||||
:gap="5"
|
||||
:pagination-enabled="false"
|
||||
:wrap-around="false"
|
||||
:mouse-wheel="true"
|
||||
:breakpoints-enabled="true"
|
||||
>
|
||||
<Slide v-for="item in items" :key="item.id">
|
||||
<NuxtLink :to="formattedItem(item).url" class="slide">
|
||||
<div class="image-container">
|
||||
<img class="image" :src="formattedItem(item).image" alt="" />
|
||||
</div>
|
||||
<span>{{ formattedItem(item).name }}</span>
|
||||
</NuxtLink>
|
||||
</Slide>
|
||||
<template #addons>
|
||||
<Navigation />
|
||||
</template>
|
||||
</Carousel>
|
||||
|
||||
<!-- <div class="arrow-right-wrapper col-2 col-sm-1">
|
||||
<img
|
||||
class="arrow"
|
||||
src="@/assets/img/categories-row-arrow-right.svg"
|
||||
alt=""
|
||||
@click="slideCarousel('next')"
|
||||
/>
|
||||
</div> -->
|
||||
</ClientOnly>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Carousel, Slide, Navigation } from 'vue3-carousel'
|
||||
import 'vue3-carousel/dist/carousel.css'
|
||||
import defaultImage from '@/assets/img/latienda-product-default.png'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Carousel,
|
||||
Slide,
|
||||
Navigation
|
||||
},
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
items: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
defaultImage,
|
||||
config: {
|
||||
height: 200,
|
||||
breakpointMode: 'carousel', // o 'viewport'
|
||||
breakpoints: {
|
||||
300: {
|
||||
itemsToShow: 2,
|
||||
snapAlign: 'center',
|
||||
},
|
||||
400: {
|
||||
itemsToShow: 3,
|
||||
snapAlign: 'start',
|
||||
},
|
||||
500: {
|
||||
itemsToShow: 4,
|
||||
snapAlign: 'start',
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
formattedItem(item) {
|
||||
if (this.type === 'product') {
|
||||
return {
|
||||
name: item.name,
|
||||
image:
|
||||
item.image || this.defaultImage,
|
||||
url: `/productos/${item.id}`,
|
||||
}
|
||||
}
|
||||
if (this.type === 'company') {
|
||||
return {
|
||||
name: item.company_name,
|
||||
image:
|
||||
item.logo || this.defaultImage,
|
||||
url: `/c/${item.id}`,
|
||||
}
|
||||
}
|
||||
if (this.type === 'category') {
|
||||
return {
|
||||
name: item.name,
|
||||
image:
|
||||
item.image || this.defaultImage,
|
||||
url: `/busqueda?category=${item.name}`,
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.slide {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: stretch;
|
||||
padding: 0.3rem;
|
||||
span {
|
||||
text-align: center;
|
||||
display: -webkit-box;
|
||||
--webkit-line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
width: 25vw;
|
||||
max-width: 110px;
|
||||
font-weight: $regular;
|
||||
font-size: $s;
|
||||
}
|
||||
}
|
||||
|
||||
.image-container {
|
||||
width: 100%;
|
||||
height: 5rem;
|
||||
margin-bottom: 0.7rem;
|
||||
@include mobile {
|
||||
max-height: 10rem;
|
||||
max-width: 10rem;
|
||||
}
|
||||
.image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
204
components/NavBar.vue
Normal file
204
components/NavBar.vue
Normal file
@@ -0,0 +1,204 @@
|
||||
<template>
|
||||
<header class="header">
|
||||
<div class="container wrapper">
|
||||
<div class="navmenu-container">
|
||||
<NavMenu @logout="logout" />
|
||||
</div>
|
||||
<!-- isAdmin: {{ isAdmin }} <br>
|
||||
isAuthenticated: {{ isAuthenticated }} <br> -->
|
||||
<nav>
|
||||
<NuxtLink to="/">
|
||||
<img
|
||||
class="logo"
|
||||
src="@/assets/img/latienda-logo.png"
|
||||
alt="latienda.coop"
|
||||
/>
|
||||
</NuxtLink>
|
||||
<SearchInput v-if="$route.name == 'index'" class="search-input"/>
|
||||
<div class="nav-buttons">
|
||||
<NuxtLink to="/page/info">
|
||||
<img
|
||||
class="nav-buttons-info nav-icon"
|
||||
src="@/assets/img/latienda-info.svg"
|
||||
alt="latienda.coop"
|
||||
/>
|
||||
</NuxtLink>
|
||||
<div class="nav-buttons-dots"></div>
|
||||
<NuxtLink v-if="isAuthenticated & !isAdmin" to="/editar/perfil">
|
||||
<div class="nav-buttons-acceso">
|
||||
<img
|
||||
class="nav-icon"
|
||||
src="@/assets/img/latienda-acceder.svg"
|
||||
alt="latienda.coop"
|
||||
/>
|
||||
<div class="nav-text">{{ name }}</div>
|
||||
</div>
|
||||
</NuxtLink>
|
||||
<NuxtLink v-else-if="isAuthenticated & isAdmin" to="/admin">
|
||||
<div class="nav-buttons-acceso">
|
||||
<img
|
||||
class="nav-icon"
|
||||
src="@/assets/img/latienda-acceder.svg"
|
||||
alt="latienda.coop"
|
||||
/>
|
||||
<div class="nav-text">{{ name }}</div>
|
||||
</div>
|
||||
</NuxtLink>
|
||||
<NuxtLink v-else to="/login">
|
||||
<div class="nav-buttons-acceso">
|
||||
<img
|
||||
class="nav-icon"
|
||||
src="@/assets/img/latienda-acceder.svg"
|
||||
alt="latienda.coop"
|
||||
/>
|
||||
<div class="nav-text">Acceder</div>
|
||||
</div>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
|
||||
<!-- <nuxt-link to="/">Búsqueda</nuxt-link>
|
||||
<nuxt-link to="/auth/registro">Registrarse</nuxt-link>
|
||||
<nuxt-link to="/auth/login">Login</nuxt-link>
|
||||
<nuxt-link to="/editar">{{ $store.state.auth.email }}</nuxt-link>
|
||||
<nuxt-link to="/admin" v-if="isAdmin">Panel de administración</nuxt-link> -->
|
||||
<!-- <button @click="logout">Logout</button> -->
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions } from 'pinia'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
export default {
|
||||
|
||||
setup() {
|
||||
const auth = useAuthStore();
|
||||
return {
|
||||
auth,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isAdmin() {
|
||||
return this.auth.isAdmin
|
||||
},
|
||||
isAuthenticated() {
|
||||
return this.auth.isAuthenticated
|
||||
},
|
||||
name() {
|
||||
return this.auth.getName
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
...mapActions('auth', ['logout']),
|
||||
async logout() {
|
||||
try {
|
||||
await this.logout()
|
||||
this.$router.push('/login')
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.header {
|
||||
background-color: $color-green;
|
||||
padding: 10px;
|
||||
|
||||
@include mobile {
|
||||
position: fixed;
|
||||
z-index: 999999;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
nav {
|
||||
width: 100%;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.search-and-login {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 10rem;
|
||||
margin: 0 0.5rem;
|
||||
@include mobile {
|
||||
width: 9rem;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-icon {
|
||||
height: 1.25rem;
|
||||
}
|
||||
|
||||
.nav-buttons {
|
||||
width: auto;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin: 0 0.6rem;
|
||||
margin-left: 1.25rem;
|
||||
|
||||
@include mobile {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&-info {
|
||||
cursor: pointer;
|
||||
}
|
||||
&-dots:after {
|
||||
color: $color-navy;
|
||||
content: '\22EE';
|
||||
margin: 0.5rem;
|
||||
@include mobile {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
&-acceso {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
.nav-buttons-info {
|
||||
@include mobile {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav-text {
|
||||
font-size: $xs;
|
||||
color: $color-navy;
|
||||
margin: 0.5rem;
|
||||
@include mobile {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
115
components/NavBarEditar.vue
Normal file
115
components/NavBarEditar.vue
Normal file
@@ -0,0 +1,115 @@
|
||||
<template>
|
||||
<div class="navsearch_container container-fluid">
|
||||
<NuxtLink to="/editar/perfil">Mi perfil</NuxtLink>
|
||||
<NuxtLink :class="{ disabled: !coopIsValidated }" to="/editar/cooperativa"
|
||||
>Cooperativa</NuxtLink
|
||||
>
|
||||
<!-- <NuxtLink to="/editar/cooperativa/crear">Crear cooperativa</NuxtLink> -->
|
||||
<NuxtLink :class="{ disabled: !coopIsValidated }" to="/editar/productos"
|
||||
>Productos</NuxtLink
|
||||
>
|
||||
<NuxtLink
|
||||
:class="{ disabled: !coopIsValidated }"
|
||||
to="/editar/productos/importar"
|
||||
>Importar</NuxtLink
|
||||
>
|
||||
<NuxtLink to="/" @click="logout" >Cerrar sesión</NuxtLink>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
export default {
|
||||
setup() {
|
||||
const auth = useAuthStore();
|
||||
return {
|
||||
auth,
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
coopIsValidated: false,
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
await this.checkIfCoopValidated()
|
||||
},
|
||||
methods: {
|
||||
async logout() {
|
||||
await this.auth.logout()
|
||||
},
|
||||
//TODO: check if cooperative is validated is working
|
||||
async checkIfCoopValidated() {
|
||||
const result = await $fetch('my_company/', {
|
||||
baseURL: config.public.baseURL,
|
||||
method: 'GET',
|
||||
})
|
||||
this.coopIsValidated = result.data.company.is_validated
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.navsearch_container {
|
||||
border-bottom: 3px solid $color-grey-nav;
|
||||
text-align: center;
|
||||
padding: 20px 20px;
|
||||
|
||||
a {
|
||||
font-size: $m;
|
||||
font-weight: $bold;
|
||||
color: $color-navy;
|
||||
text-decoration: none;
|
||||
}
|
||||
a:nth-child(1):after,
|
||||
a:nth-child(2):after,
|
||||
a:nth-child(3):after,
|
||||
a:nth-child(4):after {
|
||||
color: $color-navy;
|
||||
content: '\22EE';
|
||||
margin: 0.5rem;
|
||||
}
|
||||
@include mobile {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.tooltip {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
border-bottom: 1px dotted black;
|
||||
}
|
||||
|
||||
.tooltip .tooltiptext {
|
||||
visibility: hidden;
|
||||
width: 120px;
|
||||
background-color: #555;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
border-radius: 6px;
|
||||
padding: 5px 0;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
bottom: 125%;
|
||||
left: 50%;
|
||||
margin-left: -60px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
.tooltip .tooltiptext::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 50%;
|
||||
margin-left: -5px;
|
||||
border-width: 5px;
|
||||
border-style: solid;
|
||||
border-color: #555 transparent transparent transparent;
|
||||
}
|
||||
|
||||
.tooltip:hover .tooltiptext {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
||||
46
components/NavBarEditarUser.vue
Normal file
46
components/NavBarEditarUser.vue
Normal file
@@ -0,0 +1,46 @@
|
||||
<template>
|
||||
<div class="navsearch_container container-fluid">
|
||||
<NuxtLink to="/editar/perfil">Mi perfil</NuxtLink>
|
||||
<NuxtLink to="/" @click="logout" >Cerrar sesión</NuxtLink>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
export default {
|
||||
setup() {
|
||||
const auth = useAuthStore();
|
||||
return {
|
||||
auth,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async logout() {
|
||||
await this.auth.logout()
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.navsearch_container {
|
||||
border-bottom: 3px solid $color-grey-nav;
|
||||
text-align: center;
|
||||
padding: 20px 20px;
|
||||
|
||||
a {
|
||||
font-size: $m;
|
||||
font-weight: $bold;
|
||||
color: $color-navy;
|
||||
text-decoration: none;
|
||||
}
|
||||
a:nth-child(1):after {
|
||||
color: $color-navy;
|
||||
content: '\22EE';
|
||||
margin: 0.5rem;
|
||||
}
|
||||
@include mobile {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
40
components/NavBarSearch.vue
Normal file
40
components/NavBarSearch.vue
Normal file
@@ -0,0 +1,40 @@
|
||||
<template>
|
||||
<div class="navsearch_container container-fluid">
|
||||
<NuxtLink to="/busqueda"> Todos</NuxtLink>
|
||||
<NuxtLink :to="{ name: 'busqueda', query: { order: 'newest' } }">
|
||||
Últimos productos</NuxtLink
|
||||
>
|
||||
<NuxtLink to="/busqueda"> Más buscados</NuxtLink>
|
||||
<NuxtLink to="/c"> Cooperativas</NuxtLink>
|
||||
<NuxtLink to="/registro"> Regístrate</NuxtLink>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script></script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.navsearch_container {
|
||||
border-bottom: 3px solid $color-grey-nav;
|
||||
text-align: center;
|
||||
padding: 1.25em 1.25em;
|
||||
|
||||
@include mobile {
|
||||
display: none;
|
||||
}
|
||||
|
||||
a {
|
||||
font-size: $m;
|
||||
font-weight: $bold;
|
||||
color: $color-navy;
|
||||
text-decoration: none;
|
||||
}
|
||||
a:nth-child(1):after,
|
||||
a:nth-child(2):after,
|
||||
a:nth-child(3):after,
|
||||
a:nth-child(4):after {
|
||||
color: $color-navy;
|
||||
content: '\22EE';
|
||||
margin: 0.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
276
components/NavMenu copy.vue
Normal file
276
components/NavMenu copy.vue
Normal file
@@ -0,0 +1,276 @@
|
||||
<template>
|
||||
<div class="nav-menu-container">
|
||||
<img
|
||||
class="burger"
|
||||
src="@/assets/img/latienda-burger-nav.svg"
|
||||
alt=""
|
||||
@click="isMenuOpen = !isMenuOpen"
|
||||
/>
|
||||
<div :class="isMenuOpen ? `shadow` : ''">
|
||||
<transition name="slider" mode="out-in">
|
||||
<div v-if="isMenuOpen" class="nav-menu">
|
||||
<img
|
||||
class="close-icon"
|
||||
src="@/assets/img/latienda-close-nav.svg"
|
||||
alt=""
|
||||
@click="isMenuOpen = !isMenuOpen"
|
||||
/>
|
||||
<nav class="nav">
|
||||
<ul class="section-list">
|
||||
<NuxtLink to="/">
|
||||
<li class="section" @click="isMenuOpen = !isMenuOpen">
|
||||
<img
|
||||
class="section-img"
|
||||
src="@/assets/img/latienda-ubicacion.svg"
|
||||
alt=""
|
||||
/>
|
||||
<span class="section-text">Inicio</span>
|
||||
</li>
|
||||
</NuxtLink>
|
||||
<NuxtLink to="/c">
|
||||
<li class="section" @click="isMenuOpen = !isMenuOpen">
|
||||
<img
|
||||
class="section-img"
|
||||
src="@/assets/img/latienda-tienda-nav.svg"
|
||||
alt=""
|
||||
/>
|
||||
<span class="section-text">Cooperativas</span>
|
||||
</li>
|
||||
</NuxtLink>
|
||||
<NuxtLink to="/page/info">
|
||||
<li class="section" @click="isMenuOpen = !isMenuOpen">
|
||||
<img
|
||||
class="section-img"
|
||||
src="@/assets/img/latienda-bag.svg"
|
||||
alt=""
|
||||
/>
|
||||
<span class="section-text">Sobre nosotros</span>
|
||||
</li>
|
||||
</NuxtLink>
|
||||
<li class="section" @click="isMenuOpen = !isMenuOpen">
|
||||
<a href="mailto:info@latienda.coop">
|
||||
<img
|
||||
class="section-img"
|
||||
src="@/assets/img/envelope-simple.svg"
|
||||
alt=""
|
||||
/>
|
||||
<span class="section-text">Contacto</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<ul class="login-list">
|
||||
<NuxtLink v-if="!isAuthenticated" to="/login">
|
||||
<li class="section" @click="isMenuOpen = !isMenuOpen">
|
||||
<img
|
||||
class="section-img"
|
||||
src="@/assets/img/latienda-lock.svg"
|
||||
alt=""
|
||||
/>
|
||||
<span class="section-text">Acceder</span>
|
||||
</li>
|
||||
</NuxtLink>
|
||||
<NuxtLink v-if="isManager" to="/editar/perfil">
|
||||
<li class="section" @click="isMenuOpen = !isMenuOpen">
|
||||
<img
|
||||
class="section-img"
|
||||
src="@/assets/img/latienda-user.svg"
|
||||
alt=""
|
||||
/>
|
||||
<span class="section-text">Perfil</span>
|
||||
</li>
|
||||
</NuxtLink>
|
||||
<NuxtLink v-if="isManager" to="/editar/cooperativa">
|
||||
<li class="section" @click="isMenuOpen = !isMenuOpen">
|
||||
<span class="section-text login">Cooperativa</span>
|
||||
</li>
|
||||
</NuxtLink>
|
||||
<NuxtLink v-if="isManager" to="/editar/productos">
|
||||
<li class="section" @click="isMenuOpen = !isMenuOpen">
|
||||
<span class="section-text login">Productos</span>
|
||||
</li>
|
||||
</NuxtLink>
|
||||
<NuxtLink v-if="isManager" to="/editar/productos/importar">
|
||||
<li class="section" @click="isMenuOpen = !isMenuOpen">
|
||||
<span class="section-text login">Importar</span>
|
||||
</li>
|
||||
</NuxtLink>
|
||||
<NuxtLink v-if="isAuthenticated" @click.native="logout" to="/">
|
||||
<li class="section" @click="isMenuOpen = !isMenuOpen">
|
||||
<img
|
||||
class="section-img"
|
||||
src="@/assets/img/latienda-sign-out.svg"
|
||||
alt=""
|
||||
/>
|
||||
<span class="section-text">Cerrar sesión</span>
|
||||
</li>
|
||||
</NuxtLink>
|
||||
</ul>
|
||||
<ul class="link-list">
|
||||
<li class="link">
|
||||
<a href="https://coceta.coop/" target="_blank">
|
||||
<span class="link-text">Coceta</span>
|
||||
</a>
|
||||
</li>
|
||||
<NuxtLink to="/page/terminos">
|
||||
<li class="link" @click="isMenuOpen = !isMenuOpen">
|
||||
<span class="link-text">Términos y condiciones</span>
|
||||
</li>
|
||||
</NuxtLink>
|
||||
<NuxtLink to="/page/legal">
|
||||
<li class="link" @click="isMenuOpen = !isMenuOpen">
|
||||
<span class="link-text">Política de privacidad</span>
|
||||
</li>
|
||||
</NuxtLink>
|
||||
<NuxtLink to="/page/cookies">
|
||||
<li class="link" @click="isMenuOpen = !isMenuOpen">
|
||||
<span class="link-text">Cookies</span>
|
||||
</li>
|
||||
</NuxtLink>
|
||||
</ul>
|
||||
<div class="credits">
|
||||
<span>2021 La Tienda.Coop</span>
|
||||
<a href="http://enreda.coop/" target="_blank"
|
||||
>Sitio desarrollado por Enreda</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
isMenuOpen: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isAuthenticated() {
|
||||
return this.$store.getters['auth/isAuthenticated']
|
||||
},
|
||||
isManager() {
|
||||
return this.$store.getters['auth/isManager']
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async logout() {
|
||||
this.isMenuOpen = false
|
||||
await this.$store.dispatch('auth/logout')
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.slider-enter-active,
|
||||
.slider-leave-active {
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
.slider-enter,
|
||||
.slider-leave-to {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
.nav-menu-container {
|
||||
@include tablet {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-menu {
|
||||
font-family: $font-primary;
|
||||
padding: 30px 0 0 20px;
|
||||
background-color: $color-green;
|
||||
height: 100vh;
|
||||
top: 0;
|
||||
left: 0;
|
||||
position: fixed;
|
||||
z-index: 9999999999;
|
||||
box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2);
|
||||
overflow: scroll;
|
||||
@include mobile {
|
||||
width: 70%;
|
||||
}
|
||||
@include tablet {
|
||||
width: 30%;
|
||||
}
|
||||
}
|
||||
|
||||
.shadow {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 999999;
|
||||
}
|
||||
|
||||
.burger,
|
||||
.close-icon {
|
||||
width: 1.8rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.close-icon {
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.section {
|
||||
padding: 0.4em 0;
|
||||
}
|
||||
|
||||
.section-list {
|
||||
padding-bottom: 1rem;
|
||||
border-bottom: 1px solid $color-navy;
|
||||
}
|
||||
|
||||
.section-text {
|
||||
font-weight: $medium;
|
||||
font-size: $s;
|
||||
}
|
||||
|
||||
.section-img {
|
||||
width: 1.2rem;
|
||||
margin-right: 0.8rem;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
color: $color-navy;
|
||||
}
|
||||
|
||||
.link-list,
|
||||
.credits {
|
||||
margin-top: 1rem;
|
||||
margin-left: 1rem;
|
||||
padding: 0.1em;
|
||||
}
|
||||
.link {
|
||||
padding: 0.3em 0;
|
||||
font-size: $xs;
|
||||
}
|
||||
.credits {
|
||||
margin-top: 1.5rem;
|
||||
span,
|
||||
a {
|
||||
display: block;
|
||||
color: $color-navy;
|
||||
font-size: $xs;
|
||||
padding: 0.3em 0;
|
||||
}
|
||||
margin-bottom: 4rem;
|
||||
}
|
||||
.login {
|
||||
padding-left: 2rem;
|
||||
font-weight: $regular;
|
||||
}
|
||||
</style>
|
||||
287
components/NavMenu.vue
Normal file
287
components/NavMenu.vue
Normal file
@@ -0,0 +1,287 @@
|
||||
<template>
|
||||
<div class="nav-menu-container">
|
||||
<img
|
||||
class="burger"
|
||||
src="@/assets/img/latienda-burger-nav.svg"
|
||||
alt=""
|
||||
@click="isMenuOpen = !isMenuOpen"
|
||||
/>
|
||||
<div :class="isMenuOpen ? `shadow` : ''">
|
||||
<transition name="slider" mode="out-in">
|
||||
<div v-if="isMenuOpen" class="nav-menu">
|
||||
<img
|
||||
class="close-icon"
|
||||
src="@/assets/img/latienda-close-nav.svg"
|
||||
alt=""
|
||||
@click="isMenuOpen = !isMenuOpen"
|
||||
/>
|
||||
<nav class="nav">
|
||||
<ul class="section-list">
|
||||
<NuxtLink to="/">
|
||||
<li class="section" @click="isMenuOpen = !isMenuOpen">
|
||||
<img
|
||||
class="section-img"
|
||||
src="@/assets/img/latienda-ubicacion.svg"
|
||||
alt=""
|
||||
/>
|
||||
<span class="section-text">Inicio</span>
|
||||
</li>
|
||||
</NuxtLink>
|
||||
<NuxtLink to="/c">
|
||||
<li class="section" @click="isMenuOpen = !isMenuOpen">
|
||||
<img
|
||||
class="section-img"
|
||||
src="@/assets/img/latienda-tienda-nav.svg"
|
||||
alt=""
|
||||
/>
|
||||
<span class="section-text">Cooperativas</span>
|
||||
</li>
|
||||
</NuxtLink>
|
||||
<NuxtLink to="/page/info">
|
||||
<li class="section" @click="isMenuOpen = !isMenuOpen">
|
||||
<img
|
||||
class="section-img"
|
||||
src="@/assets/img/latienda-bag.svg"
|
||||
alt=""
|
||||
/>
|
||||
<span class="section-text">Sobre nosotros</span>
|
||||
</li>
|
||||
</NuxtLink>
|
||||
<li class="section" @click="isMenuOpen = !isMenuOpen">
|
||||
<a href="mailto:info@latienda.coop">
|
||||
<img
|
||||
class="section-img"
|
||||
src="@/assets/img/envelope-simple.svg"
|
||||
alt=""
|
||||
/>
|
||||
<span class="section-text">Contacto</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<ul class="login-list">
|
||||
<NuxtLink v-if="!isAuthenticated" to="/login">
|
||||
<li class="section" @click="isMenuOpen = !isMenuOpen">
|
||||
<img
|
||||
class="section-img"
|
||||
src="@/assets/img/latienda-lock.svg"
|
||||
alt=""
|
||||
/>
|
||||
<span class="section-text">Acceder</span>
|
||||
</li>
|
||||
</NuxtLink>
|
||||
<NuxtLink v-if="isManager" to="/editar/perfil">
|
||||
<li class="section" @click="isMenuOpen = !isMenuOpen">
|
||||
<img
|
||||
class="section-img"
|
||||
src="@/assets/img/latienda-user.svg"
|
||||
alt=""
|
||||
/>
|
||||
<span class="section-text">Perfil</span>
|
||||
</li>
|
||||
</NuxtLink>
|
||||
<NuxtLink v-if="isManager" to="/editar/cooperativa">
|
||||
<li class="section" @click="isMenuOpen = !isMenuOpen">
|
||||
<span class="section-text login">Cooperativa</span>
|
||||
</li>
|
||||
</NuxtLink>
|
||||
<NuxtLink v-if="isManager" to="/editar/productos">
|
||||
<li class="section" @click="isMenuOpen = !isMenuOpen">
|
||||
<span class="section-text login">Productos</span>
|
||||
</li>
|
||||
</NuxtLink>
|
||||
<NuxtLink v-if="isManager" to="/editar/productos/importar">
|
||||
<li class="section" @click="isMenuOpen = !isMenuOpen">
|
||||
<span class="section-text login">Importar</span>
|
||||
</li>
|
||||
</NuxtLink>
|
||||
<NuxtLink v-if="isAuthenticated" @click="logout" to="/">
|
||||
<li class="section" @click="isMenuOpen = !isMenuOpen">
|
||||
<img
|
||||
class="section-img"
|
||||
src="@/assets/img/latienda-sign-out.svg"
|
||||
alt=""
|
||||
/>
|
||||
<span class="section-text">Cerrar sesión</span>
|
||||
</li>
|
||||
</NuxtLink>
|
||||
</ul>
|
||||
<ul class="link-list">
|
||||
<li class="link">
|
||||
<a href="https://coceta.coop/" target="_blank">
|
||||
<span class="link-text">Coceta</span>
|
||||
</a>
|
||||
</li>
|
||||
<NuxtLink to="/page/terminos">
|
||||
<li class="link" @click="isMenuOpen = !isMenuOpen">
|
||||
<span class="link-text">Términos y condiciones</span>
|
||||
</li>
|
||||
</NuxtLink>
|
||||
<NuxtLink to="/page/legal">
|
||||
<li class="link" @click="isMenuOpen = !isMenuOpen">
|
||||
<span class="link-text">Política de privacidad</span>
|
||||
</li>
|
||||
</NuxtLink>
|
||||
<NuxtLink to="/page/cookies">
|
||||
<li class="link" @click="isMenuOpen = !isMenuOpen">
|
||||
<span class="link-text">Cookies</span>
|
||||
</li>
|
||||
</NuxtLink>
|
||||
</ul>
|
||||
<div class="credits">
|
||||
<span>2021 La Tienda.Coop</span>
|
||||
<a href="http://enreda.coop/" target="_blank"
|
||||
>Sitio desarrollado por Enreda</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions } from 'pinia'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
const auth = useAuthStore();
|
||||
return {
|
||||
auth,
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isMenuOpen: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isAuthenticated() {
|
||||
return this.auth.isAuthenticated
|
||||
},
|
||||
isManager() {
|
||||
return this.auth.isManager
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions('auth', ['logout']),
|
||||
async logout() {
|
||||
this.isMenuOpen = false
|
||||
this.$emit('logout')
|
||||
await this.logout()
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.slider-enter-active,
|
||||
.slider-leave-active {
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
.slider-enter,
|
||||
.slider-leave-to {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
.nav-menu-container {
|
||||
@include tablet {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-menu {
|
||||
font-family: $font-primary;
|
||||
padding: 30px 0 0 20px;
|
||||
background-color: $color-green;
|
||||
height: 100vh;
|
||||
top: 0;
|
||||
left: 0;
|
||||
position: fixed;
|
||||
z-index: 9999999999;
|
||||
box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2);
|
||||
overflow: scroll;
|
||||
@include mobile {
|
||||
width: 70%;
|
||||
}
|
||||
@include tablet {
|
||||
width: 30%;
|
||||
}
|
||||
}
|
||||
|
||||
.shadow {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 999999;
|
||||
}
|
||||
|
||||
.burger,
|
||||
.close-icon {
|
||||
width: 1.8rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.close-icon {
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.section {
|
||||
padding: 0.4em 0;
|
||||
}
|
||||
|
||||
.section-list {
|
||||
padding-bottom: 1rem;
|
||||
border-bottom: 1px solid $color-navy;
|
||||
}
|
||||
|
||||
.section-text {
|
||||
font-weight: $medium;
|
||||
font-size: $s;
|
||||
}
|
||||
|
||||
.section-img {
|
||||
width: 1.2rem;
|
||||
margin-right: 0.8rem;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
color: $color-navy;
|
||||
}
|
||||
|
||||
.link-list,
|
||||
.credits {
|
||||
margin-top: 1rem;
|
||||
margin-left: 1rem;
|
||||
padding: 0.1em;
|
||||
}
|
||||
.link {
|
||||
padding: 0.3em 0;
|
||||
font-size: $xs;
|
||||
}
|
||||
.credits {
|
||||
margin-top: 1.5rem;
|
||||
span,
|
||||
a {
|
||||
display: block;
|
||||
color: $color-navy;
|
||||
font-size: $xs;
|
||||
padding: 0.3em 0;
|
||||
}
|
||||
margin-bottom: 4rem;
|
||||
}
|
||||
.login {
|
||||
padding-left: 2rem;
|
||||
font-weight: $regular;
|
||||
}
|
||||
</style>
|
||||
304
components/SearchHeader.vue
Normal file
304
components/SearchHeader.vue
Normal file
@@ -0,0 +1,304 @@
|
||||
<template>
|
||||
<div class="container wrapper">
|
||||
<form @submit.prevent="search" class="search-container">
|
||||
<div class="categorias-wrapper">
|
||||
<select v-model="selectedCategory" class="categorias">
|
||||
<option selected value="">Todas las categorías</option>
|
||||
<option
|
||||
v-for="(category, key) in categories"
|
||||
:key="key"
|
||||
:value="category"
|
||||
>
|
||||
{{ category }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<input
|
||||
id="searchbox"
|
||||
@focus="focused"
|
||||
@blur="focusedOut"
|
||||
v-model="searchText"
|
||||
class="search-text"
|
||||
type="text"
|
||||
autocomplete="off"
|
||||
placeholder=""
|
||||
/>
|
||||
<div class="search-link">
|
||||
<img
|
||||
class="search-icon"
|
||||
src="@/assets/img/latienda-search.svg"
|
||||
alt="latienda.coop-search"
|
||||
@click="search"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'SearchHeader',
|
||||
data() {
|
||||
return {
|
||||
searchText: '',
|
||||
|
||||
typing: null,
|
||||
|
||||
selectedCategory: '',
|
||||
|
||||
categories: [
|
||||
'Alimentación, bebida y tabaco',
|
||||
'Arte y ocio',
|
||||
'Bebés y niños pequeños',
|
||||
'Bricolaje',
|
||||
'Cámaras y ópticas',
|
||||
'Casa y jardín',
|
||||
'Economía e industria',
|
||||
'Electrónica',
|
||||
'Elementos religiosos y ceremoniales',
|
||||
'Equipamiento deportivo',
|
||||
'Juegos y juguetes',
|
||||
'Maletas y bolsos de viaje',
|
||||
'Material de oficina',
|
||||
'Mobiliario',
|
||||
'Multimedia',
|
||||
'Productos para adultos',
|
||||
'Productos para mascotas y animales',
|
||||
'Ropa y accesorios',
|
||||
'Salud y belleza',
|
||||
'Software',
|
||||
'Vehículos y recambios',
|
||||
],
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.startTyping()
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.stopTyping()
|
||||
},
|
||||
|
||||
methods: {
|
||||
focused() {
|
||||
this.stopTyping()
|
||||
document.querySelector('#searchbox').setAttribute('placeholder', '')
|
||||
},
|
||||
focusedOut() {
|
||||
document.querySelector('#searchbox').setAttribute('placeholder', '')
|
||||
},
|
||||
sleep(ms) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms))
|
||||
},
|
||||
startTyping() {
|
||||
let current = ''
|
||||
let i = 0
|
||||
let word = 0
|
||||
let step = 0
|
||||
let input = document.querySelector('#searchbox')
|
||||
let placeholderTexts = [
|
||||
'Jabón sólido',
|
||||
'Huertos de libertad',
|
||||
'Hierbabuena',
|
||||
'Energía eléctrica',
|
||||
]
|
||||
this.typing = setInterval(() => {
|
||||
if (current === placeholderTexts[word]) {
|
||||
step++
|
||||
if (step === 10) {
|
||||
current = ''
|
||||
i = 0
|
||||
word++
|
||||
input.setAttribute('placeholder', current)
|
||||
step = 0
|
||||
if (word === placeholderTexts.length) {
|
||||
word = 0
|
||||
}
|
||||
}
|
||||
} else {
|
||||
current += placeholderTexts[word].charAt(i)
|
||||
input.setAttribute('placeholder', current)
|
||||
i++
|
||||
}
|
||||
}, 100)
|
||||
},
|
||||
stopTyping() {
|
||||
clearInterval(this.typing)
|
||||
},
|
||||
search() {
|
||||
if (this.searchText) {
|
||||
if (this.selectedCategory !== '') {
|
||||
return this.$router.push({
|
||||
name: 'busqueda',
|
||||
query: {
|
||||
q: this.searchText,
|
||||
category: this.selectedCategory,
|
||||
},
|
||||
})
|
||||
} else {
|
||||
return this.$router.push({
|
||||
name: 'busqueda',
|
||||
query: { q: this.searchText },
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
clearSearchText() {
|
||||
this.searchText = ''
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.wrapper {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
background-color: $color-light;
|
||||
height: 60px;
|
||||
border-radius: 40px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin: 15px 0 50px;
|
||||
-webkit-box-shadow: 0px 0px 20px 0px #d1d1d1; /* Android 2.3+, iOS 4.0.2-4.2, Safari 3-4 */
|
||||
box-shadow: 0px 0px 20px 0px #d1d1d1;
|
||||
@include mobile {
|
||||
height: 40px;
|
||||
margin: 1rem auto;
|
||||
}
|
||||
@include tablet {
|
||||
width: 70%;
|
||||
}
|
||||
}
|
||||
|
||||
.search-link {
|
||||
@include mobile {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
padding: 0.6rem;
|
||||
float: right;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-decoration: none;
|
||||
transition: 0.4s;
|
||||
}
|
||||
@include tablet {
|
||||
width: 4rem;
|
||||
margin-right: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.categorias-wrapper {
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, #1aceb8, #0bbfba);
|
||||
padding: 0.4em 0.5em 0.4em 1.2em;
|
||||
|
||||
@include mobile {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.categorias {
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
background: transparent;
|
||||
color: $color-light;
|
||||
height: 100%;
|
||||
width: 18rem;
|
||||
-moz-appearance: none;
|
||||
text-align: center;
|
||||
|
||||
@include mobile {
|
||||
display: none;
|
||||
}
|
||||
@include tablet {
|
||||
width: 14rem;
|
||||
}
|
||||
}
|
||||
|
||||
.search-icon {
|
||||
cursor: pointer;
|
||||
@include mobile {
|
||||
margin-left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
@include tablet {
|
||||
float: right;
|
||||
height: 70%;
|
||||
}
|
||||
}
|
||||
|
||||
.search-text {
|
||||
outline: none;
|
||||
width: 100%;
|
||||
|
||||
::-webkit-input-placeholder {
|
||||
display: inline-block;
|
||||
opacity: 0.2;
|
||||
transition: all 0.3s ease-in-out;
|
||||
padding-right: 0.15em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
input:focus::-webkit-input-placeholder {
|
||||
-webkit-transform: translateY(-125%);
|
||||
transform: translateY(-125%);
|
||||
font-size: 75%;
|
||||
opacity: 0.05;
|
||||
}
|
||||
|
||||
input.imitatefocus::-webkit-input-placeholder {
|
||||
-webkit-transform: translateY(-125%);
|
||||
transform: translateY(-125%);
|
||||
opacity: 0.05;
|
||||
}
|
||||
|
||||
@include mobile {
|
||||
border: none;
|
||||
background: none;
|
||||
outline: none;
|
||||
float: left;
|
||||
color: $color-greytext;
|
||||
font-size: 16px;
|
||||
transition: 0.4s;
|
||||
line-height: 2.5rem;
|
||||
width: 0rem;
|
||||
}
|
||||
@include tablet {
|
||||
padding: 0 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
select {
|
||||
-webkit-appearance: auto;
|
||||
}
|
||||
|
||||
.categorias option {
|
||||
color: $color-grey-darker;
|
||||
font-family: $font-primary, Arial;
|
||||
}
|
||||
|
||||
@include mobile {
|
||||
.search-container:matches(:hover, :focus-within) > .search-text {
|
||||
width: 12rem;
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
.search-text:hover > .search-link {
|
||||
align-self: right;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
224
components/SearchInput.vue
Normal file
224
components/SearchInput.vue
Normal file
@@ -0,0 +1,224 @@
|
||||
<template>
|
||||
<form class="search-container" @submit.prevent="search">
|
||||
<div class="categorias-wrapper">
|
||||
<select v-model="searchCategory" class="categorias">
|
||||
<option selected value="">Todas las categorías</option>
|
||||
<option
|
||||
v-for="(category, key) in categories"
|
||||
:key="key"
|
||||
:value="category"
|
||||
>
|
||||
{{ category }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<input
|
||||
v-model="searchText"
|
||||
class="search-text"
|
||||
type="text"
|
||||
autocomplete="off"
|
||||
placeholder="Buscar"
|
||||
/>
|
||||
<div class="search-link">
|
||||
<img
|
||||
class="search-icon"
|
||||
src="@/assets/img/latienda-search-blue.svg"
|
||||
alt="latienda.coop-search"
|
||||
@click="search"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'SearchInput',
|
||||
data() {
|
||||
return {
|
||||
searchText: '',
|
||||
searchCategory: '',
|
||||
|
||||
categories: [
|
||||
'Alimentación, bebida y tabaco',
|
||||
'Arte y ocio',
|
||||
'Bebés y niños pequeños',
|
||||
'Bricolaje',
|
||||
'Cámaras y ópticas',
|
||||
'Casa y jardín',
|
||||
'Economía e industria',
|
||||
'Electrónica',
|
||||
'Elementos religiosos y ceremoniales',
|
||||
'Equipamiento deportivo',
|
||||
'Juegos y juguetes',
|
||||
'Maletas y bolsos de viaje',
|
||||
'Material de oficina',
|
||||
'Mobiliario',
|
||||
'Multimedia',
|
||||
'Productos para adultos',
|
||||
'Productos para mascotas y animales',
|
||||
'Ropa y accesorios',
|
||||
'Salud y belleza',
|
||||
'Software',
|
||||
'Vehículos y recambios',
|
||||
],
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
search() {
|
||||
if (this.searchText) {
|
||||
if (this.searchCategory) {
|
||||
return this.$router.push({
|
||||
name: 'busqueda',
|
||||
query: { q: this.searchText, category: [this.searchCategory] },
|
||||
})
|
||||
} else {
|
||||
return this.$router.push({
|
||||
name: 'busqueda',
|
||||
query: { q: this.searchText },
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.search-container {
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
height: 40px;
|
||||
border-radius: 40px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin: 50px 5px;
|
||||
|
||||
@include mobile {
|
||||
}
|
||||
@include tablet {
|
||||
width: 40%;
|
||||
}
|
||||
@include desktop {
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.categorias-wrapper {
|
||||
height: 100%;
|
||||
padding: 6px, 10px;
|
||||
border-right: 1px solid rgba(104, 102, 102, 0.5);
|
||||
|
||||
@include mobile {
|
||||
display: none;
|
||||
}
|
||||
@include tablet {
|
||||
display: none;
|
||||
}
|
||||
@include desktop {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.categorias {
|
||||
outline: none;
|
||||
border: none;
|
||||
--webkit-appearance: none;
|
||||
--moz-appearance: none;
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
background: transparent;
|
||||
color: $color-navy;
|
||||
height: 100%;
|
||||
width: 200px;
|
||||
font-size: $s;
|
||||
padding-left: 1rem;
|
||||
@include mobile {
|
||||
display: none;
|
||||
}
|
||||
@include tablet {
|
||||
display: none;
|
||||
}
|
||||
@include desktop {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.search-link {
|
||||
@include mobile {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
padding: 0.6rem;
|
||||
float: right;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-decoration: none;
|
||||
transition: 0.4s;
|
||||
}
|
||||
@include tablet {
|
||||
width: 4rem;
|
||||
margin-right: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.search-icon {
|
||||
@include mobile {
|
||||
margin-left: 0;
|
||||
width: 100%;
|
||||
padding: 0.1rem;
|
||||
}
|
||||
@include tablet {
|
||||
float: right;
|
||||
width: 100%;
|
||||
padding: 1rem;
|
||||
}
|
||||
@include desktop {
|
||||
margin-left: 0;
|
||||
width: 100%;
|
||||
padding: 0.4rem;
|
||||
}
|
||||
}
|
||||
|
||||
.search-text {
|
||||
outline: none;
|
||||
border: none;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
color: $color-navy;
|
||||
font-size: $s;
|
||||
|
||||
@include mobile {
|
||||
border: none;
|
||||
background: none;
|
||||
float: left;
|
||||
color: $color-greytext;
|
||||
font-size: 16px;
|
||||
transition: 0.4s;
|
||||
line-height: 2.5rem;
|
||||
width: 0rem;
|
||||
}
|
||||
}
|
||||
|
||||
::placeholder {
|
||||
color: $color-navy;
|
||||
font-size: $s;
|
||||
}
|
||||
|
||||
select {
|
||||
--webkit-appearance: auto;
|
||||
}
|
||||
|
||||
.search-container:matches(:hover, :focus-within) > .search-text {
|
||||
@include mobile {
|
||||
width: 60px;
|
||||
padding: 0 0.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.search-text:hover > .search-link {
|
||||
@include mobile {
|
||||
align-self: right;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
33
components/SubmitButton.vue
Normal file
33
components/SubmitButton.vue
Normal file
@@ -0,0 +1,33 @@
|
||||
<template>
|
||||
<button class="submit-btn" type="submit">
|
||||
<span>{{ text }}</span>
|
||||
<img :src="imageUrl" alt="" />
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
text: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
imageUrl: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.submit-btn {
|
||||
background-color: $color-orange;
|
||||
color: $color-light;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
text-transform: uppercase;
|
||||
padding: 15px 20px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user