feat: show all Letzshop products in Products tab without vendor filter
- Update loadProducts() to show all Letzshop marketplace products when no vendor is selected, filtered by vendor when one is selected - Add vendor column to products table (shown when no vendor filter) - Update header to show context-aware subtitle - Hide Import/Export buttons when no vendor selected - Remove "Marketplace Products" from sidebar menu (accessible via Marketplace > Letzshop > Products tab) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -7,10 +7,13 @@
|
||||
<div class="flex items-center justify-between mb-6">
|
||||
<div>
|
||||
<h3 class="text-lg font-semibold text-gray-700 dark:text-gray-200">Letzshop Products</h3>
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400">Vendor products synced with Letzshop marketplace</p>
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400">
|
||||
<span x-show="selectedVendor" x-text="'Products from ' + (selectedVendor?.name || '')"></span>
|
||||
<span x-show="!selectedVendor">All Letzshop marketplace products</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex items-center gap-3">
|
||||
<!-- Import Button -->
|
||||
<div class="flex items-center gap-3" x-show="selectedVendor">
|
||||
<!-- Import Button (only when vendor selected) -->
|
||||
<button
|
||||
@click="showImportModal = true"
|
||||
:disabled="importing"
|
||||
@@ -20,7 +23,7 @@
|
||||
<span x-show="importing" x-html="$icon('spinner', 'w-4 h-4 mr-2')"></span>
|
||||
<span x-text="importing ? 'Importing...' : 'Import'"></span>
|
||||
</button>
|
||||
<!-- Export Button -->
|
||||
<!-- Export Button (only when vendor selected) -->
|
||||
<button
|
||||
@click="exportAllLanguages()"
|
||||
:disabled="exporting"
|
||||
@@ -138,6 +141,7 @@
|
||||
<thead>
|
||||
<tr class="text-xs font-semibold tracking-wide text-left text-gray-500 uppercase border-b dark:border-gray-700 bg-gray-50 dark:text-gray-400 dark:bg-gray-800">
|
||||
<th class="px-4 py-3">Product</th>
|
||||
<th class="px-4 py-3" x-show="!selectedVendor">Vendor</th>
|
||||
<th class="px-4 py-3">Identifiers</th>
|
||||
<th class="px-4 py-3">Price</th>
|
||||
<th class="px-4 py-3">Status</th>
|
||||
@@ -148,11 +152,11 @@
|
||||
<!-- Empty State -->
|
||||
<template x-if="products.length === 0">
|
||||
<tr>
|
||||
<td colspan="5" class="px-4 py-8 text-center text-gray-600 dark:text-gray-400">
|
||||
<td :colspan="selectedVendor ? 5 : 6" class="px-4 py-8 text-center text-gray-600 dark:text-gray-400">
|
||||
<div class="flex flex-col items-center">
|
||||
<span x-html="$icon('cube', 'w-12 h-12 mb-2 text-gray-300')"></span>
|
||||
<p class="font-medium">No products found</p>
|
||||
<p class="text-xs mt-1" x-text="productFilters.search ? 'Try adjusting your search' : 'Import products to get started'"></p>
|
||||
<p class="text-xs mt-1" x-text="productFilters.search ? 'Try adjusting your search' : (selectedVendor ? 'Import products to get started' : 'No Letzshop products in the catalog')"></p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -183,6 +187,11 @@
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<!-- Vendor (shown when no vendor filter) -->
|
||||
<td class="px-4 py-3 text-sm" x-show="!selectedVendor">
|
||||
<span class="font-medium" x-text="product.vendor_name || '-'"></span>
|
||||
</td>
|
||||
|
||||
<!-- Identifiers -->
|
||||
<td class="px-4 py-3 text-sm">
|
||||
<div class="space-y-1">
|
||||
|
||||
@@ -78,7 +78,6 @@
|
||||
<!-- Vendor Operations Section -->
|
||||
{{ section_header('Vendor Operations', 'vendorOps') }}
|
||||
{% call section_content('vendorOps') %}
|
||||
{{ menu_item('marketplace-products', '/admin/marketplace-products', 'database', 'Marketplace Products') }}
|
||||
{{ menu_item('vendor-products', '/admin/vendor-products', 'cube', 'Vendor Products') }}
|
||||
{{ menu_item('customers', '/admin/customers', 'user-group', 'Customers') }}
|
||||
{{ menu_item('inventory', '/admin/inventory', 'archive', 'Inventory') }}
|
||||
|
||||
@@ -218,7 +218,7 @@ function adminMarketplaceLetzshop() {
|
||||
},
|
||||
|
||||
/**
|
||||
* Load cross-vendor aggregate data
|
||||
* Load cross-vendor aggregate data (when no vendor is selected)
|
||||
*/
|
||||
async loadCrossVendorData() {
|
||||
marketplaceLetzshopLog.info('Loading cross-vendor data');
|
||||
@@ -226,6 +226,7 @@ function adminMarketplaceLetzshop() {
|
||||
|
||||
try {
|
||||
await Promise.all([
|
||||
this.loadProducts(),
|
||||
this.loadOrders(),
|
||||
this.loadExceptions(),
|
||||
this.loadExceptionStats(),
|
||||
@@ -428,27 +429,25 @@ function adminMarketplaceLetzshop() {
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
||||
/**
|
||||
* Load Letzshop products for selected vendor
|
||||
* Uses /admin/products endpoint with marketplace=Letzshop filter
|
||||
* Load Letzshop products
|
||||
* When vendor is selected: shows products for that vendor
|
||||
* When no vendor selected: shows ALL Letzshop marketplace products
|
||||
*/
|
||||
async loadProducts() {
|
||||
if (!this.selectedVendor) {
|
||||
this.products = [];
|
||||
this.totalProducts = 0;
|
||||
this.productStats = { total: 0, active: 0, inactive: 0, last_sync: null };
|
||||
return;
|
||||
}
|
||||
|
||||
this.loadingProducts = true;
|
||||
|
||||
try {
|
||||
const params = new URLSearchParams({
|
||||
marketplace: 'Letzshop',
|
||||
vendor_name: this.selectedVendor.name,
|
||||
skip: ((this.productsPage - 1) * this.productsLimit).toString(),
|
||||
limit: this.productsLimit.toString()
|
||||
});
|
||||
|
||||
// Filter by vendor if one is selected
|
||||
if (this.selectedVendor) {
|
||||
params.append('vendor_name', this.selectedVendor.name);
|
||||
}
|
||||
|
||||
if (this.productFilters.search) {
|
||||
params.append('search', this.productFilters.search);
|
||||
}
|
||||
@@ -474,15 +473,19 @@ function adminMarketplaceLetzshop() {
|
||||
|
||||
/**
|
||||
* Load product statistics for Letzshop products
|
||||
* Shows stats for selected vendor or all Letzshop products
|
||||
*/
|
||||
async loadProductStats() {
|
||||
if (!this.selectedVendor) return;
|
||||
|
||||
try {
|
||||
const params = new URLSearchParams({
|
||||
marketplace: 'Letzshop',
|
||||
vendor_name: this.selectedVendor.name
|
||||
marketplace: 'Letzshop'
|
||||
});
|
||||
|
||||
// Filter by vendor if one is selected
|
||||
if (this.selectedVendor) {
|
||||
params.append('vendor_name', this.selectedVendor.name);
|
||||
}
|
||||
|
||||
const response = await apiClient.get(`/admin/products/stats?${params}`);
|
||||
this.productStats = {
|
||||
total: response.total || 0,
|
||||
|
||||
Reference in New Issue
Block a user