Merge stable version before large change #16

Merged
xeovalyte merged 28 commits from dev into main 2023-02-14 15:37:45 +01:00
2 changed files with 183 additions and 110 deletions
Showing only changes of commit 2b6afffa73 - Show all commits

View File

@ -1,6 +1,36 @@
<template> <template>
<div @click.self="showModel = false" v-if="showModel" class="fixed flex justify-center items-center h-screen w-full bg-black top-0 left-0 z-50 bg-opacity-50" >
<form @submit.prevent="submitModelForm" class="dark:bg-neutral-800 bg-neutral-200 p-10 rounded-xl flex flex-col w-full max-w-sm">
<h1 class="font-bold text-center text-lg mb-5">Deelnemer Toevoegen</h1>
<label class="font-bold text-default">Deelnemer</label>
<select :disabled="modelData.edit" required v-model="modelData.relatiecode" class="input dark:bg-neutral-700 bg-neutral-300 mb-5">
<option v-if="!modelData.edit" v-for="user in competitors.filter(x => !contest.events[modelData.event].competitors.map(y => y.relatiecode).includes(x.relatiecode))" :value="user.relatiecode">{{ user.name}} ({{ user.relatiecode }})</option>
<option v-else v-for="user in competitors" :value="user.relatiecode">{{ user.name}} ({{ user.relatiecode }})</option>
</select>
<label class="font-bold text-default">Tijd</label>
<div class="mb-1">
<input v-model="modelData.time.minutes" type="number" step="1" min="0" max="99" placeholder="mm" class="input dark:bg-neutral-700 bg-neutral-300 w-10 text-center p-1" />
<span class="text-default text-xl font-bold mx-1">:</span>
<input v-model="modelData.time.seconds" type="number" step="1" min="0" max="99" placeholder="ss" class="input dark:bg-neutral-700 bg-neutral-300 w-10 text-center p-1" />
<span class="text-default text-xl font-bold mx-1">:</span>
<input v-model="modelData.time.milliseconds" type="number" step="1" min="0" max="99" placeholder="ms" class="input dark:bg-neutral-700 bg-neutral-300 w-10 text-center p-1" />
</div>
<div class="flex items-center mb-5">
<input type="checkbox" v-model="modelData.dsq" class="mr-1 checkbox">
<span class="text-default">Diskwalificatie</span>
</div>
<label class="font-bold">Info (Optioneel)</label>
<input v-model="modelData.info" type="text" placeholder="Bijv. Een diskwalificatie" class="input dark:bg-neutral-700 bg-neutral-300 mb-10" />
<input type="submit" class="btn" :value="modelData.edit ? 'Bewerken' : 'Toevoegen'" />
</form>
</div>
<div class="flex flex-col gap-5 mx-auto p-2 w-full max-w-md"> <div class="flex flex-col gap-5 mx-auto p-2 w-full max-w-md">
<form v-if="!newEvent" @submit.prevent="saveEmail" class="flex flex-col"> <form @submit.prevent="submitContestForm" class="flex flex-col">
<label class="font-bold">Naam Wedstrijd</label> <label class="font-bold">Naam Wedstrijd</label>
<input v-model="contest.name" required="true" class="input mb-5 " type="text"> <input v-model="contest.name" required="true" class="input mb-5 " type="text">
@ -8,11 +38,14 @@
<input v-model="contest.date" required="true" class="input w-min hover:cursor-pointer pr-0 mb-5 " type="date"> <input v-model="contest.date" required="true" class="input w-min hover:cursor-pointer pr-0 mb-5 " type="date">
<label class="font-bold">Onderdelen</label> <label class="font-bold">Onderdelen</label>
<button @click="newEvent = true" class="item-hover border-dashed border-2 container text-center font-bold border-neutral-500 mb-3">Onderdeel Toevoegen</button> <div class="flex flex-col gap-y-5">
<div class="flex flex-col gap-y-5 mb-5"> <div v-if="competitors" v-for="event in contest.events" class="container p-2">
<div v-for="(event, index) in contest.events" :key="index" class="container p-2 flex flex-col gap-y-3"> <div @click="event.open = !event.open" class="flex hover:cursor-pointer">
<h2 class="text-center text-primary font-bold text-lg">{{ event.type }}</h2> <h2 class="font-bold">{{ event.name }}</h2>
<table class="table-fixed text-left odd:bg-blue-500"> <Icon size="1.2em" name="ion:arrow-down-b" class="ml-auto my-auto mr-2 transition-all" :class="{'rotate-180' : event.open }" />
</div>
<div v-if="event.open" class="mt-2">
<table class="table-fixed text-left w-full even:bg-gray-500">
<thead class="font-bold"> <thead class="font-bold">
<tr> <tr>
<th class="w-3/6">Naam</th> <th class="w-3/6">Naam</th>
@ -21,103 +54,85 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr v-for="competitor in event.competitors" class="even:dark:bg-neutral-700 even:bg-neutral-300"> <tr @click="handleModel(competitor, event.id, true, index)" v-for="(competitor, index) in event.competitors" class="even:dark:bg-neutral-700 even:bg-neutral-300 hover:cursor-pointer">
<td>{{ competitors.find(x => x.relatiecode === competitor.relatiecode ).name }}</td> <td class="py-1 pl-1">{{ competitors.find(x => x.relatiecode === competitor.relatiecode ).name }}</td>
<td>{{ competitor.time.minute}}:{{ competitor.time.seconds }}:{{ competitor.time.milliseconds }}</td> <td>{{ competitor.time.minutes.toString().padStart(2, '0') }}:{{ competitor.time.seconds.toString().padStart(2, '0') }}:{{ competitor.time.milliseconds.toString().padStart(2, '0') }}</td>
<td>{{ competitor.dsq }}</td> <td>{{ competitor.dsq }}</td>
</tr> </tr>
<tr v-if="competitors.filter(x => !event.competitors.map(y => y.relatiecode).includes(x.relatiecode)).length > 0" class="even:dark:bg-neutral-700 even:bg-neutral-300">
<td @click="handleModel(null, event.id)" class="hover:cursor-pointer py-1 pl-1">+ Deelnemer toevoegen</td>
<td></td>
<td></td>
</tr>
</tbody> </tbody>
</table> </table>
</div> </div>
</div> </div>
<div class="w-full flex flex-wrap justify-between">
<input :disabled="disableButtons" type="submit" value="Wedstrijd Toevoegen" class="btn w-full sm:w-48 mb-1">
<button @click="resetContest" class="hover:underline font-bold w-full sm:w-max sm:ml-auto">Reset</button>
</div>
</form>
<form v-else @submit.prevent="addEvent" class="flex flex-col">
<label class="font-bold">Onderdeel</label>
<select v-model="tempEvent.type" class="input mb-5">
<option value="200m-Obstacle-Swim">200m Obstacle Swim (Hindernis)</option>
<option value="50m-Manikin-Carry">50m Manikin Carry (Popvervoeren)</option>
<option value="100m-Rescue-Medley">100m Rescue Medley (Reddingswissel)</option>
<option value="100m-Manikin-Carry-with-Fins">100m Manikin Carry with Fins (Popvervoeren met finnen)</option>
<option value="100m-Manikin-Tow-with-Fins">100m Manikin Tow with Fins (Lifesaver)</option>
<option value="200m-Super-Lifesaver">200m Super Lifesaver</option>
<option value="Line-Throw">Line Throw</option>
<option value="4x25m-Manikin-Relay">4x25m Manikin Relay (Popvervoeren)</option>
<option value="4x50m-Obstacle-Relay">4x50m Obstacle Relay (Hindernis)</option>
<option value="4x50m-Medley-Relay">4x50m Medley Relay (Torpedoboei)</option>
</select>
<label class="font-bold">Deelnemers</label>
<button @click="tempEvent.competitors.unshift({ relatiecode: '', dsq: false, info: '', time: { minute: null, seconds: null, milliseconds: null }})" type="button" class="item-hover border-dashed border-2 container text-center font-bold border-neutral-500 mb-3">Deelnemer Toevoegen</button>
<div class="flex flex-col gap-y-3 mb-5">
<div v-for="(competitor, index) in tempEvent.competitors" :key="index">
<div class="container flex flex-col p-4">
<label class="font-bold">Deelnemer</label>
<select v-model="competitor.relatiecode" class="input dark:bg-neutral-700 bg-neutral-300 mb-5">
<option v-for="user in competitors" :value="user.relatiecode">{{ user.name}} ({{ user.relatiecode }})</option>
</select>
<label class="font-bold">Tijd</label>
<div class="flex dark:bg-neutral-700 bg-neutral-300 gap-x-2 w-min rounded mb-2">
<select v-model="competitor.time.minute" class="input pl-3 pr-8 bg-opacity-0 shadow-none ">
<option value="null" disabled selected>mm</option>
<option v-for="n in 60" :value="n < 11 ? `0${n-1}` : `${n-1}`">{{ n < 11 ? `0${n-1}` : `${n-1}` }}</option>
</select>
<span class="my-auto text-xl">:</span>
<select v-model="competitor.time.seconds" class="input pl-2 pr-8 bg-opacity-0 shadow-none ">
<option value="null" disabled selected>ss</option>
<option v-for="n in 60" :value="n < 11 ? `0${n-1}` : `${n-1}`">{{ n < 11 ? `0${n-1}` : `${n-1}`}}</option>
</select>
<span class="my-auto text-xl">:</span>
<select v-model="competitor.time.milliseconds" class="input pl-2 pr-8 bg-opacity-0 shadow-none ">
<option value="null" disabled selected>ms</option>
<option v-for="n in 100" :value="n < 11 ? `0${n-1}` : `${n-1}`">{{ n < 11 ? `0${n-1}` : `${n-1}` }}</option>
</select>
</div>
<div class="flex items-center mb-5">
<input type="checkbox" v-model="competitor.dsq" class="mr-1 checkbox">
<span>Diskwalificatie</span>
</div>
<label class="font-bold">Info (Optioneel)</label>
<input v-model="competitor.info" type="text" placeholder="Bijv. Een diskwalificatie" class="input dark:bg-neutral-700 bg-neutral-300" />
</div>
</div>
</div>
<div class="w-full flex flex-wrap justify-between">
<input :disabled="disableButtons" type="submit" value="Onderdeel Toevoegen" class="btn w-full sm:w-48 mb-1">
<button @click="backEvent" class="hover:underline font-bold w-full sm:w-max sm:ml-auto">Cancel</button>
</div> </div>
<input type="submit" class="btn mt-10 px-5 w-min mx-auto" value="Wedstrijd toevoegen" />
</form> </form>
</div> </div>
<span class="whitespace-pre">{{ contest }}</span>
</template> </template>
<script setup> <script setup>
import { getDocs, collection } from "firebase/firestore" import { getDocs, collection, writeBatch, doc } from "firebase/firestore"
definePageMeta({ definePageMeta({
title: 'Wedstrijd Toevoegen' title: 'Wedstrijd Toevoegen',
key: 'back'
}) })
const { userData, db, competitors } = inject('firebase') const { userData, db, competitors } = inject('firebase')
const disableButtons = ref(false) const showModel = ref(false)
const router = useRouter()
const newEvent = ref(false) const modelData = ref({
relatiecode: '',
time: {
minutes: null,
seconds: null,
milliseconds: null,
},
dsq: false,
info: '',
})
const contest = ref({ const contest = ref({
name: '', name: '',
date: null, date: '',
events: [], events: {
}) obstacleSwim: {
open: false,
const tempEvent = ref({ name: '200m Obstacle Swim',
type: '', id: 'obstacleSwim',
competitors: [] competitors: [],
},
manikinCarry: {
open: false,
name: '50m Manikin Carry',
id: 'manikinCarry',
competitors: [],
},
rescueMedley: {
open: false,
name: '100m Rescue Medley',
id: 'rescueMedley',
competitors: [],
},
manikinCarryWithFins: {
open: false,
name: '100m Manikin Carry with Fins',
id: 'manikinCarryWithFins',
competitors: [],
},
superLifesaver: {
open: false,
name: '200m Super Lifesaver',
id: 'superLifesaver',
competitors: [],
},
}
}) })
const getCompetitors = async () => { const getCompetitors = async () => {
@ -128,18 +143,76 @@ const getCompetitors = async () => {
}) })
} }
const addEvent = () => { const handleModel = (competitor, event, edit, index) => {
newEvent.value = false if(!competitor) competitor = {
contest.value.events.unshift(tempEvent.value) relatiecode: '',
tempEvent.value = { type: '', competitors: []} time: {
minutes: null,
seconds: null,
milliseconds: null,
},
dsq: false,
info: '',
} }
const backEvent = () => { modelData.value = competitor
newEvent.value = false modelData.value.event = event
tempEvent.value = { type: '', competitors: []} modelData.value.edit = edit
modelData.value.index = index
showModel.value = true
}
const submitModelForm = () => {
if (!modelData.value.time.minutes) modelData.value.time.minutes = 0
if (!modelData.value.time.seconds) modelData.value.time.seconds = 0
if (!modelData.value.time.milliseconds) modelData.value.time.milliseconds = 0
const index = modelData.value.index
const edit = modelData.value.edit
delete modelData.value.index
delete modelData.value.edit
if (!edit) contest.value.events[modelData.value.event].competitors.push(modelData.value)
showModel.value = false
}
const submitContestForm = async () => {
const batch = writeBatch(db)
Object.values(contest.value.events).forEach(event => {
event.competitors.forEach(competitor => {
const combinedTime = competitor.time.minutes.toString() + competitor.time.seconds.toString() + competitor.time.milliseconds.toString()
const docRef = doc(collection(db, 'timings'))
batch.set(docRef, {
relatiecode: competitor.relatiecode,
contest: { name: contest.value.name, date: contest.value.date.toString() },
event: event.id,
time: { minutes: competitor.time.minutes, seconds: competitor.time.seconds, milliseconds: competitor.time.milliseconds, combined: combinedTime },
dsq: competitor.dsq,
info: competitor.info || ''
})
})
})
await batch.commit()
} }
onMounted(() => { onMounted(() => {
getCompetitors() getCompetitors()
}) })
</script> </script>
<style scoped>
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
input[type=number] {
-moz-appearance: textfield;
appearance: textfield;
}
</style>