PronounsPage/pages/team.vue
Andrea Vos 6dbd121186 Merge branch 'nynorsk' into 'main'
Publish Nynorsk

See merge request PronounsPage/PronounsPage!554
2025-01-19 17:08:35 +00:00

236 lines
7.5 KiB
Vue

<script setup lang="ts">
import { useNuxtApp, useAsyncData } from 'nuxt/app';
import useConfig from '../composables/useConfig.ts';
import useSimpleHead from '../composables/useSimpleHead.ts';
import useSpelling from '../composables/useSpelling.ts';
interface Admin {
username: string;
teamName: string;
locale: string;
credentials: string[] | null;
credentialsLevel: number | null;
credentialsName: string | null;
}
definePageMeta({
translatedPaths: (config) => {
if (!config.contact.enabled) {
return [];
}
return translatedPathByConfigModule(config.contact.team);
},
});
const { $translator: translator } = useNuxtApp();
const config = useConfig();
useSimpleHead({
title: translator.translate('contact.team.name'),
description: translator.translate('contact.team.description'),
}, translator);
const { convertName } = useSpelling();
const teamAsyncData = useAsyncData(async () => {
const membersByLocaleRaw = await $fetch<Record<string, Admin[]>>('/api/admin/list');
const membersByLocale = Object.fromEntries(Object.entries(membersByLocaleRaw).filter(([_, members]) => {
return members.length > 0;
}));
const credentials = (membersByLocale[config.locale] ?? [])
.filter((member) => member.credentials !== null)
.toSorted((a, b) => {
if (a.credentialsLevel! > b.credentialsLevel!) {
return -1;
}
if (a.credentialsLevel! < b.credentialsLevel!) {
return 1;
}
return Math.random() > 0.5 ? 1 : -1;
});
return { membersByLocale, credentials };
}, {
lazy: true,
});
const membersByLocale = computed(() => teamAsyncData.data.value?.membersByLocale);
const credentials = computed(() => teamAsyncData.data.value?.credentials);
</script>
<template>
<Page>
<CommunityNav />
<h2>
<Icon v="collective-logo.svg" class="invertible" />
<T>contact.team.name</T>
</h2>
<figure class="float-end border rounded m-3">
<img src="/img-local/logo/logo-full-path.svg" alt="" class="invertible">
<hr>
<figcaption>
<p><T>contact.team.logo</T></p>
<p class="text-center bigger mb-0">
<Icon v="transgender-alt" />
+
<Icon v="comment" />
=
<Icon v="collective-logo.svg" class="invertible" />
</p>
<nuxt-link to="/design" class="mt-3 btn btn-outline-primary btn-sm w-100">
<Icon v="cloud-download" />
<T>crud.download</T>
</nuxt-link>
</figcaption>
</figure>
<section>
<p><T>contact.team.description</T></p>
<ul v-if="$te('contact.team.extra')">
<li v-for="item in $t('contact.team.extra')">
<LinkedText :text="item" />
</li>
</ul>
</section>
<Mission />
<section v-if="$te('contact.team.credentials')">
<h3>
<Icon v="graduation-cap" />
<T>contact.team.credentials.header</T>
</h3>
<T>contact.team.credentials.description</T>
<ul>
<li v-for="credential in credentials" :key="credential.username">
<Spelling :text="convertName(credential.credentialsName || credential.teamName)" />
<a :href="`https://pronouns.page/@${credential.username}`" class="badge bg-light text-dark border">
@{{ credential.username }}
</a>
<ul>
<li v-for="item in credential.credentials" :key="item">
<ProfileLink v-if="item.startsWith('https://') || item.startsWith('http://')" :link="item" />
<LinkedText v-else :text="item" />
</li>
</ul>
</li>
</ul>
</section>
<section>
<Contribute id="contribute" />
</section>
<section v-if="false && $te('contact.team.join')">
<h3>
<Icon v="user-plus" />
<T>contact.team.join.header</T>
</h3>
<p><T>contact.team.join.encouragement</T></p>
<p><T>contact.team.join.areasIntro</T></p>
<ul>
<li v-for="item in $t('contact.team.join.areas')">
<Spelling :text="item" />
</li>
</ul>
<p><T>contact.team.join.allies</T></p>
<div v-if="$te('contact.team.join.warning')" class="alert alert-warning">
<p class="mb-0">
<Icon v="exclamation-triangle" />
<T>contact.team.join.warning</T>
</p>
</div>
<p><T>contact.team.join.how</T></p>
<ul>
<li v-for="item in $t('contact.team.join.application')">
<Spelling :text="item" />
</li>
</ul>
</section>
<AdPlaceholder :phkey="['content-0', 'content-mobile-0']" />
<Loading :value="membersByLocale">
<template #header>
<h3>
<Icon v="user-friends" />
<T>contact.team.members</T>
</h3>
</template>
<template v-for="(members, locale) in membersByLocale">
<h4 class="mt-4">
<template v-if="locale === ''">
<T>contact.team.upcoming</T>
</template>
<template v-else-if="locale === config.locale">
{{ $locales[locale].fullName }}
</template>
<a v-else :href="$locales[locale].url">
{{ $locales[locale].fullName }}
</a>
</h4>
<ul class="list-unstyled member-list">
<li v-for="member in members" class="mb-3 d-flex">
<a :href="`https://pronouns.page/@${member.username}`">
<Avatar :user="member" dsize="4rem" />
</a>
<span class="ms-2">
<Spelling :text="convertName(member.teamName)" />
<br>
<a :href="`https://pronouns.page/@${member.username}`" class="badge bg-light text-dark border">
@{{ member.username }}
</a>
</span>
</li>
</ul>
</template>
</Loading>
<AdPlaceholder :phkey="['content-1', 'content-mobile-1']" />
</Page>
</template>
<style lang="scss" scoped>
@import "assets/variables";
img {
max-width: 100%;
}
figure {
width: 100%;
max-width: 18rem;
padding: $spacer;
> img {
width: 100%;
}
figcaption {
font-size: $small-font-size;
}
}
@include media-breakpoint-down('md', $grid-breakpoints) {
figure {
float: none !important;
margin: 0 auto;
}
}
.bigger {
font-size: 2rem;
}
@include media-breakpoint-up('md', $grid-breakpoints) {
.member-list {
column-count: 3;
column-width: 16rem;
}
}
</style>