2026-02-18 03:06:14 +01:00
|
|
|
<template>
|
|
|
|
|
<div class="grid grid-cols-[63%,35%] w-full font-thin sticky top-0 bg-white p-2 z-20">
|
|
|
|
|
<div>
|
|
|
|
|
<div class="text-5xl p-2"> <NuxtLink to='/'>michael winter</NuxtLink></div>
|
|
|
|
|
<div class="inline-flex text-2xl ml-4">
|
|
|
|
|
<NuxtLink class="px-3" to='/'>works</NuxtLink>
|
|
|
|
|
<NuxtLink class="px-3" to='/events'>events</NuxtLink>
|
|
|
|
|
<NuxtLink class="px-3" to='/about'>about</NuxtLink>
|
|
|
|
|
<NuxtLink class="px-3" to='https://unboundedpress.org/code'>code</NuxtLink>
|
|
|
|
|
<NuxtLink class="px-3 block" to='https://unboundedpress.org/legacy'>legacy</NuxtLink>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- hdp link while active -->
|
|
|
|
|
<!------
|
|
|
|
|
<div class="inline-flex text-2xl ml-4 font-bold">
|
|
|
|
|
<NuxtLink class="px-3" to='/a_history_of_the_domino_problem'>A HISTORY OF THE DOMINO PROBLEM | 17.11 - 01.12.2023 </NuxtLink>
|
|
|
|
|
</div>
|
|
|
|
|
--->
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- TODO: this needs to be automatically flipped off when there are no upcoming events-->
|
|
|
|
|
<!------
|
|
|
|
|
<div class="px-1 bg-zinc-100 rounded-lg text-center">
|
|
|
|
|
<div class="text-sm">upcoming events</div>
|
|
|
|
|
<EventSlider :upcoming_events="upcoming_events" class="max-w-[95%] min-h-[80%]"></EventSlider>
|
|
|
|
|
</div>
|
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
<slot /> <!-- required here only -->
|
|
|
|
|
<div class="fixed bottom-0 bg-white p-2 w-full flex justify-center z-20">
|
|
|
|
|
<iframe width="400rem" height="20px" scrolling="no" frameborder="no" allow="autoplay" v-if="audioPlayerStore.soundcloud_trackid !== 'undefined'"
|
|
|
|
|
:src="'https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/' + audioPlayerStore.soundcloud_trackid + '&inverse=false&auto_play=true&show_user=false'"></iframe>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<Modal v-model="modalStore.isOpen">
|
|
|
|
|
<ModalBody :class="modalStore.aspect">
|
|
|
|
|
<ImageSlider v-if="modalStore.type === 'image'" :bucket="modalStore.bucket" :gallery="modalStore.gallery"></ImageSlider>
|
2026-02-19 01:37:29 +01:00
|
|
|
<div v-if="modalStore.type === 'video'" class="w-full" :class="modalStore.aspect">
|
|
|
|
|
<iframe :src="'https://player.vimeo.com/video/' + modalStore.vimeo_trackid" width="100%" height="100%" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
|
|
|
|
</div>
|
2026-02-19 01:09:17 +01:00
|
|
|
<iframe v-if="modalStore.type === 'pdf'" :src="modalStore.pdfUrl + '#toolbar=1&navpanes=0'" width="100%" height="100%" frameborder="0" class="max-h-[calc(85vh-2rem)]"></iframe>
|
2026-02-19 01:32:33 +01:00
|
|
|
<div v-if="modalStore.type === 'pdf' || modalStore.type === 'image'" class="absolute bottom-2 right-2 z-10">
|
|
|
|
|
<a :href="modalStore.type === 'pdf' ? modalStore.pdfUrl : '/' + modalStore.bucket + '/' + modalStore.gallery[0]?.image" target="_blank" rel="noopener noreferrer" class="p-2 bg-gray-600 rounded-lg inline-flex items-center justify-center">
|
|
|
|
|
<Icon name="mdi:open-in-new" class="w-5 h-5 text-white" />
|
|
|
|
|
</a>
|
|
|
|
|
</div>
|
2026-02-18 03:06:14 +01:00
|
|
|
</ModalBody>
|
|
|
|
|
</Modal>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
import { useAudioPlayerStore } from "@/stores/AudioPlayerStore"
|
|
|
|
|
import { useModalStore } from "@/stores/ModalStore"
|
|
|
|
|
|
|
|
|
|
const audioPlayerStore = useAudioPlayerStore()
|
|
|
|
|
const modalStore = useModalStore()
|
|
|
|
|
|
|
|
|
|
const route = useRoute()
|
|
|
|
|
|
|
|
|
|
if(route.params.files == 'scores') {
|
|
|
|
|
const { data: works } = await useFetch('/api/works', {
|
|
|
|
|
transform: (works) => {
|
|
|
|
|
return works.find(w => w.score === route.params.filename)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
if(works.value?.soundcloud_trackid){
|
|
|
|
|
audioPlayerStore.setSoundCloudTrackID(works.value.soundcloud_trackid)
|
|
|
|
|
} else {
|
|
|
|
|
audioPlayerStore.clearSoundCloudTrackID()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const { data: upcoming_events } = await useFetch('/api/events', {
|
|
|
|
|
transform: (events) => {
|
|
|
|
|
const now = new Date().getTime()
|
|
|
|
|
const upcoming = events.filter(e => new Date(e.start_date).getTime() >= now)
|
|
|
|
|
for (const event of upcoming) {
|
|
|
|
|
let date = new Date(event.start_date)
|
|
|
|
|
event.formatted_date = ("0" + (date.getMonth() + 1)).slice(-2) + "." + ("0" + date.getDate()).slice(-2) + "." + date.getFullYear()
|
|
|
|
|
}
|
|
|
|
|
return upcoming.sort((a,b) => new Date(a.start_date) - new Date(b.start_date))
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
</script>
|