diff --git a/src/Bundle/ChillMainBundle/Resources/public/modules/bootstrap/bootstrap.scss b/src/Bundle/ChillMainBundle/Resources/public/modules/bootstrap/bootstrap.scss index 4d3b86ed3..8a77ac48f 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/modules/bootstrap/bootstrap.scss +++ b/src/Bundle/ChillMainBundle/Resources/public/modules/bootstrap/bootstrap.scss @@ -28,7 +28,7 @@ // @import "bootstrap/scss/card"; // @import "bootstrap/scss/breadcrumb"; // @import "bootstrap/scss/pagination"; -// @import "bootstrap/scss/badge"; +@import "bootstrap/scss/badge"; // @import "bootstrap/scss/jumbotron"; // @import "bootstrap/scss/alert"; // @import "bootstrap/scss/progress"; @@ -41,7 +41,7 @@ // @import "bootstrap/scss/popover"; // @import "bootstrap/scss/carousel"; // @import "bootstrap/scss/spinners"; -// @import "bootstrap/scss/utilities"; +@import "bootstrap/scss/utilities"; // @import "bootstrap/scss/print"; @import "custom"; diff --git a/src/Bundle/ChillMainBundle/Resources/public/modules/scratch/custom/modules/_buttons.scss b/src/Bundle/ChillMainBundle/Resources/public/modules/scratch/custom/modules/_buttons.scss index e94aa494e..0b7af263b 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/modules/scratch/custom/modules/_buttons.scss +++ b/src/Bundle/ChillMainBundle/Resources/public/modules/scratch/custom/modules/_buttons.scss @@ -5,7 +5,7 @@ @include button($green, $white); } - &.bt-reset, &.bt-delete { + &.bt-reset, &.bt-delete, &.bt-remove { @include button($red, $white); } @@ -24,6 +24,7 @@ &.bt-save::before, &.bt-new::before, &.bt-delete::before, + &.bt-remove::before, &.bt-update::before, &.bt-edit::before, &.bt-cancel::before, @@ -56,7 +57,12 @@ // add a trash content: ""; } - + + &.bt-remove::before { + // add a times + content: ""; + } + &.bt-edit::before, &.bt-update::before { // add a pencil content: ""; @@ -94,6 +100,7 @@ &.bt-save::before, &.bt-new::before, &.bt-delete::before, + &.bt-remove::before, &.bt-update::before, &.bt-edit::before, &.bt-cancel::before, @@ -123,6 +130,7 @@ &.bt-save::before, &.bt-new::before, &.bt-delete::before, + &.bt-remove::before, &.bt-update::before, &.bt-edit::before, &.bt-cancel::before, diff --git a/src/Bundle/ChillMainBundle/Resources/public/scss/chillmain.scss b/src/Bundle/ChillMainBundle/Resources/public/scss/chillmain.scss index 4f9ecf46d..a27dcdc42 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/scss/chillmain.scss +++ b/src/Bundle/ChillMainBundle/Resources/public/scss/chillmain.scss @@ -39,6 +39,8 @@ div.subheader { height: 130px; } +//// VUEJS //// + div.vue-component { padding: 1.5em; margin: 2em 0; @@ -55,3 +57,97 @@ div.vue-component { } dd { margin-left: 1em; } } + +//// MODAL //// +.modal-mask { + position: fixed; + z-index: 9998; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.75); + display: table; + transition: opacity 0.3s ease; +} +.modal-header .close { // bootstrap classes, override sc-button 0 radius + border-top-right-radius: 0.3rem; +} + +/* +* The following styles are auto-applied to elements with +* transition="modal" when their visibility is toggled +* by Vue.js. +* +* You can easily play with the modal transition by editing +* these styles. +*/ +.modal-enter { + opacity: 0; +} +.modal-leave-active { + opacity: 0; +} +.modal-enter .modal-container, +.modal-leave-active .modal-container { + -webkit-transform: scale(1.1); + transform: scale(1.1); +} + +//// AddPersons modal +div.modal-body.up { + margin: auto 4em; + div.search { + position: relative; + input { + padding: 1.2em 1.5em 1.2em 2.5em; + margin: 1em 0; + } + i { + position: absolute; + top: 50%; + left: 0.5em; + padding: 0.65em 0; + opacity: 0.5; + } + + } +} +div.results { + div.count { + margin: -0.5em 0 0.7em; + display: flex; + justify-content: space-between; + } + div.list-item { + line-height: 26pt; + padding: 0.3em 0.8em; + display: flex; + flex-direction: row; + &.checked { + background-color: #ececec; + border-bottom: 1px dotted #8b8b8b; + } + div.container { + & > input { + margin-right: 0.8em; + } + } + div.right_actions { + margin: 0 0 0 auto; + & > * { + margin-left: 0.5em; + } + a.sc-button { + border: 1px solid lightgrey; + font-size: 70%; + padding: 4px; + } + } + } +} + +.discret { + color: grey; + margin-right: 1em; +} diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/_components/Modal.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/_components/Modal.vue new file mode 100644 index 000000000..cbd2d0738 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/_components/Modal.vue @@ -0,0 +1,45 @@ + + + diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/_js/i18n.js b/src/Bundle/ChillMainBundle/Resources/public/vuejs/_js/i18n.js new file mode 100644 index 000000000..4f5c64e30 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/_js/i18n.js @@ -0,0 +1,55 @@ +import { createI18n } from 'vue-i18n' + +const datetimeFormats = { + fr: { + short: { + year: "numeric", + month: "numeric", + day: "numeric" + }, + long: { + year: "numeric", + month: "short", + day: "numeric", + weekday: "short", + hour: "numeric", + minute: "numeric", + hour12: false + } + } +}; +const messages = { + fr: { + action: { + actions: "Actions", + show: "Voir", + edit: "Modifier", + create: "Créer", + remove: "Enlever", + delete: "Supprimer", + save: "Enregistrer", + add: "Ajouter", + show_modal: "Ouvrir une modale", + ok: "OK", + cancel: "Annuler", + close: "Fermer", + next: "Suivant", + previous: "Précédent", + back: "Retour", + check_all: "cocher tout", + reset: "réinitialiser" + }, + } +}; + +const _createI18n = (appMessages) => { + Object.assign(messages.fr, appMessages.fr); + return createI18n({ + locale: 'fr', + fallbackLocale: 'fr', + datetimeFormats, + messages, + }) +}; + +export { _createI18n } diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseController.php index 9bc732d87..05a1934e6 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseController.php @@ -121,7 +121,7 @@ class AccompanyingCourseController extends Controller * @Route( * "/{_locale}/person/api/1.0/accompanying-course/{accompanying_period_id}/participation.{_format}", * name="chill_person_accompanying_course_api_add_participation", - * methods={"POST"}, + * methods={"POST","DELETE"}, * format="json", * requirements={ * "_format": "json", @@ -129,7 +129,7 @@ class AccompanyingCourseController extends Controller * ) * @ParamConverter("accompanyingCourse", options={"id": "accompanying_period_id"}) */ - public function addParticipationAPI(Request $request, AccompanyingPeriod $accompanyingCourse, $_format): Response + public function participationAPI(Request $request, AccompanyingPeriod $accompanyingCourse, $_format): Response { switch ($_format) { case 'json': @@ -146,7 +146,9 @@ class AccompanyingCourseController extends Controller } // TODO add acl - $accompanyingCourse->addPerson($person); + $participation = ($request->getMethod() === 'POST') ? + $accompanyingCourse->addPerson($person) : $accompanyingCourse->removePerson($person); + $errors = $this->validator->validate($accompanyingCourse); if ($errors->count() > 0) { @@ -156,6 +158,6 @@ class AccompanyingCourseController extends Controller $this->getDoctrine()->getManager()->flush(); - return new JsonResponse(); + return $this->json($participation); } } diff --git a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadAccompanyingPeriod.php b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadAccompanyingPeriod.php new file mode 100644 index 000000000..a30943bcb --- /dev/null +++ b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadAccompanyingPeriod.php @@ -0,0 +1,88 @@ +, + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +namespace Chill\PersonBundle\DataFixtures\ORM; + +use Doctrine\Common\DataFixtures\AbstractFixture; +use Doctrine\Common\DataFixtures\OrderedFixtureInterface; +use Doctrine\Persistence\ObjectManager; +use Symfony\Component\DependencyInjection\ContainerAwareInterface; + +use Chill\PersonBundle\Entity\AccompanyingPeriod; +use Chill\PersonBundle\Entity\Person; + +/** + * Description of LoadAccompanyingPeriod + * + * @author Champs-Libres Coop + */ +class LoadAccompanyingPeriod extends AbstractFixture implements OrderedFixtureInterface, ContainerAwareInterface +{ + use \Symfony\Component\DependencyInjection\ContainerAwareTrait; + + + public const ACCOMPANYING_PERIOD = 'parcours 1'; + + public function getOrder() + { + return 10004; + } + + public static $references = array(); + + public function load(ObjectManager $manager) + { + + $centerA = $this->getReference('centerA'); + $centerAId = $centerA->getId(); + + $personIds = $this->container->get('doctrine.orm.entity_manager') + ->createQueryBuilder() + ->select('p.id') + ->from('ChillPersonBundle:Person', 'p') + ->where('p.center = :centerAId') + ->orderBy('p.id', 'ASC') + ->setParameter('centerAId', $centerAId) + ->getQuery() + ->getScalarResult(); + + $openingDate = new \DateTime('2020-04-01'); + + $person1 = $manager->getRepository(Person::class)->find($personIds[0]); + $person2 = $manager->getRepository(Person::class)->find($personIds[1]); + + $socialScope = $this->getReference('scope_social'); + + $a = new AccompanyingPeriod($openingDate); + $a->addPerson($person1); + $a->addPerson($person2); + $a->addScope($socialScope); + $a->setStep(AccompanyingPeriod::STEP_CONFIRMED); + + $manager->persist($a); + + $this->addReference(self::ACCOMPANYING_PERIOD, $a); + echo "Adding one AccompanyingPeriod\n"; + + $manager->flush(); + } +} diff --git a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadAccompanyingPeriodOrigin.php b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadAccompanyingPeriodOrigin.php new file mode 100644 index 000000000..cbec9c439 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadAccompanyingPeriodOrigin.php @@ -0,0 +1,62 @@ +, + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +namespace Chill\PersonBundle\DataFixtures\ORM; + +use Doctrine\Common\DataFixtures\AbstractFixture; +use Doctrine\Common\DataFixtures\OrderedFixtureInterface; +use Doctrine\Persistence\ObjectManager; + +use Chill\PersonBundle\Entity\AccompanyingPeriod\Origin; + +/** + * Description of LoadAccompanyingPeriodOrigin + * + * @author Champs-Libres Coop + */ +class LoadAccompanyingPeriodOrigin extends AbstractFixture implements OrderedFixtureInterface +{ + + public const ACCOMPANYING_PERIOD_ORIGIN = 'accompanying_period_origin'; + + public function getOrder() + { + return 10005; + } + + private $phoneCall = ['en' => 'phone call', 'fr' => 'appel téléphonique']; + + public static $references = array(); + + public function load(ObjectManager $manager) + { + $o = new Origin(); + $o->setLabel(json_encode($this->phoneCall)); + + $manager->persist($o); + + $this->addReference(self::ACCOMPANYING_PERIOD_ORIGIN, $o); + echo "Adding one AccompanyingPeriod Origin\n"; + + $manager->flush(); + } +} diff --git a/src/Bundle/ChillPersonBundle/Resources/public/js/AccompanyingCourse/App.vue b/src/Bundle/ChillPersonBundle/Resources/public/js/AccompanyingCourse/App.vue deleted file mode 100644 index 971eca1c7..000000000 --- a/src/Bundle/ChillPersonBundle/Resources/public/js/AccompanyingCourse/App.vue +++ /dev/null @@ -1,45 +0,0 @@ - - - - - diff --git a/src/Bundle/ChillPersonBundle/Resources/public/js/AccompanyingCourse/components/AccompanyingCourse.vue b/src/Bundle/ChillPersonBundle/Resources/public/js/AccompanyingCourse/components/AccompanyingCourse.vue deleted file mode 100644 index d08798c00..000000000 --- a/src/Bundle/ChillPersonBundle/Resources/public/js/AccompanyingCourse/components/AccompanyingCourse.vue +++ /dev/null @@ -1,26 +0,0 @@ - - - diff --git a/src/Bundle/ChillPersonBundle/Resources/public/js/AccompanyingCourse/components/PersonItem.vue b/src/Bundle/ChillPersonBundle/Resources/public/js/AccompanyingCourse/components/PersonItem.vue deleted file mode 100644 index f75f0779b..000000000 --- a/src/Bundle/ChillPersonBundle/Resources/public/js/AccompanyingCourse/components/PersonItem.vue +++ /dev/null @@ -1,25 +0,0 @@ - - - diff --git a/src/Bundle/ChillPersonBundle/Resources/public/js/AccompanyingCourse/components/PersonsAssociated.vue b/src/Bundle/ChillPersonBundle/Resources/public/js/AccompanyingCourse/components/PersonsAssociated.vue deleted file mode 100644 index f4ccf6964..000000000 --- a/src/Bundle/ChillPersonBundle/Resources/public/js/AccompanyingCourse/components/PersonsAssociated.vue +++ /dev/null @@ -1,69 +0,0 @@ - - - diff --git a/src/Bundle/ChillPersonBundle/Resources/public/js/AccompanyingCourse/components/Requestor.vue b/src/Bundle/ChillPersonBundle/Resources/public/js/AccompanyingCourse/components/Requestor.vue deleted file mode 100644 index 75a95e241..000000000 --- a/src/Bundle/ChillPersonBundle/Resources/public/js/AccompanyingCourse/components/Requestor.vue +++ /dev/null @@ -1,16 +0,0 @@ - - - diff --git a/src/Bundle/ChillPersonBundle/Resources/public/js/AccompanyingCourse/index.js b/src/Bundle/ChillPersonBundle/Resources/public/js/AccompanyingCourse/index.js deleted file mode 100644 index 4335113f7..000000000 --- a/src/Bundle/ChillPersonBundle/Resources/public/js/AccompanyingCourse/index.js +++ /dev/null @@ -1,8 +0,0 @@ -import App from './App.vue'; -import { createApp } from 'vue'; - -const app = createApp({ - template: `` -}) -.component('app', App) -.mount('#accompanying-course'); diff --git a/src/Bundle/ChillPersonBundle/Resources/public/js/AccompanyingCourse/store/.keep b/src/Bundle/ChillPersonBundle/Resources/public/js/AccompanyingCourse/store/.keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/App.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/App.vue new file mode 100644 index 000000000..480b882dc --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/App.vue @@ -0,0 +1,25 @@ + + + diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/api.js b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/api.js new file mode 100644 index 000000000..0f71f7170 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/api.js @@ -0,0 +1,49 @@ +const + locale = 'fr', + format = 'json' + , accompanying_period_id = window.accompanyingCourseId //tmp +; + +/* +* Endpoint chill_person_accompanying_course_api_show +* method GET, get AccompanyingCourse Object +* +* @accompanying_period_id___ integer +* @TODO var is not used but necessary in method signature +*/ +let getAccompanyingCourse = (accompanying_period_id___) => { //tmp + const url = `/${locale}/person/api/1.0/accompanying-course/${accompanying_period_id}/show.${format}`; + return fetch(url) + .then(response => { + if (response.ok) { return response.json(); } + throw Error('Error with request resource response'); + }); +}; + +/* +* Endpoint chill_person_accompanying_course_api_add_participation, +* method POST/DELETE, add/close a participation to the accompanyingCourse +* +* @accompanying_period_id integer - id of accompanyingCourse +* @person_id integer - id of person +* @method string - POST or DELETE +*/ +let postParticipation = (accompanying_period_id, person_id, method) => { + const url = `/${locale}/person/api/1.0/accompanying-course/${accompanying_period_id}/participation.${format}` + return fetch(url, { + method: method, + headers: { + 'Content-Type': 'application/json;charset=utf-8' + }, + body: JSON.stringify({id: person_id}) + }) + .then(response => { + if (response.ok) { return response.json(); } + throw Error('Error with request resource response'); + }); +}; + +export { + getAccompanyingCourse, + postParticipation +}; diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/AccompanyingCourse.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/AccompanyingCourse.vue new file mode 100644 index 000000000..be3014ddb --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/AccompanyingCourse.vue @@ -0,0 +1,28 @@ + + + diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/PersonItem.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/PersonItem.vue new file mode 100644 index 000000000..0d81d61c4 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/PersonItem.vue @@ -0,0 +1,56 @@ + + + diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/PersonsAssociated.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/PersonsAssociated.vue new file mode 100644 index 000000000..631534fcb --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/PersonsAssociated.vue @@ -0,0 +1,66 @@ + + + diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Requestor.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Requestor.vue new file mode 100644 index 000000000..6086ab515 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Requestor.vue @@ -0,0 +1,86 @@ + + + diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/index.js b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/index.js new file mode 100644 index 000000000..66b6d6683 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/index.js @@ -0,0 +1,23 @@ +import { createApp } from 'vue' +import { _createI18n } from 'ChillMainAssets/vuejs/_js/i18n' +import { appMessages } from './js/i18n' +import { initPromise } from './store' + +import App from './App.vue'; + +initPromise.then(store => { + + //console.log('store in create_store', store); + //console.log('store accompanyingCourse', store.state.accompanyingCourse); + + const i18n = _createI18n(appMessages); + + const app = createApp({ + template: ``, + }) + .use(store) + .use(i18n) + .component('app', App) + .mount('#accompanying-course'); + +}); diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/js/i18n.js b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/js/i18n.js new file mode 100644 index 000000000..045476686 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/js/i18n.js @@ -0,0 +1,32 @@ +import { personMessages } from 'ChillPersonAssets/vuejs/_js/i18n' + +const appMessages = { + fr: { + course: { + id: "id", + title: "Parcours", + opening_date: "Date d'ouverture", + closing_date: "Date de clôture", + remark: "Commentaire", + closing_motive: "Motif de clôture", + }, + persons_associated: { + title: "Usagers concernés", + counter: "Pas d'usager | 1 usager | {count} usagers", + firstname: "Prénom", + lastname: "Nom", + startdate: "Date d'entrée", + enddate: "Date de sortie", + addPerson: "Ajouter un usager", + }, + requestor: { + title: "Demandeur", + }, + } +}; + +Object.assign(appMessages.fr, personMessages.fr); + +export { + appMessages +}; diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/store/index.js b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/store/index.js new file mode 100644 index 000000000..04785eca5 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/store/index.js @@ -0,0 +1,76 @@ +import 'es6-promise/auto'; +import { createStore } from 'vuex'; +import addPersons from './modules/addPersons' +import { getAccompanyingCourse, postParticipation } from '../api'; + +const debug = process.env.NODE_ENV !== 'production'; + +const id = window.accompanyingCourseId; //tmp + +let initPromise = getAccompanyingCourse(id) + .then(accompanying_course => new Promise((resolve, reject) => { + + const store = createStore({ + strict: debug, + modules: { + addPersons + }, + state: { + accompanyingCourse: accompanying_course, + errorMsg: [] + }, + getters: { + }, + mutations: { + removeParticipation(state, item) { + //console.log('mutation: remove item', item.id); + state.accompanyingCourse.participations = state.accompanyingCourse.participations.filter(participation => participation !== item); + }, + closeParticipation(state, { participation, payload }) { + console.log('### mutation: close item', { participation, payload }); + // trouve dans le state le payload et le supprime du state + state.accompanyingCourse.participations = state.accompanyingCourse.participations.filter(participation => participation !== payload); + // pousse la participation + state.accompanyingCourse.participations.push(participation); + }, + addParticipation(state, participation) { + //console.log('### mutation: add participation', participation); + state.accompanyingCourse.participations.push(participation); + }, + }, + actions: { + removeParticipation({ commit }, payload) { + commit('removeParticipation', payload); + }, + closeParticipation({ commit }, payload) { + //console.log('## action: fetch delete participation: payload', payload.person.id); + postParticipation(id, payload.person.id, 'DELETE') + .then(participation => new Promise((resolve, reject) => { + //console.log('payload', payload); + commit('closeParticipation', { participation, payload }); + resolve(); + })) + .catch((error) => { + state.errorMsg.push(error.message); + }); + }, + addParticipation(addPersons, payload) { + //console.log('## action: fetch post participation: payload', payload.id); + postParticipation(id, payload.id, 'POST') + .then(participation => new Promise((resolve, reject) => { + //console.log(participation, payload); + addPersons.commit('addParticipation', participation); + addPersons.commit('resetState', payload); + resolve(); + })) + .catch((error) => { + state.errorMsg.push(error.message); + }); + }, + } + }); + //console.log('store object', store.state.accompanyingCourse.id); + resolve(store); + })); + +export { initPromise }; diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/store/modules/addPersons.js b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/store/modules/addPersons.js new file mode 100644 index 000000000..e65f94fa9 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/store/modules/addPersons.js @@ -0,0 +1,76 @@ +import { searchPersons } from 'ChillPersonAssets/vuejs/_api/AddPersons' +import { postParticipation } from '../../api'; + + +// initial state +const state = { + query: "", + suggested: [], + selected: [] +} + +// getters +const getters = { + selectedAndSuggested: state => { + const uniqBy = (a, key) => [ + ...new Map( + a.map(x => [key(x), x]) + ).values() + ]; + let union = [...new Set([ + ...state.suggested.slice().reverse(), + ...state.selected.slice().reverse(), + ])]; + return uniqBy(union, k => k.id); + } +} + +// mutations +const mutations = { + setQuery(state, query) { + //console.log('q=', query); + state.query = query; + }, + loadSuggestions(state, suggested) { + state.suggested = suggested; + }, + updateSelected(state, value) { + state.selected = value; + }, + resetState(state, selected) { + //console.log('avant', state.selected); + state.selected = state.selected.filter(value => value !== selected); + //console.log('après', state.selected); + state.query = ""; + state.suggested = []; + } +} + +// actions +const actions = { + setQuery({ commit }, payload) { + //console.log('## action: setquery: payload', payload); + commit('setQuery', payload.query); + if (payload.query.length >= 3) { + searchPersons(payload.query) + .then(suggested => new Promise((resolve, reject) => { + commit('loadSuggestions', suggested.results); + resolve(); + })); + } else { + commit('loadSuggestions', []); + } + }, + updateSelected({ commit }, payload) { + //console.log('## action: update selected values: payload', payload); + commit('updateSelected', payload); + } +} + +export default { + //namespaced: true, + state, + getters, + actions, + mutations +} diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_api/AddPersons.js b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_api/AddPersons.js new file mode 100644 index 000000000..d5ac91ac5 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_api/AddPersons.js @@ -0,0 +1,20 @@ +const + locale = 'fr', + format = 'json' +; + +/* +* Endpoint chill_person_search, method GET, get a list of persons +* +* @query string - the query to search for +*/ +let searchPersons = (query) => { + let url = `/${locale}/search.${format}?name=person_regular&q=${query}`; + return fetch(url) + .then(response => { + if (response.ok) { return response.json(); } + throw Error('Error with request resource response'); + }); +}; + +export { searchPersons }; diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/AddPersons.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/AddPersons.vue new file mode 100644 index 000000000..53600da1c --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/AddPersons.vue @@ -0,0 +1,132 @@ + + + diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/PersonSuggestion.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/PersonSuggestion.vue new file mode 100644 index 000000000..f2561b0af --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/PersonSuggestion.vue @@ -0,0 +1,53 @@ + + + diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_js/i18n.js b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_js/i18n.js new file mode 100644 index 000000000..34044441e --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_js/i18n.js @@ -0,0 +1,21 @@ +const personMessages = { + fr: { + add_persons: { + search_add_others_persons: "Rechercher et ajouter d'autres usagers", + title: "Ajouter des usagers", + suggested_counter: "Pas de résultats | 1 résultat | {count} résultats", + selected_counter: " 1 sélectionné | {count} sélectionnés", + search_some_persons: "Rechercher des personnes..", + }, + item: { + type_person: "Usager", + type_tms: "TMS", + type_3rdparty: "Tiers", + type_menage: "Ménage" + } + } +}; + +export { + personMessages +}; diff --git a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourse/show.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourse/show.html.twig index a33b65cff..427f5f0ac 100644 --- a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourse/show.html.twig +++ b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourse/show.html.twig @@ -5,15 +5,13 @@ {% endblock %} {% block content %} -

{{ block('title') }}

-
+{% endblock %} - {{ encore_entry_script_tags('accompanying_course') }} - +{% block js %} - + {{ encore_entry_script_tags('accompanying_course') }} {% endblock %} diff --git a/src/Bundle/ChillPersonBundle/chill.webpack.config.js b/src/Bundle/ChillPersonBundle/chill.webpack.config.js index 7987ee124..53aed5d91 100644 --- a/src/Bundle/ChillPersonBundle/chill.webpack.config.js +++ b/src/Bundle/ChillPersonBundle/chill.webpack.config.js @@ -7,6 +7,6 @@ module.exports = function(encore, entries) encore.addAliases({ ChillPersonAssets: __dirname + '/Resources/public' }); - - encore.addEntry('accompanying_course', __dirname + '/Resources/public/js/AccompanyingCourse/index.js'); + + encore.addEntry('accompanying_course', __dirname + '/Resources/public/vuejs/AccompanyingCourse/index.js'); };