diff --git a/CHANGELOG.md b/CHANGELOG.md index 90f4c2503..42f5a1522 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,15 +11,20 @@ and this project adheres to ## Unreleased +* [person] add civility when creating a person (with the on-the-fly component or in the php form) (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/557) +* [person] add address when creating a person (with the on-the-fly component or in the php form) (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/557) +* [person] add household creation API point (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/557) + + +## Test releases + +### 2021-04-29 + * [person] prevent circular references in PersonDocGenNormalizer (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/527) * [person] add maritalStatusComment to PersonDocGenNormalizer (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/582) * Load relationships without gender in french fixtures * Add command to remove old draft accompanying periods - - -## Test releases - ### 2021-04-28 * [address] fix bug when editing address: update location and addressreferenceId + better update of the map in edition (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/593) diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/OnTheFly/components/OnTheFly.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/OnTheFly/components/OnTheFly.vue index 669c225dd..e3991fe2f 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/OnTheFly/components/OnTheFly.vue +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/OnTheFly/components/OnTheFly.vue @@ -210,10 +210,10 @@ export default { let type = this.type, data = {} ; - switch (type) { case 'person': data = this.$refs.castPerson.$data.person; + console.log('person data are', data); break; case 'thirdparty': @@ -238,7 +238,7 @@ export default { if (typeof data.civility !== 'undefined' && null !== data.civility) { data.civility = data.civility !== null ? {type: 'chill_main_civility', id: data.civility.id} : null; } - if (typeof data.civility !== 'undefined' && null !== data.profession) { + if (typeof data.profession !== 'undefined' && null !== data.profession) { data.profession = data.profession !== null ? {type: 'third_party_profession', id: data.profession.id} : null; } // console.log('onthefly data', data); diff --git a/src/Bundle/ChillMainBundle/Resources/views/layout.html.twig b/src/Bundle/ChillMainBundle/Resources/views/layout.html.twig index c11422a1b..f59e0aaff 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/layout.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/layout.html.twig @@ -36,33 +36,35 @@ {# Flash messages ! #} {% if app.session.flashbag.keys()|length > 0 %} -
+
+
+ + {% for flashMessage in app.session.flashbag.get('success') %} +
+ {{ flashMessage|raw }} +
+ {% endfor %} + + {% for flashMessage in app.session.flashbag.get('error') %} +
+ {{ flashMessage|raw }} +
+ {% endfor %} + + {% for flashMessage in app.session.flashbag.get('notice') %} +
+ {{ flashMessage|raw }} +
+ {% endfor %} - {% for flashMessage in app.session.flashbag.get('success') %} -
- {{ flashMessage|raw }}
- {% endfor %} - - {% for flashMessage in app.session.flashbag.get('error') %} -
- {{ flashMessage|raw }} -
- {% endfor %} - - {% for flashMessage in app.session.flashbag.get('notice') %} -
- {{ flashMessage|raw }} -
- {% endfor %} - -
+
{% endif %} {% block content %} - + {# DISABLED {{ chill_widget('homepage', {} ) }} #} - + {% include '@ChillMain/Homepage/index.html.twig' %} - + {% endblock %}
diff --git a/src/Bundle/ChillPersonBundle/Controller/PersonController.php b/src/Bundle/ChillPersonBundle/Controller/PersonController.php index bd53cd8b3..a4a29216c 100644 --- a/src/Bundle/ChillPersonBundle/Controller/PersonController.php +++ b/src/Bundle/ChillPersonBundle/Controller/PersonController.php @@ -12,12 +12,15 @@ declare(strict_types=1); namespace Chill\PersonBundle\Controller; use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper; +use Chill\PersonBundle\Entity\Household\Household; +use Chill\PersonBundle\Entity\Household\HouseholdMember; use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Form\CreationPersonType; use Chill\PersonBundle\Form\PersonType; use Chill\PersonBundle\Privacy\PrivacyEvent; use Chill\PersonBundle\Repository\PersonRepository; use Chill\PersonBundle\Search\SimilarPersonMatcher; +use DateTimeImmutable; use Doctrine\ORM\EntityManagerInterface; use Psr\Log\LoggerInterface; use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; @@ -31,8 +34,8 @@ use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Security\Core\Security; use Symfony\Component\Validator\Validator\ValidatorInterface; -use Symfony\Contracts\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; use function count; use function hash; use function implode; @@ -248,6 +251,31 @@ final class PersonController extends AbstractController $this->em->flush(); $this->lastPostDataReset(); + $address = $form->get('address')->getData(); + $addressForm = (bool) $form->get('addressForm')->getData(); + + if (null !== $address && $addressForm) { + $household = new Household(); + + $member = new HouseholdMember(); + $member->setPerson($person); + $member->setStartDate(new DateTimeImmutable()); + + $household->addMember($member); + $household->setForceAddress($address); + + $this->em->persist($member); + $this->em->persist($household); + $this->em->flush(); + + if ($form->get('createHousehold')->isClicked()) { + return $this->redirectToRoute('chill_person_household_members_editor', [ + 'persons' => [$person->getId()], + 'household' => $household->getId(), + ]); + } + } + if ($form->get('createPeriod')->isClicked()) { return $this->redirectToRoute('chill_person_accompanying_course_new', [ 'person_id' => [$person->getId()], diff --git a/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php b/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php index 25fc251e5..99c408ff1 100644 --- a/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php +++ b/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php @@ -555,6 +555,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac 'methods' => [ Request::METHOD_GET => true, Request::METHOD_HEAD => true, + Request::METHOD_POST => true, ], ], 'suggestHouseholdByAccompanyingPeriodParticipation' => [ diff --git a/src/Bundle/ChillPersonBundle/Entity/Household/HouseholdMember.php b/src/Bundle/ChillPersonBundle/Entity/Household/HouseholdMember.php index 22c33f85f..2de526ee6 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Household/HouseholdMember.php +++ b/src/Bundle/ChillPersonBundle/Entity/Household/HouseholdMember.php @@ -35,7 +35,7 @@ class HouseholdMember /** * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) * @Serializer\Groups({"read", "docgen:read"}) - * @Assert\GreaterThan( + * @Assert\GreaterThanOrEqual( * propertyPath="startDate", * message="household_membership.The end date must be after start date", * groups={"household_memberships"} @@ -82,14 +82,13 @@ class HouseholdMember /** * @ORM\ManyToOne(targetEntity=Position::class) * @Serializer\Groups({"read", "docgen:read"}) - * @Assert\NotNull(groups={"household_memberships_created"}) */ private ?Position $position = null; /** * @ORM\Column(type="boolean", name="sharedhousehold") */ - private bool $shareHousehold = false; + private bool $shareHousehold = true; /** * @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) @@ -201,15 +200,18 @@ class HouseholdMember return $this; } - public function setPosition(Position $position): self + public function setPosition(?Position $position): self { - if ($this->position instanceof Position) { + if ($this->position instanceof Position && $this->position !== $position) { throw new LogicException('The position is already set. You cannot change ' . 'a position of a membership'); } $this->position = $position; - $this->shareHousehold = $position->getShareHousehold(); + + if (null !== $position) { + $this->shareHousehold = $position->getShareHousehold(); + } return $this; } diff --git a/src/Bundle/ChillPersonBundle/Form/CreationPersonType.php b/src/Bundle/ChillPersonBundle/Form/CreationPersonType.php index 2aed9df97..124db26eb 100644 --- a/src/Bundle/ChillPersonBundle/Form/CreationPersonType.php +++ b/src/Bundle/ChillPersonBundle/Form/CreationPersonType.php @@ -11,10 +11,13 @@ declare(strict_types=1); namespace Chill\PersonBundle\Form; +use Chill\MainBundle\Entity\Address; use Chill\MainBundle\Form\Event\CustomizeFormEvent; use Chill\MainBundle\Form\Type\ChillDateType; use Chill\MainBundle\Form\Type\ChillPhoneNumberType; +use Chill\MainBundle\Form\Type\PickAddressType; use Chill\MainBundle\Form\Type\PickCenterType; +use Chill\MainBundle\Form\Type\PickCivilityType; use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper; use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Form\Type\GenderType; @@ -24,9 +27,12 @@ use libphonenumber\PhoneNumberType; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\Extension\Core\Type\CheckboxType; use Symfony\Component\Form\Extension\Core\Type\EmailType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\Validator\Constraints\Callback; +use Symfony\Component\Validator\Context\ExecutionContextInterface; final class CreationPersonType extends AbstractType { @@ -55,6 +61,11 @@ final class CreationPersonType extends AbstractType $builder ->add('firstName') ->add('lastName') + ->add('civility', PickCivilityType::class, [ + 'required' => false, + 'label' => 'Civility', + 'placeholder' => 'choose civility', + ]) ->add('gender', GenderType::class, [ 'required' => true, 'placeholder' => null, ]) @@ -71,6 +82,17 @@ final class CreationPersonType extends AbstractType ]) ->add('email', EmailType::class, [ 'required' => false, + ]) + ->add('addressForm', CheckboxType::class, [ + 'label' => 'Create a household and add an address', + 'required' => false, + 'mapped' => false, + 'help' => 'A new household will be created. The person will be member of this household.', + ]) + ->add('address', PickAddressType::class, [ + 'required' => false, + 'mapped' => false, + 'label' => false, ]); if ($this->askCenters) { @@ -97,6 +119,9 @@ final class CreationPersonType extends AbstractType { $resolver->setDefaults([ 'data_class' => Person::class, + 'constraints' => [ + new Callback([$this, 'validateCheckedAddress']), + ], ]); } @@ -107,4 +132,18 @@ final class CreationPersonType extends AbstractType { return self::NAME; } + + public function validateCheckedAddress($data, ExecutionContextInterface $context, $payload): void + { + /** @var bool $addressFrom */ + $addressFrom = $context->getObject()->get('addressForm')->getData(); + /** @var ?Address $address */ + $address = $context->getObject()->get('address')->getData(); + + if ($addressFrom && null === $address) { + $context->buildViolation('person_creation.If you want to create an household, an address is required') + ->atPath('addressForm') + ->addViolation(); + } + } } diff --git a/src/Bundle/ChillPersonBundle/Form/HouseholdMemberType.php b/src/Bundle/ChillPersonBundle/Form/HouseholdMemberType.php index 99c698c91..192142043 100644 --- a/src/Bundle/ChillPersonBundle/Form/HouseholdMemberType.php +++ b/src/Bundle/ChillPersonBundle/Form/HouseholdMemberType.php @@ -26,12 +26,15 @@ class HouseholdMemberType extends AbstractType 'input' => 'datetime_immutable', ]); - if (!$options['data']->getPosition()->getShareHousehold()) { - $builder->add('endDate', ChillDateType::class, [ - 'label' => 'household.End date', - 'input' => 'datetime_immutable', - ]); + if (null !== $options['data']->getPosition()) { + if (!$options['data']->getPosition()->getShareHousehold()) { + $builder->add('endDate', ChillDateType::class, [ + 'label' => 'household.End date', + 'input' => 'datetime_immutable', + ]); + } } + $builder ->add('comment', ChillTextareaType::class, [ 'label' => 'household.Comment', diff --git a/src/Bundle/ChillPersonBundle/Household/MembersEditor.php b/src/Bundle/ChillPersonBundle/Household/MembersEditor.php index 1c7cbb538..8ae41a98b 100644 --- a/src/Bundle/ChillPersonBundle/Household/MembersEditor.php +++ b/src/Bundle/ChillPersonBundle/Household/MembersEditor.php @@ -55,7 +55,7 @@ class MembersEditor $this->eventDispatcher = $eventDispatcher; } - public function addMovement(DateTimeImmutable $date, Person $person, Position $position, ?bool $holder = false, ?string $comment = null): self + public function addMovement(DateTimeImmutable $date, Person $person, ?Position $position, ?bool $holder = false, ?string $comment = null): self { if (null === $this->household) { throw new LogicException('You must define a household first'); @@ -69,68 +69,70 @@ class MembersEditor ->setComment($comment); $this->household->addMember($membership); - if ($position->getShareHousehold()) { - // launch event only if moving to a "share household" position, - // and if the destination household is different than the previous one - $event = new PersonAddressMoveEvent($person); - $event->setNextMembership($membership); + if (null !== $position) { + if ($position->getShareHousehold()) { + // launch event only if moving to a "share household" position, + // and if the destination household is different than the previous one + $event = new PersonAddressMoveEvent($person); + $event->setNextMembership($membership); - $counter = 0; + $counter = 0; - foreach ($person->getHouseholdParticipationsShareHousehold() as $participation) { - if ($participation === $membership) { - continue; - } + foreach ($person->getHouseholdParticipationsShareHousehold() as $participation) { + if ($participation === $membership) { + continue; + } - if ($participation->getStartDate() > $membership->getStartDate()) { - continue; - } + if ($participation->getStartDate() > $membership->getStartDate()) { + continue; + } - ++$counter; + ++$counter; - if ($participation->getEndDate() === null || $participation->getEndDate() > $date) { - $participation->setEndDate($date); - $this->membershipsAffected[] = $participation; - $this->oldMembershipsHashes[] = spl_object_hash($participation); + if ($participation->getEndDate() === null || $participation->getEndDate() > $date) { + $participation->setEndDate($date); + $this->membershipsAffected[] = $participation; + $this->oldMembershipsHashes[] = spl_object_hash($participation); - if ($participation->getHousehold() !== $this->household) { - $event->setPreviousMembership($participation); - $this->events[] = $event; + if ($participation->getHousehold() !== $this->household) { + $event->setPreviousMembership($participation); + $this->events[] = $event; + } } } - } - // send also the event if there was no participation before - if (0 === $counter) { - $this->events[] = $event; - } - - foreach ($person->getHouseholdParticipationsNotShareHousehold() as $participation) { - if ($participation->getHousehold() === $this->household - && $participation->getEndDate() === null || $participation->getEndDate() > $membership->getStartDate() - && $participation->getStartDate() <= $membership->getStartDate() - ) { - $participation->setEndDate($membership->getStartDate()); - } - } - } else { - // if a members is moved to the same household than the one he belongs to, - // we should make it leave the household - if ($person->getCurrentHousehold($date) === $this->household) { - $this->leaveMovement($date, $person); - } - - // if there are multiple belongings not sharing household, close the others - foreach ($person->getHouseholdParticipationsNotShareHousehold() as $participation) { - if ($participation === $membership) { - continue; + // send also the event if there was no participation before + if (0 === $counter) { + $this->events[] = $event; } - if ($participation->getHousehold() === $this->household - && ($participation->getEndDate() === null || $participation->getEndDate() > $membership->getStartDate()) - && $participation->getStartDate() <= $membership->getStartDate() - ) { - $participation->setEndDate($membership->getStartDate()); + foreach ($person->getHouseholdParticipationsNotShareHousehold() as $participation) { + if ($participation->getHousehold() === $this->household + && $participation->getEndDate() === null || $participation->getEndDate() > $membership->getStartDate() + && $participation->getStartDate() <= $membership->getStartDate() + ) { + $participation->setEndDate($membership->getStartDate()); + } + } + } else { + // if a members is moved to the same household than the one he belongs to, + // we should make it leave the household + if ($person->getCurrentHousehold($date) === $this->household) { + $this->leaveMovement($date, $person); + } + + // if there are multiple belongings not sharing household, close the others + foreach ($person->getHouseholdParticipationsNotShareHousehold() as $participation) { + if ($participation === $membership) { + continue; + } + + if ($participation->getHousehold() === $this->household + && ($participation->getEndDate() === null || $participation->getEndDate() > $membership->getStartDate()) + && $participation->getStartDate() <= $membership->getStartDate() + ) { + $participation->setEndDate($membership->getStartDate()); + } } } } diff --git a/src/Bundle/ChillPersonBundle/Resources/public/page/person/create-person.js b/src/Bundle/ChillPersonBundle/Resources/public/page/person/create-person.js new file mode 100644 index 000000000..7e29c4530 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/public/page/person/create-person.js @@ -0,0 +1,18 @@ +import { ShowHide } from 'ShowHide'; + +const addressForm = document.getElementById("addressForm"); +const address = document.getElementById("address"); + +new ShowHide({ + froms: [addressForm], + container: [address], + test: function(froms) { + for (let f of froms.values()) { + for (let input of f.querySelectorAll('input').values()) { + return input.checked; + } + } + return false; + }, + event_name: 'change' +}); diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/PersonsAssociated/ParticipationItem.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/PersonsAssociated/ParticipationItem.vue index 1a1a7e26e..ff8aef961 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/PersonsAssociated/ParticipationItem.vue +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/PersonsAssociated/ParticipationItem.vue @@ -123,6 +123,7 @@ export default { body.email = payload.data.email; body.altNames = payload.data.altNames; body.gender = payload.data.gender; + body.civility = payload.data.civility; makeFetch('PATCH', `/api/1.0/person/person/${payload.data.id}.json`, body) .then(response => { diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Resources/ResourceItem.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Resources/ResourceItem.vue index df2bd0c35..605ab6443 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Resources/ResourceItem.vue +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Resources/ResourceItem.vue @@ -150,6 +150,7 @@ export default { body.email = payload.data.email; body.altNames = payload.data.altNames; body.gender = payload.data.gender; + body.civility = payload.data.civility; makeFetch('PATCH', `/api/1.0/person/person/${payload.data.id}.json`, body) .then(response => { diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_api/OnTheFly.js b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_api/OnTheFly.js index 20ed1c8da..338094122 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_api/OnTheFly.js +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_api/OnTheFly.js @@ -14,8 +14,13 @@ const getPersonAltNames = () => fetch('/api/1.0/person/config/alt_names.json').then(response => { if (response.ok) { return response.json(); } throw Error('Error with request resource response'); - });; + }); +const getCivilities = () => + fetch('/api/1.0/main/civility.json').then(response => { + if (response.ok) { return response.json(); } + throw Error('Error with request resource response'); + }); /* * POST a new person @@ -56,6 +61,7 @@ const patchPerson = (id, body) => { export { getPerson, getPersonAltNames, + getCivilities, postPerson, patchPerson }; diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/AddPersons.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/AddPersons.vue index 90505a1e2..f84fc2e1d 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/AddPersons.vue +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/AddPersons.vue @@ -277,12 +277,79 @@ export default { } }, saveFormOnTheFly({ type, data }) { - // console.log('saveFormOnTheFly from addPersons, type', type, ', data', data); + console.log('saveFormOnTheFly from addPersons, type', type, ', data', data); if (type === 'person') { + makeFetch('POST', '/api/1.0/person/person.json', data) - .then(response => { - this.newPriorSuggestion(response); + .then(responsePerson => { + + this.newPriorSuggestion(responsePerson); this.$refs.onTheFly.closeModal(); + + if (null !== data.addressId) { + const household = { + 'type': 'household' + }; + const address = { + 'id': data.addressId + }; + makeFetch('POST', '/api/1.0/person/household.json', household) + .then(responseHousehold => { + const member = { + 'concerned': [ + { + 'person': { + 'type': 'person', + 'id': responsePerson.id + }, + 'start_date': { + // TODO: use date.js methods (low priority) + 'datetime': `${new Date().toISOString().split('T')[0]}T00:00:00+02:00` + }, + 'holder': false, + 'comment': null + } + ], + 'destination': { + 'type': 'household', + 'id': responseHousehold.id + }, + 'composition': null + }; + return makeFetch('POST', '/api/1.0/person/household/members/move.json', member) + .then(_response => { + makeFetch('POST', `/api/1.0/person/household/${responseHousehold.id}/address.json`, address) + .then(_response => {}) + .catch((error) => { + if (error.name === 'ValidationException') { + for (let v of error.violations) { + this.$toast.open({message: v }); + } + } else { + this.$toast.open({message: 'An error occurred'}); + } + }); + }) + .catch((error) => { + if (error.name === 'ValidationException') { + for (let v of error.violations) { + this.$toast.open({message: v }); + } + } else { + this.$toast.open({message: 'An error occurred'}); + } + }); + }) + .catch((error) => { + if (error.name === 'ValidationException') { + for (let v of error.violations) { + this.$toast.open({message: v }); + } + } else { + this.$toast.open({message: 'An error occurred'}); + } + }); + } }) .catch((error) => { if (error.name === 'ValidationException') { @@ -292,7 +359,8 @@ export default { } else { this.$toast.open({message: 'An error occurred'}); } - }) + }); + } else if (type === 'thirdparty') { makeFetch('POST', '/api/1.0/thirdparty/thirdparty.json', data) diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/OnTheFly/Person.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/OnTheFly/Person.vue index e6fa85902..5a8708cc3 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/OnTheFly/Person.vue +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/OnTheFly/Person.vue @@ -87,6 +87,20 @@ +
+ + +
+
+
+ + +
+
+

{{ $t('person.address.warning') }}

+ + +
+ +