wip coop/[id] page
This commit is contained in:
237
components/CoopCard.vue
Normal file
237
components/CoopCard.vue
Normal file
@@ -0,0 +1,237 @@
|
||||
<template>
|
||||
<div class="productcard_container">
|
||||
<div class="row productcard_container-basic">
|
||||
<div class="image_container col-md-2">
|
||||
<img
|
||||
v-if="coop.logo"
|
||||
class="image"
|
||||
:src="coop.logo"
|
||||
:alt="coop.company_name"
|
||||
/>
|
||||
<img
|
||||
v-else
|
||||
class="image"
|
||||
src="@/assets/img/latienda-product-default.svg"
|
||||
:alt="coop.company_name"
|
||||
/>
|
||||
</div>
|
||||
<div class="info_container col-md-6" align="left">
|
||||
<NuxtLink :to="`/c/${this.coop.id}`">
|
||||
<h2>{{ coop.company_name }}</h2>
|
||||
</NuxtLink>
|
||||
<p class="description">{{ coop.description }}</p>
|
||||
<div class="tags_container">
|
||||
<NuxtLink
|
||||
:to="tagRoute(n)"
|
||||
class="tag_container"
|
||||
v-for="n in coop.tags"
|
||||
:key="n"
|
||||
>
|
||||
<img class="tag_img" src="@/assets/img/latienda-tag.svg" />
|
||||
<span>{{ n }}</span>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 button_container" align="center">
|
||||
<a v-if="coop.shop_link" :href="coop.shop_link" class="button_buy">
|
||||
<img
|
||||
alt="tienda"
|
||||
class="button_cart_img"
|
||||
src="@/assets/img/latienda-tienda.svg"
|
||||
/>
|
||||
<span>Tienda online</span>
|
||||
</a>
|
||||
<a v-if="coop.web_link" :href="coop.web_link" class="button_buy">
|
||||
<img
|
||||
alt="web"
|
||||
class="button_cart_img"
|
||||
src="@/assets/img/latienda-web.svg"
|
||||
/>
|
||||
<span>Página web</span>
|
||||
</a>
|
||||
<div class="smlogos_container">
|
||||
<div class="smlogo_container">
|
||||
<a @click="shareFacebook">
|
||||
<img
|
||||
class="smlogo_img"
|
||||
alt="facebook logo"
|
||||
src="@/assets/img/latienda-smlogo-facebook.svg"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
<a @click="shareTwitter">
|
||||
<div class="smlogo_container">
|
||||
<img
|
||||
class="smlogo_img"
|
||||
alt="twitter logo"
|
||||
src="@/assets/img/latienda-smlogo-twitter.svg"
|
||||
/>
|
||||
</div>
|
||||
</a>
|
||||
<a
|
||||
:href="shareWhatsApp()"
|
||||
data-action="share/whatsapp/share"
|
||||
target="_blank"
|
||||
title="latiendacoop"
|
||||
>
|
||||
<div class="smlogo_container">
|
||||
<img
|
||||
alt="whatsapp logo"
|
||||
class="smlogo_img"
|
||||
src="@/assets/img/latienda-smlogo-whatsapp.svg"
|
||||
/>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import socialShare from '~/utils/socialShare'
|
||||
export default {
|
||||
name: 'CoopCard',
|
||||
props: ['coop'],
|
||||
|
||||
computed: {
|
||||
coopUrl() {
|
||||
return `${window.location.origin}/c/${this.coop.id}`
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
tagRoute(tag) {
|
||||
return `/busqueda?tags=${tag}`
|
||||
},
|
||||
|
||||
shareFacebook() {
|
||||
const url = socialShare.facebook(this.coopUrl)
|
||||
window.open(url, '_blank')
|
||||
},
|
||||
shareTwitter() {
|
||||
const url = socialShare.twitter(this.coopUrl)
|
||||
window.open(url, '_blank')
|
||||
},
|
||||
shareWhatsApp() {
|
||||
return socialShare.whatsApp(this.coopUrl)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.productcard_container {
|
||||
border: 3px #e9e9e9 solid;
|
||||
border-radius: 5px;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
.productcard_container-basic {
|
||||
padding: 25px 20px;
|
||||
}
|
||||
|
||||
.image_container {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.info_container {
|
||||
h2 {
|
||||
outline: none;
|
||||
font-weight: $medium;
|
||||
color: $color-navy;
|
||||
font-size: $m;
|
||||
}
|
||||
.price {
|
||||
font-weight: $bold;
|
||||
color: $color-navy;
|
||||
font-size: $m;
|
||||
}
|
||||
span {
|
||||
color: #808080;
|
||||
}
|
||||
.description {
|
||||
margin-top: 8px;
|
||||
font-family: $font-secondary;
|
||||
font-size: $s;
|
||||
color: $color-greytext;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 5;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.button_container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-size: $s;
|
||||
|
||||
.button_buy {
|
||||
width: 100%;
|
||||
color: $color-orange;
|
||||
font-weight: $bold;
|
||||
padding: 10px 0;
|
||||
margin-bottom: 5px;
|
||||
border: 3px solid $color-orange;
|
||||
border-radius: 5px;
|
||||
background-color: $color-light;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 4px 16px rgba(99, 99, 99, 0.2);
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tag_container {
|
||||
margin: 25px 6px 0 0;
|
||||
border: 2px solid $color-greylayout;
|
||||
border-radius: 5px;
|
||||
padding: 6px 10px;
|
||||
display: inline-block;
|
||||
font-family: $font-secondary;
|
||||
font-size: $xs;
|
||||
color: $color-greytext;
|
||||
|
||||
.tag_img {
|
||||
width: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
.smlogo_container {
|
||||
display: inline-block;
|
||||
margin-top: 15px;
|
||||
|
||||
.smlogo_img {
|
||||
width: 35px;
|
||||
fill: $color-greytext;
|
||||
margin: 2px;
|
||||
}
|
||||
img:hover {
|
||||
transform: scale(1.1);
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
}
|
||||
|
||||
.button_cart_img {
|
||||
width: 20px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.content > h2,
|
||||
h3,
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -1,276 +0,0 @@
|
||||
<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>
|
||||
506
components/ProductCard.vue
Normal file
506
components/ProductCard.vue
Normal file
@@ -0,0 +1,506 @@
|
||||
<template>
|
||||
<div class="productcard_container">
|
||||
<div class="row productcard_container-basic">
|
||||
<div class="image_container" :class="expanded ? 'col-md-5' : 'col-md-2'">
|
||||
<img
|
||||
v-if="product.image"
|
||||
class="image"
|
||||
:src="product.image"
|
||||
:alt="product.name"
|
||||
/>
|
||||
<img
|
||||
v-else
|
||||
class="image"
|
||||
src="@/assets/img/latienda-product-default.svg"
|
||||
:alt="product.name"
|
||||
/>
|
||||
</div>
|
||||
<div class="info_container" :class="expanded ? 'col-md-5' : 'col-md-6'">
|
||||
<h2 v-b-toggle="'collapse-' + product.id" variant="primary">
|
||||
{{ product.name }}
|
||||
</h2>
|
||||
<span v-if="product.price" class="price">{{
|
||||
`${product.price}€`
|
||||
}}</span>
|
||||
<span v-else class="price">Precio a consultar</span>
|
||||
<span v-if="Number(product.shipping_cost)"
|
||||
>| {{ `Gastos de envío ${product.shipping_cost}€` }}</span
|
||||
>
|
||||
<span v-else>| Sin gastos de envío</span>
|
||||
|
||||
<span v-if="product.stock">| {{ `Stock ${product.stock}` }} </span>
|
||||
|
||||
<div
|
||||
class="description"
|
||||
:class="{ 'not-expanded-description': !expanded }"
|
||||
>
|
||||
<p
|
||||
v-if="product.description"
|
||||
v-sanitize="[
|
||||
{
|
||||
allowedTags: ['p'],
|
||||
allowedAttributes: {},
|
||||
},
|
||||
product.description,
|
||||
]"
|
||||
>
|
||||
<span v-if="product.shipping_terms">{{
|
||||
product.shipping_terms
|
||||
}}</span>
|
||||
</p>
|
||||
</div>
|
||||
<b-collapse :id="'collapse-' + product.id" accordion="my-accordion">
|
||||
<div class="tags_container">
|
||||
<NuxtLink
|
||||
:to="tagRoute(n)"
|
||||
class="tag_container"
|
||||
v-for="n in product.tags"
|
||||
:key="n"
|
||||
>
|
||||
<img
|
||||
alt="tag image"
|
||||
class="tag_img"
|
||||
src="@/assets/img/latienda-tag.svg"
|
||||
/>
|
||||
<span>{{ n }}</span>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
<div class="smlogos_container">
|
||||
<p class="share-text">Comparte:</p>
|
||||
<div class="smlogo_container">
|
||||
<a class="smlogo_link" @click="shareFacebook">
|
||||
<img
|
||||
class="smlogo_img"
|
||||
alt="facebook logo"
|
||||
src="@/assets/img/latienda-smlogo-facebook.svg"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
<!-- <a @click="shareTwitter"> -->
|
||||
<a :href="shareTwitter()">
|
||||
<div class="smlogo_container">
|
||||
<img
|
||||
class="smlogo_img"
|
||||
alt="twitter logo"
|
||||
src="@/assets/img/latienda-smlogo-twitter.svg"
|
||||
/>
|
||||
</div>
|
||||
</a>
|
||||
<a
|
||||
:href="shareWhatsApp()"
|
||||
data-action="share/whatsapp/share"
|
||||
target="_blank"
|
||||
title="latiendacoop"
|
||||
>
|
||||
<div class="smlogo_container">
|
||||
<img
|
||||
alt="whatsapp logo"
|
||||
class="smlogo_img"
|
||||
src="@/assets/img/latienda-smlogo-whatsapp.svg"
|
||||
/>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div v-if="product.company" class="coop_info">
|
||||
<NuxtLink :to="`c/${product.company.id}`">
|
||||
<h2>{{ product.company.company_name }}</h2>
|
||||
</NuxtLink>
|
||||
<p>{{ product.company.description }}</p>
|
||||
<a :href="product.company.web_link">{{
|
||||
product.company.web_link
|
||||
}}</a>
|
||||
</div>
|
||||
</b-collapse>
|
||||
</div>
|
||||
<div
|
||||
:class="
|
||||
expanded
|
||||
? 'col-md-2 button_container-detail'
|
||||
: 'col-md-4 button_container'
|
||||
"
|
||||
align="center"
|
||||
>
|
||||
<button
|
||||
@click="buyIntent"
|
||||
:class="expanded ? 'button_buy-simple' : 'button_buy'"
|
||||
>
|
||||
<img
|
||||
class="button_cart_img"
|
||||
alt="cart"
|
||||
src="@/assets/img/latienda-carrito.svg"
|
||||
/>
|
||||
<span v-show="!expanded">Comprar</span>
|
||||
</button>
|
||||
<div
|
||||
v-if="product.discount && product.discount > 0"
|
||||
class="discount-tag"
|
||||
>
|
||||
{{ `Descuento ${product.discount}%` }}
|
||||
</div>
|
||||
<span v-if="product.company" v-show="!expanded">{{
|
||||
product.company.company_name
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="expanded && relatedProducts" class="related_products">
|
||||
<h2>Productos relacionados</h2>
|
||||
<ProductsRelated :relatedProducts="relatedProducts" />
|
||||
</div>
|
||||
<ProductModal v-if="modal" :product="product" @close="closeModal" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'pinia'
|
||||
import ProductModal from './ProductModal.vue'
|
||||
import ProductsRelated from './ProductsRelated.vue'
|
||||
import socialShare from '~/utils/socialShare'
|
||||
export default {
|
||||
components: { ProductsRelated, ProductModal },
|
||||
props: {
|
||||
product: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
expanded: false,
|
||||
modal: false,
|
||||
productUrl: null,
|
||||
relatedProducts: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(useAuthStore, ['access']),
|
||||
},
|
||||
mounted() {
|
||||
this.productUrl = window.location.origin + `/productos/${this.product.id}`
|
||||
|
||||
this.$root.$on('bv::collapse::state', async (collapseId, isJustShown) => {
|
||||
if (collapseId === `collapse-${this.product.id}`) {
|
||||
this.expanded = isJustShown
|
||||
if (this.expanded) {
|
||||
await this.getRelatedProducts()
|
||||
await this.sendLog('view')
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
methods: {
|
||||
tagRoute(tag) {
|
||||
return `/busqueda?tags=${tag}`
|
||||
},
|
||||
async getRelatedProducts() {
|
||||
try {
|
||||
const { data } = await this.$api.get(
|
||||
`/products/${this.product.id}/related/`
|
||||
)
|
||||
this.relatedProducts = data
|
||||
} catch {
|
||||
this.relatedProducts = null
|
||||
}
|
||||
},
|
||||
|
||||
openUrl(url) {
|
||||
window.open(url)
|
||||
},
|
||||
|
||||
buyIntent() {
|
||||
this.sendLog('shop')
|
||||
return this.product.url
|
||||
? this.openUrl(this.product.url)
|
||||
: (this.modal = true)
|
||||
},
|
||||
|
||||
async getPosition() {
|
||||
const geoLocation = () =>
|
||||
new Promise((resolve, reject) =>
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
(posData) => {
|
||||
resolve(posData)
|
||||
},
|
||||
(error) => {
|
||||
reject(error)
|
||||
}
|
||||
)
|
||||
)
|
||||
try {
|
||||
const position = await geoLocation()
|
||||
const geo = {
|
||||
latitude: position.coords.latitude,
|
||||
longitude: position.coords.longitude,
|
||||
}
|
||||
return geo
|
||||
} catch {
|
||||
const geo = null
|
||||
return geo
|
||||
}
|
||||
},
|
||||
|
||||
async sendLog(action) {
|
||||
const geo = await this.getPosition()
|
||||
try {
|
||||
const config = useRuntimeConfig()
|
||||
const accessToken = this.access
|
||||
const data = await $fetch('https://api.ipify.org?format=json', {
|
||||
baseURL: config.public.baseURL,
|
||||
method: 'GET'
|
||||
})
|
||||
const ip = data.ip
|
||||
const object = {
|
||||
action: action,
|
||||
action_object: {
|
||||
model: 'product',
|
||||
id: this.product.id,
|
||||
},
|
||||
}
|
||||
if (ip) object.ip = ip
|
||||
if (geo) object.geo = geo
|
||||
//TODO: review problems with 406 error backend
|
||||
await $fetch(`/stats/me/`, {
|
||||
baseURL: config.public.baseURL,
|
||||
method: 'POST',
|
||||
body: object,
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Error sending log:', error)
|
||||
}
|
||||
},
|
||||
|
||||
closeModal(value) {
|
||||
this.modal = false
|
||||
if (value === 200) {
|
||||
this.$bvToast.toast(`Email enviado correctamente`, {
|
||||
title: 'latienda.coop',
|
||||
autoHideDelay: 5000,
|
||||
appendToast: true,
|
||||
variant: 'success',
|
||||
})
|
||||
} else if (value) {
|
||||
this.$bvToast.toast(`Se ha producido un error en el envío`, {
|
||||
title: 'latienda.coop',
|
||||
autoHideDelay: 5000,
|
||||
appendToast: true,
|
||||
variant: 'danger',
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
shareFacebook() {
|
||||
const url = socialShare.facebook(this.productUrl)
|
||||
window.open(url, '_blank')
|
||||
},
|
||||
shareTwitter() {
|
||||
return socialShare.twitter(this.productUrl)
|
||||
},
|
||||
shareWhatsApp() {
|
||||
return socialShare.whatsApp(this.productUrl)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.productcard_container {
|
||||
border: 3px $color-grey-nav solid;
|
||||
border-radius: 5px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.productcard_container-basic {
|
||||
padding: 25px 20px;
|
||||
}
|
||||
|
||||
.image_container {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.info_container {
|
||||
h2 {
|
||||
outline: none;
|
||||
font-weight: $regular;
|
||||
color: $color-navy;
|
||||
font-size: $m;
|
||||
}
|
||||
.price {
|
||||
font-weight: $bold;
|
||||
color: $color-navy;
|
||||
font-size: $m;
|
||||
}
|
||||
span {
|
||||
color: $color-greytext;
|
||||
}
|
||||
.description {
|
||||
margin-top: 8px;
|
||||
font-family: $font-secondary;
|
||||
font-size: $s;
|
||||
color: $color-greytext;
|
||||
}
|
||||
}
|
||||
|
||||
.not-expanded-description {
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 5;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
@include mobile {
|
||||
-webkit-line-clamp: 3;
|
||||
}
|
||||
}
|
||||
|
||||
.button_container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-size: $m;
|
||||
|
||||
span {
|
||||
margin-top: 15px;
|
||||
text-align: center;
|
||||
font-weight: medium;
|
||||
font-size: $m;
|
||||
color: $color-navy;
|
||||
}
|
||||
|
||||
.button_buy {
|
||||
border: 3px solid $color-orange;
|
||||
border-radius: 5px;
|
||||
background-color: $color-light;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 4px 16px rgba(99, 99, 99, 0.2);
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
span {
|
||||
color: $color-orange;
|
||||
font-weight: $bold;
|
||||
display: inline-block;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.button_buy-simple {
|
||||
border: 3px solid $color-orange;
|
||||
border-radius: 8px;
|
||||
background-color: $color-light;
|
||||
padding: 10px 20px;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 4px 16px rgba(99, 99, 99, 0.2);
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.button_cart_img {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.tag_container {
|
||||
margin: 25px 6px 0 0;
|
||||
border: 2px solid $color-greylayout;
|
||||
border-radius: 5px;
|
||||
padding: 6px 10px;
|
||||
display: inline-block;
|
||||
font-family: $font-secondary;
|
||||
font-size: $xs;
|
||||
color: $color-greytext;
|
||||
|
||||
.tag_img {
|
||||
width: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
.discount-tag {
|
||||
margin: 5px;
|
||||
border: none;
|
||||
background-color: $color-green;
|
||||
border-radius: 5px;
|
||||
padding: 6px 10px;
|
||||
display: inline-block;
|
||||
font-family: $font-secondary;
|
||||
font-size: $xs;
|
||||
color: $color-greytext;
|
||||
}
|
||||
|
||||
.share-text {
|
||||
color: $color-navy;
|
||||
font-size: $m;
|
||||
margin-top: 2rem;
|
||||
padding-bottom: 0.2em;
|
||||
}
|
||||
|
||||
.smlogo_container {
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
margin-bottom: 0.5rem;
|
||||
|
||||
.smlogo_img {
|
||||
width: 40px;
|
||||
fill: $color-greytext;
|
||||
}
|
||||
|
||||
img:hover {
|
||||
transform: scale(1.1);
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
}
|
||||
|
||||
.button_cart_img {
|
||||
width: 20px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.coop_info {
|
||||
margin-top: 25px;
|
||||
p,
|
||||
a {
|
||||
margin-top: 8px;
|
||||
font-family: $font-secondary;
|
||||
font-size: $s;
|
||||
color: $color-greytext;
|
||||
}
|
||||
a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
p {
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.related_products {
|
||||
background-color: $color-lighter-green;
|
||||
text-align: center;
|
||||
padding: 0 15px;
|
||||
|
||||
h2 {
|
||||
margin: 35px auto;
|
||||
font-weight: $regular;
|
||||
color: $color-navy;
|
||||
font-size: $m;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.content > h2,
|
||||
h3,
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -110,6 +110,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'pinia'
|
||||
import DOMPurify from 'dompurify'
|
||||
import socialShare from '~/utils/socialShare'
|
||||
export default {
|
||||
@@ -138,7 +139,9 @@ export default {
|
||||
geolocation: null,
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapState(useAuthStore, ['id', 'access']),
|
||||
},
|
||||
mounted() {
|
||||
this.productUrl = window.location.href
|
||||
this.sendLog('view')
|
||||
@@ -173,6 +176,7 @@ export default {
|
||||
})
|
||||
}
|
||||
},
|
||||
// TODO: implement buyIntent (review functionality)
|
||||
buyIntent() {
|
||||
this.sendLog('shop')
|
||||
return this.product.url
|
||||
@@ -208,10 +212,13 @@ export default {
|
||||
async sendLog(action) {
|
||||
const geo = await this.getPosition()
|
||||
try {
|
||||
const { data } = await this.$axios.get(
|
||||
'https://api.ipify.org?format=json'
|
||||
)
|
||||
const ip = data.ip
|
||||
const config = useRuntimeConfig()
|
||||
const accessToken = this.access
|
||||
const response = await $fetch('https://api.ipify.org?format=json', {
|
||||
baseURL: config.public.baseURL,
|
||||
method: 'GET'
|
||||
})
|
||||
const ip = response.ip
|
||||
const object = {
|
||||
action: action,
|
||||
action_object: {
|
||||
@@ -219,10 +226,21 @@ export default {
|
||||
id: this.product.id,
|
||||
},
|
||||
}
|
||||
console.log('Sending log OBJECT:', object)
|
||||
if (ip) object.ip = ip
|
||||
if (geo) object.geo = geo
|
||||
await this.$api.post(`/stats/me/`, object)
|
||||
} catch {}
|
||||
//TODO: review problems with 406 error backend
|
||||
await $fetch(`/stats/me/`, {
|
||||
baseURL: config.public.baseURL,
|
||||
method: 'POST',
|
||||
body: object,
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Error sending log:', error)
|
||||
}
|
||||
},
|
||||
|
||||
shareFacebook() {
|
||||
|
||||
Reference in New Issue
Block a user