refactor: consolidate Product types into single source of truth
- Replace dual Product interfaces with unified domain model in types/market.ts - Rename API response type to ProductApiResponse for clarity - Add mapApiResponseToProduct() function for clean API-to-domain conversion - Update MerchantStore.vue to use mapping function instead of manual property assignment - Fix CreateProductDialog.vue to properly handle type conversions for API calls - Resolve TypeScript readonly type conflicts using type assertions instead of array spreading - Add missing reactive references (searchQuery) and remove unused imports - Prevent Vue 3 recursion issues by maintaining original reactive object references This eliminates confusion between API response structure and application domain model, following single source of truth principle for better maintainability and type safety.
This commit is contained in:
parent
478b83ddd3
commit
25d17b481d
4 changed files with 100 additions and 40 deletions
|
|
@ -258,7 +258,7 @@
|
|||
<div class="space-y-3">
|
||||
<div>
|
||||
<h4 class="font-semibold text-foreground">{{ product.name }}</h4>
|
||||
<p v-if="product.config.description" class="text-sm text-muted-foreground mt-1">
|
||||
<p v-if="product.config?.description" class="text-sm text-muted-foreground mt-1">
|
||||
{{ product.config.description }}
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -266,7 +266,7 @@
|
|||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<span class="text-lg font-bold text-foreground">
|
||||
{{ product.price }} {{ product.config.currency || activeStall?.currency || 'sat' }}
|
||||
{{ product.price }} {{ product.config?.currency || activeStall?.currency || 'sat' }}
|
||||
</span>
|
||||
<div class="text-sm text-muted-foreground">
|
||||
Qty: {{ product.quantity }}
|
||||
|
|
@ -342,7 +342,9 @@ import {
|
|||
AlertCircle,
|
||||
User
|
||||
} from 'lucide-vue-next'
|
||||
import type { NostrmarketAPI, Merchant, Stall, Product } from '../services/nostrmarketAPI'
|
||||
import type { NostrmarketAPI, Merchant, Stall } from '../services/nostrmarketAPI'
|
||||
import type { Product } from '../types/market'
|
||||
import { mapApiResponseToProduct } from '../types/market'
|
||||
import { auth } from '@/composables/useAuthService'
|
||||
import { useToast } from '@/core/composables/useToast'
|
||||
import { injectService, SERVICE_TOKENS } from '@/core/di-container'
|
||||
|
|
@ -516,26 +518,14 @@ const loadStallProducts = async () => {
|
|||
inkey,
|
||||
activeStall.value.id!
|
||||
)
|
||||
// Enrich products with stall name and missing properties to match Product interface
|
||||
const enrichedProducts = (products || []).map(product => ({
|
||||
id: product.id || `${product.stall_id}-${Date.now()}`, // Ensure id is always string
|
||||
stall_id: product.stall_id,
|
||||
stallName: activeStall.value?.name || 'Unknown Stall',
|
||||
name: product.name,
|
||||
description: product.config?.description || '',
|
||||
price: product.price,
|
||||
currency: activeStall.value?.currency || 'sats', // Use stall currency
|
||||
quantity: product.quantity,
|
||||
images: product.images,
|
||||
categories: product.categories,
|
||||
createdAt: product.event_created_at || Date.now(),
|
||||
updatedAt: Date.now(),
|
||||
nostrEventId: product.event_id,
|
||||
// API-specific properties that are expected by the template
|
||||
active: product.active ?? true,
|
||||
pending: product.pending ?? false,
|
||||
config: product.config || { currency: activeStall.value?.currency || 'sats' }
|
||||
}))
|
||||
// Convert API responses to domain models using clean mapping function
|
||||
const enrichedProducts = (products || []).map(product =>
|
||||
mapApiResponseToProduct(
|
||||
product,
|
||||
activeStall.value?.name || 'Unknown Stall',
|
||||
activeStall.value?.currency || 'sats'
|
||||
)
|
||||
)
|
||||
stallProducts.value = enrichedProducts
|
||||
|
||||
// Only add active products to the market store so they appear in the main market
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue