<template> <div class="requirement-list"> <v-row no-gutters class="mb-5"> <v-col cols="12"> <div class="text-h5 text--primary">Requirement List</div> <div class="mb-3 body-2"> Define which requirements are necessary for the product to meet the user requirements. A requirement is a slice of functionality that describes a product's appearance, components, and/or capabilities. Please do the following steps: (1) Add a requirement through the button, (2) Choose its importance from 100%, and (3) Assign purposes (Exploration, Evaluation, and/or Communication) that you need to assess during your experiments. </div> </v-col> <v-col cols="12"> <v-btn depressed :block="$vuetify.breakpoint.smAndDown" min-width="150" color="primary" @click="addRequirement">Add Requirement</v-btn> </v-col> </v-row> <v-row no-gutters class="pb-2" v-if="requirements.length > 0"> <v-col cols="5" class="accent--text body-2 font-weight-bold">Requirement Name</v-col> <v-col cols="2" class="accent--text body-2 font-weight-bold">Ranking</v-col> <v-col cols="1" class="accent--text body-2 font-weight-bold"></v-col> <v-col cols="4" class="accent--text body-2 font-weight-bold"> <v-row v-if="$vuetify.breakpoint.mdAndUp" no-gutters> <v-col cols="4">Explore (Ex)</v-col> <v-col cols="4">Evaluate (Ev)</v-col> <v-col cols="4">Communicate (Com)</v-col> </v-row> <v-row v-else no-gutters> <v-col cols="4">(Ex)</v-col> <v-col cols="4">(Ev)</v-col> <v-col cols="4">(Com)</v-col> </v-row> </v-col> </v-row> <v-row v-for="(requirement, i) in requirements" :key="i" no-gutters> <v-col cols="5" class="pr-1"> <v-text-field v-model="requirement.name" label="What is the Requirement Name?" outlined counter maxlength="60" :rules="[value => !!value || 'Name is required.']" ></v-text-field> </v-col> <v-col cols="2" class="px-1"> <v-text-field v-model.number="requirement.rating" label="Ranking" outlined maxlength="3" @input="ratingChanged" type="number" :rules="[value => !!value || 'Ranking is required.', value => (value > 0 && value <= 100) || 'Ranking invalid.', value => ratingSum === 100 || 'Rankings must sum to 100.']" ></v-text-field> </v-col> <v-col cols="1" class="px-0"> <v-btn icon color="gray" class="pt-4" @click="deleteRequirement(i)"> <v-icon>mdi-delete</v-icon> </v-btn> </v-col> <v-col cols="4"> <v-row no-gutters> <v-col cols="4"> <v-checkbox v-model="requirement.purpose.exploration" :label="$vuetify.breakpoint.smAndUp ? 'Ex' : ''" :rules="[() => rules.atLeastOne(requirement.purpose)]" ></v-checkbox> </v-col> <v-col cols="4"> <v-checkbox v-model="requirement.purpose.evaluation" :label="$vuetify.breakpoint.smAndUp ? 'Ev' : ''" :rules="[() => rules.atLeastOne(requirement.purpose)]" hide-details ></v-checkbox> </v-col> <v-col cols="4"> <v-checkbox v-model="requirement.purpose.communication" :label="$vuetify.breakpoint.smAndUp ? 'Com' : ''" :rules="[() => rules.atLeastOne(requirement.purpose)]" hide-details ></v-checkbox> </v-col> </v-row> </v-col> </v-row> <v-row no-gutters v-if="requirements.length > 0"> <v-col cols="12" class="body-2"> Ranking left: {{ 100 - ratingSum }}/100 </v-col> </v-row> </div> </template> <script> import sumBy from 'lodash/sumBy' export default { name: "AddRequirementList", props: ['requirements', 'cycleId', 'finish', 'requirementsDeleted'], data: () => ({ name: '', rules: { atLeastOne: (requirement) => Object.values(requirement).some(x => !!x) || 'At least one required.' }, }), methods: { addRequirement() { this.requirements.push({ name: this.name, rating: null, purpose: {exploration: false, evaluation: false, communication: false}, finish: this.finish, }) this.name = '' }, deleteRequirement(i) { this.requirementsDeleted.push(...this.requirements.splice(i, 1)) }, ratingChanged() { this.$emit('rating-changed') } }, computed: { ratingSum() { return sumBy(this.requirements, 'rating') }, }, created: async function () { if (this.requirements.length === 0) { // one can toggle the checkbox and get copies of the same list await this.$http.get(`/board/label?cycle-id=${this.cycleId}`).then(res => { if (!res.data.finish) { // one can repeat requirement list planning and therefore return empty list let requirements = Object.values(res.data.requirements) requirements.forEach(requirement => { // Process requirements for checkboxes let purposes = {} requirement.purpose.forEach(purpose => { if (purpose.name === 'Explore') purposes.exploration = true; if (purpose.name === 'Evaluate') purposes.evaluation = true; if (purpose.name === 'Communicate') purposes.communication = true; }) requirement.purpose = purposes requirement.finish = this.finish this.requirements.push(requirement) }) } // otherwise nothing to finalize }) } } } </script> <style scoped> </style>