Compare commits

..
9 Commits
18 changed files with 240 additions and 29 deletions
+41
View File
@@ -4,6 +4,47 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
## [0.26.3] - 2026-09-28
### Added
- `Modules\Core\Localization\Database\Seeders\ValidationTranslationsSeeder` — moved in from
3dealer's own `database/seeders/`, alongside the existing
`Modules\Core\Checkout\Database\Seeders\CheckoutTranslationsSeeder`, so the `validation` and
`checkout` translation groups are seeded from core rather than duplicated per consuming app.
Same idempotent per-key upsert as `lunar:install`'s own seeding — a key already present (or
since edited via the Filament Language Lines UI) is left untouched. Both are run explicitly
via `php artisan db:seed --class=...`, wired into 3dealer's entrypoint right after
`lunar:install`.
- `storefront.auth.captcha_failed` — was referenced by `HCaptcha`, `LoginController`, and
`ContactRequest` but never seeded in `StorefrontLabels`, so it silently fell back to the raw
key. Re-running `lunar:install` now fills it in for any existing store.
## [0.26.2] - 2026-09-28
### Changed
- Checkout line-item custom fields (`checkout/partials/line-custom-fields.blade.php`):
non-file fields now render inline as a single muted `Label: value` line instead of a
separate `<dt>`/`<dd>` pair. File fields keep the stacked label/link layout, with a
colon after the label and a small top margin on the value.
### Fixed
- Wishlist routes are now registered inside the `web` middleware group
(`WishlistServiceProvider`). Before, `loadRoutesFrom()` loaded them with no middleware,
so they had no session, cookies, CSRF protection or authenticated user. That broke
anything that depends on the current guest or logged-in user.
## [0.26.1] - 2026-09-28
### Added
- `Modules\Core\Order\Support\OrderReferenceDisplay` — a human-facing form of
`Order::reference` for emails and storefront views. `Lunar\Base\OrderReferenceGenerator`
zero-pads the order's own id out to a fixed length (8 characters by default), so a shop's
first real orders read as `#00000001` rather than `#1`. This strips leading zeros until the
first non-zero digit (falling back to `0` if none remain), purely for display — the raw,
padded `reference` is untouched everywhere else (DB lookups, the order-status API, staff
search, GDPR exports). Wired into the checkout confirmation page and all customer-facing
order notification emails.
## [0.26.0] - 2026-09-28 ## [0.26.0] - 2026-09-28
### Added ### Added
+1 -1
View File
@@ -2,7 +2,7 @@
"name": "boboko/core", "name": "boboko/core",
"description": "Core module — authentication and shared panel behaviour", "description": "Core module — authentication and shared panel behaviour",
"type": "library", "type": "library",
"version": "0.26.0", "version": "0.26.3",
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"Modules\\Core\\": "src/" "Modules\\Core\\": "src/"
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@boboko/core", "name": "@boboko/core",
"version": "0.26.0", "version": "0.26.3",
"private": true, "private": true,
"type": "module", "type": "module",
"description": "Portable Stimulus controllers and styles for boboko-core's cart + checkout module. Installed as a real npm dependency (file:../boboko-core in dev, a tagged git install in prod) so a consuming app's `npm install` resolves this package's own dependencies (leaflet, @hotwired/stimulus) transitively, the same way `composer update boboko/*` does for PHP. See CONTRIBUTE.md's \"JS/CSS: a real npm package\" section.", "description": "Portable Stimulus controllers and styles for boboko-core's cart + checkout module. Installed as a real npm dependency (file:../boboko-core in dev, a tagged git install in prod) so a consuming app's `npm install` resolves this package's own dependencies (leaflet, @hotwired/stimulus) transitively, the same way `composer update boboko/*` does for PHP. See CONTRIBUTE.md's \"JS/CSS: a real npm package\" section.",
+2 -2
View File
@@ -223,13 +223,13 @@ a.bbk-cart-item-title:hover { text-decoration: underline; }
font-size: 0.8125rem; font-size: 0.8125rem;
} }
.bbk-line-field span,
.bbk-line-field dt { .bbk-line-field dt {
color: var(--bbk-color-muted); color: var(--bbk-color-muted);
} }
.bbk-line-field dd { .bbk-line-field dd {
margin: 0; margin: 3px 0 0 0;
white-space: pre-line;
overflow-wrap: anywhere; overflow-wrap: anywhere;
} }
@@ -14,7 +14,7 @@
<dl class="bbk-confirmation-meta"> <dl class="bbk-confirmation-meta">
<div class="bbk-confirmation-meta-row"> <div class="bbk-confirmation-meta-row">
<dt>{{ __('checkout.page.confirmation_order_number') }}</dt> <dt>{{ __('checkout.page.confirmation_order_number') }}</dt>
<dd>{{ $order->reference }}</dd> <dd>{{ \Modules\Core\Order\Support\OrderReferenceDisplay::resolve($order) }}</dd>
</div> </div>
@if ($order->billingAddress?->contact_email) @if ($order->billingAddress?->contact_email)
@@ -19,9 +19,9 @@
<dl class="bbk-line-fields"> <dl class="bbk-line-fields">
@foreach ($fields as $field) @foreach ($fields as $field)
<div class="bbk-line-field"> <div class="bbk-line-field">
<dt>{{ $field['label'] }}</dt>
<dd>
@if ($field['type'] === 'file') @if ($field['type'] === 'file')
<dt>{{ $field['label'] }}:</dt>
<dd>
@php @php
$file = \Modules\Core\File\Models\File::find($field['file_id'] ?? null); $file = \Modules\Core\File\Models\File::find($field['file_id'] ?? null);
@endphp @endphp
@@ -39,11 +39,12 @@
@endif @endif
<span>{{ $file->original_name }}</span> <span>{{ $file->original_name }}</span>
</a> </a>
@endif
@else
{{ $field['value'] }}
@endif @endif
</dd> </dd>
@else
<span>{{ $field['label'] }}: {{ $field['value'] }}</span>
@endif
</div> </div>
@endforeach @endforeach
</dl> </dl>
@@ -0,0 +1,114 @@
<?php
namespace Modules\Core\Localization\Database\Seeders;
use Illuminate\Database\Seeder;
use Modules\Core\Localization\Services\TranslationService;
use Spatie\TranslationLoader\LanguageLine;
/**
* Default `validation` translation lines — Laravel's own error-message group
* (`validation.required`, `validation.email`, `validation.attributes.*`, …),
* resolved by every `Validator::make()`/`$request->validate()` call in a
* consuming app (checkout addresses, cart, product reviews, stock checks).
*
* Spatie's DB loader (spatie/laravel-translation-loader, wired in
* LocalizationServiceProvider) merges this group over Laravel's file-based
* validation.php — without this, Greek requests fall back to Laravel's
* untranslated English defaults. Only the rule keys and field attributes
* actually in use are seeded; add more as new rules/fields show up.
*
* Additive and idempotent: a key that already exists is left untouched, so
* anything edited in the Filament Language Lines UI wins on a re-run. Runs
* explicitly — `php artisan db:seed --class="Modules\Core\Localization\
* Database\Seeders\ValidationTranslationsSeeder"` — it is not wired into any
* app's own DatabaseSeeder.
*
* Greek copy uses the project's informal register (εσύ/σου).
*/
class ValidationTranslationsSeeder extends Seeder
{
public function run(): void
{
$translations = app(TranslationService::class);
foreach ($this->lines() as $key => [$en, $el]) {
$exists = LanguageLine::query()
->where('group', 'validation')
->where('key', $key)
->exists();
if ($exists) {
$this->command?->warn("validation.{$key} already exists — skipped");
continue;
}
$translations->create('validation', $key, ['en' => $en, 'el' => $el]);
$this->command?->info("validation.{$key} added");
}
}
/**
* key => [English, Greek].
*
* @return array<string, array{0: string, 1: string}>
*/
private function lines(): array
{
return [
// ── Rule messages ─────────────────────────────────────────────
'required' => ['The :attribute field is required.', 'Το πεδίο :attribute είναι υποχρεωτικό.'],
'email' => ['The :attribute field must be a valid email address.', 'Το πεδίο :attribute πρέπει να είναι έγκυρη διεύθυνση email.'],
'string' => ['The :attribute field must be a string.', 'Το πεδίο :attribute πρέπει να είναι κείμενο.'],
'integer' => ['The :attribute field must be an integer.', 'Το πεδίο :attribute πρέπει να είναι ακέραιος αριθμός.'],
'boolean' => ['The :attribute field must be true or false.', 'Το πεδίο :attribute πρέπει να είναι true ή false.'],
'min.numeric' => ['The :attribute field must be at least :min.', 'Το πεδίο :attribute πρέπει να είναι τουλάχιστον :min.'],
'max.string' => ['The :attribute field must not be greater than :max characters.', 'Το πεδίο :attribute δεν πρέπει να ξεπερνά τους :max χαρακτήρες.'],
'between.numeric' => ['The :attribute field must be between :min and :max.', 'Το πεδίο :attribute πρέπει να είναι μεταξύ :min και :max.'],
'exists' => ['The selected :attribute is invalid.', 'Η επιλεγμένη τιμή για το πεδίο :attribute δεν είναι έγκυρη.'],
// Product custom-field photo uploads (CustomFieldUploadController, CartController).
'file' => ['The :attribute field must be a file.', 'Το πεδίο :attribute πρέπει να είναι αρχείο.'],
'mimes' => ['The :attribute field must be a file of type: :values.', 'Το πεδίο :attribute πρέπει να είναι αρχείο τύπου: :values.'],
'max.file' => ['The :attribute field must not be greater than :max kilobytes.', 'Το αρχείο στο πεδίο :attribute δεν πρέπει να ξεπερνά τα :max kilobytes.'],
'uploaded' => ['The :attribute failed to upload.', 'Η μεταφόρτωση στο πεδίο :attribute απέτυχε.'],
// ── Field names (checkout: billing/shipping address) ──────────
'attributes.contact_email' => ['email', 'email'],
'attributes.billing_first_name' => ['first name', 'όνομα'],
'attributes.billing_last_name' => ['last name', 'επώνυμο'],
'attributes.billing_company_name' => ['company name', 'επωνυμία εταιρείας'],
'attributes.billing_tax_identifier' => ['tax ID', 'ΑΦΜ'],
'attributes.billing_line_one' => ['address', 'διεύθυνση'],
'attributes.billing_line_two' => ['address line 2', 'διεύθυνση (γραμμή 2)'],
'attributes.billing_city' => ['city', 'πόλη'],
'attributes.billing_state' => ['region', 'νομό / περιοχή'],
'attributes.billing_postcode' => ['postcode', 'ταχυδρομικό κώδικα'],
'attributes.billing_country_id' => ['country', 'χώρα'],
'attributes.billing_contact_phone' => ['phone', 'τηλέφωνο'],
'attributes.shipping_first_name' => ['first name', 'όνομα'],
'attributes.shipping_last_name' => ['last name', 'επώνυμο'],
'attributes.shipping_company_name' => ['company name', 'επωνυμία εταιρείας'],
'attributes.shipping_line_one' => ['address', 'διεύθυνση'],
'attributes.shipping_line_two' => ['address line 2', 'διεύθυνση (γραμμή 2)'],
'attributes.shipping_city' => ['city', 'πόλη'],
'attributes.shipping_state' => ['region', 'νομό / περιοχή'],
'attributes.shipping_postcode' => ['postcode', 'ταχυδρομικό κώδικα'],
'attributes.shipping_country_id' => ['country', 'χώρα'],
'attributes.shipping_contact_phone' => ['phone', 'τηλέφωνο'],
'attributes.shipping_delivery_instructions' => ['delivery notes', 'σχόλια για την παράδοση'],
// ── Field names (cart) ─────────────────────────────────────────
'attributes.purchasable_id' => ['product', 'προϊόν'],
'attributes.quantity' => ['quantity', 'ποσότητα'],
'attributes.code' => ['coupon code', 'κωδικό κουπονιού'],
// ── Field names (product reviews / stock check) ────────────────
'attributes.variant' => ['variant', 'παραλλαγή'],
'attributes.rating' => ['rating', 'βαθμολογία'],
'attributes.content' => ['review text', 'κείμενο κριτικής'],
'attributes.name' => ['name', 'όνομα'],
'attributes.email' => ['email', 'email'],
];
}
}
@@ -108,6 +108,10 @@ class StorefrontLabels
'en' => 'Too many attempts. Please wait a few minutes and try again.', 'en' => 'Too many attempts. Please wait a few minutes and try again.',
'el' => 'Πολλές προσπάθειες. Περίμενε λίγα λεπτά και ξαναδοκίμασε.', 'el' => 'Πολλές προσπάθειες. Περίμενε λίγα λεπτά και ξαναδοκίμασε.',
], ],
'auth.captcha_failed' => [
'en' => 'Please complete the captcha and try again.',
'el' => 'Παρακαλούμε ολοκλήρωσε το captcha και ξαναδοκίμασε.',
],
// Account profile page (account/show.blade.php) // Account profile page (account/show.blade.php)
'account.nav_profile' => ['en' => 'Profile', 'el' => 'Προφίλ'], 'account.nav_profile' => ['en' => 'Profile', 'el' => 'Προφίλ'],
@@ -7,6 +7,7 @@ use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Facades\Notification as NotificationFacade; use Illuminate\Support\Facades\Notification as NotificationFacade;
use Modules\Core\Notification\BaseNotification; use Modules\Core\Notification\BaseNotification;
use Modules\Core\Order\Events\OrderCaptured; use Modules\Core\Order\Events\OrderCaptured;
use Modules\Core\Order\Support\OrderReferenceDisplay;
class OrderCapturedNotification extends BaseNotification class OrderCapturedNotification extends BaseNotification
{ {
@@ -40,10 +41,12 @@ class OrderCapturedNotification extends BaseNotification
{ {
$order = $this->event->order; $order = $this->event->order;
$reference = OrderReferenceDisplay::resolve($order);
return (new MailMessage) return (new MailMessage)
->subject(__('Payment captured for your order :reference', ['reference' => $order->reference])) ->subject(__('Payment captured for your order :reference', ['reference' => $reference]))
->view('core::order.notifications.captured', [ ->view('core::order.notifications.captured', [
'reference' => $order->reference, 'reference' => $reference,
'amount' => $this->event->transaction->amount->formatted, 'amount' => $this->event->transaction->amount->formatted,
]); ]);
} }
@@ -7,6 +7,7 @@ use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Facades\Notification as NotificationFacade; use Illuminate\Support\Facades\Notification as NotificationFacade;
use Modules\Core\Notification\BaseNotification; use Modules\Core\Notification\BaseNotification;
use Modules\Core\Order\Events\OrderCompleted; use Modules\Core\Order\Events\OrderCompleted;
use Modules\Core\Order\Support\OrderReferenceDisplay;
class OrderCompletedNotification extends BaseNotification class OrderCompletedNotification extends BaseNotification
{ {
@@ -40,10 +41,12 @@ class OrderCompletedNotification extends BaseNotification
{ {
$order = $this->event->order; $order = $this->event->order;
$reference = OrderReferenceDisplay::resolve($order);
return (new MailMessage) return (new MailMessage)
->subject(__('Your order :reference is complete', ['reference' => $order->reference])) ->subject(__('Your order :reference is complete', ['reference' => $reference]))
->view('core::order.notifications.completed', [ ->view('core::order.notifications.completed', [
'reference' => $order->reference, 'reference' => $reference,
]); ]);
} }
} }
@@ -7,6 +7,7 @@ use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Facades\Notification as NotificationFacade; use Illuminate\Support\Facades\Notification as NotificationFacade;
use Modules\Core\Notification\BaseNotification; use Modules\Core\Notification\BaseNotification;
use Modules\Core\Order\Events\OrderDelivered; use Modules\Core\Order\Events\OrderDelivered;
use Modules\Core\Order\Support\OrderReferenceDisplay;
class OrderDeliveredNotification extends BaseNotification class OrderDeliveredNotification extends BaseNotification
{ {
@@ -40,10 +41,12 @@ class OrderDeliveredNotification extends BaseNotification
{ {
$order = $this->event->order; $order = $this->event->order;
$reference = OrderReferenceDisplay::resolve($order);
return (new MailMessage) return (new MailMessage)
->subject(__('Your order :reference has been delivered', ['reference' => $order->reference])) ->subject(__('Your order :reference has been delivered', ['reference' => $reference]))
->view('core::order.notifications.delivered', [ ->view('core::order.notifications.delivered', [
'reference' => $order->reference, 'reference' => $reference,
]); ]);
} }
} }
@@ -7,6 +7,7 @@ use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Facades\Notification as NotificationFacade; use Illuminate\Support\Facades\Notification as NotificationFacade;
use Modules\Core\Notification\BaseNotification; use Modules\Core\Notification\BaseNotification;
use Modules\Core\Order\Events\OrderDispatched; use Modules\Core\Order\Events\OrderDispatched;
use Modules\Core\Order\Support\OrderReferenceDisplay;
/** /**
* Fills a real, previously-unfilled customer-communication gap — before * Fills a real, previously-unfilled customer-communication gap — before
@@ -45,10 +46,12 @@ class OrderDispatchedNotification extends BaseNotification
{ {
$order = $this->event->order; $order = $this->event->order;
$reference = OrderReferenceDisplay::resolve($order);
return (new MailMessage) return (new MailMessage)
->subject(__('Your order :reference is on its way', ['reference' => $order->reference])) ->subject(__('Your order :reference is on its way', ['reference' => $reference]))
->view('core::order.notifications.dispatched', [ ->view('core::order.notifications.dispatched', [
'reference' => $order->reference, 'reference' => $reference,
]); ]);
} }
} }
@@ -7,6 +7,7 @@ use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Facades\Notification as NotificationFacade; use Illuminate\Support\Facades\Notification as NotificationFacade;
use Modules\Core\Notification\BaseNotification; use Modules\Core\Notification\BaseNotification;
use Modules\Core\Order\Events\OrderReadyForPickup; use Modules\Core\Order\Events\OrderReadyForPickup;
use Modules\Core\Order\Support\OrderReferenceDisplay;
/** /**
* "Your order is ready to collect" — listens to the specific * "Your order is ready to collect" — listens to the specific
@@ -50,10 +51,12 @@ class OrderPickupReadyNotification extends BaseNotification
{ {
$order = $this->event->order; $order = $this->event->order;
$reference = OrderReferenceDisplay::resolve($order);
return (new MailMessage) return (new MailMessage)
->subject(__('Your order :reference is ready for pickup', ['reference' => $order->reference])) ->subject(__('Your order :reference is ready for pickup', ['reference' => $reference]))
->view('core::order.notifications.pickup-ready', [ ->view('core::order.notifications.pickup-ready', [
'reference' => $order->reference, 'reference' => $reference,
]); ]);
} }
} }
@@ -7,6 +7,7 @@ use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Facades\Notification as NotificationFacade; use Illuminate\Support\Facades\Notification as NotificationFacade;
use Modules\Core\Checkout\Events\OrderPlaced; use Modules\Core\Checkout\Events\OrderPlaced;
use Modules\Core\Notification\BaseNotification; use Modules\Core\Notification\BaseNotification;
use Modules\Core\Order\Support\OrderReferenceDisplay;
/** /**
* The order confirmation email — fires once, for every capture_mode and * The order confirmation email — fires once, for every capture_mode and
@@ -51,10 +52,12 @@ class OrderPlacedNotification extends BaseNotification
{ {
$order = $this->event->order; $order = $this->event->order;
$reference = OrderReferenceDisplay::resolve($order);
return (new MailMessage) return (new MailMessage)
->subject(__('Your order :reference is confirmed', ['reference' => $order->reference])) ->subject(__('Your order :reference is confirmed', ['reference' => $reference]))
->view('core::order.notifications.placed', [ ->view('core::order.notifications.placed', [
'reference' => $order->reference, 'reference' => $reference,
'total' => $order->total->formatted, 'total' => $order->total->formatted,
'lines' => $order->lines, 'lines' => $order->lines,
]); ]);
@@ -7,6 +7,7 @@ use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Facades\Notification as NotificationFacade; use Illuminate\Support\Facades\Notification as NotificationFacade;
use Modules\Core\Notification\BaseNotification; use Modules\Core\Notification\BaseNotification;
use Modules\Core\Order\Events\OrderRefunded; use Modules\Core\Order\Events\OrderRefunded;
use Modules\Core\Order\Support\OrderReferenceDisplay;
class OrderRefundedNotification extends BaseNotification class OrderRefundedNotification extends BaseNotification
{ {
@@ -40,10 +41,12 @@ class OrderRefundedNotification extends BaseNotification
{ {
$order = $this->event->order; $order = $this->event->order;
$reference = OrderReferenceDisplay::resolve($order);
return (new MailMessage) return (new MailMessage)
->subject(__('A refund has been issued for your order :reference', ['reference' => $order->reference])) ->subject(__('A refund has been issued for your order :reference', ['reference' => $reference]))
->view('core::order.notifications.refunded', [ ->view('core::order.notifications.refunded', [
'reference' => $order->reference, 'reference' => $reference,
'amount' => $this->event->transaction->amount->formatted, 'amount' => $this->event->transaction->amount->formatted,
]); ]);
} }
@@ -7,6 +7,7 @@ use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Facades\Notification as NotificationFacade; use Illuminate\Support\Facades\Notification as NotificationFacade;
use Modules\Core\Notification\BaseNotification; use Modules\Core\Notification\BaseNotification;
use Modules\Core\Order\Events\OrderStatusUpdated; use Modules\Core\Order\Events\OrderStatusUpdated;
use Modules\Core\Order\Support\OrderReferenceDisplay;
class OrderStatusUpdatedNotification extends BaseNotification class OrderStatusUpdatedNotification extends BaseNotification
{ {
@@ -52,10 +53,12 @@ class OrderStatusUpdatedNotification extends BaseNotification
{ {
$order = $this->event->order; $order = $this->event->order;
$reference = OrderReferenceDisplay::resolve($order);
return (new MailMessage) return (new MailMessage)
->subject(__('Your order :reference has been updated', ['reference' => $order->reference])) ->subject(__('Your order :reference has been updated', ['reference' => $reference]))
->view('core::order.notifications.status-updated', [ ->view('core::order.notifications.status-updated', [
'reference' => $order->reference, 'reference' => $reference,
'statusLabel' => config("lunar.orders.statuses.{$order->status}.label", $order->status), 'statusLabel' => config("lunar.orders.statuses.{$order->status}.label", $order->status),
]); ]);
} }
@@ -0,0 +1,26 @@
<?php
namespace Modules\Core\Order\Support;
use Lunar\Models\Order;
/**
* A shorter, human-facing form of Order::reference for emails/views —
* Lunar\Base\OrderReferenceGenerator pads the order's own id out to a fixed
* length (config('lunar.orders.reference_format'), 8 characters/'0'-padded
* by default), so a shop's first real orders read as "#00000001" rather
* than "#1". Strips leading zeros until the first non-zero digit; if
* nothing but zeros remain (or the reference is empty), shows "0".
*
* $order->reference itself is untouched anywhere else (DB lookups, the
* order-status API, staff search) — this is purely a display helper.
*/
class OrderReferenceDisplay
{
public static function resolve(Order $order): string
{
$reference = ltrim((string) $order->reference, '0');
return $reference !== '' ? $reference : '0';
}
}
+2 -1
View File
@@ -3,6 +3,7 @@
namespace Modules\Core\Providers; namespace Modules\Core\Providers;
use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
use Modules\Core\Auth\Events\UserAuthenticated; use Modules\Core\Auth\Events\UserAuthenticated;
use Modules\Core\Wishlist\Listeners\MergeGuestWishlistOnLogin; use Modules\Core\Wishlist\Listeners\MergeGuestWishlistOnLogin;
@@ -19,7 +20,7 @@ class WishlistServiceProvider extends ServiceProvider
public function boot(): void public function boot(): void
{ {
$this->loadRoutesFrom(__DIR__.'/../Wishlist/routes/web.php'); Route::middleware('web')->group(__DIR__.'/../Wishlist/routes/web.php');
Event::listen(UserAuthenticated::class, MergeGuestWishlistOnLogin::class); Event::listen(UserAuthenticated::class, MergeGuestWishlistOnLogin::class);
} }