Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Camp create: choose prototype UX improvement #4162

Merged
merged 10 commits into from
Dec 19, 2023
6 changes: 6 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,12 @@
"ignoreKeysRegex": "^(global|entity|contentNode\\.[a-z][a-zA-Z]+|print\\.(global|activity|cover|picasso|program|story|toc))\\..+",
"translationKeyPropRegex": "[a-zA-Z0-9]-i18n-key$"
}
],
"vue/no-mutating-props": [
"error",
{
"shallowOnly": false
}
]
},
"parserOptions": {
Expand Down
11 changes: 11 additions & 0 deletions frontend/src/components/buttons/ButtonContinue.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<template>
<v-btn color="primary" v-bind="$attrs" v-on="$listeners">
{{ $tc('global.button.continue') }}
</v-btn>
</template>

<script>
export default {
name: 'ButtonContinue',
}
</script>
95 changes: 95 additions & 0 deletions frontend/src/components/campCreate/CampCreate.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<template>
<v-stepper v-model="step" flat>
<v-stepper-header class="elevation-0">
<v-spacer v-if="$vuetify.breakpoint.smAndUp" />
<v-stepper-step :complete="step > 1" :step="1" class="px-4">
{{ $tc('components.campCreate.campCreate.steps.infos') }}
</v-stepper-step>
<v-divider class="mx-n2" />
<v-stepper-step :complete="step > 2" :step="2" class="px-4">
{{ $tc('components.campCreate.campCreate.steps.template') }}
</v-stepper-step>
<v-spacer v-if="$vuetify.breakpoint.smAndUp" />
</v-stepper-header>
<v-divider />
<v-stepper-items>
<CampCreateStep1
:camp="camp"
:is-saving="isSaving"
@add-period="addPeriod"
@delete-period="deletePeriod"
@next-step="step++"
/>
<CampCreateStep2
:camp="camp"
:is-saving="isSaving"
:server-error="serverError"
@create-camp="createCamp"
@previous-step="step--"
/>
</v-stepper-items>
</v-stepper>
</template>
<script>
import { camelCase } from 'lodash'
import { campRoute } from '@/router.js'
import CampCreateStep1 from '@/components/campCreate/CampCreateStep1.vue'
import CampCreateStep2 from '@/components/campCreate/CampCreateStep2.vue'
export default {
name: 'CampCreate',
components: { CampCreateStep1, CampCreateStep2 },
data() {
return {
step: 1,
camp: {
name: '',
title: '',
motto: '',
periods: [
{
start: '',
end: '',
description: this.$tc('entity.period.defaultDescription'),
},
],
campPrototype: '',
},
serverError: null,
isSaving: false,
}
},
computed: {
campsUrl() {
return this.api.get().camps()._meta.self
},
},
created() {},
methods: {
camelCase,
createCamp: async function () {
this.isSaving = true
try {
const camp = await this.api.post(this.campsUrl, this.camp)
await this.$router.push(campRoute(camp, 'admin'))
this.api.reload(this.campsUrl)
} catch (error) {
this.serverError = error
}
this.isSaving = false
},
addPeriod: function () {
this.camp.periods.push({
start: '',
end: '',
description: '',
})
},
deletePeriod: function (idx) {
this.camp.periods.splice(idx, 1)
},
},
}
</script>
95 changes: 95 additions & 0 deletions frontend/src/components/campCreate/CampCreateStep1.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<template>
<v-stepper-content :step="1" class="pa-0">
<ValidationObserver v-slot="{ handleSubmit, valid, validate }">
<v-form ref="form" @submit.prevent="handleSubmit(() => $emit('next-step'))">
<v-card-text>
<e-text-field
v-model="localCamp.name"
:name="$tc('entity.camp.fields.name')"
vee-rules="required"
required
autofocus
/>
<e-text-field
v-model="localCamp.title"
:name="$tc('entity.camp.fields.title')"
vee-rules="required"
required
/>
<e-text-field
v-model="localCamp.motto"
:name="$tc('entity.camp.fields.motto')"
/>
<create-camp-periods
:add-period="addPeriod"
:periods="localCamp.periods"
:delete-period="deletePeriod"
:period-deletable="periodDeletable"
/>
</v-card-text>
<v-divider />
<ContentActions>
<v-spacer />
<ButtonCancel :disabled="isSaving" @click="$router.go(-1)" />
<ButtonContinue v-if="valid" @click="$emit('next-step')" />
<v-tooltip v-else top>
<template #activator="{ attrs, on }">
<v-btn
elevation="0"
color="secondary"
v-bind="attrs"
@click="validate()"
v-on="on"
>
{{ $tc('global.button.continue') }}
</v-btn>
</template>
{{ $tc('components.campCreate.campCreateStep1.submitTooltip') }}
</v-tooltip>
</ContentActions>
</v-form>
</ValidationObserver>
</v-stepper-content>
</template>
<script>
import { ValidationObserver } from 'vee-validate'
import ButtonCancel from '@/components/buttons/ButtonCancel.vue'
import ButtonContinue from '@/components/buttons/ButtonContinue.vue'
import ContentActions from '@/components/layout/ContentActions.vue'
import CreateCampPeriods from '@/components/campAdmin/CreateCampPeriods.vue'
import ETextField from '@/components/form/base/ETextField.vue'

export default {
name: 'CampCreateStep1',
components: {
ButtonCancel,
ButtonContinue,
ContentActions,
CreateCampPeriods,
ETextField,
ValidationObserver,
},
props: {
camp: { type: Object, required: true },
isSaving: { type: Boolean, required: true },
},
data: function () {
return {
localCamp: this.camp,
}
},
computed: {
periodDeletable() {
return this.camp.periods.length > 1
},
},
methods: {
addPeriod: function () {
this.$emit('add-period')
},
deletePeriod: function (idx) {
this.$emit('delete-period', idx)
},
},
}
</script>
Loading