diff --git a/Dockerfile b/Dockerfile index 341cf29..54d20ef 100644 --- a/Dockerfile +++ b/Dockerfile @@ -119,13 +119,11 @@ COPY docker/php/php.dev.ini /etc/php/8.5/cli/conf.d/99-app.ini WORKDIR /var/www/html -COPY composer.json composer.lock ./ -RUN composer install \ - --no-interaction \ - --no-scripts \ - --prefer-dist \ - --ignore-platform-reqs - +# No build-time `composer install` here: composer.json's boboko/core path repo +# (../boboko-core) isn't visible in the build context, only once bind-mounted at +# container start — entrypoint.sh already runs composer install + +# composer update boboko/* on every boot, so this would be redundant even if it +# could work. COPY docker/entrypoint.sh /entrypoint.sh COPY docker/entrypoint-worker.sh /entrypoint-worker.sh RUN chmod +x /entrypoint.sh /entrypoint-worker.sh diff --git a/app/Http/Controllers/CategoryController.php b/app/Http/Controllers/CategoryController.php index 406e6bf..87aa156 100644 --- a/app/Http/Controllers/CategoryController.php +++ b/app/Http/Controllers/CategoryController.php @@ -2,7 +2,6 @@ namespace App\Http\Controllers; -use Illuminate\Pagination\LengthAwarePaginator; use Lunar\Models\Collection; use Modules\Core\Catalog\ProductFilters; use Modules\Core\Catalog\ProductService; @@ -19,29 +18,19 @@ 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. It returns plain - // arrays (already localized/flattened), not Product models. - $result = $this->products->list( + // not Eloquent — see Modules\Core\Catalog\ProductService. list() returns a + // real LengthAwarePaginator of plain arrays (already localized/flattened), + // not Product models. + $products = $this->products->list( filters: new ProductFilters(collectionId: $collection->id), perPage: $perPage, page: $page, - ); - - $products = new LengthAwarePaginator( - items: collect($result['data'])->map(fn (array $product) => [ - 'name' => $product['name'], - 'price' => $product['price'], - 'image' => $product['media'][0]['url'] ?? null, - 'href' => route('product.show', ['product' => $product['id']]), - ]), - total: $result['meta']['total'], - perPage: $result['meta']['per_page'], - currentPage: $result['meta']['current_page'], - options: [ - 'path' => request()->url(), - 'query' => request()->query(), - ], - ); + )->through(fn (array $product) => [ + 'name' => $product['name'], + 'price' => $product['price'], + 'image' => $product['media'][0]['url'] ?? null, + 'href' => route('product.show', ['id' => $product['id']]), + ]); return view('category.show', [ 'collection' => $collection, diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 6f76ada..5717aec 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -23,7 +23,7 @@ public function index(string $locale) 'name' => $product->translateAttribute('name'), 'price' => $product->variants->first()?->prices->first()?->price->decimal, 'image' => $product->media->first()?->getUrl(), - 'href' => route('product.show', ['product' => $product]), + 'href' => route('product.show', ['id' => $product->id]), ]); return view('home', [ diff --git a/app/Http/Controllers/ProductController.php b/app/Http/Controllers/ProductController.php index 852bfbb..1765a9d 100644 --- a/app/Http/Controllers/ProductController.php +++ b/app/Http/Controllers/ProductController.php @@ -2,44 +2,44 @@ namespace App\Http\Controllers; -use Lunar\Models\Product; +use Illuminate\Http\Response; +use Lunar\Models\Collection; +use Modules\Core\Catalog\ProductService; class ProductController extends Controller { - public function show(string $locale, Product $product) + public function __construct(private readonly ProductService $products) {} + + public function show(string $locale, int $id) { - $product->load([ - "variants.prices.currency", - "variants.values.option", - "media", - "collections", - ]); + $product = $this->products->getById($id); - $option = $product->variants->first()?->values->first()?->option; + abort_if($product === null, Response::HTTP_NOT_FOUND); - $variantsData = $product->variants - ->map( - fn($v) => [ - "id" => $v->id, - "price" => $v->prices->first()?->price->decimal, - "image" => null, // variant-level media not differentiated yet - ], - ) + $collection = $product['collections'][0] ?? null; + $collectionModel = $collection !== null ? Collection::find($collection) : null; + + $variantsData = collect($product['variants']) + ->map(fn (array $variant) => [ + 'id' => $variant['id'], + 'price' => $variant['prices'][0]['price'] ?? null, + 'image' => $variant['media'][0]['url'] ?? null, + ]) ->values() - ->toArray(); + ->all(); - $firstImage = $product->media->first()?->getUrl(); + $firstVariant = $product['variants'][0] ?? null; + $option = $firstVariant['options'][0]['option'] ?? null; // temp categories here - $categories = \Lunar\Models\Collection::orderBy("_lft")->get(); + $categories = Collection::orderBy('_lft')->get(); - // dd($product); - - return view("product.show", [ - "categories" => $categories, - "product" => $product, - "option" => $option, - "variantsData" => $variantsData, + return view('product.show', [ + 'categories' => $categories, + 'collection' => $collectionModel, + 'product' => $product, + 'option' => $option, + 'variantsData' => $variantsData, ]); } } diff --git a/resources/views/components/ui/color-swatch.blade.php b/resources/views/components/ui/color-swatch.blade.php index c64a5bd..5a2562d 100644 --- a/resources/views/components/ui/color-swatch.blade.php +++ b/resources/views/components/ui/color-swatch.blade.php @@ -1,29 +1,32 @@ +{{-- $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. --}} @props(['variants', 'option' => null])
@if($option)

