portfolio/pages/works_list.vue

238 lines
4.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup>
definePageMeta({
layout: 'plain'
})
const { data: resume } = await useFetch('/api/resume')
const { data: works } = await useFetch('/api/works')
const { data: events } = await useFetch('/api/events')
const worksByYear = computed(() => {
if (!works.value) return []
const grouped = {}
for (const work of works.value) {
const year = work.date ? new Date(work.date).getFullYear() : 'Unknown'
if (!grouped[year]) {
grouped[year] = []
}
const workEvents = events.value?.filter(e => {
if (!e.program) return false
return e.program.some(p => p.work?.toLowerCase().includes(work.title.toLowerCase()))
}) || []
grouped[year].push({
...work,
location: work.instrument_tags?.[0] || '',
events: workEvents
})
}
return Object.keys(grouped)
.sort((a, b) => b - a)
.map(year => ({
year,
works: grouped[year].sort((a, b) => new Date(b.date) - new Date(a.date))
}))
})
function formatDate(dateStr) {
if (!dateStr) return ''
const date = new Date(dateStr)
if (isNaN(date)) return dateStr
return ("0" + date.getDate()).slice(-2) + "." + ("0" + (date.getMonth() + 1)).slice(-2) + "." + date.getFullYear()
}
useHead({
titleTemplate: 'Michael Winter'
})
</script>
<template>
<div class="cv-container">
<header class="cv-header">
<h1>{{ resume?.basics?.name }}</h1>
<h3>Works List with Presentation History</h3>
<p class="contact">
{{ resume?.basics?.email }} &nbsp;·&nbsp; {{ resume?.basics?.phone }} &nbsp;·&nbsp; {{ resume?.basics?.website }}
</p>
</header>
<hr />
<p class="intro">
A chronological performance / exhibition history, scores, and recordings are available at: https://unboundedpress.org.<br>
All scores are also published or forthcoming through Frog Peak at: https://frogpeak.org/fpartists/fpwinter.html.
</p>
<!-- Works by Year -->
<section v-for="yearGroup in worksByYear" :key="yearGroup.year" class="cv-section">
<h4>{{ yearGroup.year }}</h4>
<div v-for="work in yearGroup.works" :key="work.id" class="work-entry">
<div class="work-title"><em>{{ work.title }}</em></div>
<div class="work-info" v-if="work.instrument_tags">
<span v-for="(tag, idx) in work.instrument_tags" :key="tag">
{{ tag }}{{ idx < work.instrument_tags.length - 1 ? ', ' : '' }}
</span>
</div>
<div class="work-events" v-if="work.events?.length">
<div v-for="event in work.events" :key="event.id" class="event">
{{ event.venue?.name }}; {{ event.venue?.city }}, {{ event.venue?.state }} {{ formatDate(event.start_date) }}
</div>
</div>
</div>
</section>
</div>
</template>
<style>
.cv-container {
font-size: 12px;
width: 175mm;
margin: 40px auto;
max-width: 100%;
padding: 0 30px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
line-height: 1.5;
color: #222;
}
.cv-header {
text-align: center;
margin-bottom: 24px;
}
.cv-header h1 {
font-size: 28px;
font-weight: 600;
margin: 0 0 4px 0;
letter-spacing: -0.5px;
}
.cv-header h3 {
font-size: 16px;
font-weight: 400;
margin: 0 0 8px 0;
color: #555;
}
.cv-header .contact {
font-size: 11px;
color: #555;
margin: 0;
}
.cv-section {
margin-bottom: 20px;
}
.cv-section h4 {
font-size: 13px;
font-weight: 300;
text-transform: uppercase;
letter-spacing: 0.8px;
margin: 0 0 10px 0;
padding-bottom: 4px;
border-bottom: 1px solid #ccc;
color: #7F7F7F;
}
.intro {
font-size: 11px;
color: #444;
margin-bottom: 20px;
line-height: 1.5;
}
.work-entry {
margin-bottom: 10px;
margin-left: 12px;
}
.work-title {
font-size: 12px;
margin-bottom: 2px;
}
.work-info {
font-size: 11px;
color: #444;
margin-bottom: 2px;
}
.work-events {
font-size: 11px;
color: #555;
}
.event {
padding-left: 12px;
margin-top: 2px;
}
hr {
margin: 16px 0;
border: none;
border-top: 1px solid #ccc;
}
@media print {
@page {
margin: 15mm;
}
.cv-container {
margin: 0;
padding: 15mm;
width: auto;
font-size: 10pt;
max-width: none;
box-sizing: border-box;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
.cv-header h1 {
font-size: 20pt;
}
.cv-header h3 {
font-size: 12pt;
}
.cv-section h4 {
font-size: 10pt;
border-bottom: 1pt solid #999;
break-after: avoid;
page-break-after: avoid;
}
.work-entry {
break-inside: avoid;
page-break-inside: avoid;
}
.work-title {
font-size: 10pt;
}
.work-info,
.work-events {
font-size: 9pt;
}
hr {
border-top: 1pt solid #999;
}
.work-entry,
.cv-section {
margin-left: 0;
}
}
</style>