detail page port
This commit is contained in:
141
components/event/Info.vue
Normal file
141
components/event/Info.vue
Normal file
@@ -0,0 +1,141 @@
|
||||
<template>
|
||||
<div v-if="event" class="event-info">
|
||||
<h1 class="title h4">{{ event.title }}</h1>
|
||||
|
||||
<p class="date p-s">{{ date }}</p>
|
||||
|
||||
<prismic-rich-text class="description" :field="event.description" />
|
||||
|
||||
<event-rsvp
|
||||
v-if="rsvpExpanded"
|
||||
class="theme-dark"
|
||||
:event-name="event.title"
|
||||
:event-date="date"
|
||||
@success="rsvpExpanded = false"
|
||||
/>
|
||||
|
||||
<div v-else class="btn-wrap">
|
||||
<btn
|
||||
v-if="type === 'rsvp'"
|
||||
class="cta"
|
||||
:hover="false"
|
||||
@click="rsvpExpanded = true"
|
||||
>
|
||||
RSVP
|
||||
</btn>
|
||||
</div>
|
||||
|
||||
<div v-if="type === 'product' && product" class="purchase-wrap">
|
||||
<number-input
|
||||
v-model="ticketQuantity"
|
||||
:min="1"
|
||||
:max="maxTicketQuantity"
|
||||
/>
|
||||
<btn :href="checkoutUrl" :disabled="!checkoutUrl"
|
||||
>Purchase Ticket</btn
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { format } from 'fecha'
|
||||
import { ref, computed } from 'vue'
|
||||
import Btn from '@/components/Btn.vue'
|
||||
import NumberInput from '@/components/NumberInput.vue'
|
||||
import EventRsvp from '@/components/event/Rsvp.vue'
|
||||
import PrismicRichText from '@/components/prismic/RichText.vue'
|
||||
import { resolveEventType } from '@/libs/resolveEventType'
|
||||
|
||||
const DEFAULT_MAX_TICKET_QUANTITY = 4
|
||||
|
||||
const props = defineProps({ event: Object, product: Object || undefined })
|
||||
|
||||
const rsvpExpanded = ref(false)
|
||||
const ticketQuantity = ref(1)
|
||||
|
||||
const date = computed(() => {
|
||||
if (!props.event?.date) return ''
|
||||
const d = new Date(props.event.date)
|
||||
return format(d, 'MM.DD.YY')
|
||||
})
|
||||
const type = computed(() => {
|
||||
const prismicType = props.event?.event_type?.trim()
|
||||
|
||||
return resolveEventType(prismicType)
|
||||
})
|
||||
|
||||
// Product checkout
|
||||
const maxTicketQuantity = computed(
|
||||
() => props.event?.max_ticket_quantity || DEFAULT_MAX_TICKET_QUANTITY,
|
||||
)
|
||||
const checkoutUrl = computed(() => {
|
||||
const edges = props.product?.product?.variants?.edges ?? []
|
||||
|
||||
const variantNode = edges
|
||||
.map((edge) => edge?.node)
|
||||
.find((node) => node?.availableForSale)
|
||||
if (!variantNode?.id) return null
|
||||
|
||||
const numericId = variantNode.id.split('/').pop()
|
||||
if (!numericId) return null
|
||||
|
||||
const quantity = Math.max(
|
||||
1,
|
||||
Math.min(ticketQuantity.value ?? 1, maxTicketQuantity.value),
|
||||
)
|
||||
|
||||
return `https://swangent.myshopify.com/cart/${numericId}:${quantity}`
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.event-info {
|
||||
padding: desktop-vw(60px) var(--layout-margin);
|
||||
|
||||
.title {
|
||||
margin-bottom: desktop-vw(20px);
|
||||
}
|
||||
.date {
|
||||
margin-bottom: desktop-vw(30px);
|
||||
}
|
||||
.description {
|
||||
margin-bottom: desktop-vw(30px);
|
||||
width: desktop-vw(330px);
|
||||
|
||||
p {
|
||||
@include p-xxs;
|
||||
}
|
||||
}
|
||||
.btn-wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5em;
|
||||
|
||||
.btn {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.purchase-wrap {
|
||||
.btn {
|
||||
width: 100%;
|
||||
margin-top: desktop-vw(20px);
|
||||
}
|
||||
}
|
||||
|
||||
@include mobile {
|
||||
padding: mobile-vw(30px) var(--layout-margin);
|
||||
|
||||
.title {
|
||||
margin-bottom: mobile-vw(20px);
|
||||
}
|
||||
.date {
|
||||
margin-bottom: mobile-vw(30px);
|
||||
}
|
||||
.description {
|
||||
margin-bottom: mobile-vw(30px);
|
||||
width: mobile-vw(330px);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user