Files
miniplan/public/src/components/ListView.vue
T

270 lines
6.4 KiB
Vue

<script setup lang="ts">
import {ref} from "vue"
import type {Gottesdienst, Mark, SimplifiedMinistrant} from "@/models/models"
import GottesdienstCard from "@/components/GottesdienstCard.vue"
defineProps<{
gottesdienste: Gottesdienst[]
ministranten: SimplifiedMinistrant[]
marks: Mark[]
editable: string[]
currentUsername: string
admin: boolean
}>()
const emit = defineEmits<{
toggleMark: [gid: number, mid: number]
addGottesdienst: []
editGottesdienst: [id: number]
addMinistrant: []
editMinistrant: [id: number]
importZelebrationsplan: []
}>()
const activeTab = ref<"gottesdienste" | "ministranten">("gottesdienste")
</script>
<template>
<div class="list-view">
<div class="tab-bar">
<button
class="tab"
:class="{ active: activeTab === 'gottesdienste' }"
@click="activeTab = 'gottesdienste'"
><i class="icon">list</i> Gottesdienste</button>
<button
class="tab"
:class="{ active: activeTab === 'ministranten' }"
@click="activeTab = 'ministranten'"
><i class="icon">groups</i> Ministranten</button>
</div>
<template v-if="activeTab === 'gottesdienste'">
<GottesdienstCard
v-for="godi in gottesdienste"
:key="godi.id"
:gottesdienst="godi"
:ministranten="ministranten"
:marks="marks"
:editable="editable"
:current-username="currentUsername"
@toggle-mark="(gid, mid) => emit('toggleMark', gid, mid)"
@edit-gottesdienst="(id) => emit('editGottesdienst', id)"
/>
<button v-if="admin" class="add-godi" @click="emit('addGottesdienst')">
<i class="icon">add</i> Gottesdienst
</button>
<button v-if="admin" class="import-btn" @click="emit('importZelebrationsplan')">
<i class="icon">upload</i> Zelebrationsplan importieren
</button>
</template>
<template v-else>
<div class="mini-list">
<div v-for="mini in ministranten" :key="mini.id" class="mini-row">
<span class="mini-name">{{ mini.firstname }} {{ mini.lastname }}</span>
<span class="mini-username">@{{ mini.username }}</span>
<button v-if="admin" class="edit-btn" @click="emit('editMinistrant', mini.id)">
<i class="icon">edit</i>
</button>
</div>
<div v-if="ministranten.length === 0" class="empty-state">
Keine Ministranten
</div>
<button v-if="admin" class="add-mini" @click="emit('addMinistrant')">
<i class="icon">add</i> Ministrant
</button>
</div>
</template>
</div>
</template>
<style scoped lang="less">
.list-view {
padding: 12px;
}
.tab-bar {
display: flex;
gap: 4px;
margin-bottom: 12px;
background: #f0f0f0;
border-radius: 8px;
padding: 3px;
.tab {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
padding: 8px;
font-size: 14px;
font-weight: 600;
border: none;
border-radius: 6px;
background: transparent;
color: #777;
cursor: pointer;
transition: 100ms;
i {
font-size: 20px;
}
&.active {
background: #ffffff;
color: #222;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
&:not(.active):hover {
color: #555;
}
}
}
.mini-list {
background: #ffffff;
border: 1px solid #e0e0e0;
border-radius: 8px;
overflow: hidden;
.mini-row {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 14px;
border-bottom: 1px solid #f0f0f0;
&:last-child {
border-bottom: none;
}
.mini-name {
font-size: 15px;
font-weight: 500;
}
.mini-username {
font-size: 13px;
color: #999;
}
}
.mini-row {
.edit-btn {
display: flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
padding: 0;
margin: 0;
border: none;
border-radius: 4px;
background: transparent;
color: #aaa;
cursor: pointer;
transition: 100ms;
flex-shrink: 0;
i {
font-size: 18px;
margin: 0;
}
&:hover {
background: #f0f0f0;
color: #555;
}
}
}
.empty-state {
padding: 24px;
text-align: center;
color: #999;
font-size: 14px;
}
.add-mini {
display: flex;
width: 100%;
padding: 10px;
font-size: 14px;
justify-content: center;
background: #fafafa;
border: none;
border-top: 1px solid #f0f0f0;
border-radius: 0;
cursor: pointer;
color: #777;
transition: 100ms;
margin: 0;
i {
font-size: 20px;
margin-right: 6px;
}
&:hover {
background: #f0f0f0;
color: #444;
}
}
}
.add-godi {
display: flex;
width: 100%;
margin: 16px 0;
padding: 12px;
font-size: 15px;
justify-content: center;
background: #f5f5f5;
border: 1px dashed #c4c4c4;
border-radius: 8px;
cursor: pointer;
color: #555;
transition: 100ms;
i {
font-size: 22px;
margin-right: 6px;
}
&:hover {
background: #eaeaea;
border-color: #999;
color: #333;
}
}
.import-btn {
display: flex;
width: 100%;
margin: 16px 0;
padding: 12px;
font-size: 15px;
justify-content: center;
background: #f5f5f5;
border: 1px dashed #c4c4c4;
border-radius: 8px;
cursor: pointer;
color: #555;
transition: 100ms;
i {
font-size: 22px;
margin-right: 6px;
}
&:hover {
background: #eaeaea;
border-color: #999;
color: #333;
}
}
</style>