From ce3c0f2ab661044c91404b03cfaeb5342c778d0a Mon Sep 17 00:00:00 2001 From: VANCLOOSTER Mickael Date: Thu, 21 Jul 2022 11:36:11 +0200 Subject: [PATCH 1/2] [TASK] Add closed period on location --- README.md | 2 +- src/DependencyInjection/Configuration.php | 15 ++++++ src/Entity/ClosedPeriod.php | 53 +++++++++++++++++++ src/Entity/ClosedPeriodInterface.php | 19 +++++++ src/Entity/Location.php | 24 +++++++++ src/Entity/LocationInterface.php | 9 ++++ src/Form/Type/ClosedPeriodType.php | 41 ++++++++++++++ src/Form/Type/LocationType.php | 12 ++++- .../config/doctrine/ClosedPeriod.orm.xml | 21 ++++++++ .../config/doctrine/Location.orm.xml | 4 ++ src/Resources/public/click_n_collect.js | 38 ++++++++++++- src/Resources/translations/messages.bg.yml | 1 + src/Resources/translations/messages.en.yml | 1 + src/Resources/translations/messages.es.yml | 1 + src/Resources/translations/messages.fr.yml | 1 + src/Resources/translations/messages.pl.yml | 1 + 16 files changed, 240 insertions(+), 3 deletions(-) create mode 100644 src/Entity/ClosedPeriod.php create mode 100644 src/Entity/ClosedPeriodInterface.php create mode 100644 src/Form/Type/ClosedPeriodType.php create mode 100644 src/Resources/config/doctrine/ClosedPeriod.orm.xml diff --git a/README.md b/README.md index 34632e7..759cce8 100644 --- a/README.md +++ b/README.md @@ -161,7 +161,7 @@ Note: to test the plugin locally, see [CONTRIBUTING.md](CONTRIBUTING.md) bin/console sylius:theme:assets:install 10. Add your products and stocks or [import them](https://github.com/coopTilleuls/CoopTilleulsSyliusQuickImportPlugin) -11. Configure the pick up locations, the available time slots, and how many people you can safely serve in parallel +11. Configure the pick up locations, the available time slots, closed periods, and how many people you can safely serve in parallel 12. Create a dedicated shipping method 13. Optionally, configure an online payment method from the admin (Stripe and PayPal are supported out of the box) diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 2a4aa97..d017e6d 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -13,6 +13,8 @@ namespace CoopTilleuls\SyliusClickNCollectPlugin\DependencyInjection; +use CoopTilleuls\SyliusClickNCollectPlugin\Entity\ClosedPeriod; +use CoopTilleuls\SyliusClickNCollectPlugin\Entity\ClosedPeriodInterface; use CoopTilleuls\SyliusClickNCollectPlugin\Entity\Location; use CoopTilleuls\SyliusClickNCollectPlugin\Entity\LocationInterface; use CoopTilleuls\SyliusClickNCollectPlugin\Form\Type\LocationType; @@ -73,6 +75,19 @@ private function addResourcesSection(ArrayNodeDefinition $node): void ->end() ->end() ->end() + ->arrayNode('closedPeriod') + ->addDefaultsIfNotSet() + ->children() + ->variableNode('options')->end() + ->arrayNode('classes') + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('model')->defaultValue(ClosedPeriod::class)->cannotBeEmpty()->end() + ->scalarNode('interface')->defaultValue(ClosedPeriodInterface::class)->cannotBeEmpty()->end() + ->end() + ->end() + ->end() + ->end() ->end() ->end() ->end(); diff --git a/src/Entity/ClosedPeriod.php b/src/Entity/ClosedPeriod.php new file mode 100644 index 0000000..439f0d3 --- /dev/null +++ b/src/Entity/ClosedPeriod.php @@ -0,0 +1,53 @@ +id; + } + + public function setId(int $id): void + { + $this->id = $id; + } + + public function getStartAt(): \DateTimeInterface + { + return $this->startAt; + } + + public function setStartAt(\DateTimeInterface $startAt): void + { + $this->startAt = $startAt; + } + + public function getEndAt(): ?\DateTimeInterface + { + return $this->endAt; + } + + public function setEndAt(?\DateTimeInterface $endAt): void + { + $this->endAt = $endAt; + } + + public function getLocation(): LocationInterface + { + return $this->location; + } + + public function setLocation(LocationInterface $location): void + { + $this->location = $location; + } +} diff --git a/src/Entity/ClosedPeriodInterface.php b/src/Entity/ClosedPeriodInterface.php new file mode 100644 index 0000000..bedd6f7 --- /dev/null +++ b/src/Entity/ClosedPeriodInterface.php @@ -0,0 +1,19 @@ +createdAt = new \DateTimeImmutable(); $this->shippingMethods = new ArrayCollection(); + $this->closedPeriods = new ArrayCollection(); } public function getId() @@ -206,4 +212,22 @@ public function removeShippingMethod(ClickNCollectShippingMethodInterface $shipp $this->shippingMethods->removeElement($shippingMethod); $shippingMethod->getLocations()->removeElement($this); } + + public function getClosedPeriods(): Collection + { + return $this->closedPeriods; + } + + public function addClosedPeriod(ClosedPeriodInterface $closedPeriod): void + { + if (!$this->closedPeriods->contains($closedPeriod)) { + $this->closedPeriods->add($closedPeriod); + $closedPeriod->setLocation($this); + } + } + + public function removeClosedPeriod(ClosedPeriodInterface $closedPeriod): void + { + $this->closedPeriods->removeElement($closedPeriod); + } } diff --git a/src/Entity/LocationInterface.php b/src/Entity/LocationInterface.php index f9e9d77..dbbe14b 100644 --- a/src/Entity/LocationInterface.php +++ b/src/Entity/LocationInterface.php @@ -99,4 +99,13 @@ public function getShippingMethods(): Collection; public function addShippingMethod(ClickNCollectShippingMethodInterface $shippingMethod): void; public function removeShippingMethod(ClickNCollectShippingMethodInterface $shippingMethod): void; + + /** + * @return ClosedPeriodInterface[]|Collection + */ + public function getClosedPeriods(): Collection; + + public function addClosedPeriod(ClosedPeriodInterface $closedPeriod): void; + + public function removeClosedPeriod(ClosedPeriodInterface $closedPeriod): void; } diff --git a/src/Form/Type/ClosedPeriodType.php b/src/Form/Type/ClosedPeriodType.php new file mode 100644 index 0000000..519a413 --- /dev/null +++ b/src/Form/Type/ClosedPeriodType.php @@ -0,0 +1,41 @@ +add('startAt', DateType::class, [ + 'label' => 'sylius.ui.start_date', + 'widget' => 'single_text', + 'empty_data' => null, + 'constraints' => [ + new NotBlank(['groups' => ['sylius']]), + ] + ]) + ->add('endAt', DateType::class, [ + 'required' => false, + 'label' => 'sylius.ui.end_date', + 'widget' => 'single_text', + ]) + ; + } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults([ + 'data_class' => ClosedPeriod::class, + ]); + } +} diff --git a/src/Form/Type/LocationType.php b/src/Form/Type/LocationType.php index fb7e7b0..c6acb36 100644 --- a/src/Form/Type/LocationType.php +++ b/src/Form/Type/LocationType.php @@ -17,6 +17,7 @@ use Sylius\Bundle\ResourceBundle\Form\EventSubscriber\AddCodeFormSubscriber; use Sylius\Bundle\ResourceBundle\Form\Type\AbstractResourceType; use Symfony\Component\Form\Extension\Core\Type\CheckboxType; +use Symfony\Component\Form\Extension\Core\Type\CollectionType; use Symfony\Component\Form\Extension\Core\Type\IntegerType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; @@ -38,6 +39,14 @@ public function buildForm(FormBuilderInterface $builder, array $options): void 'empty_data' => '', 'label' => 'coop_tilleuls_click_n_collect.form.location.rrule', ]) + ->add('closedPeriods', CollectionType::class, [ + 'required' => false, + 'entry_type' => ClosedPeriodType::class, + 'allow_add' => true, + 'allow_delete' => true, + 'by_reference' => false, + 'label' => 'coop_tilleuls_click_n_collect.form.location.closed_periods', + ]) ->add('orderPreparationDelay', IntegerType::class, [ 'attr' => ['min' => 0], 'label' => 'coop_tilleuls_click_n_collect.form.location.order_preparation_delay', @@ -78,6 +87,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void ->add('enabled', CheckboxType::class, [ 'required' => false, 'label' => 'coop_tilleuls_click_n_collect.form.location.enabled', - ]); + ]) + ; } } diff --git a/src/Resources/config/doctrine/ClosedPeriod.orm.xml b/src/Resources/config/doctrine/ClosedPeriod.orm.xml new file mode 100644 index 0000000..ef30887 --- /dev/null +++ b/src/Resources/config/doctrine/ClosedPeriod.orm.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/Resources/config/doctrine/Location.orm.xml b/src/Resources/config/doctrine/Location.orm.xml index 3c18a3f..dc52ead 100644 --- a/src/Resources/config/doctrine/Location.orm.xml +++ b/src/Resources/config/doctrine/Location.orm.xml @@ -35,6 +35,10 @@ + + + + diff --git a/src/Resources/public/click_n_collect.js b/src/Resources/public/click_n_collect.js index debb1dc..721eb2e 100644 --- a/src/Resources/public/click_n_collect.js +++ b/src/Resources/public/click_n_collect.js @@ -3,6 +3,8 @@ $(function () { var config = JSON.parse($('#calendar_config').text()); var locale = config.locale.includes('_') ? config.locale.split('_')[0] : config.locale; + // eslint-disable-next-line prefer-destructuring + var excludeDays = []; $('input.click_n_collect_location').each(function () { var n = $(this).attr('id').match(/sylius_checkout_select_shipping_shipments_([0-9]+)_location/)[1]; @@ -25,6 +27,10 @@ $(function () { }, eventColor: config.unselectedBackgroundColor, eventRender: function (info) { + var eventStartString = info.event.start.toISOString().substring(0, 10); + if (excludeDays && $.inArray(eventStartString, excludeDays) > -1) { + $(info.el).hide() + } if (info.event.id.slice(0, 19) !== $collectionTime.val().slice(0, 19)) return; selectEvent(info.el); }, @@ -88,12 +94,42 @@ $(function () { if (currentValue) $locations.val(currentValue); else currentValue = $locations.val(); + //get good location + var currentLocation = findLocationByCode(currentValue); + //check if closed periods exist and populate excludeDays + if (currentLocation.closedPeriods && currentLocation.closedPeriods.length > 0) { + currentLocation.closedPeriods.forEach(function (period) { + var start = new Date(period.startAt.substring(0, 10)); + if (period.endAt) { + var end = new Date(period.endAt.substring(0, 10)); + var rangeDates = getDatesInRange(start, end); + for (var i = 0; i < rangeDates.length; i++) { + excludeDays.push(rangeDates[i].toISOString().substring(0, 10)); + } + } else { + var startString = start.toISOString().substring(0, 10); + excludeDays.push(startString); + } + }); + } + $locations.show(); populateCalendar(currentValue); - populateLocationAddress(findLocationByCode(currentValue)); + populateLocationAddress(currentLocation); }); } + function getDatesInRange(startDate, endDate) { + const date = new Date(startDate.getTime()); + const dates = []; + while (date <= endDate) { + dates.push(new Date(date)); + date.setDate(date.getDate() + 1); + } + + return dates; + } + function populateLocationAddress(location) { $locationAddress.text((location.street || '') + ' ' + (location.postcode || '') + ' ' + (location.city || '') + ' ' + (location.provinceCode || '') + ' ' + (location.provinceName || '') + ' ' + (location.countryCode || '')); $locationAddress.show(); diff --git a/src/Resources/translations/messages.bg.yml b/src/Resources/translations/messages.bg.yml index c2eb7ab..22ee017 100644 --- a/src/Resources/translations/messages.bg.yml +++ b/src/Resources/translations/messages.bg.yml @@ -46,6 +46,7 @@ coop_tilleuls_click_n_collect: province_code: Код на област province_name: име на област enabled: Включено + closed_periods: Затворени периоди shipping_method: click_n_collect: Click 'N' Collect locations: Локации за Click 'N' Collect diff --git a/src/Resources/translations/messages.en.yml b/src/Resources/translations/messages.en.yml index dac8e6a..70b8400 100644 --- a/src/Resources/translations/messages.en.yml +++ b/src/Resources/translations/messages.en.yml @@ -50,6 +50,7 @@ coop_tilleuls_click_n_collect: province_code: Province code province_name: Province name enabled: Enabled + closed_periods: Closed periods shipping_method: click_n_collect: Click 'N' Collect locations: Collection locations diff --git a/src/Resources/translations/messages.es.yml b/src/Resources/translations/messages.es.yml index 571dd12..fe47cdd 100644 --- a/src/Resources/translations/messages.es.yml +++ b/src/Resources/translations/messages.es.yml @@ -50,6 +50,7 @@ coop_tilleuls_click_n_collect: province_code: Código de Provincia province_name: Nombre de Provincia enabled: Habilitado + closed_periods: Periodos cerrados shipping_method: click_n_collect: Click 'N' Collect locations: Ubicaciones de recogida diff --git a/src/Resources/translations/messages.fr.yml b/src/Resources/translations/messages.fr.yml index 70c07df..1ca788a 100644 --- a/src/Resources/translations/messages.fr.yml +++ b/src/Resources/translations/messages.fr.yml @@ -50,6 +50,7 @@ coop_tilleuls_click_n_collect: province_code: Code de la province province_name: Nom de la province enabled: Activé + closed_periods: Périodes de fermeture shipping_method: click_n_collect: Click 'N' Collect locations: Lieux diff --git a/src/Resources/translations/messages.pl.yml b/src/Resources/translations/messages.pl.yml index 9e4ef57..3f2d829 100644 --- a/src/Resources/translations/messages.pl.yml +++ b/src/Resources/translations/messages.pl.yml @@ -46,6 +46,7 @@ coop_tilleuls_click_n_collect: province_code: Kod województwa province_name: Nazwa województwa enabled: Włączone + closed_periods: Zamknięte okresy shipping_method: click_n_collect: Click 'N' Collect locations: Lokalizacje odbioru From aaa92e0d2a84ce9c1396f1bd120eeeeade341f4b Mon Sep 17 00:00:00 2001 From: VANCLOOSTER Mickael Date: Thu, 21 Jul 2022 11:58:53 +0200 Subject: [PATCH 2/2] [TASK] Manage default view for full calendar --- README.md | 15 +++++++++++++++ src/Resources/public/click_n_collect.js | 10 ++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 759cce8..6af0b84 100644 --- a/README.md +++ b/README.md @@ -164,6 +164,21 @@ Note: to test the plugin locally, see [CONTRIBUTING.md](CONTRIBUTING.md) 11. Configure the pick up locations, the available time slots, closed periods, and how many people you can safely serve in parallel 12. Create a dedicated shipping method 13. Optionally, configure an online payment method from the admin (Stripe and PayPal are supported out of the box) +14. Manage range days in full calendar view. Edit templates/bundles/SyliusShopBundle/Checkout/SelectShipping/_shipment.html.twig and change config json + ```javascript + + ``` +By default, defaultView is timeGridFourDay and minDay is 4. **Export data** diff --git a/src/Resources/public/click_n_collect.js b/src/Resources/public/click_n_collect.js index 721eb2e..1ecba9d 100644 --- a/src/Resources/public/click_n_collect.js +++ b/src/Resources/public/click_n_collect.js @@ -5,6 +5,8 @@ $(function () { var locale = config.locale.includes('_') ? config.locale.split('_')[0] : config.locale; // eslint-disable-next-line prefer-destructuring var excludeDays = []; + var defaultView = config.defaultView ?? 'timeGridFourDay'; + var minDay = config.minDay ?? 4; $('input.click_n_collect_location').each(function () { var n = $(this).attr('id').match(/sylius_checkout_select_shipping_shipments_([0-9]+)_location/)[1]; @@ -17,12 +19,12 @@ $(function () { var calendar = new FullCalendar.Calendar($calendar[0], { nowIndicator: true, plugins: [ 'timeGrid' ], - defaultView: 'timeGridFourDay', + defaultView: defaultView, views: { - timeGridFourDay: { + [defaultView]: { type: 'timeGrid', - duration: { days: 4 }, - buttonText: '4 day' + duration: { days: minDay }, + buttonText: minDay+' day' } }, eventColor: config.unselectedBackgroundColor,