142 lines
4.8 KiB
Vue

<script setup lang="ts">
import { useNuxtApp } from 'nuxt/app';
import useConfig from '~/composables/useConfig.ts';
import useSimpleHead from '~/composables/useSimpleHead.ts';
import type { ZineRelease } from '~/locale/config.ts';
import { useMainStore } from '~/store/index.ts';
definePageMeta({
translatedPaths: (config) => translatedPathByConfigModule(config.links.zine),
});
const { $translator: translator } = useNuxtApp();
const config = useConfig();
if (!config.links.zine?.enabled) {
throw new Error('config.links.zine is disabled');
}
useSimpleHead({
title: translator.translate('links.zine.headerLong'),
banner: config.links.zine.releases.length
? `img/${config.locale}/zine/${config.links.zine.releases[0].banner}`
: null,
}, translator);
const { data: stats } = useFetch('/api/downloads', {
default: () => ({}),
});
const selectedFormat = ref<string | null>(null);
const store = useMainStore();
const downloadsCount = (release: ZineRelease): number => {
let count = 0;
for (const { filename } of Object.values(release.downloads)) {
count += stats.value[filename] ?? 0;
}
return count;
};
</script>
<template>
<Page v-if="config.links.zine?.enabled">
<LinksNav />
<h2>
<Icon v="zine.svg" :inverse="store.darkMode" />
<T>links.zine.headerLong</T>
</h2>
<section v-if="config.links.zine.releases.length">
<ul class="list-unstyled">
<li v-for="release in config.links.zine.releases" class="row">
<div class="col-12 col-lg-3">
<img :src="`/img/${config.locale}/zine/${release.cover}`" class="cover border shadow">
</div>
<div class="col-12 col-lg-9 py-3 py-lg-0 px-lg-3">
<h3>{{ release.title }}</h3>
<LinkedText :text="release.description" />
<ul class="list-inline my-3">
<li v-for="({ filename, icon }, format) in release.downloads" class="list-inline-item download-btn">
<a
:href="`/api/download/${filename}`"
class="btn btn-primary m-1"
@mouseenter="selectedFormat = format"
@mouseleave="selectedFormat = null"
>
<Icon :v="icon || 'file-download'" />
<T>links.zine.format.{{ format }}.name</T>
<small v-if="stats[filename] !== undefined">({{ stats[filename] }})</small>
</a>
</li>
</ul>
<ul v-if="release.extra" class="small">
<li v-for="line in release.extra">
<LinkedText :text="line" />
</li>
</ul>
<p v-if="downloadsCount(release)">
<Icon v="download" />
{{ downloadsCount(release) }}
</p>
<div v-if="selectedFormat" class="alert alert-info small">
<Icon v="info-circle" />
<T>links.zine.format.{{ selectedFormat }}.description</T>
</div>
</div>
</li>
</ul>
<Separator icon="bullhorn" />
</section>
<h3 class="mb-3">
<Icon v="bullhorn" />
<T>links.zine.submissions.header</T>
</h3>
<T>links.zine.info</T>
<ZineSubmissions v-if="config.links.zine.open" class="alert alert-info" />
<div v-else>
<div class="alert alert-warning">
<p class="h6 mb-0">
<Icon v="exclamation-triangle" />
<T>links.zine.submissions.closed</T>
</p>
</div>
<details class="border mb-3">
<summary class="bg-light p-3">
<T>links.zine.submissions.header</T>
</summary>
<ZineSubmissions class="p-3 border-top" />
</details>
</div>
<Separator icon="heart" />
<Support />
<section>
<Share :title="$t('links.zine.header')" />
</section>
</Page>
</template>
<style lang="scss" scoped>
@import "assets/variables";
.cover {
width: 100%;
height: auto;
}
@include media-breakpoint-down('lg') {
.download-btn {
display: block;
margin-right: 0;
.btn {
display: block;
}
}
}
</style>