{{-- Shared sync panel for Shopify integrations. Rendered by both Integrations\Index (per row) and Integrations\Edit (full page). Required variables in scope: - $integration (App\Models\Integration) - $snapshots (array{customers: ?array, orders: ?array}) - $canManage (bool) - $resetConfirm (?string) staged "{integrationId}:{type}" - $isLocal (bool) - $queueDriver (string) - $shopifyQueueName (string) e.g. "shopify-sync" - $pendingShopifyJobsCount (?int) - $nextShopifyJobAt (?\Illuminate\Support\Carbon) - $autoProcess (bool) - $lastAutoProcessAt (?string) ISO8601 - $lastAutoProcessResult (string) - $autoProcessPollSeconds (int) Methods on the parent Livewire component: - startSync(int, string), cancelSync(int, string), resumeSync(int, string), confirmResetProgress(int, string), cancelResetConfirmation(), resetProgress(int, string), processQueueNow(), toggleAutoProcess(), autoProcessTick() --}} @php $stateLabel = function (?string $state): string { return match ($state) { 'idle' => __('Synced'), 'syncing' => __('Syncing…'), 'queued' => __('Queued'), 'failed' => __('Failed'), 'cancelled' => __('Cancelled'), null => __('Not started'), default => (string) $state, }; }; $stateColor = function (?string $state): string { return match ($state) { 'idle' => 'lime', 'syncing' => 'sky', 'queued' => 'zinc', 'failed' => 'red', 'cancelled' => 'zinc', default => 'zinc', }; }; $relativeTime = function (?string $iso): ?string { if (! is_string($iso) || $iso === '') { return null; } try { return \Illuminate\Support\Carbon::parse($iso)->diffForHumans(); } catch (\Throwable) { return null; } }; $resources = [ ['key' => 'customers', 'label' => __('Customers'), 'snapshot' => $snapshots['customers'] ?? null], ['key' => 'orders', 'label' => __('Orders'), 'snapshot' => $snapshots['orders'] ?? null], ]; @endphp
{{ __('Not started yet.') }}
@endif @php // Stale = running state with a saved cursor but // no continuation job on the queue. Computed by // the parent Livewire component and folded into // the snapshot so the view can present a clear // recovery affordance. $isStale = (bool) ($snap['is_stale'] ?? false); @endphp @if ($isStale)@if ($isRunning) {{ __('Cancel stops future continuation jobs but does not delete imported data.') }} @elseif ($isConfirmingReset) {{ __('Reset clears sync progress and cursor but does not delete imported data.') }} @else {{ __('Start sync resumes from saved cursor where one exists, otherwise starts fresh.') }} @endif
@endif{{ $queueDriver }}
·
{{ __('Queue') }}:
{{ $shopifyQueueName }}
@if ($pendingShopifyJobsCount !== null)
·
{{ __('Pending') }}:
{{ $pendingShopifyJobsCount }}
@endif
@if ($nextShopifyJobAt !== null)
·
@if ($nextShopifyJobAt->isPast())
{{ __('Next job ready now') }}
@else
{{ __('Next job ready in') }} {{ $nextShopifyJobAt->diffForHumans(null, true) }}
@endif
@endif
{{ __('Queued jobs require a queue worker to be running.') }}
{{ __('In production this should be run by Supervisor / Forge.') }}
{{ __('In local development you can use the "Process queue now" button below, or run:') }}
php artisan shopify-sync:work --limit=20 --timeout=60
{{ __('Local development only. In production a persistent Supervisor / Forge worker must run:') }}
php artisan queue:work database --queue={{ $shopifyQueueName }}