365 lines
8.2 KiB
Vue
365 lines
8.2 KiB
Vue
<script setup lang="ts">
|
|
|
|
import {API} from "@/services/api";
|
|
|
|
import {onMounted, reactive, ref, toRaw} from "vue";
|
|
import type {Gottesdienst, Mark, PlanModel, SimplifiedMinistrant} from "@/models/models";
|
|
import Input from "@/components/Input.vue";
|
|
import GroupView from "@/components/GroupView.vue";
|
|
|
|
const props = defineProps<{
|
|
gottesdienste: Gottesdienst[],
|
|
ministranten: SimplifiedMinistrant[]
|
|
marks: Mark[],
|
|
editable: string[]
|
|
edit: boolean,
|
|
smallMode: boolean
|
|
}>()
|
|
const emit = defineEmits(["toggleMark", "added", "delete", "edit", "endEdit", "resetPassword", "deleteMinistrant", "createMinistrant", "editMinistrant"])
|
|
const openEditUser = ref<number>(-1)
|
|
const miniCopy = reactive<{ data?: SimplifiedMinistrant }>({})
|
|
const data = reactive({
|
|
godi: {}
|
|
})
|
|
|
|
|
|
function getIconForMark(gid, mid) {
|
|
const mark = getMark(gid, mid).value
|
|
switch (mark) {
|
|
case -1:
|
|
return "remove";
|
|
case 0:
|
|
return "question_mark";
|
|
// return ""
|
|
case 1:
|
|
return "close"
|
|
}
|
|
return ""
|
|
}
|
|
|
|
function getClassForMark(gid, mid) {
|
|
const mark = getMark(gid, mid).value
|
|
return {
|
|
minus: mark == -1,
|
|
neutral: mark == 0,
|
|
cross: mark == 1,
|
|
showIcon: !props.smallMode
|
|
}
|
|
}
|
|
|
|
function getHintForMark(gid, mid) {
|
|
const mark = getMark(gid, mid).value
|
|
switch (mark) {
|
|
case -1:
|
|
return "Ich kann nicht";
|
|
case 0:
|
|
return "Egal";
|
|
case 1:
|
|
return "Ich komme"
|
|
}
|
|
}
|
|
|
|
function two(s) {
|
|
return (s < 10 ? "0" : "") + s
|
|
}
|
|
|
|
function formatDay(time) {
|
|
let date = new Date(time)
|
|
return two(date.getDate()) + "." + two(date.getMonth() + 1) + "."
|
|
}
|
|
|
|
function formatTime(time) {
|
|
let date = new Date(time)
|
|
return two(date.getHours()) + ":" + two(date.getMinutes())
|
|
}
|
|
|
|
function formatWeekday(time) {
|
|
let date = new Date(time)
|
|
switch (date.getDay()) {
|
|
case 1:
|
|
return "Mo";
|
|
case 2:
|
|
return "Di";
|
|
case 3:
|
|
return "Mi";
|
|
case 4:
|
|
return "Do";
|
|
case 5:
|
|
return "Fr";
|
|
case 6:
|
|
return "Sa";
|
|
case 0:
|
|
return "So"
|
|
}
|
|
}
|
|
|
|
function getMark(gid, mid) {
|
|
const mark = props.marks.find(mark => mark.mid == mid && mark.gid == gid)
|
|
return mark ? mark : {gid, mid, value: 0}
|
|
}
|
|
|
|
function getMinistrantClasses(mini: SimplifiedMinistrant) {
|
|
return {
|
|
edit: props.editable.includes(mini.username)
|
|
}
|
|
}
|
|
|
|
function toggleEditMinistrant(mini: SimplifiedMinistrant) {
|
|
console.log("Toggled", miniCopy.data, mini, props.ministranten, openEditUser)
|
|
if (openEditUser.value == mini.id) {
|
|
miniCopy.data = undefined
|
|
openEditUser.value = -1;
|
|
} else {
|
|
openEditUser.value = mini.id
|
|
miniCopy.data = toRaw(mini)
|
|
}
|
|
|
|
}
|
|
|
|
function getAmount(mid: number, value: number): number {
|
|
return props.marks.filter(m => m.mid == mid && m.value == value).length
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
|
|
<div class="container">
|
|
|
|
<table>
|
|
|
|
<thead>
|
|
|
|
<tr v-if="props.edit" class="no-print">
|
|
<th></th>
|
|
<th v-for="godi in props.gottesdienste"><i @click="$emit('delete', godi.id)" style="cursor: pointer">delete</i></th>
|
|
</tr>
|
|
|
|
<tr v-if="props.edit" class="no-print">
|
|
<th></th>
|
|
<th v-for="godi in props.gottesdienste"><i @click="$emit('edit', godi.id)" style="cursor: pointer">edit</i></th>
|
|
</tr>
|
|
|
|
<tr>
|
|
<th></th>
|
|
<th v-for="godi in props.gottesdienste" class="name">{{ godi.name }}</th>
|
|
</tr>
|
|
<tr class="bold">
|
|
<th>Datum</th>
|
|
<th v-for="godi in props.gottesdienste">{{ formatDay(godi.date) }}</th>
|
|
</tr>
|
|
<tr>
|
|
<th>Uhrzeit</th>
|
|
<th v-for="godi in props.gottesdienste">{{ formatTime(godi.date) }}</th>
|
|
</tr>
|
|
<tr class="bold">
|
|
<th>Anwesenheit</th>
|
|
<th v-for="godi in props.gottesdienste">{{ formatTime(godi.attendance) }}</th>
|
|
</tr>
|
|
<tr>
|
|
<th>Wochentag</th>
|
|
<th v-for="godi in props.gottesdienste">{{ formatWeekday(godi.date) }}</th>
|
|
</tr>
|
|
|
|
</thead>
|
|
<tbody>
|
|
|
|
<tr v-for="mini in props.ministranten" class="ministrant" :class="getMinistrantClasses(mini)">
|
|
<td class="name">
|
|
<div class="center">
|
|
<div style="width: 100%;">
|
|
<i class="edit-button no-print"
|
|
v-if="edit"
|
|
style="margin-right: 10px; font-size: 18px"
|
|
@click="$emit('editMinistrant', mini.id)">edit</i>
|
|
{{ mini.firstname }}
|
|
{{ mini.lastname }}
|
|
</div>
|
|
<div style="flex-shrink: 0" v-if="edit">
|
|
{{getAmount(mini.id, 1)}}
|
|
</div>
|
|
|
|
</div>
|
|
</td>
|
|
<td
|
|
v-for="godi in props.gottesdienste"
|
|
class="mark"
|
|
:class="getClassForMark(godi.id, mini.id)"
|
|
@click="$emit('toggleMark', godi.id, mini.id)">
|
|
<i class="icon"> {{ getIconForMark(godi.id, mini.id) }} </i><br>
|
|
<span class="hint no-print">{{ getHintForMark(godi.id, mini.id) }}</span>
|
|
</td>
|
|
</tr>
|
|
|
|
</tbody>
|
|
</table>
|
|
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped lang="less">
|
|
|
|
|
|
table {
|
|
border-spacing: 0;
|
|
min-width: 100%;
|
|
}
|
|
|
|
tr {
|
|
th {
|
|
font-weight: 400;
|
|
|
|
&.edit {
|
|
text-align: start;
|
|
}
|
|
padding: 10px;
|
|
}
|
|
|
|
&.bold th {
|
|
font-weight: 700;
|
|
}
|
|
}
|
|
|
|
td {
|
|
background: #ffffff;
|
|
}
|
|
|
|
td:first-child, th:first-child {
|
|
padding: 6px 30px 6px 12px;
|
|
text-align: left;
|
|
min-width: 150px;
|
|
}
|
|
|
|
td:nth-child(2n), th:nth-child(2n) {
|
|
background: #8ce081;
|
|
}
|
|
|
|
.mark {
|
|
text-align: center;
|
|
vertical-align: center;
|
|
justify-content: center;
|
|
align-items: center;
|
|
min-width: 100px;
|
|
height: 20px;
|
|
user-select: none;
|
|
|
|
|
|
i {
|
|
border-radius: 100%;
|
|
padding: 1px;
|
|
font-size: 22px;
|
|
margin: 2px;
|
|
}
|
|
|
|
@media not print {
|
|
&.minus {
|
|
background: #fdd5d5;
|
|
color: #690b0b;
|
|
}
|
|
|
|
&.cross {
|
|
background: #d1fcd1;
|
|
color: #045b04;
|
|
}
|
|
}
|
|
|
|
&.neutral i {
|
|
opacity: 0;
|
|
color: #9f9f9f;
|
|
font-variation-settings: "wght" 350;
|
|
mix-blend-mode: difference;
|
|
}
|
|
|
|
.hint {
|
|
margin-top: 4px;
|
|
opacity: 0.7;
|
|
display: none;
|
|
font-size: 14px;
|
|
//mix-blend-mode: difference;
|
|
}
|
|
|
|
&:not(.showIcon) {
|
|
padding: 0 !important;
|
|
|
|
.hint, br {
|
|
display: none !important;
|
|
}
|
|
}
|
|
}
|
|
|
|
.ministrant {
|
|
.center {
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
.edit-button {
|
|
cursor: pointer;
|
|
user-select: none;
|
|
}
|
|
}
|
|
|
|
.controls {
|
|
display: flex;
|
|
flex-direction: column;
|
|
|
|
&:not(.show) {
|
|
display: none;
|
|
}
|
|
|
|
padding: 20px 10px;
|
|
|
|
.input {
|
|
padding-bottom: 8px;
|
|
}
|
|
}
|
|
}
|
|
|
|
.ministrant.edit {
|
|
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);
|
|
z-index: 10;
|
|
position: relative;
|
|
|
|
td {
|
|
padding-top: 10px;
|
|
padding-bottom: 10px;
|
|
}
|
|
|
|
.name {
|
|
align-items: center;
|
|
height: 100%;
|
|
|
|
i {
|
|
opacity: 0.5;
|
|
}
|
|
}
|
|
|
|
.mark {
|
|
cursor: pointer;
|
|
|
|
@media not print {
|
|
&.neutral i {
|
|
opacity: 0.5;
|
|
}
|
|
}
|
|
|
|
.hint {
|
|
display: inline-block;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
td, th {
|
|
--color-outline: #908888;
|
|
border-right: 1px solid var(--color-outline);
|
|
border-bottom: 1px solid var(--color-outline);
|
|
}
|
|
|
|
td:first-child, th:first-child {
|
|
border-right: 2px solid #575757;
|
|
}
|
|
|
|
thead tr:last-child th, tr:nth-child(5n) td {
|
|
border-bottom: 2px solid #575757;
|
|
}
|
|
</style>
|