@php $isDone = in_array($this->jobStatus, ['completed', 'failed']); $pct = $this->totalRows > 0 ? min(100, (int) round(($this->processedRows / $this->totalRows) * 100)) : ($this->jobStatus === 'processing' ? 5 : 0); $isRunning = $this->jobId && !$isDone; @endphp {{-- Polling is managed by JS setInterval in the Alpine component below --}}
{{-- ── PROGRESS STATE ── --}} @if($this->jobId) @if($isDone) {{ $this->jobStatus === 'completed' ? 'Import Complete' : 'Import Failed' }} @else Importing Images… @endif @if($isDone) {{ $this->importedRows }} updated · {{ $this->skippedRows }} skipped · {{ $this->failedRows }} failed @else Processing in the background — you can leave this page and come back. @endif {{-- Progress bar --}}
@if($this->totalRows > 0) {{ $this->processedRows }} / {{ $this->totalRows }} rows @elseif($this->jobStatus === 'pending') Queued… @else Starting… @endif {{ $pct }}%
{{-- Stats row --}} @if($this->totalRows > 0 || $isDone)
{{ $this->importedRows }}
Updated
{{ $this->skippedRows }}
Skipped
{{ $this->failedRows }}
Failed
@endif {{-- Error message --}} @if($this->firstError)
{{ $this->firstError }}
@endif @if($isDone) Import Another File @endif
@endif {{-- ── UPLOAD FORMS (hidden while job running) ── --}} @if(!$this->jobId) {{-- ZIP + CSV --}} Upload ZIP + CSV Upload a ZIP of your image files (any filenames) and a CSV that maps each SKU to the filenames inside the ZIP. Only referenced images are uploaded to R2 — nothing is stored unless it appears in the CSV.
{{ $this->zipForm }} Start Import
{{-- CSV + URLs --}} Import via CSV + URLs Upload a CSV with SKU and image URL columns. Images are downloaded from the public URLs and attached to matching products.
{{ $this->form }} Start Import
{{-- CSV Preview (shown when a CSV+URL file is selected) --}}
File Preview Green = SKU column, blue = image URL column, grey = ignored.
Missing required columns
Missing sku column. No image columns found (expected image_1, image_2, etc.).
#

Showing first rows — full file will be processed on import.

@endif {{-- Instructions (always visible) --}} Import Instructions Two methods are available depending on whether you have image files locally or hosted online.
{{-- ZIP + CSV --}}
1 ZIP + CSV — for local image files

CSV column headers

Columns
sku required
image_1 required
image_2 optional
image_N… optional

Example: PROD-001, front.jpg, back.jpg

How it works

1. Put all your images in a ZIP (any folder structure is fine).

2. Create a CSV where each row maps a SKU to filenames that exist in the ZIP.

3. Upload both files — only images listed in the CSV are uploaded to R2.

4. The ZIP is deleted from the server after processing.


{{-- CSV + URLs --}}
2 CSV + URLs — for images already hosted online

CSV column headers

Columns
sku required
image_1 required
image_2 optional
image_N… optional

URLs must be publicly accessible at import time.

Image Modes
Append
Adds new images alongside existing ones.
Replace
Clears existing and sets only the imported images.
Download CSV Template