fix: improve onboarding UX and fix order sync error

- Remove redundant 1/4 progress counter from header
- Make step indicators mobile-friendly (smaller circles, hidden labels)
- Add CSV URL help text pointing to Letzshop Admin > API > Export Products
- Fix AttributeError in order sync progress (use correct model attributes)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-28 09:13:16 +01:00
parent 4e6e6a27f9
commit ff2f475ae4
3 changed files with 43 additions and 46 deletions

View File

@@ -541,28 +541,31 @@ class OnboardingService:
elif job.status == "failed":
progress = 0
elif job.status == "processing":
if job.total_shipments and job.total_shipments > 0:
progress = int((job.processed_shipments or 0) / job.total_shipments * 100)
# Use orders_processed and shipments_fetched for progress
total = job.shipments_fetched or 0
processed = job.orders_processed or 0
if total > 0:
progress = int(processed / total * 100)
else:
progress = 50 # Indeterminate
elif job.status == "fetching":
# Show partial progress during fetch phase
if job.total_pages and job.total_pages > 0:
progress = int((job.current_page or 0) / job.total_pages * 50)
else:
progress = 25 # Indeterminate
# Determine current phase
current_phase = None
if job.status == "fetching":
current_phase = "fetching"
elif job.status == "processing":
current_phase = "orders"
elif job.status == "completed":
current_phase = "complete"
current_phase = job.current_phase or job.status
return {
"job_id": job.id,
"status": job.status,
"progress_percentage": progress,
"current_phase": current_phase,
"orders_imported": job.processed_shipments or 0,
"orders_total": job.total_shipments,
"products_imported": 0, # TODO: Track this
"orders_imported": job.orders_imported or 0,
"orders_total": job.shipments_fetched,
"products_imported": job.products_matched or 0,
"started_at": job.started_at,
"completed_at": job.completed_at,
"estimated_remaining_seconds": None, # TODO: Calculate

View File

@@ -23,51 +23,45 @@
</div>
<span class="text-xl font-semibold text-gray-800 dark:text-white">Wizamart</span>
</div>
<div class="flex items-center space-x-4">
<!-- Language Selector -->
<div class="relative" x-data="{ open: false }">
<button @click="open = !open"
class="flex items-center space-x-2 px-3 py-2 rounded-lg bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 transition-colors">
<span x-text="languageFlags[lang]"></span>
<span class="text-sm text-gray-700 dark:text-gray-300" x-text="languageNames[lang]"></span>
<svg class="w-4 h-4 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</button>
<div x-show="open" @click.away="open = false" x-cloak
class="absolute right-0 mt-2 w-40 bg-white dark:bg-gray-700 rounded-lg shadow-lg border border-gray-200 dark:border-gray-600 z-50">
<template x-for="langCode in availableLanguages" :key="langCode">
<button @click="setLang(langCode); open = false"
class="w-full flex items-center space-x-2 px-4 py-2 text-left hover:bg-gray-50 dark:hover:bg-gray-600 first:rounded-t-lg last:rounded-b-lg"
:class="{ 'bg-purple-50 dark:bg-purple-900/20': lang === langCode }">
<span x-text="languageFlags[langCode]"></span>
<span class="text-sm text-gray-700 dark:text-gray-300" x-text="languageNames[langCode]"></span>
</button>
</template>
</div>
</div>
<!-- Progress -->
<div class="text-sm text-gray-600 dark:text-gray-400">
<span x-text="completedSteps"></span> / 4
<!-- Language Selector -->
<div class="relative" x-data="{ open: false }">
<button @click="open = !open"
class="flex items-center space-x-2 px-3 py-2 rounded-lg bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 transition-colors">
<span x-text="languageFlags[lang]"></span>
<span class="text-sm text-gray-700 dark:text-gray-300 hidden sm:inline" x-text="languageNames[lang]"></span>
<svg class="w-4 h-4 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</button>
<div x-show="open" @click.away="open = false" x-cloak
class="absolute right-0 mt-2 w-40 bg-white dark:bg-gray-700 rounded-lg shadow-lg border border-gray-200 dark:border-gray-600 z-50">
<template x-for="langCode in availableLanguages" :key="langCode">
<button @click="setLang(langCode); open = false"
class="w-full flex items-center space-x-2 px-4 py-2 text-left hover:bg-gray-50 dark:hover:bg-gray-600 first:rounded-t-lg last:rounded-b-lg"
:class="{ 'bg-purple-50 dark:bg-purple-900/20': lang === langCode }">
<span x-text="languageFlags[langCode]"></span>
<span class="text-sm text-gray-700 dark:text-gray-300" x-text="languageNames[langCode]"></span>
</button>
</template>
</div>
</div>
</div>
</div>
<!-- Progress Indicator -->
<div class="max-w-4xl mx-auto mb-8">
<div class="max-w-4xl mx-auto mb-8 px-2 sm:px-0">
<div class="flex items-center justify-between">
<template x-for="(step, index) in steps" :key="step.id">
<div class="flex items-center" :class="{ 'flex-1': index < steps.length - 1 }">
<!-- Step Circle -->
<div class="flex flex-col items-center">
<div class="w-10 h-10 rounded-full flex items-center justify-center text-sm font-semibold transition-all duration-200"
<div class="w-8 h-8 sm:w-10 sm:h-10 rounded-full flex items-center justify-center text-xs sm:text-sm font-semibold transition-all duration-200"
:class="{
'bg-purple-600 text-white': isStepCompleted(step.id) || currentStep === step.id,
'bg-gray-200 dark:bg-gray-700 text-gray-600 dark:text-gray-400': !isStepCompleted(step.id) && currentStep !== step.id
}">
<template x-if="isStepCompleted(step.id)">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg class="w-4 h-4 sm:w-5 sm:h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
</template>
@@ -75,12 +69,12 @@
<span x-text="index + 1"></span>
</template>
</div>
<span class="mt-2 text-xs font-medium text-gray-600 dark:text-gray-400 text-center w-24"
<span class="mt-2 text-xs font-medium text-gray-600 dark:text-gray-400 text-center w-16 sm:w-24 hidden sm:block"
x-text="step.title"></span>
</div>
<!-- Connector Line -->
<template x-if="index < steps.length - 1">
<div class="flex-1 h-1 mx-4 rounded"
<div class="flex-1 h-1 mx-1 sm:mx-4 rounded"
:class="{
'bg-purple-600': isStepCompleted(step.id),
'bg-gray-200 dark:bg-gray-700': !isStepCompleted(step.id)

