Add member completion
This commit is contained in:
parent
1f7f70a459
commit
e0ab18a469
|
@ -1,21 +1,10 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="relative">
|
<v-checkbox :id="innerId" :name="field.key" :label="field.description" :required="field.required" v-model="inner"></v-checkbox>
|
||||||
<div class="grid grid-cols-1 gap-2">
|
|
||||||
<label :for="innerId" class="p-0 block leading-none relative flex items-start">
|
|
||||||
<input :id="innerId" v-model="inner" type="checkbox" :name="field.key" class="peer absolute invisible" />
|
|
||||||
<span class="border-neutral-400 border-4 border-solid peer-checked:border-primary absolute left-0 w-6 h-6 rounded block top-0"></span>
|
|
||||||
<span class="peer-checked:bg-primary left-[0.5rem] top-[0.5rem] w-2 h-2 absolute rounded block top-0"></span>
|
|
||||||
<span class="pl-8 pt-1 @sm:pt-0 text-gray-600 text-sm @sm:text-base">
|
|
||||||
<span v-text="field.description"></span>
|
|
||||||
<span v-show="field.required" class="text-red-800">*</span>
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {computed} from 'vue';
|
import {computed} from 'vue';
|
||||||
|
import VCheckbox from './VCheckbox.vue';
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue']);
|
const emit = defineEmits(['update:modelValue']);
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
|
|
@ -1,12 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="relative w-full flex flex-col">
|
<div class="relative w-full flex flex-col">
|
||||||
<info :step="1" v-model="step">
|
<info :step="1" v-model="step">
|
||||||
<template #finished>
|
|
||||||
<div class="flex items-center justify-between">
|
|
||||||
<div>Erfolgreich eingeloggt als {{ user }}.</div>
|
|
||||||
<v-btn class="self-end" @click.prevent="innerLogout">Abmelden</v-btn>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template #current>
|
<template #current>
|
||||||
<div class="space-y-1">
|
<div class="space-y-1">
|
||||||
<p>Bitte melde dich mit deinen <span class="font-semibold">NaMi Zugangsdaten</span> an. Im Anschluss kannst du deine Grüpplinge aus deiner Gruppierung hier hinzufügen.</p>
|
<p>Bitte melde dich mit deinen <span class="font-semibold">NaMi Zugangsdaten</span> an. Im Anschluss kannst du deine Grüpplinge aus deiner Gruppierung hier hinzufügen.</p>
|
||||||
|
@ -26,80 +20,114 @@
|
||||||
<v-btn class="self-end" @click.prevent="innerLogin">Anmelden</v-btn>
|
<v-btn class="self-end" @click.prevent="innerLogin">Anmelden</v-btn>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<template #finished>
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div>Erfolgreich eingeloggt als {{ user }}.</div>
|
||||||
|
<v-btn class="self-end" @click.prevent="innerLogout">Abmelden</v-btn>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</info>
|
</info>
|
||||||
|
|
||||||
<info class="mt-4" :step="2" v-model="step">
|
<info class="mt-4" :step="2" v-model="step">
|
||||||
<template #finished>
|
|
||||||
<div class="flex items-center justify-between">
|
|
||||||
<div>{{ inner.length }} Mitglieder ausgewählt</div>
|
|
||||||
<v-btn class="self-end" @click.prevent="logout">Bearbeiten</v-btn>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template #due>
|
<template #due>
|
||||||
<div>Mitglieder auswählen</div>
|
<div>Mitglieder auswählen</div>
|
||||||
</template>
|
</template>
|
||||||
<template #current>
|
<template #current>
|
||||||
<p>
|
<p>
|
||||||
Nun kannst du hier nach Mitgliedern suchen. Wähle die Mitglieder aus, die <span class="font-semibold">mit zur Veranstaltung fahren</span>. Dich selbst musst du hier nicht nochmal
|
Nun kannst du hier nach Mitgliedern suchen. Wähle die Mitglieder aus, die <span class="font-semibold">an der Veranstaltung teilnehmen</span>. Dich selbst musst du hier nicht
|
||||||
auswählen.
|
nochmal auswählen.
|
||||||
</p>
|
</p>
|
||||||
<div class="flex mt-4 space-x-3">
|
<div class="flex mt-4 space-x-3">
|
||||||
<v-text name="search_firstname" label="Vorname" id="search_firstname" v-model="searchData.vorname" @input="searchForMember"></v-text>
|
<v-text name="search_firstname" label="Vorname" id="search_firstname" v-model="searchData.vorname" @input="searchForMember"></v-text>
|
||||||
<v-text name="search_lastname" label="Nachname" id="search_lastname" v-model="searchData.nachname" @input="searchForMember"></v-text>
|
<v-text name="search_lastname" label="Nachname" id="search_lastname" v-model="searchData.nachname" @input="searchForMember"></v-text>
|
||||||
<v-dropdown name="search_group" label="Stufe" id="search_group" v-model="searchData.untergliederungId" @input="searchForMember" :options="eventMeta.agegroups"></v-dropdown>
|
<v-dropdown name="search_group" label="Stufe" id="search_group" v-model="searchData.untergliederungId" @input="searchForMember" :options="eventMeta.agegroups"></v-dropdown>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="relative min-h-48">
|
<div class="relative min-h-48">
|
||||||
<div class="relative grid grid-cols-[repeat(auto-fit,minmax(200px,1fr))] gap-2 mt-2">
|
<div class="relative grid grid-cols-[repeat(auto-fit,minmax(200px,1fr))] gap-2 mt-2">
|
||||||
<div v-for="member in searchResults.data" :id="member.id">
|
<v-checkbox
|
||||||
{{ member.name }}
|
:modelValue="memberSelected(member)"
|
||||||
</div>
|
@update:modelValue="toggleMember(member)"
|
||||||
|
:name="`${field.key}-memberselect-${member.id}`"
|
||||||
|
:id="`${field.key}-memberselect-${member.id}`"
|
||||||
|
:label="member.name"
|
||||||
|
v-for="member in searchResults.data"
|
||||||
|
></v-checkbox>
|
||||||
</div>
|
</div>
|
||||||
<pagination class="mt-5" :model-value="searchResults" @reload="searchForMember($event)" v-if="searchResults.current_page"></pagination>
|
<pagination class="mt-5" :model-value="searchResults" @reload="searchForMember($event)" v-if="searchResults.current_page"></pagination>
|
||||||
<div class="absolute flex h-full w-full top-0 left-0 justify-center items-center backdrop-blur-sm" v-if="searching">
|
<div class="absolute flex h-full w-full top-0 left-0 justify-center items-center backdrop-blur-sm" v-if="searching">
|
||||||
<spinner class="w-20 h-20"></spinner>
|
<spinner class="w-20 h-20"></spinner>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex justify-center mt-5">
|
||||||
<div v-for="(member, index) in inner" class="flex space-x-2 mt-6" :key="index">
|
<v-btn @click.prevent="membersAccepted = true">Weiter</v-btn>
|
||||||
<label class="w-full border border-solid border-gray-500 focus-within:border-primary rounded-lg relative flex mt-2">
|
</div>
|
||||||
<input
|
</template>
|
||||||
:id="`${field.key}-${index}`"
|
<template #finished>
|
||||||
v-model="member.id"
|
<div class="flex items-center justify-between">
|
||||||
:name="`${field.key}-${index}`"
|
<div>{{ inner.length }} Mitglieder ausgewählt</div>
|
||||||
type="text"
|
<v-btn class="self-end" @click.prevent="membersAccepted = false">Bearbeiten</v-btn>
|
||||||
placeholder=""
|
|
||||||
class="bg-white rounded-lg focus:outline-none text-gray-600 text-left py-1 px-2 @sm:py-2 text-sm @sm:text-base @sm:px-3 w-full"
|
|
||||||
/>
|
|
||||||
<field-label name="Mitgliedsnr" :required="true"></field-label>
|
|
||||||
</label>
|
|
||||||
<div class="w-full" v-for="(memberField, memberIndex) in memberFields" :key="field.key">
|
|
||||||
<component
|
|
||||||
:is="resolveComponentName(memberField)"
|
|
||||||
:id="`${field.key}-${memberIndex}`"
|
|
||||||
v-model="member[memberField.key]"
|
|
||||||
:fields="fields"
|
|
||||||
:payload="member"
|
|
||||||
:field="memberField"
|
|
||||||
>
|
|
||||||
</component>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</info>
|
</info>
|
||||||
|
|
||||||
<button type="button" class="bg-primary hover:bg-secondary px-4 py-2 shadow text-font leading-none rounded-lg mt-5" @click.prevent="addMember">Mitglieder hinzufügen</button>
|
<info class="mt-4" :step="3" v-model="step">
|
||||||
|
<template #due>
|
||||||
|
<div>Mitgliederdaten vervollständigen</div>
|
||||||
|
</template>
|
||||||
|
<template #current>
|
||||||
|
<p>
|
||||||
|
Hier siehst du noch einmal alle ausgewählten Mitglieder. Ggf sind hier pro Mitglied noch weitere Informationen erforderlich. Bitte gebe diese pro Mitglied an und klicke dann auf
|
||||||
|
"weiter".
|
||||||
|
</p>
|
||||||
|
<div class="grid items-center gap-2 mt-6" :style="{'grid-template-columns': `max-content repeat(${memberFields.length}, 1fr)`}">
|
||||||
|
<template v-for="member in inner" :key="member.id">
|
||||||
|
<div v-text="member.innerFormName"></div>
|
||||||
|
<template v-for="(memberField, memberIndex) in memberFields">
|
||||||
|
<v-checkbox
|
||||||
|
v-if="memberField.type === 'CheckboxField'"
|
||||||
|
v-model="member[memberField.key]"
|
||||||
|
:name="`${field.key}-memberattr-${member.id}-${memberField.key}`"
|
||||||
|
:id="`${field.key}-memberattr-${member.id}-${memberField.key}`"
|
||||||
|
:label="memberField.name"
|
||||||
|
></v-checkbox>
|
||||||
|
<v-dropdown
|
||||||
|
v-if="memberField.type === 'DropdownField'"
|
||||||
|
v-model="member[memberField.key]"
|
||||||
|
:name="`${field.key}-memberattr-${member.id}-${memberField.key}`"
|
||||||
|
:id="`${field.key}-memberattr-${member.id}-${memberField.key}`"
|
||||||
|
:label="memberField.name"
|
||||||
|
:options="
|
||||||
|
memberField.options.map((o) => {
|
||||||
|
return {id: o, name: o};
|
||||||
|
})
|
||||||
|
"
|
||||||
|
></v-dropdown>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-center mt-5">
|
||||||
|
<v-btn @click.prevent="membersCompleted = true">Mitgliederdaten speichern</v-btn>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #finished>
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div>Daten vervollständigt</div>
|
||||||
|
<v-btn class="self-end" @click.prevent="membersCompleted = false">Bearbeiten</v-btn>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</info>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {computed, ref} from 'vue';
|
import {computed, ref, warn} from 'vue';
|
||||||
import FieldLabel from '../FieldLabel.vue';
|
import FieldLabel from '../FieldLabel.vue';
|
||||||
import VText from './VText.vue';
|
import VText from './VText.vue';
|
||||||
import VDropdown from './VDropdown.vue';
|
import VDropdown from './VDropdown.vue';
|
||||||
import useFields from '../../composables/useFieldsWithoutNami.js';
|
import useFields from '../../composables/useFieldsWithoutNami.js';
|
||||||
import Info from '../Info.vue';
|
import Info from '../Info.vue';
|
||||||
import VBtn from '../VBtn.vue';
|
import VBtn from '../VBtn.vue';
|
||||||
|
import VCheckbox from './VCheckbox.vue';
|
||||||
import Spinner from '../Spinner.vue';
|
import Spinner from '../Spinner.vue';
|
||||||
import useAdremaLogin from '../../composables/useAdremaLogin.js';
|
import useAdremaLogin from '../../composables/useAdremaLogin.js';
|
||||||
import useEventMeta from '../../composables/useEventMeta.js';
|
import useEventMeta from '../../composables/useEventMeta.js';
|
||||||
|
@ -119,9 +147,19 @@ const step = computed(() => {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 2;
|
if (!membersAccepted.value) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!membersCompleted.value) {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 4;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const membersAccepted = ref(false);
|
||||||
|
const membersCompleted = ref(false);
|
||||||
const emit = defineEmits(['update:modelValue']);
|
const emit = defineEmits(['update:modelValue']);
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: {
|
modelValue: {
|
||||||
|
@ -148,10 +186,6 @@ const defaultMember = computed(() => {
|
||||||
|
|
||||||
const memberFields = computed(() => props.fields.filter((field) => field.for_members === true && field.nami_type === null));
|
const memberFields = computed(() => props.fields.filter((field) => field.for_members === true && field.nami_type === null));
|
||||||
|
|
||||||
function addMember() {
|
|
||||||
inner.value.push({id: '', ...defaultMember.value});
|
|
||||||
}
|
|
||||||
|
|
||||||
const inner = computed(
|
const inner = computed(
|
||||||
{
|
{
|
||||||
get: () => props.modelValue,
|
get: () => props.modelValue,
|
||||||
|
@ -161,13 +195,29 @@ const inner = computed(
|
||||||
);
|
);
|
||||||
async function innerLogin() {
|
async function innerLogin() {
|
||||||
await login();
|
await login();
|
||||||
|
membersAccepted.value = false;
|
||||||
|
membersCompleted.value = false;
|
||||||
resetSearchData();
|
resetSearchData();
|
||||||
searchForMember();
|
searchForMember();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function memberSelected(member) {
|
||||||
|
return inner.value.map((m) => m.id).includes(member.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleMember(member) {
|
||||||
|
if (memberSelected(member)) {
|
||||||
|
inner.value = inner.value.filter((m) => m.id !== member.id);
|
||||||
|
} else {
|
||||||
|
inner.value.push({id: member.id, innerFormName: member.name, ...defaultMember.value});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function innerLogout() {
|
async function innerLogout() {
|
||||||
logout();
|
logout();
|
||||||
resetSearchData();
|
resetSearchData();
|
||||||
|
membersAccepted.value = false;
|
||||||
|
membersCompleted.value = false;
|
||||||
inner.value = [];
|
inner.value = [];
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
<template>
|
||||||
|
<div class="relative">
|
||||||
|
<div class="grid grid-cols-1 gap-2">
|
||||||
|
<label :for="id" class="p-0 block leading-none relative flex items-start">
|
||||||
|
<input :id="id" v-model="inner" type="checkbox" :name="name" class="peer absolute invisible" />
|
||||||
|
<span
|
||||||
|
class="border-neutral-400 border-4 group-[.info]:border-2 border-solid peer-checked:border-primary absolute left-0 w-6 h-6 group-[.info]:w-4 group-[.info]:h-4 group-[.info]:top-[5px] rounded block top-0"
|
||||||
|
></span>
|
||||||
|
<span class="peer-checked:bg-primary left-[0.5rem] top-[0.5rem] group-[.info]:top-[0.58rem] group-[.info]:left-[0.25rem] w-2 h-2 absolute rounded block top-0"></span>
|
||||||
|
<span v-if="label" class="pl-8 group-[.info]:pl-6 pt-1 @sm:pt-0 @sm:group-[.info]:pt-1 text-gray-600 text-sm @sm:text-base @sm:group-[.info]:text-sm">
|
||||||
|
<span v-text="label"></span>
|
||||||
|
<span v-show="required" class="text-red-800">*</span>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {computed} from 'vue';
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:modelValue']);
|
||||||
|
const props = defineProps({
|
||||||
|
modelValue: {
|
||||||
|
required: true,
|
||||||
|
validator: (value) => value === true || value === false,
|
||||||
|
},
|
||||||
|
id: {
|
||||||
|
required: true,
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
required: true,
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
required: false,
|
||||||
|
type: String,
|
||||||
|
default: () => '',
|
||||||
|
},
|
||||||
|
required: {
|
||||||
|
required: false,
|
||||||
|
type: Boolean,
|
||||||
|
default: () => false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const inner = computed({
|
||||||
|
get: () => props.modelValue,
|
||||||
|
set: (v) => emit('update:modelValue', v),
|
||||||
|
});
|
||||||
|
</script>
|
Loading…
Reference in New Issue