diff --git a/README.md b/README.md
index 34632e7..6af0b84 100644
--- a/README.md
+++ b/README.md
@@ -161,9 +161,24 @@ 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)
+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/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..1ecba9d 100644
--- a/src/Resources/public/click_n_collect.js
+++ b/src/Resources/public/click_n_collect.js
@@ -3,6 +3,10 @@
$(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 = [];
+ 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];
@@ -15,16 +19,20 @@ $(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,
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 +96,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