mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-13 13:54:23 +00:00
Merge branch 'features/localize-accompanying-course-2' into 'master'
Improve UX for handling location in accompanying course See merge request Chill-Projet/chill-bundles!125
This commit is contained in:
commit
71e6b356c3
@ -499,6 +499,17 @@ class AccompanyingPeriod implements TrackCreationInterface, TrackUpdateInterface
|
|||||||
return $collection->count() > 0 ? $collection->first() : NULL;
|
return $collection->count() > 0 ? $collection->first() : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getOPenParticipations(): Collection
|
||||||
|
{
|
||||||
|
return $this
|
||||||
|
->getParticipations()
|
||||||
|
->filter(
|
||||||
|
static function(AccompanyingPeriodParticipation $participation): bool {
|
||||||
|
return null === $participation->getEndDate();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if the accompanying period contains a person.
|
* Return true if the accompanying period contains a person.
|
||||||
*
|
*
|
||||||
@ -974,6 +985,22 @@ class AccompanyingPeriod implements TrackCreationInterface, TrackUpdateInterface
|
|||||||
return $this->personLocation;
|
return $this->personLocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of person which have an adresse available for a valid location
|
||||||
|
*
|
||||||
|
* @return Collection|Person[]
|
||||||
|
*/
|
||||||
|
public function getAvailablePersonLocation(): Collection
|
||||||
|
{
|
||||||
|
return $this->getOPenParticipations()
|
||||||
|
->filter(function(AccompanyingPeriodParticipation $p) {
|
||||||
|
return $p->getPerson()->hasCurrentHouseholdAddress();
|
||||||
|
})
|
||||||
|
->map(function(AccompanyingPeriodParticipation $p) {
|
||||||
|
return $p->getPerson();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Groups({"write"})
|
* @Groups({"write"})
|
||||||
*/
|
*/
|
||||||
|
@ -169,7 +169,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||||||
* orphanRemoval=true
|
* orphanRemoval=true
|
||||||
* )
|
* )
|
||||||
* @Serializer\Groups({"read"})
|
* @Serializer\Groups({"read"})
|
||||||
* @internal /!\ the serialization for read / write evaluations is handled in `AccompanyingPeriodWorkDenormalizer`
|
* @internal /!\ the serialization for write evaluations is handled in `AccompanyingPeriodWorkDenormalizer`
|
||||||
*/
|
*/
|
||||||
private Collection $accompanyingPeriodWorkEvaluations;
|
private Collection $accompanyingPeriodWorkEvaluations;
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
|||||||
*
|
*
|
||||||
* @ORM\Column(type="date", nullable=true)
|
* @ORM\Column(type="date", nullable=true)
|
||||||
*/
|
*/
|
||||||
private $birthdate;
|
private $birthdate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The person's deathdate
|
* The person's deathdate
|
||||||
@ -736,8 +736,8 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
|||||||
{
|
{
|
||||||
return $this->birthdate;
|
return $this->birthdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAge(): ?int
|
public function getAge(): ?int
|
||||||
{
|
{
|
||||||
if ($this->birthdate instanceof \DateTimeInterface) {
|
if ($this->birthdate instanceof \DateTimeInterface) {
|
||||||
return date_diff($this->birthdate, date_create('now'))->format("%y");
|
return date_diff($this->birthdate, date_create('now'))->format("%y");
|
||||||
@ -1439,6 +1439,11 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function hasCurrentHouseholdAddress(?\DateTimeImmutable $at = null): bool
|
||||||
|
{
|
||||||
|
return null !== $this->getCurrentHouseholdAddress($at);
|
||||||
|
}
|
||||||
|
|
||||||
public function getGenderComment(): CommentEmbeddable
|
public function getGenderComment(): CommentEmbeddable
|
||||||
{
|
{
|
||||||
return $this->genderComment;
|
return $this->genderComment;
|
||||||
|
@ -0,0 +1,49 @@
|
|||||||
|
const onSubmit = function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
let
|
||||||
|
form = e.target,
|
||||||
|
formData = new FormData(form),
|
||||||
|
url = form.action,
|
||||||
|
payload = {
|
||||||
|
type: 'accompanying_period',
|
||||||
|
id: Number.parseInt(formData.get('periodId'), 10),
|
||||||
|
personLocation: {
|
||||||
|
type: 'person',
|
||||||
|
id: Number.parseInt(formData.get('personLocation'), 10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
console.log('event', e);
|
||||||
|
console.log('form', form);
|
||||||
|
console.log('formData', formData);
|
||||||
|
console.log('url', url);
|
||||||
|
console.log('payload', payload);
|
||||||
|
|
||||||
|
window.fetch(url, {
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify(payload),
|
||||||
|
})
|
||||||
|
.then(r => {
|
||||||
|
if (r.ok) {
|
||||||
|
console.log('response ok');
|
||||||
|
window.location.reload();
|
||||||
|
} else {
|
||||||
|
console.err("could not patch accompanying course");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('DOMContentLoaded', function(e) {
|
||||||
|
let forms = document.querySelectorAll('.quickLocationForm');
|
||||||
|
|
||||||
|
console.log(forms);
|
||||||
|
|
||||||
|
forms.forEach(function(form){
|
||||||
|
console.log('form quickLocation found', form);
|
||||||
|
form.addEventListener('submit', onSubmit);
|
||||||
|
})
|
||||||
|
});
|
@ -1,374 +0,0 @@
|
|||||||
import { createStore } from 'vuex';
|
|
||||||
import { householdMove, fetchHouseholdSuggestionByAccompanyingPeriod, fetchAddressSuggestionByPerson} from './../api.js';
|
|
||||||
import { datetimeToISO } from 'ChillMainAssets/chill/js/date.js';
|
|
||||||
|
|
||||||
const debug = process.env.NODE_ENV !== 'production';
|
|
||||||
|
|
||||||
const concerned = window.household_members_editor_data.persons.map(p => {
|
|
||||||
return {
|
|
||||||
person: p,
|
|
||||||
position: null,
|
|
||||||
allowRemove: false,
|
|
||||||
holder: false,
|
|
||||||
comment: "",
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log('expand suggestions', window.household_members_editor_expand_suggestions === 1);
|
|
||||||
|
|
||||||
const store = createStore({
|
|
||||||
strict: debug,
|
|
||||||
state: {
|
|
||||||
concerned,
|
|
||||||
household: window.household_members_editor_data.household,
|
|
||||||
positions: window.household_members_editor_data.positions.sort((a, b) => {
|
|
||||||
if (a.ordering < b.ordering) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (a.ordering > b.ordering) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}),
|
|
||||||
startDate: new Date(),
|
|
||||||
allowHouseholdCreate: window.household_members_editor_data.allowHouseholdCreate,
|
|
||||||
allowHouseholdSearch: window.household_members_editor_data.allowHouseholdSearch,
|
|
||||||
allowLeaveWithoutHousehold: window.household_members_editor_data.allowLeaveWithoutHousehold,
|
|
||||||
forceLeaveWithoutHousehold: false,
|
|
||||||
householdSuggestionByAccompanyingPeriod: [],
|
|
||||||
showHouseholdSuggestion: window.household_members_editor_expand_suggestions === 1,
|
|
||||||
addressesSuggestion: [],
|
|
||||||
warnings: [],
|
|
||||||
errors: []
|
|
||||||
},
|
|
||||||
getters: {
|
|
||||||
isHouseholdNew(state) {
|
|
||||||
if (state.household === null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !Number.isInteger(state.household.id);
|
|
||||||
},
|
|
||||||
hasHousehold(state) {
|
|
||||||
return state.household !== null;
|
|
||||||
},
|
|
||||||
hasHouseholdOrLeave(state) {
|
|
||||||
return state.household !== null || state.forceLeaveWithoutHousehold;
|
|
||||||
},
|
|
||||||
hasHouseholdSuggestion(state, getters) {
|
|
||||||
return getters.filterHouseholdSuggestionByAccompanyingPeriod.length > 0;
|
|
||||||
},
|
|
||||||
countHouseholdSuggestion(state, getters) {
|
|
||||||
return getters.filterHouseholdSuggestionByAccompanyingPeriod.length;
|
|
||||||
},
|
|
||||||
filterHouseholdSuggestionByAccompanyingPeriod(state) {
|
|
||||||
if (state.household === null) {
|
|
||||||
return state.householdSuggestionByAccompanyingPeriod;
|
|
||||||
}
|
|
||||||
|
|
||||||
return state.householdSuggestionByAccompanyingPeriod
|
|
||||||
.filter(h => h.id !== state.household.id)
|
|
||||||
;
|
|
||||||
},
|
|
||||||
hasPersonsWellPositionnated(state, getters) {
|
|
||||||
return getters.needsPositionning === false
|
|
||||||
|| (getters.persons.length > 0 && getters.concUnpositionned.length === 0);
|
|
||||||
},
|
|
||||||
persons(state) {
|
|
||||||
return state.concerned.map(conc => conc.person);
|
|
||||||
},
|
|
||||||
concUnpositionned(state) {
|
|
||||||
return state.concerned
|
|
||||||
.filter(conc => conc.position === null)
|
|
||||||
;
|
|
||||||
},
|
|
||||||
positions(state) {
|
|
||||||
return state.positions;
|
|
||||||
},
|
|
||||||
personByPosition: (state) => (position_id) => {
|
|
||||||
return state.concerned
|
|
||||||
.filter(conc =>
|
|
||||||
conc.position !== null ? conc.position.id === position_id : false
|
|
||||||
)
|
|
||||||
.map(conc => conc.person)
|
|
||||||
;
|
|
||||||
},
|
|
||||||
concByPosition: (state) => (position_id) => {
|
|
||||||
return state.concerned
|
|
||||||
.filter(conc =>
|
|
||||||
conc.position !== null ? conc.position.id === position_id : false
|
|
||||||
)
|
|
||||||
;
|
|
||||||
},
|
|
||||||
concByPersonId: (state) => (person_id) => {
|
|
||||||
return state.concerned
|
|
||||||
.find(conc => conc.person.id === person_id)
|
|
||||||
;
|
|
||||||
},
|
|
||||||
needsPositionning(state) {
|
|
||||||
return state.forceLeaveWithoutHousehold === false;
|
|
||||||
},
|
|
||||||
buildPayload: (state) => {
|
|
||||||
let
|
|
||||||
conc,
|
|
||||||
payload_conc,
|
|
||||||
payload = {
|
|
||||||
concerned: [],
|
|
||||||
destination: null
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
if (state.forceLeaveWithoutHousehold === false) {
|
|
||||||
payload.destination = {
|
|
||||||
id: state.household.id,
|
|
||||||
type: state.household.type
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i in state.concerned) {
|
|
||||||
conc = state.concerned[i];
|
|
||||||
payload_conc = {
|
|
||||||
person: {
|
|
||||||
id: conc.person.id,
|
|
||||||
type: conc.person.type
|
|
||||||
},
|
|
||||||
start_date: {
|
|
||||||
datetime: datetimeToISO(state.startDate)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (state.forceLeaveWithoutHousehold === false) {
|
|
||||||
payload_conc.position = {
|
|
||||||
id: conc.position.id,
|
|
||||||
type: conc.position.type
|
|
||||||
};
|
|
||||||
payload_conc.holder = conc.holder;
|
|
||||||
payload_conc.comment = conc.comment;
|
|
||||||
}
|
|
||||||
|
|
||||||
payload.concerned.push(payload_conc);
|
|
||||||
}
|
|
||||||
|
|
||||||
return payload;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mutations: {
|
|
||||||
addConcerned(state, person) {
|
|
||||||
let persons = state.concerned.map(conc => conc.person.id);
|
|
||||||
if (!persons.includes(person.id)) {
|
|
||||||
state.concerned.push({
|
|
||||||
person,
|
|
||||||
position: null,
|
|
||||||
allowRemove: true,
|
|
||||||
holder: false,
|
|
||||||
comment: "",
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.err("person already included");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
markPosition(state, { person_id, position_id}) {
|
|
||||||
let
|
|
||||||
position = state.positions.find(pos => pos.id === position_id),
|
|
||||||
conc = state.concerned.find(c => c.person.id === person_id);
|
|
||||||
conc.position = position;
|
|
||||||
},
|
|
||||||
setComment(state, {conc, comment}) {
|
|
||||||
conc.comment = comment;
|
|
||||||
},
|
|
||||||
toggleHolder(state, conc) {
|
|
||||||
conc.holder = !conc.holder;
|
|
||||||
},
|
|
||||||
removePosition(state, conc) {
|
|
||||||
conc.holder = false;
|
|
||||||
conc.position = null;
|
|
||||||
},
|
|
||||||
removeConcerned(state, conc) {
|
|
||||||
state.concerned = state.concerned.filter(c =>
|
|
||||||
c.person.id !== conc.person.id
|
|
||||||
)
|
|
||||||
},
|
|
||||||
createHousehold(state) {
|
|
||||||
state.household = { type: 'household', members: [], current_address: null,
|
|
||||||
current_members_id: [] };
|
|
||||||
state.forceLeaveWithoutHousehold = false;
|
|
||||||
},
|
|
||||||
removeHousehold(state) {
|
|
||||||
state.household = null;
|
|
||||||
state.forceLeaveWithoutHousehold = false;
|
|
||||||
},
|
|
||||||
setHouseholdAddress(state, address) {
|
|
||||||
if (null === state.household) {
|
|
||||||
console.error("no household");
|
|
||||||
throw new Error("No household");
|
|
||||||
}
|
|
||||||
|
|
||||||
state.household.current_address = address;
|
|
||||||
state.household.force_new_address = address;
|
|
||||||
},
|
|
||||||
forceLeaveWithoutHousehold(state) {
|
|
||||||
state.household = null;
|
|
||||||
state.forceLeaveWithoutHousehold = true;
|
|
||||||
},
|
|
||||||
selectHousehold(state, household) {
|
|
||||||
state.household = household;
|
|
||||||
state.forceLeaveWithoutHousehold = false;
|
|
||||||
},
|
|
||||||
setHouseholdSuggestionByAccompanyingPeriod(state, households) {
|
|
||||||
let existingIds = state.householdSuggestionByAccompanyingPeriod
|
|
||||||
.map(h => h.id);
|
|
||||||
for (let i in households) {
|
|
||||||
if (!existingIds.includes(households[i].id)) {
|
|
||||||
state.householdSuggestionByAccompanyingPeriod.push(households[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setStartDate(state, dateI) {
|
|
||||||
state.startDate = dateI;
|
|
||||||
},
|
|
||||||
toggleHouseholdSuggestion(state) {
|
|
||||||
state.showHouseholdSuggestion = !state.showHouseholdSuggestion;
|
|
||||||
},
|
|
||||||
setWarnings(state, warnings) {
|
|
||||||
state.warnings = warnings;
|
|
||||||
// reset errors, which should come from servers
|
|
||||||
state.errors.splice(0, state.errors.length);
|
|
||||||
},
|
|
||||||
setErrors(state, errors) {
|
|
||||||
state.errors = errors;
|
|
||||||
},
|
|
||||||
addAddressesSuggestion(state, addresses) {
|
|
||||||
let existingIds = state.addressesSuggestion
|
|
||||||
.map(a => a.id);
|
|
||||||
|
|
||||||
for (let i in addresses) {
|
|
||||||
if (!existingIds.includes(addresses[i].id)) {
|
|
||||||
state.addressesSuggestion.push(addresses[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
addConcerned({ commit, dispatch }, person) {
|
|
||||||
commit('addConcerned', person);
|
|
||||||
dispatch('computeWarnings');
|
|
||||||
dispatch('fetchAddressSuggestions');
|
|
||||||
},
|
|
||||||
markPosition({ commit, state, dispatch }, { person_id, position_id }) {
|
|
||||||
commit('markPosition', { person_id, position_id });
|
|
||||||
dispatch('computeWarnings');
|
|
||||||
},
|
|
||||||
toggleHolder({ commit, dispatch }, conc) {
|
|
||||||
commit('toggleHolder', conc);
|
|
||||||
dispatch('computeWarnings');
|
|
||||||
},
|
|
||||||
removePosition({ commit, dispatch }, conc) {
|
|
||||||
commit('removePosition', conc);
|
|
||||||
dispatch('computeWarnings');
|
|
||||||
},
|
|
||||||
removeConcerned({ commit, dispatch }, conc) {
|
|
||||||
commit('removeConcerned', conc);
|
|
||||||
dispatch('computeWarnings');
|
|
||||||
dispatch('fetchAddressSuggestions');
|
|
||||||
},
|
|
||||||
removeHousehold({ commit, dispatch }) {
|
|
||||||
commit('removeHousehold');
|
|
||||||
dispatch('computeWarnings');
|
|
||||||
},
|
|
||||||
createHousehold({ commit, dispatch }) {
|
|
||||||
commit('createHousehold');
|
|
||||||
dispatch('computeWarnings');
|
|
||||||
},
|
|
||||||
forceLeaveWithoutHousehold({ commit, dispatch }) {
|
|
||||||
commit('forceLeaveWithoutHousehold');
|
|
||||||
dispatch('computeWarnings');
|
|
||||||
},
|
|
||||||
selectHousehold({ commit }, h) {
|
|
||||||
commit('selectHousehold', h);
|
|
||||||
dispatch('computeWarnings');
|
|
||||||
},
|
|
||||||
setStartDate({ commit, dispatch }, date) {
|
|
||||||
commit('setStartDate', date);
|
|
||||||
dispatch('computeWarnings');
|
|
||||||
},
|
|
||||||
setComment({ commit }, payload) {
|
|
||||||
commit('setComment', payload);
|
|
||||||
},
|
|
||||||
fetchHouseholdSuggestionForConcerned({ commit, state }, person) {
|
|
||||||
fetchHouseholdSuggestionByAccompanyingPeriod(person.id)
|
|
||||||
.then(households => {
|
|
||||||
commit('setHouseholdSuggestionByAccompanyingPeriod', households);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
fetchAddressSuggestions({ commit, state }) {
|
|
||||||
for (let i in state.concerned) {
|
|
||||||
fetchAddressSuggestionByPerson(state.concerned[i].person.id)
|
|
||||||
.then(addresses => {
|
|
||||||
commit('addAddressesSuggestion', addresses);
|
|
||||||
})
|
|
||||||
.catch(e => {
|
|
||||||
console.log(e);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computeWarnings({ commit, state, getters }) {
|
|
||||||
let warnings = [],
|
|
||||||
payload;
|
|
||||||
|
|
||||||
if (!getters.hasHousehold && !state.forceLeaveWithoutHousehold) {
|
|
||||||
warnings.push({ m: 'household_members_editor.add_destination', a: {} });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.concerned.length === 0) {
|
|
||||||
warnings.push({ m: 'household_members_editor.add_at_least_onePerson', a: {} });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getters.concUnpositionned.length > 0
|
|
||||||
&& !state.forceLeaveWithoutHousehold) {
|
|
||||||
warnings.push({ m: 'household_members_editor.give_a_position_to_every_person', a: {} })
|
|
||||||
}
|
|
||||||
|
|
||||||
commit('setWarnings', warnings);
|
|
||||||
},
|
|
||||||
confirm({ getters, state, commit }) {
|
|
||||||
let payload = getters.buildPayload,
|
|
||||||
errors = [],
|
|
||||||
person_id,
|
|
||||||
household_id,
|
|
||||||
error
|
|
||||||
;
|
|
||||||
|
|
||||||
householdMove(payload).then(household => {
|
|
||||||
if (household === null) {
|
|
||||||
person_id = getters.persons[0].id;
|
|
||||||
window.location.replace(`/fr/person/${person_id}/general`);
|
|
||||||
} else {
|
|
||||||
if (household.type === 'household') {
|
|
||||||
household_id = household.id;
|
|
||||||
// nothing to do anymore here, bye-bye !
|
|
||||||
window.location.replace(`/fr/person/household/${household_id}/summary`);
|
|
||||||
} else {
|
|
||||||
// we assume the answer was 422...
|
|
||||||
error = household;
|
|
||||||
for (let i in error.violations) {
|
|
||||||
let e = error.violations[i];
|
|
||||||
errors.push(e.title);
|
|
||||||
}
|
|
||||||
|
|
||||||
commit('setErrors', errors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
store.dispatch('computeWarnings');
|
|
||||||
store.dispatch('fetchAddressSuggestions');
|
|
||||||
|
|
||||||
if (concerned.length > 0) {
|
|
||||||
concerned.forEach(c => {
|
|
||||||
store.dispatch('fetchHouseholdSuggestionForConcerned', c.person);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export { store };
|
|
@ -7,35 +7,43 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-if="isHouseholdNew && !hasHouseholdAddress">
|
<div v-if="isHouseholdNew && !hasHouseholdAddress">
|
||||||
|
|
||||||
<h3>À quelle adresse habite ce ménage ?</h3>
|
<h3 >À quelle adresse habite ce ménage ?</h3>
|
||||||
|
|
||||||
<ul v-if="filterAddressesSuggestion.length > 0">
|
<div v-if="filterAddressesSuggestion.length > 0" class="flex-table householdAddressSuggestionList">
|
||||||
<li v-for="a in filterAddressesSuggestion">
|
<div v-for="a in filterAddressesSuggestion" class="item-bloc">
|
||||||
<show-address :address="a"></show-address>
|
<show-address :address="a"></show-address>
|
||||||
<button class="btn" @click="setHouseholdAddress(a)">
|
<button class="btn btn-action" @click="setHouseholdAddress(a)">
|
||||||
Le ménage habite cette adresse
|
Le ménage habite cette adresse
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</div>
|
||||||
</ul>
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<span class="chill-no-data-statement">Aucune adresse à suggérer</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<ul class="record_actions">
|
<ul class="record_actions">
|
||||||
<li >
|
<li >
|
||||||
<button class="btn">
|
<add-address
|
||||||
Créer une adresse
|
:context="addAddress.context"
|
||||||
</button>
|
:key="addAddress.key"
|
||||||
|
:options="addAddress.options"
|
||||||
|
:result="addAddress.result"
|
||||||
|
@submitAddress="setHouseholdCreatedAddress"
|
||||||
|
ref="addAddress">
|
||||||
|
</add-address>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div v-if="isHouseholdNew && hasHouseholdAddress">
|
<div v-if="isHouseholdNew && hasHouseholdAddress">
|
||||||
<ul class="record_actions">
|
<ul class="record_actions">
|
||||||
<li >
|
<li >
|
||||||
<button class="btn" @click="removeHouseholdAddress">
|
<button class="btn btn-misc" @click="removeHouseholdAddress">
|
||||||
Supprimer cette adresse
|
Supprimer cette adresse
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="isForceLeaveWithoutHousehold">
|
<div v-else-if="isForceLeaveWithoutHousehold">
|
||||||
@ -51,7 +59,7 @@
|
|||||||
class="btn btn-misc"
|
class="btn btn-misc"
|
||||||
@click="toggleHouseholdSuggestion"
|
@click="toggleHouseholdSuggestion"
|
||||||
>
|
>
|
||||||
{{ $tc('household_members_editor.show_household_suggestion',
|
{{ $tc('household_members_editor.show_household_suggestion',
|
||||||
countHouseholdSuggestion) }}
|
countHouseholdSuggestion) }}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
@ -106,11 +114,24 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|
||||||
|
div.householdAddressSuggestionList {
|
||||||
|
/*
|
||||||
|
display: flex;
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
& > li {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.householdSuggestionList {
|
.householdSuggestionList {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@ -136,12 +157,45 @@
|
|||||||
import { mapGetters, mapState } from 'vuex';
|
import { mapGetters, mapState } from 'vuex';
|
||||||
import HouseholdViewer from 'ChillPersonAssets/vuejs/_components/Household/Household.vue';
|
import HouseholdViewer from 'ChillPersonAssets/vuejs/_components/Household/Household.vue';
|
||||||
import ShowAddress from 'ChillMainAssets/vuejs/Address/components/ShowAddress.vue';
|
import ShowAddress from 'ChillMainAssets/vuejs/Address/components/ShowAddress.vue';
|
||||||
|
import AddAddress from 'ChillMainAssets/vuejs/Address/components/AddAddress.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Household',
|
name: 'Household',
|
||||||
components: {
|
components: {
|
||||||
HouseholdViewer,
|
HouseholdViewer,
|
||||||
ShowAddress,
|
ShowAddress,
|
||||||
|
AddAddress,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
addAddress: {
|
||||||
|
context: {
|
||||||
|
entity: {
|
||||||
|
type: 'household_create',
|
||||||
|
id: 0
|
||||||
|
},
|
||||||
|
edit: false,
|
||||||
|
addressId: null
|
||||||
|
},
|
||||||
|
key: 'household_new',
|
||||||
|
options: {
|
||||||
|
hideDateFrom: true,
|
||||||
|
bindModal: {
|
||||||
|
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
text: {
|
||||||
|
create: null,
|
||||||
|
edit: null,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
create: null,
|
||||||
|
edit: null,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters([
|
...mapGetters([
|
||||||
@ -172,13 +226,13 @@ export default {
|
|||||||
allowRemoveHousehold() {
|
allowRemoveHousehold() {
|
||||||
return this.$store.getters.hasHousehold &&
|
return this.$store.getters.hasHousehold &&
|
||||||
(
|
(
|
||||||
this.allowHouseholdCreate || this.allowHouseholdSearch ||
|
this.allowHouseholdCreate || this.allowHouseholdSearch ||
|
||||||
this.allowLeaveWithoutHousehold
|
this.allowLeaveWithoutHousehold
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
},
|
},
|
||||||
allowChangeHousehold() {
|
allowChangeHousehold() {
|
||||||
return this.allowHouseholdCreate || this.allowHouseholdSearch ||
|
return this.allowHouseholdCreate || this.allowHouseholdSearch ||
|
||||||
this.allowLeaveWithoutHousehold;
|
this.allowLeaveWithoutHousehold;
|
||||||
},
|
},
|
||||||
isForceLeaveWithoutHousehold() {
|
isForceLeaveWithoutHousehold() {
|
||||||
@ -202,8 +256,15 @@ export default {
|
|||||||
this.$store.dispatch('removeHousehold');
|
this.$store.dispatch('removeHousehold');
|
||||||
},
|
},
|
||||||
setHouseholdAddress(a) {
|
setHouseholdAddress(a) {
|
||||||
|
let payload = this.$refs.addAddress.submitNewAddress();
|
||||||
|
console.log('setHouseholdAddress', a);
|
||||||
this.$store.commit('setHouseholdAddress', a);
|
this.$store.commit('setHouseholdAddress', a);
|
||||||
},
|
},
|
||||||
|
setHouseholdCreatedAddress() {
|
||||||
|
let payload = this.$refs.addAddress.submitNewAddress();
|
||||||
|
console.log('setHouseholdAddress', payload);
|
||||||
|
this.$store.dispatch('setHouseholdNewAddress', payload);
|
||||||
|
},
|
||||||
removeHouseholdAddress() {
|
removeHouseholdAddress() {
|
||||||
this.$store.commit('removeHouseholdAddress');
|
this.$store.commit('removeHouseholdAddress');
|
||||||
}
|
}
|
||||||
|
@ -14,8 +14,6 @@ const concerned = window.household_members_editor_data.persons.map(p => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('expand suggestions', window.household_members_editor_expand_suggestions === 1);
|
|
||||||
|
|
||||||
const store = createStore({
|
const store = createStore({
|
||||||
strict: debug,
|
strict: debug,
|
||||||
state: {
|
state: {
|
||||||
@ -211,7 +209,12 @@ const store = createStore({
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
createHousehold(state) {
|
createHousehold(state) {
|
||||||
state.household = { type: 'household', members: [], current_address: null, current_members_id: [] }
|
state.household = {
|
||||||
|
type: 'household',
|
||||||
|
members: [],
|
||||||
|
current_address: null,
|
||||||
|
current_members_id: []
|
||||||
|
};
|
||||||
state.forceLeaveWithoutHousehold = false;
|
state.forceLeaveWithoutHousehold = false;
|
||||||
},
|
},
|
||||||
removeHousehold(state) {
|
removeHousehold(state) {
|
||||||
@ -274,7 +277,7 @@ const store = createStore({
|
|||||||
state.addressesSuggestion.push(addresses[i]);
|
state.addressesSuggestion.push(addresses[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
addConcerned({ commit, dispatch }, person) {
|
addConcerned({ commit, dispatch }, person) {
|
||||||
@ -307,6 +310,19 @@ const store = createStore({
|
|||||||
commit('createHousehold');
|
commit('createHousehold');
|
||||||
dispatch('computeWarnings');
|
dispatch('computeWarnings');
|
||||||
},
|
},
|
||||||
|
setHouseholdNewAddress({ commit }, payload) {
|
||||||
|
let url = `/api/1.0/main/address/${payload.addressId}.json`;
|
||||||
|
window.fetch(url).then(r => {
|
||||||
|
if (r.ok) {
|
||||||
|
return r.json();
|
||||||
|
}
|
||||||
|
throw new Error("error while fetch address");
|
||||||
|
}).then(data => {
|
||||||
|
commit('setHouseholdAddress', data);
|
||||||
|
}).catch(e => {
|
||||||
|
console.error(e);
|
||||||
|
});
|
||||||
|
},
|
||||||
forceLeaveWithoutHousehold({ commit, dispatch }) {
|
forceLeaveWithoutHousehold({ commit, dispatch }) {
|
||||||
commit('forceLeaveWithoutHousehold');
|
commit('forceLeaveWithoutHousehold');
|
||||||
dispatch('computeWarnings');
|
dispatch('computeWarnings');
|
||||||
@ -373,8 +389,14 @@ const store = createStore({
|
|||||||
} else {
|
} else {
|
||||||
if (household.type === 'household') {
|
if (household.type === 'household') {
|
||||||
household_id = household.id;
|
household_id = household.id;
|
||||||
|
|
||||||
// nothing to do anymore here, bye-bye !
|
// nothing to do anymore here, bye-bye !
|
||||||
window.location.replace(`/fr/person/household/${household_id}/summary`);
|
let params = new URLSearchParams(window.location.search);
|
||||||
|
if (params.has('returnPath')) {
|
||||||
|
window.location.replace(params.get('returnPath'));
|
||||||
|
} else {
|
||||||
|
window.location.replace(`/fr/person/household/${household_id}/summary`);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// we assume the answer was 422...
|
// we assume the answer was 422...
|
||||||
error = household;
|
error = household;
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
{{ $t('household_number', { number: household.id } ) }}
|
{{ $t('household_number', { number: household.id } ) }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- member part -->
|
<!-- member part -->
|
||||||
<div v-if="hasCurrentMembers" class="members">
|
<div v-if="hasCurrentMembers" class="members">
|
||||||
<span class="current-members">{{ $t('current_members') }}: </span>
|
<span class="current-members">{{ $t('current_members') }}: </span>
|
||||||
<template v-for="(m, index) in currentMembers()" :key="m.id">
|
<template v-for="(m, index) in currentMembers()" :key="m.id">
|
||||||
@ -40,7 +40,7 @@
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.chill-entity__household {
|
.chill-entity__household {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
"identifier identifier where"
|
"identifier identifier where"
|
||||||
"who who where"
|
"who who where"
|
||||||
;
|
;
|
||||||
@ -50,7 +50,7 @@
|
|||||||
|
|
||||||
.identifier {
|
.identifier {
|
||||||
grid-area: identifier;
|
grid-area: identifier;
|
||||||
|
|
||||||
font-size: 1.3em;
|
font-size: 1.3em;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: var(--chill-blue);
|
color: var(--chill-blue);
|
||||||
@ -110,7 +110,7 @@ export default {
|
|||||||
return this.household.members.filter(m => this.household.current_members_id.includes(m.id))
|
return 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;
|
||||||
}
|
}
|
||||||
if (a.position.ordering > b.position.ordering) {
|
if (a.position.ordering > b.position.ordering) {
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
<div id="withoutHouseholdList" class="collapse p-3">
|
<div id="withoutHouseholdList" class="collapse p-3">
|
||||||
<form method="GET"
|
<form method="GET"
|
||||||
action="{{ chill_path_add_return_path('chill_person_household_members_editor') }}">
|
action="{{ path('chill_person_household_members_editor') }}">
|
||||||
|
|
||||||
<h3>{{ 'household.Select people to move'|trans }}</h3>
|
<h3>{{ 'household.Select people to move'|trans }}</h3>
|
||||||
<ul>
|
<ul>
|
||||||
@ -27,6 +27,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<input type="hidden" name="expand_suggestions" value="true" />
|
<input type="hidden" name="expand_suggestions" value="true" />
|
||||||
|
<input type="hidden" name="returnPath" value="{{ app.request.requestUri|escape('html_attr') }}" />
|
||||||
<input type="hidden" name="accompanying_period_id" value="{{ accompanyingCourse.id }}" />
|
<input type="hidden" name="accompanying_period_id" value="{{ accompanyingCourse.id }}" />
|
||||||
<ul class="record_actions mb-0">
|
<ul class="record_actions mb-0">
|
||||||
<li>
|
<li>
|
||||||
|
@ -1,5 +1,61 @@
|
|||||||
<div class="alert alert-danger alert-with-actions mb-0">
|
{%- set countPersonLocation = accompanyingCourse.availablePersonLocation|length -%}
|
||||||
<div class="message">
|
{%- set hasPersonLocation = countPersonLocation|length > 0 -%}
|
||||||
{{ 'This course is located at a temporarily address. You should locate this course to an user'|trans }}
|
{% macro quickLocationForm(accompanyingCourse, person, whichButton) %}
|
||||||
|
<form method="PATCH" action="{{ path('chill_api_single_accompanying_course__entity', {'id': accompanyingCourse.id, '_format': 'json'}) }}" class="quickLocationForm">
|
||||||
|
<input type="hidden" name="personLocation" value="{{ person.id }}" />
|
||||||
|
<input type="hidden" name="periodId" value="{{ accompanyingCourse.id }}" />
|
||||||
|
{% if whichButton == 'string' %}
|
||||||
|
<button type="submit" class="btn btn-chill-pink">
|
||||||
|
<span class="text-light">{{ 'Locate by'|trans }} {{ person|chill_entity_render_string }}</span>
|
||||||
|
</button>
|
||||||
|
{% elseif whichButton == 'icon' %}
|
||||||
|
<button type="submit" class="btn btn-sm btn-secondary">
|
||||||
|
<i class="fa fa-map-marker"></i>
|
||||||
|
</button>
|
||||||
|
{% endif %}
|
||||||
|
</form>
|
||||||
|
{% endmacro %}
|
||||||
|
<div class="border border-danger">
|
||||||
|
<div class="alert alert-danger {% if hasPersonLocation %}alert-with-actions{% endif %} mb-0">
|
||||||
|
<div class="message">
|
||||||
|
{{ 'This course is located at a temporarily address. You should locate this course to an user'|trans }}
|
||||||
|
{% if not hasPersonLocation %}
|
||||||
|
{{ 'Associate at least one member with an household, and set an address to this household'|trans }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if 1 == countPersonLocation %}
|
||||||
|
<ul class="record_actions">
|
||||||
|
<li>
|
||||||
|
{{ _self.quickLocationForm(accompanyingCourse, accompanyingCourse.availablePersonLocation.first, 'string') }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
{% elseif 1 < countPersonLocation %}
|
||||||
|
<ul class="record_actions">
|
||||||
|
<li>
|
||||||
|
<button class="btn btn-chill-pink" data-bs-toggle="collapse" href="#locateAtPerson">
|
||||||
|
<i class="fa fa-fw fa-caret-down"></i><span class="text-light">{{ 'Choose a person to locate by'|trans }}</span>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% if 1 < countPersonLocation %}
|
||||||
|
<div id="locateAtPerson" class="collapse">
|
||||||
|
<p>{{ 'Locate by'|trans }}:</p>
|
||||||
|
|
||||||
|
<div class="flex-table mb-3">
|
||||||
|
{% for p in accompanyingCourse.availablePersonLocation %}
|
||||||
|
<div class="item-bloc">
|
||||||
|
{{ p|chill_entity_render_box({
|
||||||
|
'render': 'bloc', 'addLink': false, 'addInfo': true, 'addAltNames': false, 'customButtons': {
|
||||||
|
'replace': _self.quickLocationForm(accompanyingCourse, p, 'icon')
|
||||||
|
}
|
||||||
|
}) }}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
@ -15,6 +15,11 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% block js %}
|
||||||
|
{{ parent() }}
|
||||||
|
{{ encore_entry_script_tags('page_accompanying_course_index_person_locate') }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="accompanyingcourse-resume">
|
<div class="accompanyingcourse-resume">
|
||||||
|
|
||||||
@ -27,11 +32,6 @@
|
|||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{% if accompanyingCourse.locationStatus == 'address' or accompanyingCourse.locationStatus == 'none' %}
|
|
||||||
<div class="alert alert-danger">
|
|
||||||
{{ 'This course is located at a temporarily address. You should locate this course to an user'|trans }}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<h1>{{ 'Resume Accompanying Course'|trans }}</h1>
|
<h1>{{ 'Resume Accompanying Course'|trans }}</h1>
|
||||||
@ -54,12 +54,29 @@
|
|||||||
{% if withoutHousehold|length > 0 %}
|
{% if withoutHousehold|length > 0 %}
|
||||||
{% include '@ChillPerson/AccompanyingCourse/_join_household.html.twig' with {} %}
|
{% include '@ChillPerson/AccompanyingCourse/_join_household.html.twig' with {} %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if accompanyingCourse.locationStatus == 'address' or accompanyingCourse.locationStatus == 'none' %}
|
|
||||||
{% include '@ChillPerson/AccompanyingCourse/_warning_address.html.twig' with {} %}
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="location mb-5">
|
||||||
|
<h2 class="mb-3">{{ 'Accompanying course location'|trans }}</h2>
|
||||||
|
|
||||||
|
{% if accompanyingCourse.locationStatus == 'person' %}
|
||||||
|
<p>{{ 'This course is located by'|trans }}: {{ accompanyingCourse.personLocation|chill_entity_render_string }}</p>
|
||||||
|
{% elseif accompanyingCourse.locationStatus == 'address' %}
|
||||||
|
<p>{{ 'This course has a temporarily location'|trans }}</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if accompanyingCourse.locationStatus != 'none' %}
|
||||||
|
{{ accompanyingCourse.location|chill_entity_render_box }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if accompanyingCourse.locationStatus == 'address' or accompanyingCourse.locationStatus == 'none' %}
|
||||||
|
{% include '@ChillPerson/AccompanyingCourse/_warning_address.html.twig' with {} %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="requestor mb-5">
|
<div class="requestor mb-5">
|
||||||
<h2 class="mb-3">{{ 'Requestor'|trans }}</h2>
|
<h2 class="mb-3">{{ 'Requestor'|trans }}</h2>
|
||||||
{% if accompanyingCourse.requestorPerson is not empty %}
|
{% if accompanyingCourse.requestorPerson is not empty %}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{% extends accompanyingCourse != null ? '@ChillPerson/AccompanyingCourse/layout.html.twig'
|
{% extends accompanyingCourse != null ? '@ChillPerson/AccompanyingCourse/layout.html.twig'
|
||||||
: '@ChillMain/layout.html.twig' %}
|
: '@ChillMain/layout.html.twig' %}
|
||||||
|
|
||||||
{% block title 'household.Edit household members'|trans %}
|
{% block title 'household.Edit household members'|trans %}
|
||||||
@ -13,11 +13,12 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block js %}
|
{% block js %}
|
||||||
<script type="text/javascript">
|
{{ parent() }}
|
||||||
window.household_members_editor_data = {{ data|json_encode|raw }};
|
<script type="text/javascript">
|
||||||
window.household_members_editor_expand_suggestions = {{ expandSuggestions }};
|
window.household_members_editor_data = {{ data|json_encode|raw }};
|
||||||
</script>
|
window.household_members_editor_expand_suggestions = {{ expandSuggestions }};
|
||||||
{{ encore_entry_script_tags('vue_household_members_editor') }}
|
</script>
|
||||||
|
{{ encore_entry_script_tags('vue_household_members_editor') }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block css %}
|
{% block css %}
|
||||||
|
@ -16,4 +16,5 @@ module.exports = function(encore, entries)
|
|||||||
|
|
||||||
encore.addEntry('page_household_edit_metadata', __dirname + '/Resources/public/page/household_edit_metadata/index.js');
|
encore.addEntry('page_household_edit_metadata', __dirname + '/Resources/public/page/household_edit_metadata/index.js');
|
||||||
encore.addEntry('page_person', __dirname + '/Resources/public/page/person/index.js');
|
encore.addEntry('page_person', __dirname + '/Resources/public/page/person/index.js');
|
||||||
|
encore.addEntry('page_accompanying_course_index_person_locate', __dirname + '/Resources/public/page/accompanying_course_index/person_locate.js');
|
||||||
};
|
};
|
||||||
|
@ -376,6 +376,12 @@ Edit Accompanying Course: Modifier le parcours
|
|||||||
Create Accompanying Course: Créer un nouveau parcours
|
Create Accompanying Course: Créer un nouveau parcours
|
||||||
Drop Accompanying Course: Supprimer le parcours
|
Drop Accompanying Course: Supprimer le parcours
|
||||||
This course is located at a temporarily address. You should locate this course to an user: Ce parcours est localisé à une adresse temporaire. Il devrait être localisé auprès d'un usager concerné.
|
This course is located at a temporarily address. You should locate this course to an user: Ce parcours est localisé à une adresse temporaire. Il devrait être localisé auprès d'un usager concerné.
|
||||||
|
Accompanying course location: Localisation du parcours
|
||||||
|
This course is located by: Ce parcours est localisé auprès de
|
||||||
|
This course has a temporarily location: Ce parcours a une localisation temporaire
|
||||||
|
Choose a person to locate by: Localiser auprès d'un usager concerné
|
||||||
|
Associate at least one member with an household, and set an address to this household: Associez au moins un membre du parcours à un ménage, et indiquez une adresse à ce ménage.
|
||||||
|
Locate by: Localiser auprès de
|
||||||
|
|
||||||
# Household
|
# Household
|
||||||
Household: Ménage
|
Household: Ménage
|
||||||
|
Loading…
x
Reference in New Issue
Block a user