decisions
This commit is contained in:
parent
562f6ab1f2
commit
0d559c9365
13 changed files with 78 additions and 11 deletions
151
src/views/admin/club/protocol/Protocol.vue
Normal file
151
src/views/admin/club/protocol/Protocol.vue
Normal file
|
@ -0,0 +1,151 @@
|
|||
<template>
|
||||
<MainTemplate>
|
||||
<template #topBar>
|
||||
<div class="flex flex-row items-center justify-between pt-5 pb-3 px-7">
|
||||
<h1 class="font-bold text-xl h-8">Protokolle</h1>
|
||||
</div>
|
||||
</template>
|
||||
<template #diffMain>
|
||||
<div class="flex flex-col w-full h-full gap-2 justify-center px-7">
|
||||
<div class="flex flex-col w-full grow gap-2 pr-2 overflow-y-scroll">
|
||||
<ProtocolListItem v-for="protocol in protocols" :key="protocol.id" :protocol="protocol" />
|
||||
</div>
|
||||
<div class="flex flex-row w-full justify-between select-none">
|
||||
<p class="text-sm font-normal text-gray-500">
|
||||
Elemente <span class="font-semibold text-gray-900">{{ showingText }}</span> von
|
||||
<span class="font-semibold text-gray-900">{{ entryCount }}</span>
|
||||
</p>
|
||||
<ul class="flex flex-row text-sm h-8">
|
||||
<li
|
||||
class="flex h-8 w-8 items-center justify-center text-gray-500 bg-white border border-gray-300 first:rounded-s-lg last:rounded-e-lg"
|
||||
:class="[currentPage > 0 ? 'cursor-pointer hover:bg-gray-100 hover:text-gray-700' : 'opacity-50']"
|
||||
@click="loadPage(currentPage - 1)"
|
||||
>
|
||||
<ChevronLeftIcon class="h-4" />
|
||||
</li>
|
||||
<li
|
||||
v-for="page in displayedPagesNumbers"
|
||||
:key="page"
|
||||
class="flex h-8 w-8 items-center justify-center text-gray-500 bg-white border border-gray-300 hover:bg-gray-100 hover:text-gray-700 first:rounded-s-lg last:rounded-e-lg"
|
||||
:class="[currentPage == page ? 'font-bold border-primary' : '', page != '.' ? ' cursor-pointer' : '']"
|
||||
@click="loadPage(page)"
|
||||
>
|
||||
{{ typeof page == "number" ? page + 1 : "..." }}
|
||||
</li>
|
||||
<li
|
||||
class="flex h-8 w-8 items-center justify-center text-gray-500 bg-white border border-gray-300 first:rounded-s-lg last:rounded-e-lg"
|
||||
:class="[
|
||||
currentPage + 1 < countOfPages ? 'cursor-pointer hover:bg-gray-100 hover:text-gray-700' : 'opacity-50',
|
||||
]"
|
||||
@click="loadPage(currentPage + 1)"
|
||||
>
|
||||
<ChevronRightIcon class="h-4" />
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-row gap-4">
|
||||
<button primary class="!w-fit" @click="openCreateModal">Protokoll erstellen</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</MainTemplate>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineAsyncComponent, defineComponent, markRaw } from "vue";
|
||||
import { mapActions, mapState } from "pinia";
|
||||
import MainTemplate from "@/templates/Main.vue";
|
||||
import { ChevronRightIcon, ChevronLeftIcon } from "@heroicons/vue/20/solid";
|
||||
import { useProtocolStore } from "@/stores/admin/protocol";
|
||||
import ProtocolListItem from "@/components/admin/club/protocol/ProtocolListItem.vue";
|
||||
import { useModalStore } from "@/stores/modal";
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default defineComponent({
|
||||
data() {
|
||||
return {
|
||||
currentPage: 0,
|
||||
maxEntriesPerPage: 25,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(useProtocolStore, ["protocols", "totalCount"]),
|
||||
entryCount() {
|
||||
return this.totalCount ?? this.protocols.length;
|
||||
},
|
||||
showingStart() {
|
||||
return this.currentPage * this.maxEntriesPerPage;
|
||||
},
|
||||
showingEnd() {
|
||||
let max = this.currentPage * this.maxEntriesPerPage + this.maxEntriesPerPage;
|
||||
if (max > this.entryCount) max = this.entryCount;
|
||||
return max;
|
||||
},
|
||||
showingText() {
|
||||
return `${this.entryCount != 0 ? this.showingStart + 1 : 0} - ${this.showingEnd}`;
|
||||
},
|
||||
countOfPages() {
|
||||
return Math.ceil(this.entryCount / this.maxEntriesPerPage);
|
||||
},
|
||||
displayedPagesNumbers(): Array<number | "."> {
|
||||
//indicate if "." or page number gets pushed
|
||||
let stateOfPush = false;
|
||||
|
||||
return [...new Array(this.countOfPages)].reduce((acc, curr, index) => {
|
||||
if (
|
||||
// always display first 2 pages
|
||||
index <= 1 ||
|
||||
// always display last 2 pages
|
||||
index >= this.countOfPages - 2 ||
|
||||
// always display 1 pages around current page
|
||||
(this.currentPage - 1 <= index && index <= this.currentPage + 1)
|
||||
) {
|
||||
acc.push(index);
|
||||
stateOfPush = false;
|
||||
return acc;
|
||||
}
|
||||
// abort if placeholder already added to array
|
||||
if (stateOfPush == true) return acc;
|
||||
// show placeholder if pagenumber is not actively rendered
|
||||
acc.push(".");
|
||||
stateOfPush = true;
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
},
|
||||
visibleRows() {
|
||||
return this.filterData(this.protocols, this.showingStart, this.showingEnd);
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.fetchProtocols(0, this.maxEntriesPerPage, true);
|
||||
},
|
||||
methods: {
|
||||
...mapActions(useProtocolStore, ["fetchProtocols"]),
|
||||
...mapActions(useModalStore, ["openModal"]),
|
||||
loadPage(newPage: number | ".") {
|
||||
if (newPage == ".") return;
|
||||
if (newPage < 0 || newPage >= this.countOfPages) return;
|
||||
|
||||
let pageStart = newPage * this.maxEntriesPerPage;
|
||||
let pageEnd = newPage * this.maxEntriesPerPage + this.maxEntriesPerPage;
|
||||
if (pageEnd > this.entryCount) pageEnd = this.entryCount;
|
||||
|
||||
let loadedElementCount = this.filterData(this.protocols, pageStart, pageEnd).length;
|
||||
if (loadedElementCount < this.maxEntriesPerPage) this.fetchProtocols(pageStart, this.maxEntriesPerPage);
|
||||
|
||||
this.currentPage = newPage;
|
||||
},
|
||||
filterData(array: Array<any>, start: number, end: number): Array<any> {
|
||||
return array.filter((elem, index) => (elem?.tab_pos ?? index) >= start && (elem?.tab_pos ?? index) < end);
|
||||
},
|
||||
openCreateModal() {
|
||||
// this.openModal(
|
||||
// markRaw(defineAsyncComponent(() => import("@/components/admin/club/protocol/CreateProtocolModal.vue")))
|
||||
// );
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
29
src/views/admin/club/protocol/ProtocolDecisions.vue
Normal file
29
src/views/admin/club/protocol/ProtocolDecisions.vue
Normal file
|
@ -0,0 +1,29 @@
|
|||
<template>
|
||||
<div class="flex flex-col gap-2 h-full w-full overflow-y-auto">
|
||||
<Spinner v-if="loadingActive == 'loading'" class="mx-auto" />
|
||||
<p v-else-if="loadingActive == 'failed'" @click="" class="cursor-pointer">↺ laden fehlgeschlagen</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineComponent } from "vue";
|
||||
import { mapActions, mapState } from "pinia";
|
||||
import Spinner from "@/components/Spinner.vue";
|
||||
import { useProtocolStore } from "@/stores/admin/protocol";
|
||||
import { QuillEditor } from "@vueup/vue-quill";
|
||||
import "@vueup/vue-quill/dist/vue-quill.snow.css";
|
||||
import { toolbarOptions } from "@/helpers/quillConfig";
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default defineComponent({
|
||||
props: {
|
||||
protocolId: String,
|
||||
},
|
||||
computed: {
|
||||
...mapState(useProtocolStore, ["loadingActive"]),
|
||||
},
|
||||
mounted() {},
|
||||
methods: {},
|
||||
});
|
||||
</script>
|
68
src/views/admin/club/protocol/ProtocolOverview.vue
Normal file
68
src/views/admin/club/protocol/ProtocolOverview.vue
Normal file
|
@ -0,0 +1,68 @@
|
|||
<template>
|
||||
<div class="flex flex-col gap-2 h-full w-full overflow-y-auto">
|
||||
<div v-if="activeProtocolObj != null" class="flex flex-col gap-2 w-full">
|
||||
<div class="w-full">
|
||||
<label for="title">Titel</label>
|
||||
<input type="text" id="title" v-model="activeProtocolObj.title" />
|
||||
</div>
|
||||
<div class="w-full">
|
||||
<label for="date">Datum</label>
|
||||
<input type="date" id="date" v-model="activeProtocolObj.date" />
|
||||
</div>
|
||||
<div class="flex flex-row gap-2 w-full">
|
||||
<div class="w-full">
|
||||
<label for="starttime">Startzeit</label>
|
||||
<input type="time" id="starttime" v-model="activeProtocolObj.starttime" />
|
||||
</div>
|
||||
<div class="w-full">
|
||||
<label for="endtime">Endzeit</label>
|
||||
<input type="time" id="endtime" v-model="activeProtocolObj.endtime" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col h-1/2">
|
||||
<label for="summary">Zusammenfassung</label>
|
||||
<QuillEditor
|
||||
id="summary"
|
||||
theme="snow"
|
||||
placeholder="Zusammenfassung zur Sitzung..."
|
||||
style="height: 250px; max-height: 250px; min-height: 250px"
|
||||
contentType="html"
|
||||
:toolbar="toolbarOptions"
|
||||
v-model:content="activeProtocolObj.summary"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Spinner v-if="loadingActive == 'loading'" class="mx-auto" />
|
||||
<p v-else-if="loadingActive == 'failed'" @click="fetchProtocolByActiveId" class="cursor-pointer">
|
||||
↺ laden fehlgeschlagen
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineComponent } from "vue";
|
||||
import { mapActions, mapState } from "pinia";
|
||||
import Spinner from "@/components/Spinner.vue";
|
||||
import { useProtocolStore } from "@/stores/admin/protocol";
|
||||
import { QuillEditor } from "@vueup/vue-quill";
|
||||
import "@vueup/vue-quill/dist/vue-quill.snow.css";
|
||||
import { toolbarOptions } from "@/helpers/quillConfig";
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default defineComponent({
|
||||
props: {
|
||||
protocolId: String,
|
||||
},
|
||||
computed: {
|
||||
...mapState(useProtocolStore, ["activeProtocol", "loadingActive", "activeProtocolObj"]),
|
||||
},
|
||||
mounted() {
|
||||
this.fetchProtocolByActiveId();
|
||||
},
|
||||
methods: {
|
||||
...mapActions(useProtocolStore, ["fetchProtocolByActiveId"]),
|
||||
},
|
||||
});
|
||||
</script>
|
148
src/views/admin/club/protocol/ProtocolPrecense.vue
Normal file
148
src/views/admin/club/protocol/ProtocolPrecense.vue
Normal file
|
@ -0,0 +1,148 @@
|
|||
<template>
|
||||
<div class="flex flex-col gap-2 h-full w-full overflow-y-auto">
|
||||
<Spinner v-if="loadingActive == 'loading'" class="mx-auto" />
|
||||
<p v-else-if="loadingActive == 'failed'" @click="" class="cursor-pointer">↺ laden fehlgeschlagen</p>
|
||||
<div class="w-full">
|
||||
<Combobox v-model="selected" multiple>
|
||||
<div class="relative mt-1">
|
||||
<ComboboxLabel>Anwesende suchen</ComboboxLabel>
|
||||
<div
|
||||
class="relative w-full cursor-default overflow-hidden rounded-lg bg-white text-left shadow-md focus:outline-none focus-visible:ring-2 focus-visible:ring-white/75 focus-visible:ring-offset-2 focus-visible:ring-offset-teal-300 sm:text-sm"
|
||||
>
|
||||
<ComboboxInput
|
||||
class="w-full border-none py-2 pl-3 pr-10 text-sm leading-5 text-gray-900 focus:ring-0"
|
||||
@input="query = $event.target.value"
|
||||
/>
|
||||
<ComboboxButton class="absolute inset-y-0 right-0 flex items-center pr-2">
|
||||
<ChevronUpDownIcon class="h-5 w-5 text-gray-400" aria-hidden="true" />
|
||||
</ComboboxButton>
|
||||
</div>
|
||||
<TransitionRoot
|
||||
leave="transition ease-in duration-100"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
@after-leave="query = ''"
|
||||
>
|
||||
<ComboboxOptions
|
||||
class="absolute mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black/5 focus:outline-none sm:text-sm"
|
||||
>
|
||||
<ComboboxOption v-if="filtered.length === 0" as="template" disabled>
|
||||
<li class="text-text relative cursor-default select-none py-2 pl-3 pr-4">
|
||||
<span class="font-normal block truncate"> Keine Auswahl</span>
|
||||
</li>
|
||||
</ComboboxOption>
|
||||
|
||||
<ComboboxOption
|
||||
v-for="member in filtered"
|
||||
as="template"
|
||||
:key="member.id"
|
||||
:value="member"
|
||||
v-slot="{ selected, active }"
|
||||
>
|
||||
<li
|
||||
class="relative cursor-default select-none py-2 pl-10 pr-4"
|
||||
:class="{
|
||||
'bg-primary text-white': active,
|
||||
'text-gray-900': !active,
|
||||
}"
|
||||
>
|
||||
<span class="block truncate" :class="{ 'font-medium': selected, 'font-normal': !selected }">
|
||||
{{ member.firstname }} {{ member.lastname }} {{ member.nameaffix }}
|
||||
</span>
|
||||
<span
|
||||
v-if="selected"
|
||||
class="absolute inset-y-0 left-0 flex items-center pl-3"
|
||||
:class="{ 'text-white': active, 'text-primary': !active }"
|
||||
>
|
||||
<CheckIcon class="h-5 w-5" aria-hidden="true" />
|
||||
</span>
|
||||
</li>
|
||||
</ComboboxOption>
|
||||
</ComboboxOptions>
|
||||
</TransitionRoot>
|
||||
</div>
|
||||
</Combobox>
|
||||
</div>
|
||||
<br />
|
||||
<p>Ausgewählte Anwesende</p>
|
||||
<div class="flex flex-col gap-2 grow overflow-y-auto">
|
||||
<div
|
||||
v-for="member in selected"
|
||||
:key="member.id"
|
||||
class="flex flex-row h-fit w-full border border-primary rounded-md bg-primary p-2 text-white justify-between items-center"
|
||||
>
|
||||
<p>{{ member.lastname }}, {{ member.firstname }} {{ member.nameaffix ? `- ${member.nameaffix}` : "" }}</p>
|
||||
<TrashIcon class="w-5 h-5 p-1 box-content cursor-pointer" @click="removeSelected(member.id)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineComponent } from "vue";
|
||||
import { mapActions, mapState } from "pinia";
|
||||
import Spinner from "@/components/Spinner.vue";
|
||||
import {
|
||||
Combobox,
|
||||
ComboboxLabel,
|
||||
ComboboxInput,
|
||||
ComboboxButton,
|
||||
ComboboxOptions,
|
||||
ComboboxOption,
|
||||
TransitionRoot,
|
||||
} from "@headlessui/vue";
|
||||
import { CheckIcon, ChevronUpDownIcon } from "@heroicons/vue/20/solid";
|
||||
import { TrashIcon } from "@heroicons/vue/24/outline";
|
||||
import { useProtocolStore } from "@/stores/admin/protocol";
|
||||
import { useMemberStore } from "@/stores/admin/member";
|
||||
import type { MemberViewModel } from "@/viewmodels/admin/member.models";
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default defineComponent({
|
||||
props: {
|
||||
protocolId: String,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
query: "" as String,
|
||||
selected: [] as Array<MemberViewModel>,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(useProtocolStore, ["loadingActive"]),
|
||||
...mapState(useMemberStore, ["members"]),
|
||||
filtered(): Array<MemberViewModel> {
|
||||
return this.query === ""
|
||||
? this.members
|
||||
: this.members.filter((member) =>
|
||||
(member.firstname + " " + member.lastname)
|
||||
.toLowerCase()
|
||||
.replace(/\s+/g, "")
|
||||
.includes(this.query.toLowerCase().replace(/\s+/g, ""))
|
||||
);
|
||||
},
|
||||
sorted(): Array<MemberViewModel> {
|
||||
return this.selected.sort((a, b) => {
|
||||
if (a.lastname < b.lastname) return -1;
|
||||
if (a.lastname > b.lastname) return 1;
|
||||
if (a.firstname < b.firstname) return -1;
|
||||
if (a.firstname > b.firstname) return 1;
|
||||
return 0;
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.fetchMembers();
|
||||
},
|
||||
methods: {
|
||||
...mapActions(useMemberStore, ["fetchMembers"]),
|
||||
removeSelected(id: number) {
|
||||
let index = this.selected.findIndex((s) => s.id == id);
|
||||
if (index != -1) {
|
||||
this.selected.splice(index, 1);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
51
src/views/admin/club/protocol/ProtocolProtocol.vue
Normal file
51
src/views/admin/club/protocol/ProtocolProtocol.vue
Normal file
|
@ -0,0 +1,51 @@
|
|||
<template>
|
||||
<div class="flex flex-col gap-2 h-full w-full overflow-y-auto">
|
||||
<Spinner v-if="loadingActive == 'loading'" class="mx-auto" />
|
||||
<p v-else-if="loadingActive == 'failed'" @click="" class="cursor-pointer">↺ laden fehlgeschlagen</p>
|
||||
|
||||
<details class="flex flex-col gap-2 rounded-lg w-full justify-between border border-primary overflow-hidden">
|
||||
<summary class="flex flex-row gap-2 bg-primary p-2 w-full justify-between items-center cursor-pointer">
|
||||
<input type="text" name="title" id="title" placeholder="TOP" autocomplete="off" />
|
||||
|
||||
<svg
|
||||
class="fill-white stroke-white opacity-75 w-4 h-4 -mr-1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 20 20"
|
||||
>
|
||||
<path d="M12.95 10.707l.707-.707L8 4.343 6.586 5.757 10.828 10l-4.242 4.243L8 15.657l4.95-4.95z" />
|
||||
</svg>
|
||||
</summary>
|
||||
<QuillEditor
|
||||
id="top"
|
||||
theme="snow"
|
||||
placeholder="TOP Inhalt..."
|
||||
style="height: 250px; max-height: 250px; min-height: 250px"
|
||||
contentType="html"
|
||||
:toolbar="toolbarOptions"
|
||||
/>
|
||||
</details>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineComponent } from "vue";
|
||||
import { mapActions, mapState } from "pinia";
|
||||
import Spinner from "@/components/Spinner.vue";
|
||||
import { useProtocolStore } from "@/stores/admin/protocol";
|
||||
import { QuillEditor } from "@vueup/vue-quill";
|
||||
import "@vueup/vue-quill/dist/vue-quill.snow.css";
|
||||
import { toolbarOptions } from "@/helpers/quillConfig";
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default defineComponent({
|
||||
props: {
|
||||
protocolId: String,
|
||||
},
|
||||
computed: {
|
||||
...mapState(useProtocolStore, ["loadingActive"]),
|
||||
},
|
||||
mounted() {},
|
||||
methods: {},
|
||||
});
|
||||
</script>
|
95
src/views/admin/club/protocol/ProtocolRouting.vue
Normal file
95
src/views/admin/club/protocol/ProtocolRouting.vue
Normal file
|
@ -0,0 +1,95 @@
|
|||
<template>
|
||||
<MainTemplate>
|
||||
<template #headerInsert>
|
||||
<RouterLink to="../" class="text-primary">zurück zur Liste</RouterLink>
|
||||
</template>
|
||||
<template #topBar>
|
||||
<div class="flex flex-row gap-2 items-center justify-between pt-5 pb-3 px-7">
|
||||
<h1 class="font-bold text-xl h-8 min-h-fit grow">
|
||||
{{ activeProtocolObj?.title }}, {{ activeProtocolObj?.date }}
|
||||
</h1>
|
||||
<CloudIcon v-if="syncing == 'synced'" class="w-5 h-5" />
|
||||
<CloudArrowUpIcon v-else-if="syncing == 'detectedChanges'" class="w-5 h-5" />
|
||||
<ArrowPathIcon v-else-if="syncing == 'syncing'" class="w-5 h-5 animate-spin" />
|
||||
<ExclamationTriangleIcon v-else class="w-5 h-5 animate-[ping_1s_ease-in-out_3] text-red-500" />
|
||||
<TrashIcon class="w-5 h-5 cursor-pointer" @click="openDeleteModal" />
|
||||
</div>
|
||||
</template>
|
||||
<template #diffMain>
|
||||
<div class="flex flex-col gap-2 grow px-7 overflow-hidden">
|
||||
<div class="flex flex-col grow gap-2 overflow-hidden">
|
||||
<div class="w-full flex flex-row max-lg:flex-wrap justify-center">
|
||||
<RouterLink
|
||||
v-for="tab in tabs"
|
||||
:key="tab.route"
|
||||
v-slot="{ isActive }"
|
||||
:to="{ name: tab.route }"
|
||||
class="w-1/2 md:w-1/3 lg:w-full p-0.5 first:pl-0 last:pr-0"
|
||||
>
|
||||
<p
|
||||
:class="[
|
||||
'w-full rounded-lg py-2.5 text-sm text-center font-medium leading-5 focus:ring-0 outline-none',
|
||||
isActive ? 'bg-red-200 shadow border-b-2 border-primary rounded-b-none' : ' hover:bg-red-200',
|
||||
]"
|
||||
>
|
||||
{{ tab.title }}
|
||||
</p>
|
||||
</RouterLink>
|
||||
</div>
|
||||
<RouterView />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</MainTemplate>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineAsyncComponent, defineComponent, markRaw } from "vue";
|
||||
import { mapActions, mapState } from "pinia";
|
||||
import MainTemplate from "@/templates/Main.vue";
|
||||
import { RouterLink, RouterView } from "vue-router";
|
||||
import { useProtocolStore } from "@/stores/admin/protocol";
|
||||
import {
|
||||
ArrowPathIcon,
|
||||
CloudArrowUpIcon,
|
||||
CloudIcon,
|
||||
ExclamationTriangleIcon,
|
||||
TrashIcon,
|
||||
} from "@heroicons/vue/24/outline";
|
||||
import { useModalStore } from "@/stores/modal";
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default defineComponent({
|
||||
props: {
|
||||
protocolId: String,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tabs: [
|
||||
{ route: "admin-club-protocol-overview", title: "Übersicht" },
|
||||
{ route: "admin-club-protocol-precense", title: "Anwesenheit" },
|
||||
{ route: "admin-club-protocol-voting", title: "Abstimmungen" },
|
||||
{ route: "admin-club-protocol-decisions", title: "Beschlüsse" },
|
||||
{ route: "admin-club-protocol-protocol", title: "Protokoll" },
|
||||
],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(useProtocolStore, ["activeProtocolObj", "syncing"]),
|
||||
},
|
||||
mounted() {
|
||||
this.fetchProtocolByActiveId();
|
||||
},
|
||||
methods: {
|
||||
...mapActions(useProtocolStore, ["fetchProtocolByActiveId"]),
|
||||
...mapActions(useModalStore, ["openModal"]),
|
||||
openDeleteModal() {
|
||||
// this.openModal(
|
||||
// markRaw(defineAsyncComponent(() => import("@/components/admin/club/protocol/DeleteProtocolModal.vue"))),
|
||||
// parseInt(this.protocolId ?? "")
|
||||
// );
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
29
src/views/admin/club/protocol/ProtocolVoting.vue
Normal file
29
src/views/admin/club/protocol/ProtocolVoting.vue
Normal file
|
@ -0,0 +1,29 @@
|
|||
<template>
|
||||
<div class="flex flex-col gap-2 h-full w-full overflow-y-auto">
|
||||
<Spinner v-if="loadingActive == 'loading'" class="mx-auto" />
|
||||
<p v-else-if="loadingActive == 'failed'" @click="" class="cursor-pointer">↺ laden fehlgeschlagen</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineComponent } from "vue";
|
||||
import { mapActions, mapState } from "pinia";
|
||||
import Spinner from "@/components/Spinner.vue";
|
||||
import { useProtocolStore } from "@/stores/admin/protocol";
|
||||
import { QuillEditor } from "@vueup/vue-quill";
|
||||
import "@vueup/vue-quill/dist/vue-quill.snow.css";
|
||||
import { toolbarOptions } from "@/helpers/quillConfig";
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default defineComponent({
|
||||
props: {
|
||||
protocolId: String,
|
||||
},
|
||||
computed: {
|
||||
...mapState(useProtocolStore, ["loadingActive"]),
|
||||
},
|
||||
mounted() {},
|
||||
methods: {},
|
||||
});
|
||||
</script>
|
Loading…
Add table
Add a link
Reference in a new issue