move items to route
This commit is contained in:
parent
41c42d5880
commit
a065a1328d
10 changed files with 138 additions and 85 deletions
4
.env
4
.env
|
|
@ -1,5 +1,5 @@
|
|||
VITE_STRAPI_URL=http://localhost:1337
|
||||
VITE_STRAPI_API_TOKEN=7e379ac0df1d055e91f1add3c97947068f60dc943a208524c7e10201c9d66210d6dee3ab48155581892e2cabe7a285d12395ace15a1f982e68fe5078abce0aebb826ae7c701302aa932d638ec57cb10f71fee7971e0a2b87a7fdf8eeb848eea90fb97d45fc8af69e818d1d5a59dc79cbc24f0bd1830d78670b85775ad6e05c6b
|
||||
|
||||
VITE_STRAPI_URL=https://cms.nicwands.com
|
||||
VITE_STRAPI_API_TOKEN=5934fb84b89fdca49ef58e4f493381848289fcfb09a5664c5a61d4673a6b81b10bdf1d364fa250d185049c14487b7297758c3653dbf37390f567d6d08d559b4c40aaf4dc10730a60b98011d6dc0553f2bd633b373739579d579e39a162f67ca6d8f0e5c5adb3537a7e94b303d79c4cb7f3f877e39158e37e5bd6838596ee9afe
|
||||
# VITE_STRAPI_URL=https://cms.nicwands.com
|
||||
# VITE_STRAPI_API_TOKEN=5934fb84b89fdca49ef58e4f493381848289fcfb09a5664c5a61d4673a6b81b10bdf1d364fa250d185049c14487b7297758c3653dbf37390f567d6d08d559b4c40aaf4dc10730a60b98011d6dc0553f2bd633b373739579d579e39a162f67ca6d8f0e5c5adb3537a7e94b303d79c4cb7f3f877e39158e37e5bd6838596ee9afe
|
||||
|
|
|
|||
|
|
@ -2,11 +2,7 @@
|
|||
<lenis root :options="{ duration: 1 }">
|
||||
<div :class="classes" :style="styles" id="container">
|
||||
<suspense>
|
||||
<site-header />
|
||||
</suspense>
|
||||
|
||||
<suspense>
|
||||
<router-view />
|
||||
<layout />
|
||||
</suspense>
|
||||
</div>
|
||||
</lenis>
|
||||
|
|
@ -16,7 +12,6 @@
|
|||
import { ref, computed, onMounted } from 'vue'
|
||||
import loadFonts from '@fuzzco/font-loader'
|
||||
import { useWindowSize } from '@vueuse/core'
|
||||
import useLenis from './composables/useLenis'
|
||||
|
||||
const { height } = useWindowSize()
|
||||
|
||||
|
|
|
|||
1
src/components.d.ts
vendored
1
src/components.d.ts
vendored
|
|
@ -13,6 +13,7 @@ declare module 'vue' {
|
|||
export interface GlobalComponents {
|
||||
DlRow: typeof import('./components/DlRow.vue')['default']
|
||||
InfiniteScrollContainer: typeof import('./components/InfiniteScrollContainer.vue')['default']
|
||||
Layout: typeof import('./components/Layout.vue')['default']
|
||||
Lenis: typeof import('./components/Lenis.vue')['default']
|
||||
LoadingSpinner: typeof import('./components/LoadingSpinner.vue')['default']
|
||||
MosaicModal: typeof import('./components/MosaicModal.vue')['default']
|
||||
|
|
|
|||
40
src/components/Layout.vue
Normal file
40
src/components/Layout.vue
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
<template>
|
||||
<div v-if="global" class="layout">
|
||||
<site-header :copy="headerCopy" :dl="headerDl" />
|
||||
|
||||
<mosaic-scroll :items="mosaicItems" />
|
||||
|
||||
<suspense>
|
||||
<router-view />
|
||||
</suspense>
|
||||
</div>
|
||||
</template async>
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue';
|
||||
import { useSeoMeta } from '@unhead/vue'
|
||||
import { useStrapiGlobal } from '@/composables/useStrapi'
|
||||
|
||||
const { data: global } = await useStrapiGlobal()
|
||||
|
||||
const headerCopy = computed(() => global.value?.header_copy)
|
||||
const headerDl = computed(() => global.value?.header_dl)
|
||||
const mosaicItems = computed(() => global.value?.mosaic_items || [])
|
||||
|
||||
// SEO
|
||||
const seo = computed(() => global.value?.seo)
|
||||
useSeoMeta({
|
||||
title: seo.value?.title || '',
|
||||
description: seo.value?.description || '',
|
||||
ogImage: {
|
||||
url: seo.value?.image?.url || '',
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.layout {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,10 +1,7 @@
|
|||
<template>
|
||||
<div
|
||||
class="mosaic-modal theme-dark layout-grid-inner"
|
||||
@click="emit('close')"
|
||||
>
|
||||
<div class="mosaic-modal theme-dark layout-grid-inner" @click="onClose">
|
||||
<div class="meta">
|
||||
<div class="window dl" @click.stop>
|
||||
<div v-if="item.dl?.length" class="window dl" @click.stop>
|
||||
<dl-row v-for="row in item.dl" :row="row" />
|
||||
</div>
|
||||
|
||||
|
|
@ -28,15 +25,17 @@
|
|||
</lenis>
|
||||
</div>
|
||||
|
||||
<button class="window close" @click="emit('close')">Close X</button>
|
||||
<button class="window close" @click="onClose">Close X</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const props = defineProps({ item: Object })
|
||||
console.log(props.item)
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const emit = defineEmits(['close'])
|
||||
const props = defineProps({ item: Object })
|
||||
|
||||
const router = useRouter()
|
||||
const onClose = () => router.push('/')
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
|
@ -60,6 +59,7 @@ const emit = defineEmits(['close'])
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: desktop-vw(8px);
|
||||
margin-bottom: var(--layout-margin);
|
||||
|
||||
.dl-row:first-child {
|
||||
border-top: none;
|
||||
|
|
@ -67,7 +67,6 @@ const emit = defineEmits(['close'])
|
|||
}
|
||||
}
|
||||
&.gif {
|
||||
margin-top: var(--layout-margin);
|
||||
padding: 1rem;
|
||||
text-align: center;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div class="mosaic-viewport">
|
||||
<div class="mosaic-container">
|
||||
<div
|
||||
<router-link
|
||||
v-for="cell in content.cells"
|
||||
:class="[
|
||||
'mosaic-cell',
|
||||
|
|
@ -13,26 +13,20 @@
|
|||
width: cell.width * 100 + 'vw',
|
||||
height: cell.height * 100 + 'vh',
|
||||
}"
|
||||
:to="{
|
||||
name: 'mosaic-item',
|
||||
params: { id: cell.content.slug },
|
||||
}"
|
||||
:key="`${viewport.index}-${cell.id}`"
|
||||
@click="openModal(cell.content)"
|
||||
>
|
||||
<strapi-media
|
||||
:image="cell.content.image"
|
||||
:aspect="100"
|
||||
fit="contain"
|
||||
/>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Content modal -->
|
||||
<teleport to="#container">
|
||||
<mosaic-modal
|
||||
v-if="selectedItem"
|
||||
:item="selectedItem"
|
||||
@close="closeModal"
|
||||
/>
|
||||
</teleport>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
|
@ -52,47 +46,47 @@ const props = defineProps({
|
|||
},
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
// const route = useRoute()
|
||||
// const router = useRouter()
|
||||
|
||||
const selectedItem = computed(() => {
|
||||
const { item } = route.query
|
||||
// const selectedItem = computed(() => {
|
||||
// const { item } = route.query
|
||||
|
||||
return props.content.cells.find((cell) => {
|
||||
return cell?.content?.slug === item
|
||||
})?.content
|
||||
})
|
||||
// return props.content.cells.find((cell) => {
|
||||
// return cell?.content?.slug === item
|
||||
// })?.content
|
||||
// })
|
||||
|
||||
const openModal = (cellContent) => {
|
||||
router.push({
|
||||
query: {
|
||||
item: cellContent.slug,
|
||||
},
|
||||
})
|
||||
}
|
||||
const closeModal = () => {
|
||||
router.push({
|
||||
query: null,
|
||||
})
|
||||
}
|
||||
// const openModal = (cellContent) => {
|
||||
// router.push({
|
||||
// query: {
|
||||
// item: cellContent.slug,
|
||||
// },
|
||||
// })
|
||||
// }
|
||||
// const closeModal = () => {
|
||||
// router.push({
|
||||
// query: null,
|
||||
// })
|
||||
// }
|
||||
|
||||
// Close note on Escape key
|
||||
const handleKeydown = (event) => {
|
||||
if (event.key === 'Escape' && selectedItem.value) {
|
||||
closeModal()
|
||||
}
|
||||
}
|
||||
useEventListener('keydown', handleKeydown)
|
||||
// // Close note on Escape key
|
||||
// const handleKeydown = (event) => {
|
||||
// if (event.key === 'Escape' && selectedItem.value) {
|
||||
// closeModal()
|
||||
// }
|
||||
// }
|
||||
// useEventListener('keydown', handleKeydown)
|
||||
|
||||
// Pause scroll when modal is open
|
||||
const lenis = useLenis()
|
||||
watch(selectedItem, (newItem, oldItem) => {
|
||||
if (newItem && !oldItem) {
|
||||
lenis.value.stop()
|
||||
} else if (oldItem && !newItem) {
|
||||
lenis.value.start()
|
||||
}
|
||||
})
|
||||
// // Pause scroll when modal is open
|
||||
// const lenis = useLenis()
|
||||
// watch(selectedItem, (newItem, oldItem) => {
|
||||
// if (newItem && !oldItem) {
|
||||
// lenis.value.stop()
|
||||
// } else if (oldItem && !newItem) {
|
||||
// lenis.value.start()
|
||||
// }
|
||||
// })
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
|
|
|||
|
|
@ -1,19 +1,20 @@
|
|||
<template>
|
||||
<header v-if="data" class="site-header layout-grid-inner">
|
||||
<header class="site-header layout-grid-inner">
|
||||
<img class="logo" src="/images/output.gif" />
|
||||
|
||||
<div class="info theme-red">
|
||||
<strapi-content class="copy" :content="data.header_copy" />
|
||||
<strapi-content class="copy" :content="copy" />
|
||||
|
||||
<dl-row v-for="row in data.header_dl" :row="row" />
|
||||
<dl-row v-for="row in dl" :row="row" />
|
||||
</div>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useStrapiGlobal } from '@/composables/useStrapi'
|
||||
|
||||
const { data } = await useStrapiGlobal()
|
||||
const props = defineProps({
|
||||
copy: Array,
|
||||
dl: Array,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
|
|
|||
|
|
@ -1,19 +1,8 @@
|
|||
<template>
|
||||
<main class="home">
|
||||
<mosaic-scroll :items="mosaicItems" />
|
||||
</main>
|
||||
<main class="home"></main>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useStrapiSingle } from '@/composables/useStrapi'
|
||||
import useStrapiHead from '@/composables/useStrapiHead'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const { data } = await useStrapiSingle('home')
|
||||
useStrapiHead()
|
||||
|
||||
const mosaicItems = computed(() => data.value?.mosaic_items || [])
|
||||
</script>
|
||||
<script setup></script>
|
||||
|
||||
<style lang="scss">
|
||||
main.home {
|
||||
|
|
|
|||
28
src/pages/mosaic-item.vue
Normal file
28
src/pages/mosaic-item.vue
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
<template>
|
||||
<main class="mosaic-item">
|
||||
<mosaic-modal :item="activeItem" />
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useStrapiGlobal } from '@/composables/useStrapi'
|
||||
import { computed } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
const id = route.params.id
|
||||
|
||||
const { data: global } = await useStrapiGlobal()
|
||||
|
||||
const mosaicItems = computed(() => global.value?.mosaic_items || [])
|
||||
const activeItem = computed(() =>
|
||||
mosaicItems.value.find((item) => item.slug === id),
|
||||
)
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
main.mosaic-item {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import index from './pages/index.vue'
|
||||
import mosaicItem from './pages/mosaic-item.vue'
|
||||
|
||||
export default {
|
||||
routes: [
|
||||
|
|
@ -7,5 +8,10 @@ export default {
|
|||
component: index,
|
||||
name: 'home',
|
||||
},
|
||||
{
|
||||
path: '/:id',
|
||||
component: mosaicItem,
|
||||
name: 'mosaic-item',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue