Feature: Updating Core imports after restructure

This commit is contained in:
2026-08-27 01:21:57 +03:00
parent b3405c1b60
commit 0dcaf112be
15 changed files with 52 additions and 139 deletions
+3 -3
View File
@@ -3,8 +3,8 @@
namespace App\Http\Controllers;
use Lunar\Models\Collection;
use Modules\Core\Catalog\ProductFilters;
use Modules\Core\Catalog\ProductService;
use Modules\Core\Product\DTOs\ProductFilters;
use Modules\Core\Product\Services\ProductService;
class CategoryController extends Controller
{
@@ -18,7 +18,7 @@ public function show(string $locale, Collection $collection)
$page = (int) request('page', 1);
// Listing/filtering reads from the Meilisearch index via ProductService,
// not Eloquent — see Modules\Core\Catalog\ProductService. list() returns a
// not Eloquent — see Modules\Core\Product\Services\ProductService. list() returns a
// real LengthAwarePaginator of plain arrays (already localized/flattened),
// not Product models.
$products = $this->products->list(
+1 -1
View File
@@ -4,7 +4,7 @@
use Illuminate\Http\Response;
use Lunar\Models\Collection;
use Modules\Core\Catalog\ProductService;
use Modules\Core\Product\Services\ProductService;
class ProductController extends Controller
{
+1 -1
View File
@@ -49,7 +49,7 @@
Lunar\Models\Collection::class => Lunar\Search\CollectionIndexer::class,
Lunar\Models\Customer::class => Lunar\Search\CustomerIndexer::class,
Lunar\Models\Order::class => Lunar\Search\OrderIndexer::class,
Lunar\Models\Product::class => Modules\Core\Search\ProductIndexer::class,
Lunar\Models\Product::class => Modules\Core\Product\Services\ProductIndexer::class,
Lunar\Models\ProductOption::class => Lunar\Search\ProductOptionIndexer::class,
],
-44
View File
@@ -1,44 +0,0 @@
<?php
return [
'nav' => [
'home' => 'Αρχική',
'products' => 'Προϊόντα',
'contact' => 'Επικοινωνία',
],
'product' => [
'description' => 'Περιγραφή',
'reviews' => 'Αξιολογήσεις',
],
// Laravel pluralization: {0} zero|{1} one|[2,*] many. :count is replaced automatically.
'customer_reviews' => '{0} Καμία αξιολόγηση πελάτη|{1} :count αξιολόγηση πελάτη|[2,*] :count αξιολογήσεις πελατών',
'shop' => [
// Laravel pluralization keyed on the total result count.
'showing_results' => '{0} Δεν βρέθηκαν προϊόντα|{1} Εμφάνιση :first–:last από :total αποτέλεσμα|[2,*] Εμφάνιση :first–:last από :total αποτελέσματα',
'no_products' => 'Δεν βρέθηκαν προϊόντα σε αυτή την κατηγορία.',
'search_label' => 'Αναζήτηση προϊόντων',
'search_placeholder' => 'Αναζήτησε προϊόντα…',
'filter_price' => 'Φίλτρο τιμής',
'apply' => 'Εφαρμογή',
'availability' => 'Διαθεσιμότητα',
'in_stock_only' => 'Μόνο διαθέσιμα προϊόντα',
'sort_label' => 'Ταξινόμηση προϊόντων',
'sort_default' => 'Προεπιλεγμένη ταξινόμηση',
'sort_popularity' => 'Δημοφιλή',
'sort_price_asc' => 'Τιμή: Αύξουσα',
'sort_price_desc' => 'Τιμή: Φθίνουσα',
'sort_newest' => 'Νεότερα',
],
'pagination' => [
'nav_label' => 'Σελιδοποίηση',
'page' => 'Σελίδα :page',
'next' => 'Επόμενη σελίδα',
'previous' => 'Προηγούμενη σελίδα',
],
];
-44
View File
@@ -1,44 +0,0 @@
<?php
return [
'nav' => [
'home' => 'Home',
'products' => 'Products',
'contact' => 'Contact',
],
'product' => [
'description' => 'Description',
'reviews' => 'Reviews',
],
// Laravel pluralization: {0} zero|{1} one|[2,*] many. :count is replaced automatically.
'customer_reviews' => '{0} No customer reviews|{1} :count customer review|[2,*] :count customer reviews',
'shop' => [
// Laravel pluralization keyed on the total result count.
'showing_results' => '{0} No products found|{1} Showing :first–:last of :total result|[2,*] Showing :first–:last of :total results',
'no_products' => 'No products found in this category.',
'search_label' => 'Search products',
'search_placeholder' => 'Search products…',
'filter_price' => 'Filter by price',
'apply' => 'Apply',
'availability' => 'Availability',
'in_stock_only' => 'In-stock products only',
'sort_label' => 'Sort products',
'sort_default' => 'Default sorting',
'sort_popularity' => 'Popularity',
'sort_price_asc' => 'Price: Low to High',
'sort_price_desc' => 'Price: High to Low',
'sort_newest' => 'Newest',
],
'pagination' => [
'nav_label' => 'Pagination',
'page' => 'Page :page',
'next' => 'Next page',
'previous' => 'Previous page',
],
];
+16 -16
View File
@@ -10,14 +10,14 @@
<h1 class="font-display font-extrabold text-h1">{{ $collection->translateAttribute('name') }}</h1>
<x-breadcrumb :items="[
['label' => __('general.nav.home'), 'href' => route('home')],
['label' => __('storefront.nav.home'), 'href' => route('home')],
['label' => $collection->translateAttribute('name')],
]" />
</div>
<div class="flex items-center justify-between gap-6 flex-wrap border-b border-black pb-6 mb-10">
<p class="text-neutral-600">
{{ trans_choice('general.shop.showing_results', $products->total(), [
{{ trans_choice('storefront.shop.showing_results', $products->total(), [
'first' => $products->firstItem() ?? 0,
'last' => $products->lastItem() ?? 0,
'total' => $products->total(),
@@ -26,13 +26,13 @@
{{-- Dummy — not wired to real sorting yet --}}
<x-ui.select
:ariaLabel="__('general.shop.sort_label')"
:ariaLabel="__('storefront.shop.sort_label')"
:options="[
['value' => 'default', 'label' => __('general.shop.sort_default')],
['value' => 'popularity', 'label' => __('general.shop.sort_popularity')],
['value' => 'price-asc', 'label' => __('general.shop.sort_price_asc')],
['value' => 'price-desc', 'label' => __('general.shop.sort_price_desc')],
['value' => 'newest', 'label' => __('general.shop.sort_newest')],
['value' => 'default', 'label' => __('storefront.shop.sort_default')],
['value' => 'popularity', 'label' => __('storefront.shop.sort_popularity')],
['value' => 'price-asc', 'label' => __('storefront.shop.sort_price_asc')],
['value' => 'price-desc', 'label' => __('storefront.shop.sort_price_desc')],
['value' => 'newest', 'label' => __('storefront.shop.sort_newest')],
]"
value="default"
/>
@@ -43,7 +43,7 @@
{{-- Products --}}
<div>
@if($products->isEmpty())
<p class="text-neutral-500">{{ __('general.shop.no_products') }}</p>
<p class="text-neutral-500">{{ __('storefront.shop.no_products') }}</p>
@else
<x-product-grid :products="$products->items()" cols="3" />
@@ -57,18 +57,18 @@
<aside class="flex flex-col gap-10">
<div>
<label for="shop-search" class="sr-only">{{ __('general.shop.search_label') }}</label>
<label for="shop-search" class="sr-only">{{ __('storefront.shop.search_label') }}</label>
<div class="relative">
<x-ui.input
type="search"
id="shop-search"
:placeholder="__('general.shop.search_placeholder')"
:placeholder="__('storefront.shop.search_placeholder')"
class="pr-10"
/>
<button
type="button"
class="absolute right-0 top-1/2 -translate-y-1/2"
aria-label="{{ __('general.shop.search_label') }}"
aria-label="{{ __('storefront.shop.search_label') }}"
>
<x-ui.icon name="search" :size="20" />
</button>
@@ -76,7 +76,7 @@ class="absolute right-0 top-1/2 -translate-y-1/2"
</div>
<div class="flex flex-col gap-4">
<h2 class="font-display font-extrabold uppercase">{{ __('general.shop.filter_price') }}</h2>
<h2 class="font-display font-extrabold uppercase">{{ __('storefront.shop.filter_price') }}</h2>
<div class="flex items-center gap-2" aria-hidden="true">
<x-ui.icon name="arrow-left" :size="20" />
@@ -87,15 +87,15 @@ class="absolute right-0 top-1/2 -translate-y-1/2"
<div class="flex items-center justify-between gap-4">
<span class="text-sm">€10 - €50</span>
<button type="button" class="underline-slide [--slide-h:1px] font-display font-bold italic uppercase text-sm">
{{ __('general.shop.apply') }}
{{ __('storefront.shop.apply') }}
</button>
</div>
</div>
<div class="flex flex-col gap-4">
<h2 class="font-display font-extrabold uppercase">{{ __('general.shop.availability') }}</h2>
<h2 class="font-display font-extrabold uppercase">{{ __('storefront.shop.availability') }}</h2>
<x-ui.checkbox id="shop-in-stock" name="in_stock">
{{ __('general.shop.in_stock_only') }}
{{ __('storefront.shop.in_stock_only') }}
</x-ui.checkbox>
</div>
+2 -2
View File
@@ -12,7 +12,7 @@
{{-- Products (CSS-only hover dropdown) --}}
<div class="group relative h-full flex items-center">
<a href="{{ url('/'.app()->getLocale().'/products') }}" class="nav-link uppercase inline-flex items-center gap-1 relative font-display font-extrabold italic text-black no-underline py-8">
<span>{{ __('general.nav.products') }}</span>
<span>{{ __('storefront.nav.products') }}</span>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-4 not-italic transition-transform group-hover:rotate-180">
<path fill-rule="evenodd" d="M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" />
</svg>
@@ -27,7 +27,7 @@
</div>
{{-- Contact --}}
<a href="{{ route('contact') }}" class="nav-link uppercase inline-flex items-center gap-1 relative font-display font-extrabold italic text-black no-underline"><span>{{ __('general.nav.contact') }}</span></a>
<a href="{{ route('contact') }}" class="nav-link uppercase inline-flex items-center gap-1 relative font-display font-extrabold italic text-black no-underline"><span>{{ __('storefront.nav.contact') }}</span></a>
</nav>
@@ -8,13 +8,13 @@ class="flex flex-col gap-8 mt-10"
@csrf
{{-- Rating --}}
<x-ui.field label="Βαθμολογία" for="rating" :required="true">
<x-ui.field :label="__('storefront.review.rating')" for="rating" :required="true">
<div
id="rating"
data-controller="star-rating"
class="flex items-center gap-1.5 text-brand"
role="radiogroup"
aria-label="Βαθμολογία"
aria-label="{{ __('storefront.review.rating') }}"
aria-required="true"
>
<input type="hidden" name="rating" value="0" data-star-rating-target="input">
@@ -24,7 +24,7 @@ class="flex items-center gap-1.5 text-brand"
data-star-rating-target="star"
data-value="{{ $i }}"
data-action="click->star-rating#select mouseenter->star-rating#hover mouseleave->star-rating#leave"
aria-label="{{ $i }} {{ $i === 1 ? 'αστέρι' : 'αστέρια' }}"
aria-label="{{ trans_choice('storefront.review.stars_count', $i, ['count' => $i]) }}"
aria-pressed="false"
>
<svg
@@ -43,24 +43,24 @@ class="w-6 h-6"
</div>
</x-ui.field>
<x-ui.field label="Γράψε μια αξιολόγηση" for="review-content" :required="true">
<x-ui.field :label="__('storefront.review.write_label')" for="review-content" :required="true">
<x-ui.textarea id="review-content" name="content" :required="true" />
</x-ui.field>
<x-ui.field label="Όνομα" for="review-name" labelDescription="Προαιρετικό">
<x-ui.field :label="__('storefront.review.name')" for="review-name" :labelDescription="__('storefront.review.name_optional')">
<x-ui.input id="review-name" name="name" autocomplete="name" />
</x-ui.field>
<x-ui.field label="Email" for="review-email" :required="true" labelDescription="Δεν θα δημοσιευτεί">
<x-ui.field :label="__('storefront.review.email')" for="review-email" :required="true" :labelDescription="__('storefront.review.email_not_published')">
<x-ui.input id="review-email" name="email" type="email" :required="true" autocomplete="email" />
</x-ui.field>
<x-ui.checkbox id="review-save-info" name="save_info" >
<span class="text-sm">Αποθήκευσε το όνομα και το email μου για την επόμενη φορά που θα σχολιάσω.</span>
<span class="text-sm">{{ __('storefront.review.save_info') }}</span>
</x-ui.checkbox>
<div>
<x-ui.button type="submit">Υποβολή</x-ui.button>
<x-ui.button type="submit">{{ __('storefront.review.submit') }}</x-ui.button>
</div>
</form>
@@ -29,7 +29,7 @@ class="flex items-center gap-1.5 text-brand"
@if ($showCount && $count > 0)
<span class="text-sm text-neutral-500">
({{ trans_choice('general.customer_reviews', $count, ['count' => $count]) }})
({{ trans_choice('storefront.customer_reviews', $count, ['count' => $count]) }})
</span>
@endif
@@ -1,6 +1,6 @@
{{-- $variants: array of Modules\Core\Search\ProductIndexer's mapVariant() shape
(id, options: [{option, value, meta}], ...) — plain arrays, not Eloquent
models, since this is fed from Modules\Core\Catalog\ProductService. --}}
{{-- $variants: array of Modules\Core\Product\Services\ProductIndexer's mapVariant()
shape (id, options: [{option, value, meta}], ...) — plain arrays, not Eloquent
models, since this is fed from Modules\Core\Product\Services\ProductService. --}}
@props(['variants', 'option' => null])
<div {{ $attributes }}>
@@ -9,21 +9,21 @@
--}}
@if($paginator->hasPages())
<nav aria-label="{{ __('general.pagination.nav_label') }}" {{ $attributes->merge(['class' => 'flex items-center gap-6 font-display font-bold']) }}>
<nav aria-label="{{ __('storefront.pagination.nav_label') }}" {{ $attributes->merge(['class' => 'flex items-center gap-6 font-display font-bold']) }}>
<ol class="flex items-center gap-6">
@foreach($paginator->getUrlRange(1, $paginator->lastPage()) as $page => $url)
<li>
@if($page === $paginator->currentPage())
<span class="underline-slide is-active" aria-current="page">{{ str_pad((string) $page, 2, '0', STR_PAD_LEFT) }}</span>
@else
<a href="{{ $url }}" class="underline-slide" aria-label="{{ __('general.pagination.page', ['page' => $page]) }}">{{ str_pad((string) $page, 2, '0', STR_PAD_LEFT) }}</a>
<a href="{{ $url }}" class="underline-slide" aria-label="{{ __('storefront.pagination.page', ['page' => $page]) }}">{{ str_pad((string) $page, 2, '0', STR_PAD_LEFT) }}</a>
@endif
</li>
@endforeach
</ol>
@if($paginator->hasMorePages())
<a href="{{ $paginator->nextPageUrl() }}" aria-label="{{ __('general.pagination.next') }}">
<a href="{{ $paginator->nextPageUrl() }}" aria-label="{{ __('storefront.pagination.next') }}">
<x-ui.icon name="arrow-right" :size="24" />
</a>
@endif
@@ -17,13 +17,13 @@ class="w-full h-auto block"
>
@else
<div class="w-full aspect-square bg-neutral-300 flex items-center justify-center text-neutral-500 text-sm">
Χωρίς εικόνα
{{ __('storefront.product.no_image') }}
</div>
@endif
</a>
<x-ui.button size="md" position="absolute" class="opacity-0 group-hover:opacity-100 transition-opacity duration-100">
Προσθήκη στο καλάθι
{{ __('storefront.product.add_to_cart') }}
</x-ui.button>
</div>
+1 -1
View File
@@ -1,6 +1,6 @@
@extends('layouts.app')
@section('title', __('general.nav.contact'))
@section('title', __('storefront.nav.contact'))
@section('description', 'Επικοινώνησε μαζί μας για οποιαδήποτε απορία ή ιδέα έχεις και θα σου απαντήσουμε το συντομότερο δυνατό.')
@section('content')
+2 -2
View File
@@ -56,12 +56,12 @@ class="{{ $loop->first ? '' : 'hidden' }} group h-full flex flex-col justify-cen
class="w-full h-full object-cover"
>
@else
<span class="text-neutral-500 text-sm">Χωρίς εικόνα</span>
<span class="text-neutral-500 text-sm">{{ __('storefront.product.no_image') }}</span>
@endif
</a>
<x-ui.button size="md" position="absolute" class="opacity-0 group-hover:opacity-100 transition-opacity duration-100">
Προσθήκη στο καλάθι
{{ __('storefront.product.add_to_cart') }}
</x-ui.button>
</div>
+9 -8
View File
@@ -9,7 +9,7 @@
<x-breadcrumb class="mb-14 justify-end" :items="[
$collection
? ['label' => $collection->translateAttribute('name'), 'href' => route('category.show', ['collection' => $collection])]
: ['label' => __('general.nav.products'), 'href' => '/products'],
: ['label' => __('storefront.nav.products'), 'href' => '/products'],
['label' => $product['name']],
]" />
@@ -134,7 +134,7 @@ class="absolute bottom-6 right-8 text-white text-sm"
</div>
@else
<div class="w-full bg-neutral-300 flex items-center justify-center text-neutral-500 min-h-64">
No image
{{ __('storefront.product.no_image') }}
</div>
@endif
</div>
@@ -162,7 +162,7 @@ class="absolute bottom-6 right-8 text-white text-sm"
<div class="text-base leading-relaxed">
{{ $descTruncated }}
@if($descNeedsMore)
<a href="#tab-panel-description" class="underline-slide font-semibold whitespace-nowrap">Περισσότερα</a>
<a href="#tab-panel-description" class="underline-slide font-semibold whitespace-nowrap">{{ __('storefront.product.read_more') }}</a>
@endif
</div>
@@ -172,7 +172,7 @@ class="absolute bottom-6 right-8 text-white text-sm"
<div class="flex items-stretch gap-10">
<x-ui.quantity name="quantity" />
<x-ui.button class="flex-1">Προσθήκη στο καλάθι</x-ui.button>
<x-ui.button class="flex-1">{{ __('storefront.product.add_to_cart') }}</x-ui.button>
</div>
</div>
@@ -180,8 +180,8 @@ class="absolute bottom-6 right-8 text-white text-sm"
</div>
<x-ui.tabs class="mt-16" size="lg" :tabs="[
['id' => 'description', 'label' => __('general.product.description')],
['id' => 'reviews', 'label' => __('general.product.reviews') . ' (' . $product['review_count'] . ')'],
['id' => 'description', 'label' => __('storefront.product.description')],
['id' => 'reviews', 'label' => __('storefront.product.reviews') . ' (' . $product['review_count'] . ')'],
]">
<x-slot name="description">
<div class="leading-7 [&_p]:mt-4">
@@ -207,11 +207,12 @@ class="absolute bottom-6 right-8 text-white text-sm"
@endforeach
</div>
@else
<p class="text-neutral-500 mb-10">Δεν υπάρχουν αξιολογήσεις ακόμα.</p>
<p class="text-neutral-500 mb-10">{{ __('storefront.review.no_reviews_yet') }}</p>
@endif
<h3 class="text-h4 font-bold">
{{ $product['review_count'] > 0 ? 'Πρόσθεσε μια' : 'Γράψε την πρώτη' }} αξιολόγηση για το «{{ $product['name'] }}»
{{ $product['review_count'] > 0 ? __('storefront.review.write_new') : __('storefront.review.write_first') }}
{{ __('storefront.review.for_product', ['name' => $product['name']]) }}
</h3>
<x-review-form :product="$product" />