feat: add marketplace products admin UI with copy-to-vendor functionality

- Add admin marketplace products page to browse imported products
- Add admin vendor products page to manage vendor catalog
- Add product detail pages for both marketplace and vendor products
- Implement copy-to-vendor API to copy marketplace products to vendor catalogs
- Add vendor product service with CRUD operations
- Update sidebar navigation with new product management links
- Add integration and unit tests for new endpoints and services

🤖 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-12 22:36:04 +01:00
parent 89c98cb645
commit 9c60989f1d
28 changed files with 4575 additions and 1414 deletions

View File

@@ -6,13 +6,14 @@
{% from 'shared/macros/tables.html' import table_wrapper, table_header %}
{% from 'shared/macros/headers.html' import page_header_flex, refresh_button %}
{% from 'shared/macros/inputs.html' import number_stepper %}
{% from 'shared/macros/tabs.html' import tabs_nav, tab_button, tab_panel, endtab_panel %}
{% block title %}Marketplace Import{% endblock %}
{% block alpine_data %}adminMarketplace(){% endblock %}
{% block content %}
{% call page_header_flex(title='Marketplace Import', subtitle='Import products from Letzshop marketplace for any vendor (self-service)') %}
{% call page_header_flex(title='Marketplace Import', subtitle='Import products from external marketplaces') %}
{{ refresh_button(onclick='refreshJobs()') }}
{% endcall %}
@@ -20,13 +21,21 @@
{{ error_state('Error', show_condition='error') }}
<!-- Import Form Card -->
<!-- Import Form Card with Tabs -->
<div class="mb-8 bg-white rounded-lg shadow-xs dark:bg-gray-800">
<div class="p-6">
<h3 class="mb-4 text-lg font-semibold text-gray-700 dark:text-gray-200">
Start New Import
</h3>
<!-- Marketplace Tabs -->
{% call tabs_nav(tab_var='activeImportTab') %}
{{ tab_button('letzshop', 'Letzshop', tab_var='activeImportTab', icon='shopping-cart', onclick="switchMarketplace('letzshop')") }}
{{ tab_button('codeswholesale', 'CodesWholesale', tab_var='activeImportTab', icon='code', onclick="switchMarketplace('codeswholesale')") }}
{% endcall %}
<!-- Letzshop Import Form -->
{{ tab_panel('letzshop', tab_var='activeImportTab') }}
<form @submit.prevent="startImport()">
<div class="grid gap-6 mb-4 md:grid-cols-2">
<!-- Vendor Selection -->
@@ -86,19 +95,6 @@
</p>
</div>
<!-- Marketplace -->
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400 mb-2">
Marketplace
</label>
<input
x-model="importForm.marketplace"
type="text"
readonly
class="block w-full px-3 py-2 text-sm text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-600 border border-gray-300 dark:border-gray-600 rounded-md cursor-not-allowed"
/>
</div>
<!-- Batch Size -->
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400 mb-2">
@@ -163,6 +159,23 @@
</button>
</div>
</form>
{{ endtab_panel() }}
<!-- CodesWholesale Import Form -->
{{ tab_panel('codeswholesale', tab_var='activeImportTab') }}
<div class="text-center py-12">
<span x-html="$icon('code', 'inline w-16 h-16 text-gray-300 dark:text-gray-600 mb-4')"></span>
<h4 class="text-lg font-medium text-gray-700 dark:text-gray-300 mb-2">
CodesWholesale Integration
</h4>
<p class="text-gray-500 dark:text-gray-400 mb-4">
Import digital game keys and software licenses from CodesWholesale API.
</p>
<p class="text-sm text-gray-400 dark:text-gray-500">
Coming soon - This feature is under development
</p>
</div>
{{ endtab_panel() }}
</div>
</div>
@@ -214,6 +227,7 @@
>
<option value="">All Marketplaces</option>
<option value="Letzshop">Letzshop</option>
<option value="CodesWholesale">CodesWholesale</option>
</select>
</div>