Initial commit
This commit is contained in:
parent
2d458f08f3
commit
7972ad66a8
@ -5,11 +5,18 @@ import HelloWorld from './components/HelloWorld.vue'
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<header>
|
<header>
|
||||||
Header
|
Miniplan
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<RouterView />
|
<RouterView />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
|
header{
|
||||||
|
display: flex;
|
||||||
|
padding: 20px 32px;
|
||||||
|
border-bottom: 1px solid #d7d5d5;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
html, body {
|
html, body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
font-family: "Roboto", sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon, i:not(.icon) {
|
.icon, i:not(.icon) {
|
||||||
@ -20,6 +21,34 @@ html, body {
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
.filled {
|
.icon.filled, i:not(.icon).filled {
|
||||||
font-variation-settings: "FILL" 1;
|
font-variation-settings: "FILL" 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
border: none;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 8px 14px 8px 10px;
|
||||||
|
margin: 0 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-weight: 600;
|
||||||
|
background: #d7eaf3;
|
||||||
|
color: #0e2c48;
|
||||||
|
}
|
||||||
|
|
||||||
|
button i {
|
||||||
|
margin-right: 10px;
|
||||||
|
color: #0e2c48;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
background: #e4eff6;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:active {
|
||||||
|
background: #d0e3f1;
|
||||||
|
}
|
||||||
|
|||||||
11
public/src/components/LoginPanel.vue
Normal file
11
public/src/components/LoginPanel.vue
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
|
||||||
|
</style>
|
||||||
251
public/src/components/MobilePlan.vue
Normal file
251
public/src/components/MobilePlan.vue
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
import {API} from "@/views/api";
|
||||||
|
|
||||||
|
import {onMounted, reactive, ref} from "vue";
|
||||||
|
import type {PlanModel, SimplifiedMinistrant} from "@/models/models";
|
||||||
|
|
||||||
|
const props = defineProps<PlanModel>()
|
||||||
|
defineEmits(["toggleMark"])
|
||||||
|
|
||||||
|
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
|
||||||
|
switch (mark) {
|
||||||
|
case -1:
|
||||||
|
return "minus";
|
||||||
|
case 0:
|
||||||
|
return "neutral";
|
||||||
|
case 1:
|
||||||
|
return "cross"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
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()) + "."
|
||||||
|
}
|
||||||
|
|
||||||
|
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 "Montag";
|
||||||
|
case 2:
|
||||||
|
return "Dienstag";
|
||||||
|
case 3:
|
||||||
|
return "Mittwoch";
|
||||||
|
case 4:
|
||||||
|
return "Donnerstag";
|
||||||
|
case 5:
|
||||||
|
return "Freitag";
|
||||||
|
case 6:
|
||||||
|
return "Samstag";
|
||||||
|
case 0:
|
||||||
|
return "Sonntag"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMinis() {
|
||||||
|
return props.ministranten.filter(m => props.editable.includes(m.id))
|
||||||
|
}
|
||||||
|
function getMiniName(mini) {
|
||||||
|
return mini.firstname + " " + mini.lastname
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Gottesdienst</th>
|
||||||
|
<th v-for="mini in getMinis()">
|
||||||
|
{{ getMiniName(mini) }}
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="godi in props.gottesdienste" class="gottesdienst">
|
||||||
|
<td>
|
||||||
|
<div class="gottesdienst">
|
||||||
|
<span class="name">{{godi.name !== "" ? godi.name : "Gottesdienst"}}</span>
|
||||||
|
<span class="date">am {{formatWeekday(godi.date) }} {{formatDay(godi.date) }}</span>
|
||||||
|
<span class="time">um {{formatTime(godi.date)}} Uhr</span>
|
||||||
|
<span class="attendance">Anwesenheit: {{formatTime(godi.attendance) }}</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td
|
||||||
|
v-for="mini in getMinis()"
|
||||||
|
class="mark edit"
|
||||||
|
: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">{{ getHintForMark(godi.id, mini.id) }}</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-spacing: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr {
|
||||||
|
th {
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.bold th {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
background: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
td:first-child, th:first-child {
|
||||||
|
padding: 6px 60px 6px 12px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
td:nth-child(2n), th:nth-child(2n) {
|
||||||
|
background: #8ce081;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gottesdienst{
|
||||||
|
span {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.name {
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
.date, .time {
|
||||||
|
font-weight: 700;
|
||||||
|
color: #656565;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.attendance{
|
||||||
|
color: #656565;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mark {
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: center;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
min-width: 100px;
|
||||||
|
height: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
i {
|
||||||
|
border-radius: 100%;
|
||||||
|
padding: 1px;
|
||||||
|
font-size: 22px;
|
||||||
|
margin: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.minus {
|
||||||
|
background: #fdd5d5;
|
||||||
|
color: #690b0b;
|
||||||
|
|
||||||
|
i {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.cross {
|
||||||
|
background: #d1fcd1;
|
||||||
|
color: #045b04;
|
||||||
|
|
||||||
|
i {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.neutral i {
|
||||||
|
opacity: 0.5;
|
||||||
|
color: #9f9f9f;
|
||||||
|
font-variation-settings: "wght" 350;
|
||||||
|
mix-blend-mode: difference;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hint {
|
||||||
|
margin-top: 4px;
|
||||||
|
opacity: 0.7;
|
||||||
|
font-size: 14px;
|
||||||
|
//mix-blend-mode: difference;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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>
|
||||||
64
public/src/components/PlanActionBar.vue
Normal file
64
public/src/components/PlanActionBar.vue
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
const props = defineProps<{
|
||||||
|
save: boolean,
|
||||||
|
plan: boolean,
|
||||||
|
godi: boolean
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
|
||||||
|
<div class="action-bar" :class="{save: props.save}">
|
||||||
|
<div class="other-action">
|
||||||
|
<button class="add-plan" :class="{show: props.plan}" @click="$emit('save')"> <i class="icon">add_box</i> Neuer Plan</button>
|
||||||
|
<button class="add-godi" :class="{show: props.godi}" @click="$emit('save')"> <i class="icon">add</i> Neuer Gottesdienst</button>
|
||||||
|
</div>
|
||||||
|
<button class="save" :class="{show: props.save}" @click="$emit('save')"><i class="icon">save</i> Änderungen speichern </button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
|
||||||
|
.action-bar {
|
||||||
|
width: calc(100% - 32px * 2);
|
||||||
|
border-top: 1px solid #d7d5d5;
|
||||||
|
display: flex;
|
||||||
|
padding: 10px 32px;
|
||||||
|
background: #ffffff;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
.other-action{
|
||||||
|
transition: 200ms translate;
|
||||||
|
translate: 220px;
|
||||||
|
transition-delay: 100ms;
|
||||||
|
};
|
||||||
|
|
||||||
|
&.save .other-action {
|
||||||
|
translate: 0;
|
||||||
|
transition-delay: 0ms;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
&:not(.show){
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
&.save{
|
||||||
|
&:not(.show){
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
width: 220px;
|
||||||
|
translate: 0 calc(100% + 20px);
|
||||||
|
transition: 200ms translate;
|
||||||
|
&.show {
|
||||||
|
translate: 0;
|
||||||
|
transition-delay: 100ms;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
button{
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
255
public/src/components/TablePlan.vue
Normal file
255
public/src/components/TablePlan.vue
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
import {API} from "@/views/api";
|
||||||
|
|
||||||
|
import {onMounted, reactive, ref} from "vue";
|
||||||
|
import type {PlanModel, SimplifiedMinistrant} from "@/models/models";
|
||||||
|
|
||||||
|
const props = defineProps<PlanModel>()
|
||||||
|
defineEmits(["toggleMark"])
|
||||||
|
|
||||||
|
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
|
||||||
|
switch (mark) {
|
||||||
|
case -1:
|
||||||
|
return "minus";
|
||||||
|
case 0:
|
||||||
|
return "neutral";
|
||||||
|
case 1:
|
||||||
|
return "cross"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
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()) + "."
|
||||||
|
}
|
||||||
|
|
||||||
|
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.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
|
||||||
|
<thead>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th v-for="godi in props.gottesdienste">{{ 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">{{ mini.id }} {{ mini.firstname }} {{ mini.lastname }}</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">{{ getHintForMark(godi.id, mini.id) }}</span>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-spacing: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr{
|
||||||
|
th{
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
&.bold th{
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
background: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
td:first-child, th:first-child {
|
||||||
|
padding: 6px 60px 6px 12px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.minus {
|
||||||
|
background: #fdd5d5;
|
||||||
|
color: #690b0b;
|
||||||
|
|
||||||
|
i {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.cross {
|
||||||
|
background: #d1fcd1;
|
||||||
|
color: #045b04;
|
||||||
|
|
||||||
|
i {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mark{
|
||||||
|
cursor: pointer;
|
||||||
|
&.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>
|
||||||
@ -19,7 +19,8 @@ export interface Mark {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface PlanModel {
|
export interface PlanModel {
|
||||||
gottesdienste: Array<Gottesdienst>,
|
gottesdienste: Gottesdienst[],
|
||||||
ministranten: Array<SimplifiedMinistrant>,
|
ministranten: SimplifiedMinistrant[],
|
||||||
marks: Array<Mark>
|
marks: Mark[],
|
||||||
|
editable: number[]
|
||||||
}
|
}
|
||||||
@ -1,5 +1,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
import {onMounted, reactive, ref, toRaw} from "vue";
|
||||||
|
import TablePlan from "@/components/TablePlan.vue";
|
||||||
|
import {API} from "@/views/api";
|
||||||
|
import type {Mark, PlanModel} from "@/models/models";
|
||||||
|
import MobilePlan from "@/components/MobilePlan.vue";
|
||||||
|
import PlanActionBar from "@/components/PlanActionBar.vue";
|
||||||
|
|
||||||
import {computed, onMounted, reactive, ref} from "vue";
|
import {computed, onMounted, reactive, ref} from "vue";
|
||||||
import Plan from "@/components/Plan.vue";
|
import Plan from "@/components/Plan.vue";
|
||||||
import {API} from "@/views/api";
|
import {API} from "@/views/api";
|
||||||
@ -10,6 +17,8 @@ const plan = reactive<PlanModel>({
|
|||||||
ministranten: [],
|
ministranten: [],
|
||||||
marks: []
|
marks: []
|
||||||
})
|
})
|
||||||
|
const mobile = ref(false)
|
||||||
|
const editedMarks = reactive<Mark[]>([]);
|
||||||
|
|
||||||
const sortedGottesdienste = computed(() => {
|
const sortedGottesdienste = computed(() => {
|
||||||
return plan.gottesdienste.sort((a, b) => {
|
return plan.gottesdienste.sort((a, b) => {
|
||||||
@ -44,6 +53,13 @@ async function deleteGottedienst(id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function addGodi() {
|
||||||
|
let time = 1692104646066 + ((1000 * 60 * 60 * 24) * Math.random() * 6)
|
||||||
|
let newGodi = await API.addGottesdienst("Godi", new Date(time), new Date(time - 1000 * 60 * 30), 0)
|
||||||
|
plan.gottesdienste.push(newGodi)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
let fetchedPlan = await API.getPlan(0)
|
let fetchedPlan = await API.getPlan(0)
|
||||||
plan.gottesdienste = fetchedPlan.gottesdienste
|
plan.gottesdienste = fetchedPlan.gottesdienste
|
||||||
@ -51,17 +67,35 @@ onMounted(async () => {
|
|||||||
plan.marks = fetchedPlan.marks
|
plan.marks = fetchedPlan.marks
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function getMarks(): Mark[]{
|
||||||
|
return plan.marks.filter((mark: Mark) => {
|
||||||
|
let difMark = editedMarks.find((m: Mark) => m.gid == mark.gid && m.mid == mark.mid)
|
||||||
|
return !difMark
|
||||||
|
}).concat(editedMarks);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDif(): Mark[]{
|
||||||
|
return editedMarks.filter((mark: Mark) => {
|
||||||
|
let sameMark = plan.marks.find((m: Mark) => m.gid == mark.gid && m.mid == mark.mid)
|
||||||
|
return (!sameMark && mark.value != 0) || (sameMark && mark.value != sameMark.value)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
function canEdit(mid) {
|
||||||
|
return plan.editable.includes(mid)
|
||||||
|
}
|
||||||
|
|
||||||
function toggleMark(gid, mid) {
|
function toggleMark(gid, mid) {
|
||||||
// TODO: track changes
|
// TODO: track changes
|
||||||
let existingMark = plan.marks.find(mark => mark.mid == mid && mark.gid == gid);
|
if(!canEdit(mid)) return;
|
||||||
if(existingMark) {
|
|
||||||
existingMark.value = ((existingMark.value + 2) % 3) - 1
|
let mark = editedMarks.find(m => m.mid == mid && m.gid == gid);
|
||||||
console.log(existingMark.value.valueOf())
|
if (mark) {
|
||||||
}else{
|
mark.value = ((mark.value + 2) % 3) - 1
|
||||||
const mark = {
|
} else {
|
||||||
|
mark = {
|
||||||
gid, mid, value: 1
|
gid, mid, value: 1
|
||||||
}
|
}
|
||||||
plan.marks.push(mark)
|
editedMarks.push(mark)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,22 +106,54 @@ function toggleMark(gid, mid) {
|
|||||||
<template>
|
<template>
|
||||||
<main>
|
<main>
|
||||||
|
|
||||||
<Plan
|
<TablePlan
|
||||||
:gottesdienste="sortedGottesdienste"
|
:gottesdienste="plan.gottesdienste"
|
||||||
:ministranten="plan.ministranten"
|
:ministranten="plan.ministranten"
|
||||||
:marks="plan.marks"
|
:marks="getMarks()"
|
||||||
:edit="false"
|
:editable="plan.editable"
|
||||||
@added="addGodi"
|
@added="addGodi"
|
||||||
@delete="deleteGottedienst"
|
@delete="deleteGottesdienst"
|
||||||
@toggle-mark="toggleMark">
|
@toggle-mark="toggleMark"
|
||||||
|
class="plan table"
|
||||||
|
v-if="!mobile">
|
||||||
|
|
||||||
</Plan>
|
</TablePlan>
|
||||||
|
|
||||||
|
<MobilePlan
|
||||||
|
:gottesdienste="plan.gottesdienste"
|
||||||
|
:ministranten="plan.ministranten"
|
||||||
|
:marks="getMarks()"
|
||||||
|
:editable="plan.editable"
|
||||||
|
@toggle-mark="toggleMark"
|
||||||
|
class="plan mobile"
|
||||||
|
v-else>
|
||||||
|
|
||||||
|
</MobilePlan>
|
||||||
|
|
||||||
|
<PlanActionBar
|
||||||
|
class="action-bar"
|
||||||
|
:save="getDif().length > 0"
|
||||||
|
:plan="false"
|
||||||
|
:godi="false"
|
||||||
|
/>
|
||||||
|
|
||||||
<button @click="addGodi">Add random Gottesdienst</button>
|
|
||||||
|
|
||||||
</main>
|
</main>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
|
|
||||||
|
.plan {
|
||||||
|
padding-bottom: 100px;
|
||||||
|
}
|
||||||
|
.plan.table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-bar {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
Loading…
Reference in New Issue
Block a user