form as carrousel finalized

This commit is contained in:
Julien Fastré 2021-10-15 16:40:31 +02:00
parent 61488e9876
commit 8f361567ff
13 changed files with 531 additions and 283 deletions

View File

@ -21,10 +21,8 @@ const fetchResults = async (uri, params) => {
let promises = [], let promises = [],
page = 1; page = 1;
let firstData = await _fetchAction(page, uri, params); let firstData = await _fetchAction(page, uri, params);
console.log('firstData', firstData);
promises.push(Promise.resolve(firstData.results)); promises.push(Promise.resolve(firstData.results));
console.log('more ?', firstData.pagination.more);
if (firstData.pagination.more) { if (firstData.pagination.more) {
do { do {

View File

@ -1,34 +1,127 @@
<template> <template>
<household></household> <ol class="breadcrumb">
<concerned v-if="hasHouseholdOrLeave"></concerned> <li
<dates v-if="showConfirm"></dates> v-for="s in steps"
<confirmation v-if="showConfirm"></confirmation> class="breadcrumb-item" :class="{ active: step === s }"
>
{{ $t('household_members_editor.app.steps.'+s) }}
</li>
</ol>
<concerned v-if="step === 'concerned'"></concerned>
<household v-if="step === 'household'" @ready-to-go="goToNext"></household>
<household-address v-if="step === 'household_address'"></household-address>
<positioning v-if="step === 'positioning'"></positioning>
<dates v-if="step === 'confirm'"></dates>
<confirmation v-if="step === 'confirm'"></confirmation>
<ul class="record_actions sticky-form-buttons">
<li class="cancel">
<button class="btn btn-cancel" @click="goToPrevious">
{{ $t('household_members_editor.app.cancel') }}
</button>
</li>
<li v-if="step !== 'confirm'">
<button class="btn btn-action" @click="goToNext" :disabled="!isNextAllowed">
{{ $t('household_members_editor.app.next') }}&nbsp;<i class="fa fa-arrow-right"></i>
</button>
</li>
<li v-else>
<button class="btn btn-save" @click="confirm" :disabled="hasWarnings">
{{ $t('household_members_editor.app.save') }}
</button>
</li>
</ul>
</template> </template>
<script> <script>
import { mapGetters } from 'vuex'; import {mapGetters, mapState} from 'vuex';
import Concerned from './components/Concerned.vue'; import Concerned from './components/Concerned.vue';
import Household from './components/Household.vue'; import Household from './components/Household.vue';
import HouseholdAddress from './components/HouseholdAddress';
import Dates from './components/Dates.vue'; import Dates from './components/Dates.vue';
import Confirmation from './components/Confirmation.vue'; import Confirmation from './components/Confirmation.vue';
import Positioning from "./components/Positioning";
export default { export default {
name: 'App', name: 'App',
components: { components: {
Positioning,
Concerned, Concerned,
Household, Household,
HouseholdAddress,
Dates, Dates,
Confirmation, Confirmation,
}, },
data() {
return {
step: 'concerned',
};
},
computed: { computed: {
...mapGetters([ ...mapState({
'hasHouseholdOrLeave', hasWarnings: (state) => state.warnings.length > 0 || state.errors.length > 0,
'hasPersonsWellPositionnated', }),
]), steps() {
showConfirm () { let s = ['concerned', 'household'];
return this.$store.getters.hasHouseholdOrLeave
&& this.$store.getters.hasPersonsWellPositionnated; if (this.$store.getters.isHouseholdNew) {
s.push('household_address');
}
if (!this.$store.getters.isModeLeave) {
s.push('positioning');
}
s.push('confirm');
return s;
},
// return true if the next step is allowed
isNextAllowed() {
switch (this.$data.step) {
case 'concerned':
return this.$store.state.concerned.length > 0;
case 'household':
return this.$store.state.mode !== null;
case 'household_address':
return this.$store.getters.hasHouseholdAddress || this.$store.getters.isHouseholdForceNoAddress;
case 'positioning':
return this.$store.getters.hasHouseholdOrLeave
&& this.$store.getters.hasPersonsWellPositionnated;
}
return false;
},
},
methods: {
goToNext() {
console.log('go to next');
switch (this.$data.step) {
case 'concerned':
this.$data.step = 'household';
break;
case 'household':
if (this.$store.getters.isHouseholdNew) {
this.$data.step = 'household_address';
break;
} else {
this.$data.step = 'positioning';
break;
}
case 'household_address':
this.$data.step = 'positioning';
break;
case 'positioning':
this.$data.step = 'confirm';
break;
}
},
goToPrevious() {
this.$data.step = 'concerned';
},
confirm() {
this.$store.dispatch('confirm');
}, },
} }
} }

View File

@ -1,118 +1,41 @@
<template> <template>
<h2 class="mt-4">{{ $t('household_members_editor.concerned.title') }}</h2> <h2 class="mt-4">{{ $t('household_members_editor.concerned.title') }}</h2>
<h3 v-if="needsPositionning">
{{ $t('household_members_editor.concerned.persons_to_positionnate') }}
</h3>
<h3 v-else>
{{ $t('household_members_editor.concerned.persons_leaving') }}
</h3>
<div v-if="noPerson"> <div v-if="noPerson">
<div class="alert alert-info"> <div class="alert alert-info">
{{ $t('household_members_editor.add_at_least_onePerson') }} {{ $t('household_members_editor.concerned.add_at_least_onePerson') }}
</div> </div>
</div> </div>
<div v-else-if="allPersonsPositionnated">
<span class="chill-no-data-statement">{{ $t('household_members_editor.all_positionnated') }}</span>
</div>
<div v-else> <div v-else>
<div class="flex-table list-household-members"> <p>
<div v-for="conc in concUnpositionned" {{ $t('household_members_editor.concerned.persons_will_be_moved') }}&nbsp;:
class="item-bloc" <span v-for="c in concerned">
v-bind:key="conc.person.id" <person-render-box render="badge" :options="{addLink: false}" :person="c.person"></person-render-box>
> <button class="btn" @click="removePerson(c.person)" v-if="c.allowRemove" style="padding-left:0;">
<div class="item-row"> <span class="fa-stack fa-lg" :title="$t('household_members_editor.concerned.remove_concerned')">
<div class="item-col"> <i class="fa fa-circle fa-stack-1x text-danger"></i>
<div> <i class="fa fa-times fa-stack-1x"></i>
<person-render-box render="badge" :options="{}" :person="conc.person"></person-render-box> </span>
</div> </button>
<div v-if="conc.person.birthdate !== null"> </span>
{{ $t('person.born', {'gender': conc.person.gender} ) }} </p>
{{ $d(conc.person.birthdate.datetime, 'short') }}
</div>
</div>
<div class="item-col">
<ul class="list-content fa-ul">
<li>
<i class="fa fa-li fa-map-marker"></i>
<span class="chill-no-data-statement">Sans adresse</span>
</li>
</ul>
</div>
</div>
<div v-if="needsPositionning" class="item-row move_to">
<div class="item-col">
<p class="move_hint">{{ $t('household_members_editor.concerned.move_to') }}:</p>
<template
v-for="position in positions"
>
<button
class="btn btn-outline-primary"
@click="moveToPosition(conc.person.id, position.id)"
>
{{ position.label.fr }}
</button>&nbsp;
</template>
<button v-if="conc.allowRemove" @click="removeConcerned(conc)" class="btn btn-primary">
{{ $t('household_members_editor.remove_concerned') }}
</button>
</div>
</div>
</div>
</div>
</div> </div>
<div> <ul class="record_actions">
<add-persons <li>
buttonTitle="household_members_editor.concerned.add_persons" <add-persons
modalTitle="household_members_editor.concerned.search" buttonTitle="household_members_editor.concerned.add_persons"
v-bind:key="addPersons.key" modalTitle="household_members_editor.concerned.search"
v-bind:options="addPersons.options" v-bind:key="addPersons.key"
@addNewPersons="addNewPersons" v-bind:options="addPersons.options"
ref="addPersons"> <!-- to cast child method --> @addNewPersons="addNewPersons"
</add-persons> ref="addPersons"> <!-- to cast child method -->
</div> </add-persons>
</li>
</ul>
<div v-if="needsPositionning" class="positions">
<div
v-for="position in positions"
>
<h3>{{ position.label.fr }}</h3>
<div v-if="concByPosition(position.id).length > 0" class="flex-table list-household-members">
<member-details
v-for="conc in concByPosition(position.id)"
v-bind:key="conc.person.id"
v-bind:conc="conc"
>
</member-details>
</div>
<div v-else>
<p class="chill-no-data-statement">{{ $t('household_members_editor.concerned.no_person_in_position') }}</p>
</div>
</div>
</div>
</template> </template>
<style lang="scss"> <style lang="scss">
div.person {
cursor: move;
* {
cursor: move
}
}
.move_to { .move_to {
.move_hint { .move_hint {
@ -124,33 +47,26 @@ div.person {
</style> </style>
<script> <script>
import { mapGetters } from 'vuex'; import { mapState, mapGetters } from 'vuex';
import AddPersons from 'ChillPersonAssets/vuejs/_components/AddPersons.vue'; import AddPersons from 'ChillPersonAssets/vuejs/_components/AddPersons.vue';
import PersonRenderBox from 'ChillPersonAssets/vuejs/_components/Entity/PersonRenderBox.vue'; import PersonRenderBox from 'ChillPersonAssets/vuejs/_components/Entity/PersonRenderBox.vue';
import MemberDetails from './MemberDetails.vue';
import { ISOToDatetime } from 'ChillMainAssets/chill/js/date.js';
export default { export default {
name: 'Concerned', name: 'Concerned',
components: { components: {
AddPersons, AddPersons,
MemberDetails,
PersonRenderBox, PersonRenderBox,
}, },
computed: { computed: {
...mapState([
'concerned'
]),
...mapGetters([ ...mapGetters([
'concUnpositionned', 'persons',
'positions',
'concByPosition',
'needsPositionning'
]), ]),
noPerson () { noPerson () {
return this.$store.getters.persons.length === 0; return this.$store.getters.persons.length === 0;
}, },
allPersonsPositionnated () {
return this.$store.getters.persons.length > 0
&& this.$store.getters.concUnpositionned.length === 0;
},
}, },
data() { data() {
return { return {
@ -172,11 +88,9 @@ export default {
this.$refs.addPersons.resetSearch(); // to cast child method this.$refs.addPersons.resetSearch(); // to cast child method
modal.showModal = false; modal.showModal = false;
}, },
moveToPosition(person_id, position_id) { removePerson(person) {
this.$store.dispatch('markPosition', { person_id, position_id }); console.log('remove person in concerned', person);
}, this.$store.dispatch('removePerson', person);
removeConcerned(conc) {
this.$store.dispatch('removeConcerned', conc);
}, },
} }
} }

View File

@ -1,28 +1,19 @@
<template> <template>
<div v-if="hasWarning" class="alert alert-warning">
<div v-if="hasWarnings" class="alert alert-warning">
{{ $t('household_members_editor.confirmation.there_are_warnings') }} {{ $t('household_members_editor.confirmation.there_are_warnings') }}
</div> </div>
<p v-if="hasWarnings"> <p v-if="hasWarning">
{{ $t('household_members_editor.confirmation.check_those_items') }} {{ $t('household_members_editor.confirmation.check_those_items') }}
</p> </p>
<ul> <ul>
<li v-for="(msg, index) in warnings"> <li v-for="(msg, index) in warnings" class="warning">
{{ $t(msg.m, msg.a) }} {{ $t(msg.m, msg.a) }}
</li> </li>
<li v-for="msg in errors"> <li v-for="msg in errors" class="error">
{{ msg }} {{ msg }}
</li> </li>
</ul>
<ul class="record_actions sticky-form-buttons">
<li>
<button class="btn btn-save" :disabled="hasWarnings" @click="confirm">
{{ $t('household_members_editor.confirmation.save') }}
</button>
</li>
</ul> </ul>
</template> </template>
@ -36,17 +27,11 @@ export default {
name: 'Confirmation', name: 'Confirmation',
computed: { computed: {
...mapState({ ...mapState({
hasWarnings: (state) => state.warnings.length > 0 || state.errors.length > 0,
warnings: (state) => state.warnings, warnings: (state) => state.warnings,
errors: (state) => state.errors, errors: (state) => state.errors,
hasNoWarnings: (state) => state.warnings.length === 0 && state.errors.length === 0,
hasWarnings: (state) => state.warnings.length > 0 || state.errors.length > 0,
}), }),
}, },
methods: {
confirm() {
this.$store.dispatch('confirm');
}
}
} }
</script> </script>

View File

@ -0,0 +1,31 @@
<template>
<div class="flex-table" v-if="hasHousehold">
<div class="item-bloc">
<household-render-box :household="fakeHouseholdWithConcerned"></household-render-box>
</div>
</div>
</template>
<script>
import { mapState, mapGetters } from 'vuex';
import HouseholdRenderBox from 'ChillPersonAssets/vuejs/_components/Entity/HouseholdRenderBox.vue';
export default {
name: "CurrentHousehold",
components: {
HouseholdRenderBox,
},
computed: {
...mapState([
]),
...mapGetters([
'hasHousehold',
'fakeHouseholdWithConcerned',
])
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -1,5 +1,8 @@
<template> <template>
<h2>{{ $t('household_members_editor.dates_title') }}</h2>
<current-household></current-household>
<h2>{{ $t('household_members_editor.dates.dates_title') }}</h2>
<p> <p>
<label for="start_date"> <label for="start_date">
@ -11,8 +14,13 @@
<script> <script>
import CurrentHousehold from "./CurrentHousehold";
export default { export default {
name: 'Dates', name: 'Dates',
components: {
CurrentHousehold
},
computed: { computed: {
startDate: { startDate: {
get() { get() {
@ -23,10 +31,10 @@ export default {
].join('-'); ].join('-');
}, },
set(value) { set(value) {
let let
[year, month, day] = value.split('-'), [year, month, day] = value.split('-'),
dValue = new Date(year, month-1, day); dValue = new Date(year, month-1, day);
this.$store.dispatch('setStartDate', dValue); this.$store.dispatch('setStartDate', dValue);
} }
} }

View File

@ -2,116 +2,56 @@
<h2 class="mt-4">{{ $t('household_members_editor.household_part') }}</h2> <h2 class="mt-4">{{ $t('household_members_editor.household_part') }}</h2>
<div> <div class="alert alert-info" v-if="!hasHousehold">
{{ $t('household_members_editor.household.no_household_choose_one') }}
</div>
<template v-else>
<current-household></current-household>
</template>
<div class="alert alert-info">{{ $t('household_members_editor.household.no_household_choose_one') }}</div> <div class="flex-table householdSuggestionList">
<div v-for="item in getSuggestions">
<div class="flex-table householdSuggestionList"> <div class="item-bloc">
<!-- mode new is allowed and no mode is checked --> <household-render-box :household="item.household"></household-render-box>
<div v-if="isModeNewAllowed && !isHouseholdNew" class="item-bloc"> <ul class="record_actions">
<div> <li>
<section :class="{filtered: isHouseholdNewDesactivated}"> <button class="btn btn-sm btn-choose" @click="selectHousehold(item.household)">
<div class="item-row"> {{ $t('household_members_editor.select_household') }}
<div class="item-col"> </button>
<div class="h4"> </li>
<i class="fa fa-home"></i> {{ $t('household_members_editor.household.new_household') }} </ul>
</div>
</div>
</div>
</section>
<ul :class="{filteredButActive: isHouseholdNewDesactivated}" class="record_actions">
<li>
<button @click="setModeNew" class="btn btn-sm btn-create">{{ $t('household_members_editor.household.create_household') }}</button>
</li>
</ul>
</div>
</div>
<!-- mode new is allowed and checked -->
<div>
<div v-if="isModeNewAllowed && isHouseholdNew" class="item-bloc" >
<div>
<household-render-box :household="household" :isAddressMultiline="true"></household-render-box>
<ul class="record_actions" v-if="isHouseholdNew">
<li>
<add-address
:context="getAddressContext"
:key="addAddress.key"
:options="addAddress.options"
:addressChangedCallback="addressChanged"
></add-address>
</li>
<li v-if="hasHouseholdAddress">
<button class="btn btn-remove"
@click="removeHouseholdAddress">
{{ $t('household_members_editor.household.remove_address') }}
</button>
</li>
</ul>
</div>
</div>
</div>
<!-- if allow leave household -->
<div v-if="isModeLeaveAllowed" class="item-bloc">
<div>
<section :class="{filtered: isHouseholdNewDesactivated}">
<div class="item-row">
<div class="item-col">
<div class="h4">
<span class="fa-stack fa-lg">
<i class="fa fa-home fa-stack-1x"></i>
<i class="fa fa-ban fa-stack-2x text-danger"></i>
</span>
{{ $t('household_members_editor.household.leave_without_household') }}
</div>
</div>
</div>
<div class="item-row">
{{ $t('household_members_editor.household.will_leave_any_household_explanation')}}
</div>
</section>
<ul class="record_actions" :class="{filteredButActive: isHouseholdNewDesactivated}">
<li>
<button @click="setModeLeave" class="btn btn-sm">
<i class="fa fa-sign-out"></i>
{{ $t('household_members_editor.household.leave') }}
</button>
</li>
</ul>
</div>
</div>
<div v-for="item in getSuggestions">
<div class="item-bloc">
<household-render-box :household="item.household"></household-render-box>
<ul class="record_actions">
<li>
<button class="btn btn-sm btn-choose" @click="selectHousehold(item.household)">
{{ $t('household_members_editor.select_household') }}
</button>
</li>
</ul>
</div>
</div> </div>
</div> </div>
</div> </div>
<ul class="record_actions">
<li v-if="hasHousehold">
<button @click="resetMode" class="btn btn-sm btn-misc">{{ $t('household_members_editor.household.reset_mode')}}</button>
</li>
<li v-if="!hasHousehold">
<button @click="setModeNew" class="btn btn-sm btn-create">{{ $t('household_members_editor.household.create_household') }}</button>
</li>
<li v-if="isModeLeaveAllowed && !hasHousehold">
<button @click="setModeLeave" class="btn btn-sm">
<i class="fa fa-sign-out"></i>
{{ $t('household_members_editor.household.leave') }}
</button>
</li>
</ul>
</template> </template>
<script> <script>
import { mapGetters, mapState } from 'vuex'; import { mapGetters, mapState } from 'vuex';
import HouseholdRenderBox from 'ChillPersonAssets/vuejs/_components/Entity/HouseholdRenderBox.vue'; import HouseholdRenderBox from 'ChillPersonAssets/vuejs/_components/Entity/HouseholdRenderBox.vue';
import AddressRenderBox from 'ChillMainAssets/vuejs/_components/Entity/AddressRenderBox.vue'; import CurrentHousehold from './CurrentHousehold';
import AddAddress from 'ChillMainAssets/vuejs/Address/components/AddAddress.vue';
export default { export default {
name: 'Household', name: 'Household',
components: { components: {
CurrentHousehold,
HouseholdRenderBox, HouseholdRenderBox,
AddressRenderBox,
AddAddress,
}, },
emits: ['readyToGo'],
data() { data() {
return { return {
addAddress: { addAddress: {
@ -154,6 +94,7 @@ export default {
'getAddressContext', 'getAddressContext',
]), ]),
...mapState([ ...mapState([
'household',
'showHouseholdSuggestion', 'showHouseholdSuggestion',
'showAddressSuggestion', 'showAddressSuggestion',
'mode', 'mode',
@ -175,9 +116,11 @@ export default {
methods: { methods: {
setModeNew() { setModeNew() {
this.$store.dispatch('createHousehold'); this.$store.dispatch('createHousehold');
this.$emit('readyToGo');
}, },
setModeLeave() { setModeLeave() {
this.$store.dispatch('forceLeaveWithoutHousehold'); this.$store.dispatch('forceLeaveWithoutHousehold');
this.$emit('readyToGo');
}, },
resetMode() { resetMode() {
this.$store.commit('resetMode'); this.$store.commit('resetMode');
@ -188,6 +131,7 @@ export default {
}, },
selectHousehold(h) { selectHousehold(h) {
this.$store.dispatch('selectHousehold', h); this.$store.dispatch('selectHousehold', h);
this.$emit('readyToGo');
}, },
removeHouseholdAddress() { removeHouseholdAddress() {
this.$store.commit('removeHouseholdAddress'); this.$store.commit('removeHouseholdAddress');

View File

@ -0,0 +1,88 @@
<template>
<current-household></current-household>
<ul class="record_actions">
<li v-if="!hasHouseholdAddress && !isHouseholdForceAddress">
<button class="btn" @click="markNoAddress">
{{ $t('household_members_editor.household_address.mark_no_address') }}
</button>
</li>
<li v-if="!hasHouseholdAddress">
<add-address
:context="getAddressContext"
:key="addAddress.key"
:options="addAddress.options"
:addressChangedCallback="addressChanged"
></add-address>
</li>
<li v-if="hasHouseholdAddress">
<button class="btn btn-remove"
@click="removeHouseholdAddress">
{{ $t('household_members_editor.household_address.remove_address') }}
</button>
</li>
</ul>
</template>
<script>
import AddAddress from 'ChillMainAssets/vuejs/Address/components/AddAddress.vue';
import CurrentHousehold from './CurrentHousehold';
import { mapGetters } from 'vuex';
export default {
name: "HouseholdAddress.vue",
components: {
CurrentHousehold,
AddAddress,
},
data() {
return {
addAddress: {
key: 'household_new',
options: {
useDate: {
validFrom: false,
validTo: false,
},
onlyButton: true,
button: {
text: {
create: 'household_members_editor.household_address.set_address',
edit: 'household_members_editor.household_address.update_address',
}
},
title: {
create: 'household_members_editor.household_address.create_new_address',
edit: 'household_members_editor.household_address.update_address_title',
},
}
}
}
},
computed: {
...mapGetters([
'isHouseholdNew',
'hasHouseholdAddress',
'getAddressContext',
'isHouseholdForceNoAddress'
])
},
methods: {
addressChanged(payload) {
console.log("addressChanged", payload);
this.$store.dispatch('setHouseholdNewAddress', payload.address);
},
markNoAddress() {
this.$store.commit('markHouseholdNoAddress');
},
removeHouseholdAddress() {
this.$store.commit('removeHouseholdAddress');
},
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,106 @@
<template>
<current-household></current-household>
<h2>{{ $t('household_members_editor.positioning.persons_to_positionnate')}}</h2>
<div class="list-household-members">
<div
v-for="conc in concerned"
class="item-bloc"
v-bind:key="conc.person.id"
>
<div class="pick-position">
<div class="person">
<person-render-box render="badge" :options="{}" :person="conc.person"></person-render-box>
</div>
<div class="holder">
<button
class="btn"
:disabled="!allowHolderForConcerned(conc)"
:class="{'btn-outline-chill-green': !conc.holder, 'btn-chill-green': conc.holder }"
@click="toggleHolder(conc)"
>
{{ $t('household_members_editor.positioning.holder') }}
</button>
</div>
<div
v-for="position in positions"
class="position"
>
<button
class="btn"
:class="{ 'btn-primary': conc.position === position, 'btn-outline-primary': conc.position !== position }"
@click="moveToPosition(conc.person.id, position.id)"
>
{{ position.label.fr }}
</button>
</div>
</div>
</div>
</div>
</template>
<script>
import MemberDetails from './MemberDetails.vue';
import {mapGetters, mapState} from "vuex";
import CurrentHousehold from "./CurrentHousehold";
import PersonRenderBox from 'ChillPersonAssets/vuejs/_components/Entity/PersonRenderBox.vue';
export default {
name: "Positioning",
components: {
CurrentHousehold,
PersonRenderBox,
},
computed: {
...mapState([
'concerned'
]),
...mapGetters([
'persons',
'concUnpositionned',
'positions',
'concByPosition',
]),
allPersonsPositionnated () {
return this.$store.getters.persons.length > 0
&& this.$store.getters.concUnpositionned.length === 0;
},
allowHolderForConcerned: (app) => (conc) => {
console.log('allow holder for concerned', conc);
if (conc.position === null) {
return false;
}
return conc.position.allowHolder;
}
},
methods: {
moveToPosition(person_id, position_id) {
this.$store.dispatch('markPosition', { person_id, position_id });
},
toggleHolder(conc) {
console.log('toggle holder', conc);
this.$store.dispatch('toggleHolder', conc);
}
},
}
</script>
<style lang="scss" scoped>
.pick-position {
margin: 0;
padding: 0;
display: flex;
justify-content: flex-end;
align-items: center;
.person {
margin-right: auto;
}
.holder {
margin-right: 1.2rem;
}
}
</style>

View File

@ -5,65 +5,78 @@ const appMessages = {
fr: { fr: {
household_members_editor: { household_members_editor: {
household: { household: {
no_household_choose_one: "Aucun ménage de destination. Choisissez un ménage. Les usagers concernés par la modification apparaitront ensuite.", no_household_choose_one: "Aucun ménage de destination. Choisissez un ménage.",
new_household: "Nouveau ménage", // new_household: "Nouveau ménage",
create_household: "Créer", create_household: "Créer",
search_household: "Chercher un ménage", search_household: "Chercher un ménage",
will_leave_any_household: "Les usagers ne rejoignent pas de ménage", will_leave_any_household: "Les usagers ne rejoignent pas de ménage",
leave: "Quitter", leave: "Quitter",
will_leave_any_household_explanation: "Les usagers quitteront leur ménage actuel, et ne seront pas associés à un autre ménage. Par ailleurs, ils seront enregistrés comme étant sans adresse connue.", will_leave_any_household_explanation: "Les usagers quitteront leur ménage actuel, et ne seront pas associés à un autre ménage. Par ailleurs, ils seront enregistrés comme étant sans adresse connue.",
leave_without_household: "Sans nouveau ménage", leave_without_household: "Sans nouveau ménage",
set_address: "Indiquer une adresse",
reset_mode: "Modifier la destination", reset_mode: "Modifier la destination",
remove_address: "Supprimer l'adresse",
update_address: "Mettre à jour l'adresse",
// remove ? // remove ?
/* /*
where_live_the_household: "À quelle adresse habite ce ménage ?", where_live_the_household: "À quelle adresse habite ce ménage ?",
household_live_to_this_address: "Sélectionner l'adresse", household_live_to_this_address: "Sélectionner l'adresse",
no_suggestions: "Aucune adresse à suggérer", no_suggestions: "Aucune adresse à suggérer",
delete_this_address: "Supprimer cette adresse",
create_new_address: "Créer une nouvelle adresse",
or_create_new_address: "Ou créer une nouvelle adresse", or_create_new_address: "Ou créer une nouvelle adresse",
*/ */
// end remove ? // end remove ?
}, },
household_address: {
mark_no_address: "Ne pas indiquer d'adresse",
remove_address: "Supprimer l'adresse",
update_address: "Mettre à jour l'adresse",
set_address: "Indiquer une adresse",
create_new_address: "Créer une nouvelle adresse",
},
concerned: { concerned: {
title: "Nouveaux membres du ménage", title: "Usagers déplacés",
persons_will_be_moved: "Les usagers suivants vont être déplacés",
add_at_least_onePerson: "Indiquez au moins un usager à déplacer",
remove_concerned: "Ne plus transférer",
// old ?
add_persons: "Ajouter d'autres usagers", add_persons: "Ajouter d'autres usagers",
search: "Rechercher des usagers", search: "Rechercher des usagers",
move_to: "Déplacer vers", move_to: "Déplacer vers",
persons_to_positionnate: 'Usagers à positionner',
persons_leaving: "Usagers quittant leurs ménages", persons_leaving: "Usagers quittant leurs ménages",
no_person_in_position: "Aucun usager ne sera ajouté à cette position", no_person_in_position: "Aucun usager ne sera ajouté à cette position",
},
positioning: {
persons_to_positionnate: 'Usagers à positionner',
holder: "Titulaire",
},
app: {
next: 'Suivant',
cancel: 'Annuler',
save: 'Enregistrer',
steps: {
concerned: 'Usagers concernés',
household: 'Ménage de destination',
household_address: 'Adresse du nouveau ménage',
positioning: 'Position dans le ménage',
confirm: 'Confirmation'
}
}, },
drop_persons_here: "Glissez-déposez ici les usagers pour la position \"{position}\"", drop_persons_here: "Glissez-déposez ici les usagers pour la position \"{position}\"",
all_positionnated: "Tous les usagers sont positionnés", all_positionnated: "Tous les usagers sont positionnés",
holder: "Titulaire",
is_holder: "Est titulaire",
is_not_holder: "N'est pas titulaire",
remove_position: "Retirer des {position}",
remove_concerned: "Ne plus transférer",
household_part: "Destination", household_part: "Destination",
suggestions: "Suggestions", suggestions: "Suggestions",
hide_household_suggestion: "Masquer les suggestions", hide_household_suggestion: "Masquer les suggestions",
show_household_suggestion: 'Aucune suggestion | Afficher une suggestion | Afficher {count} suggestions', show_household_suggestion: 'Aucune suggestion | Afficher une suggestion | Afficher {count} suggestions',
household_for_participants_accompanying_period: "Des ménages partagent le même parcours", household_for_participants_accompanying_period: "Des ménages partagent le même parcours",
select_household: "Sélectionner le ménage", select_household: "Sélectionner le ménage",
dates_title: "Période de validité",
dates: { dates: {
start_date: "Début de validité", start_date: "Début de validité",
end_date: "Fin de validité", end_date: "Fin de validité",
dates_title: "Période de validité",
}, },
confirmation: { confirmation: {
save: "Enregistrer", save: "Enregistrer",
there_are_warnings: "Impossible de valider actuellement", there_are_warnings: "Impossible de valider actuellement",
check_those_items: "Veuillez corriger les éléments suivants", check_those_items: "Veuillez corriger les éléments suivants",
}, },
give_a_position_to_every_person: "Indiquez une position pour chaque usager concerné",
add_destination: "Indiquez un ménage de destination",
add_at_least_onePerson: "Indiquez au moins un usager à transférer",
} }
} }
}; };

View File

@ -43,6 +43,10 @@ const store = createStore({
allowHouseholdSearch: window.household_members_editor_data.allowHouseholdSearch, allowHouseholdSearch: window.household_members_editor_data.allowHouseholdSearch,
allowLeaveWithoutHousehold: window.household_members_editor_data.allowLeaveWithoutHousehold, allowLeaveWithoutHousehold: window.household_members_editor_data.allowLeaveWithoutHousehold,
forceLeaveWithoutHousehold: false, forceLeaveWithoutHousehold: false,
/**
* If true, the user explicitly said that no address is possible
*/
forceHouseholdNoAddress: false,
/** /**
* Household suggestions * Household suggestions
* *
@ -80,6 +84,9 @@ const store = createStore({
isModeLeave(state) { isModeLeave(state) {
return state.mode === "leave"; return state.mode === "leave";
}, },
isHouseholdForceNoAddress(state) {
return state.forceHouseholdNoAddress;
},
getSuggestions(state) { getSuggestions(state) {
let suggestions = []; let suggestions = [];
state.householdSuggestionByAccompanyingPeriod.forEach(h => { state.householdSuggestionByAccompanyingPeriod.forEach(h => {
@ -90,15 +97,12 @@ const store = createStore({
}, },
isHouseholdNew(state) { isHouseholdNew(state) {
return state.mode === "new"; return state.mode === "new";
/*
if (state.household === null) {
return false;
}
return !Number.isInteger(state.household.id);
*/
}, },
getAddressContext(state, getters) { getAddressContext(state, getters) {
if (state.household === null) {
return {};
}
if (!getters.hasHouseholdAddress) { if (!getters.hasHouseholdAddress) {
return { return {
edit: false, edit: false,
@ -203,6 +207,40 @@ const store = createStore({
needsPositionning(state) { needsPositionning(state) {
return state.forceLeaveWithoutHousehold === false; return state.forceLeaveWithoutHousehold === false;
}, },
fakeHouseholdWithConcerned(state, getters) {
if (null === state.household) {
throw Error('cannot create fake household without household');
}
let h = {
type: 'household',
members: state.household.members,
current_address: state.household.current_address,
current_members_id: state.household.current_members_id,
new_members: [],
};
if (!getters.isHouseholdNew){
h.id = state.household.id;
}
state.concerned.forEach((c, index) => {
let m = {
id: index * -1,
person: c.person,
holder: c.holder,
position: c.position,
};
if (c.position === null) {
m.position = {
ordering: 999999
}
}
h.new_members.push(m);
})
console.log('fake household', h);
return h;
},
buildPayload: (state, getters) => { buildPayload: (state, getters) => {
let let
conc, conc,
@ -277,6 +315,10 @@ const store = createStore({
position = state.positions.find(pos => pos.id === position_id), position = state.positions.find(pos => pos.id === position_id),
conc = state.concerned.find(c => c.person.id === person_id); conc = state.concerned.find(c => c.person.id === person_id);
conc.position = position; conc.position = position;
// reset position if changed:
if (!position.allowHolder && conc.holder) {
conc.holder = false;
}
}, },
setComment(state, {conc, comment}) { setComment(state, {conc, comment}) {
conc.comment = comment; conc.comment = comment;
@ -288,9 +330,9 @@ const store = createStore({
conc.holder = false; conc.holder = false;
conc.position = null; conc.position = null;
}, },
removeConcerned(state, conc) { removePerson(state, person) {
state.concerned = state.concerned.filter(c => state.concerned = state.concerned.filter(c =>
c.person.id !== conc.person.id c.person.id !== person.id
) )
}, },
createHousehold(state) { createHousehold(state) {
@ -315,6 +357,7 @@ const store = createStore({
} }
state.household.current_address = address; state.household.current_address = address;
state.forceHouseholdNoAddress = false;
}, },
removeHouseholdAddress(state, address) { removeHouseholdAddress(state, address) {
if (null === state.household) { if (null === state.household) {
@ -324,6 +367,9 @@ const store = createStore({
state.household.current_address = null; state.household.current_address = null;
}, },
markHouseholdNoAddress(state) {
state.forceHouseholdNoAddress = true;
},
forceLeaveWithoutHousehold(state) { forceLeaveWithoutHousehold(state) {
state.household = null; state.household = null;
state.mode = "leave"; state.mode = "leave";
@ -389,8 +435,8 @@ const store = createStore({
commit('removePosition', conc); commit('removePosition', conc);
dispatch('computeWarnings'); dispatch('computeWarnings');
}, },
removeConcerned({ commit, dispatch }, conc) { removePerson({ commit, dispatch }, person) {
commit('removeConcerned', conc); commit('removePerson', person);
dispatch('computeWarnings'); dispatch('computeWarnings');
dispatch('fetchAddressSuggestions'); dispatch('fetchAddressSuggestions');
}, },

View File

@ -19,15 +19,18 @@
<!-- member part --> <!-- member part -->
<li v-if="hasCurrentMembers" class="members" :title="$t('current_members')"> <li v-if="hasCurrentMembers" class="members" :title="$t('current_members')">
<template v-for="m in currentMembers()" :key="m.id"> <span v-for="m in currentMembers()" :key="m.id" class="m" :class="{ is_new: m.is_new === true}">
<person-render-box render="badge" <person-render-box render="badge"
:person="m.person" :person="m.person"
:options="{ :options="{
isHolder: m.holder, isHolder: m.holder,
addLink: true addLink: true
}"> }">
<template v-slot:post-badge v-if="m.is_new === true">
<span class="post-badge is_new"><i class="fa fa-sign-in"></i></span>
</template>
</person-render-box> </person-render-box>
</template> </span>
</li> </li>
<li v-else class="members" :title="$t('current_members')"> <li v-else class="members" :title="$t('current_members')">
<p class="chill-no-data-statement">{{ $t('no_members_yet') }}</p> <p class="chill-no-data-statement">{{ $t('no_members_yet') }}</p>
@ -82,7 +85,7 @@ export default {
return this.household.current_members_id.length > 0; return this.household.current_members_id.length > 0;
}, },
currentMembers() { currentMembers() {
return this.household.members.filter(m => this.household.current_members_id.includes(m.id)) let members = this.household.members.filter(m => this.household.current_members_id.includes(m.id))
.sort((a, b) => { .sort((a, b) => {
if (a.position.ordering < b.position.ordering) { if (a.position.ordering < b.position.ordering) {
return -1; return -1;
@ -98,6 +101,17 @@ export default {
} }
return 0; return 0;
}); });
if (this.household.new_members !== undefined) {
this.household.new_members.map(m => {
m.is_new = true;
return m;
}).forEach(m => {
members.push(m);
});
}
return members;
}, },
currentMembersLength() { currentMembersLength() {
return this.household.current_members_id.length; return this.household.current_members_id.length;
@ -121,6 +135,13 @@ section.chill-entity {
content: ''; content: '';
} }
.members {
.post-badge.is_new {
margin-left: 0.5rem;
color: var(--bs-chill-green);
}
}
} }
} }
</style> </style>

View File

@ -126,6 +126,7 @@
</span> </span>
{{ person.text }} {{ person.text }}
</span> </span>
<slot name="post-badge"></slot>
</span> </span>
</template> </template>