- {{ $option->translate('name') }}: + {{ $option }}:

@endif
@foreach($variants as $variant) @php - $value = $variant->values->first(); - $label = $value?->translate('name') ?? ''; - $bg = $value?->meta['hex'] ?? '#cccccc'; + $value = $variant['options'][0] ?? null; + $label = $value['value'] ?? ''; + $bg = $value['meta']['hex'] ?? '#cccccc'; @endphp @endforeach
@@ -77,8 +75,8 @@ class="flex-1 border border-black bg-white cursor-zoom-in block p-0" {{ $product->translateAttribute('name') }} @@ -145,19 +143,19 @@ class="absolute bottom-6 right-8 text-white text-sm"

- {{ $product->translateAttribute('name') }} + {{ $product['name'] }}

- + - @if($product->variants->first()?->prices->isNotEmpty()) + @if($product['price'] !== null)

- +

@endif @php - $desc = strip_tags($product->translateAttribute('description') ?? ''); + $desc = strip_tags($product['description'] ?? ''); $descTruncated = Str::limit($desc, 137); $descNeedsMore = mb_strlen($desc) > mb_strlen(rtrim($descTruncated, '.')); @endphp @@ -168,8 +166,8 @@ class="absolute bottom-6 right-8 text-white text-sm" @endif
- @if($option && $product->variants->count() >= 1) - + @if($option && !empty($product['variants'])) + @endif
@@ -183,16 +181,12 @@ class="absolute bottom-6 right-8 text-white text-sm"
- {!! $product->translateAttribute('description') !!} + {!! $product['description'] !!}
- @if($product->translateAttribute('details')) -
{!! $product->translateAttribute('details') !!}
- @endif
  • Όλα τα προϊόντα εκτυπώνονται και προετοιμάζονται κατά παραγγελία. Ο χρόνος προετοιμασίας κυμαίνεται μεταξύ 2 και 7 εργάσιμων ημερών.
  • Όλα τα προϊόντα κατασκευάζονται με τρισδιάστατη εκτύπωση σε ειδικούς εκτυπωτές πλαστικού υλικού. Πιθανώς να έχουν εμφανείς γραμμές ένωσης, στρώσεις εκτύπωσης υλικού και μικρές ατέλειες. Είναι φυσιολογικό για το αποτέλεσμα αυτής της δημιουργικής διαδικασίας.
  • @@ -200,10 +194,16 @@ class="absolute bottom-6 right-8 text-white text-sm"
- {{-- @if(count($reviews) > 0) + @if(!empty($product['reviews']))
- @foreach($reviews as $review) - + @foreach($product['reviews'] as $review) + @endforeach
@else @@ -211,8 +211,8 @@ class="absolute bottom-6 right-8 text-white text-sm" @endif

- {{ count($reviews) > 0 ? 'Πρόσθεσε μια' : 'Γράψε την πρώτη' }} αξιολόγηση για το «{{ $product->translateAttribute('name') }}» -

--}} + {{ $product['review_count'] > 0 ? 'Πρόσθεσε μια' : 'Γράψε την πρώτη' }} αξιολόγηση για το «{{ $product['name'] }}» +
diff --git a/routes/web.php b/routes/web.php index b98e3e3..b9f10ec 100644 --- a/routes/web.php +++ b/routes/web.php @@ -12,7 +12,7 @@ ->group(function () { Route::get('/', [HomeController::class, 'index'])->name('home'); - Route::get('/products/{product}', [ProductController::class, 'show'])->name( + Route::get('/products/{id}', [ProductController::class, 'show'])->name( 'product.show', );