stage, ['fetching', 'importing'])) wire:poll.3000ms="pollStatus" @endif>
{{-- ── STAGE: IDLE ──────────────────────────────────────── --}}
@if($this->stage === 'idle')
Import Products from Shopify
Import all products immediately, or fetch first to preview and choose which ones to import.
Import All runs immediately in the background — best for large catalogues.
Fetch & Select previews the first 500 products.
Search for specific products
Searches Shopify by SKU — returns exact matches.
{{-- ── STAGE: FETCHING (background job running) ─────────── --}}
@elseif($this->stage === 'fetching')
@php $fetched = $this->importData['fetched_count'] ?? 0; @endphp
Fetching products from Shopify…
@if($fetched > 0)
{{ number_format($fetched) }}
products fetched so far
@else
Connecting to Shopify in the background. This page will update automatically.
@endif
{{-- ── STAGE: PREVIEW / SELECT ───────────────────────────── --}}
@elseif($this->stage === 'preview')
@php
$products = $this->filteredPreview;
$meta = $this->previewMeta;
$totalPages = $meta['total_pages'] ?? 1;
$totalProducts = $meta['total_products'] ?? count($this->previewProducts);
$currentPage = $this->previewPage;
$searchedFor = $this->importData['search_query'] ?? null;
@endphp
@if($searchedFor)
{{ $totalProducts }} product{{ $totalProducts !== 1 ? 's' : '' }} matching "{{ $searchedFor }}"
@else
{{ number_format($totalProducts) }} product{{ $totalProducts !== 1 ? 's' : '' }} fetched from Shopify
@endif
{{ count($this->selectedVariantIds) }} variant{{ count($this->selectedVariantIds) !== 1 ? 's' : '' }} selected across all pages
{{-- Search + select all + pagination --}}
@if($totalPages > 1)
Page {{ $currentPage + 1 }} of {{ $totalPages }}
@endif
|
|
Product / Variant |
SKU |
Price |
Status |
@forelse($products as $product)
@php
$thumb = $product['images'][0]['src'] ?? null;
$variantCount = count($product['variants'] ?? []);
@endphp
@foreach($product['variants'] ?? [] as $variant)
@php
$vid = (string) $variant['id'];
$checked = in_array($vid, $this->selectedVariantIds, true);
$varTitle = ($variant['title'] ?? 'Default Title') !== 'Default Title'
? $product['title'] . ' — ' . $variant['title']
: $product['title'];
$existing = \Webkul\Product\Models\Product::where('shopify_variant_id', $vid)->first()
?? (($variant['sku'] ?? '') ? \Webkul\Product\Models\Product::where('sku', $variant['sku'])->whereNull('shopify_variant_id')->first() : null);
$statusLabel = $existing ? 'Update' : 'New';
$statusColor = $existing ? '#3b82f6' : '#10b981';
@endphp
|
|
@if($thumb)
@else
@endif
|
{{ $varTitle }}
@if($variantCount > 1)
{{ $variantCount }} variants
@endif
|
{{ $variant['sku'] ?: '—' }}
|
£{{ number_format((float)($variant['price'] ?? 0), 2) }}
|
{{ $statusLabel }}
|
@endforeach
@empty
| No products match your search. |
@endforelse
{{-- ── STAGE: IMPORTING ─────────────────────────────────── --}}
@elseif($this->stage === 'importing' || $this->isImporting())
@php
$progress = $this->importProgress;
$hasStarted = !empty($progress) && ($progress['total'] ?? 0) > 0;
$elapsed = $this->importStartedAt
? \Carbon\Carbon::parse($this->importStartedAt)->diffForHumans(null, true)
: null;
@endphp
Importing products…
@if($hasStarted)
Running for {{ $elapsed }} — updating every 3 seconds
@foreach([
['label' => 'Processed', 'value' => $progress['total'], 'color' => '#6b7280'],
['label' => 'Created', 'value' => $progress['created'], 'color' => '#10b981'],
['label' => 'Updated', 'value' => $progress['updated'], 'color' => '#3b82f6'],
['label' => 'Errors', 'value' => $progress['errors'], 'color' => '#ef4444'],
] as $card)
{{ $card['label'] }}
{{ number_format($card['value']) }}
@endforeach
@if(($progress['errors'] ?? 0) > 0)
{{ $progress['errors'] }} error{{ $progress['errors'] !== 1 ? 's' : '' }} so far — full details shown when complete.
@endif
@else
Connecting to Shopify and downloading products.
@if($elapsed) Running for {{ $elapsed }}. @endif
Counts will appear once the first batch is processed.
@endif
Live — page auto-refreshes every 3 seconds
You can safely navigate away — the import runs in the background and will finish on its own. Come back to this page to see the results.
{{ $this->cancelImportAction }}
{{-- ── STAGE: DONE ──────────────────────────────────────── --}}
@elseif($this->stage === 'done' || ($this->importData['stage'] ?? '') === 'done')
@if($this->importData['cancelled'] ?? false)
Import Cancelled
@else
Import Complete
@endif
@if($this->importData['finished_at'])
Finished {{ \Carbon\Carbon::parse($this->importData['finished_at'])->diffForHumans() }}
@endif
@if($this->importData['error'])
Error: {{ $this->importData['error'] }}
@endif
@foreach([
['label' => 'Total', 'value' => $this->stats['total'], 'color' => '#6b7280'],
['label' => 'Created', 'value' => $this->stats['created'], 'color' => '#10b981'],
['label' => 'Updated', 'value' => $this->stats['updated'], 'color' => '#3b82f6'],
['label' => 'Errors', 'value' => $this->stats['errors'], 'color' => '#ef4444'],
] as $card)
{{ $card['label'] }}
{{ $card['value'] }}
@endforeach
@if($this->stats['total'] > 500)
Large import — showing errors only. All {{ number_format($this->stats['total']) }} products are saved to the database.
@endif
|
Product |
SKU |
Status |
Message |
@forelse($this->filteredResults as $row)
@php
$statusColor = match($row['status']) { 'created' => '#10b981', 'updated' => '#3b82f6', 'error' => '#ef4444', default => '#9ca3af' };
$thumb = null;
if (!empty($row['images'][0])) {
$filename = $row['images'][0];
if (config('filesystems.disks.r2')) {
try { $settings = app(\App\Settings\R2StorageSettings::class); $base = rtrim($settings->public_url ?? '', '/'); if ($base) $thumb = $base . '/' . ltrim($filename, '/'); } catch (\Throwable) {}
}
if (!$thumb) { try { $thumb = \Illuminate\Support\Facades\Storage::disk('public')->url($filename); } catch (\Throwable) {} }
}
@endphp
@if($thumb)
@else @endif
|
{{ $row['name'] }} |
{{ $row['sku'] }} |
{{ ucfirst($row['status']) }}
|
{{ $row['message'] ?? '' }} |
@empty
| No results. |
@endforelse
@endif