View File

@@ -61,7 +61,7 @@ const onboardingTranslations = {
csv_url_fr: 'French CSV URL',
csv_url_en: 'English CSV URL',
csv_url_de: 'German CSV URL',
csv_url_help: 'At least one CSV URL is required',
csv_url_help: 'Find your CSV URL in Letzshop Admin Panel > API > Export Products',
default_tax_rate: 'Default Tax Rate (%)',
delivery_method: 'Delivery Method',
delivery_package: 'Package Delivery',
@@ -139,7 +139,7 @@ const onboardingTranslations = {
csv_url_fr: 'URL CSV Français',
csv_url_en: 'URL CSV Anglais',
csv_url_de: 'URL CSV Allemand',
csv_url_help: 'Au moins une URL CSV est requise',
csv_url_help: 'Trouvez votre URL CSV dans Letzshop Admin > API > Exporter Produits',
default_tax_rate: 'Taux de TVA par Défaut (%)',
delivery_method: 'Méthode de Livraison',
delivery_package: 'Livraison Colis',
@@ -217,7 +217,7 @@ const onboardingTranslations = {
csv_url_fr: 'Französische CSV-URL',
csv_url_en: 'Englische CSV-URL',
csv_url_de: 'Deutsche CSV-URL',
csv_url_help: 'Mindestens eine CSV-URL ist erforderlich',
csv_url_help: 'Finden Sie Ihre CSV-URL im Letzshop Admin-Panel > API > Produkte exportieren',
default_tax_rate: 'Standard-Steuersatz (%)',
delivery_method: 'Liefermethode',
delivery_package: 'Paketlieferung',