Enhance MerchantStore component with user store creation flow

- Introduce an empty state for users without a store, prompting them to create one.
- Implement computed property to check if the user has a store based on their order history.
- Update store statistics to reflect only the user's orders.
- Add a placeholder function for future store creation functionality.

These changes improve user experience by guiding new merchants to set up their stores effectively.
This commit is contained in:
padreug 2025-09-08 12:24:17 +02:00
parent 3679c719a3
commit 8e34f2c74e
2 changed files with 87 additions and 25 deletions

View file

@ -1,23 +1,40 @@
<template>
<div class="space-y-6">
<!-- Header -->
<div class="flex items-center justify-between">
<div>
<h2 class="text-2xl font-bold text-foreground">My Store</h2>
<p class="text-muted-foreground mt-1">Manage incoming orders and your products</p>
</div>
<div class="flex items-center gap-3">
<Button @click="navigateToMarket" variant="outline">
<Store class="w-4 h-4 mr-2" />
Browse Market
</Button>
<Button @click="addProduct" variant="default">
<Plus class="w-4 h-4 mr-2" />
Add Product
</Button>
<!-- No Store Empty State -->
<div v-if="!userHasStore" class="flex flex-col items-center justify-center py-12">
<div class="w-24 h-24 bg-muted rounded-full flex items-center justify-center mb-6">
<Store class="w-12 h-12 text-muted-foreground" />
</div>
<h2 class="text-2xl font-bold text-foreground mb-2">Create Your Store</h2>
<p class="text-muted-foreground text-center mb-6 max-w-md">
You don't have a store yet. Set up your merchant profile to start selling products on the Nostr marketplace.
</p>
<Button @click="createStore" variant="default" size="lg">
<Plus class="w-5 h-5 mr-2" />
Create My Store
</Button>
</div>
<!-- Store Content (shown when user has a store) -->
<div v-else>
<!-- Header -->
<div class="flex items-center justify-between">
<div>
<h2 class="text-2xl font-bold text-foreground">My Store</h2>
<p class="text-muted-foreground mt-1">Manage incoming orders and your products</p>
</div>
<div class="flex items-center gap-3">
<Button @click="navigateToMarket" variant="outline">
<Store class="w-4 h-4 mr-2" />
Browse Market
</Button>
<Button @click="addProduct" variant="default">
<Plus class="w-4 h-4 mr-2" />
Add Product
</Button>
</div>
</div>
<!-- Store Stats -->
<div class="grid grid-cols-1 md:grid-cols-4 gap-6">
<!-- Incoming Orders -->
@ -295,6 +312,7 @@
</div>
</div>
</div>
</div> <!-- End of Store Content wrapper -->
</div>
</template>
@ -332,29 +350,60 @@ const nostrmarketService = injectService(SERVICE_TOKENS.NOSTRMARKET_SERVICE) as
const isGeneratingInvoice = ref<string | null>(null)
// Computed properties
const userHasStore = computed(() => {
// Check if user has any store/stall set up
// For now, we'll check if they have ever been a seller on any order
const currentUserPubkey = auth.currentUser?.value?.pubkey
if (!currentUserPubkey) return false
// TODO: In the future, this should check if user has created a stall
// For now, we'll show the create store prompt if they have no incoming orders
const hasIncomingOrders = Object.values(marketStore.orders).some(order =>
order.sellerPubkey === currentUserPubkey
)
return hasIncomingOrders
})
const incomingOrders = computed(() => {
// For now, show all orders as "incoming" since we don't have merchant filtering yet
// In a real implementation, this would filter orders where the current user is the seller
// Filter orders to only show those where the current user is the seller
const currentUserPubkey = auth.currentUser?.value?.pubkey
if (!currentUserPubkey) return []
return Object.values(marketStore.orders)
.filter(order => order.status === 'pending')
.filter(order => order.sellerPubkey === currentUserPubkey && order.status === 'pending')
.sort((a, b) => b.createdAt - a.createdAt)
})
const storeStats = computed(() => {
const orders = Object.values(marketStore.orders)
const currentUserPubkey = auth.currentUser?.value?.pubkey
if (!currentUserPubkey) {
return {
incomingOrders: 0,
pendingOrders: 0,
paidOrders: 0,
totalSales: 0,
totalProducts: 0,
activeProducts: 0,
satisfaction: 0,
totalReviews: 0
}
}
// Filter orders to only count those where current user is the seller
const myOrders = Object.values(marketStore.orders).filter(o => o.sellerPubkey === currentUserPubkey)
const now = Date.now() / 1000
const thirtyDaysAgo = now - (30 * 24 * 60 * 60)
return {
incomingOrders: orders.filter(o => o.status === 'pending').length,
pendingOrders: orders.filter(o => o.status === 'pending').length,
paidOrders: orders.filter(o => o.status === 'paid').length,
totalSales: orders
incomingOrders: myOrders.filter(o => o.status === 'pending').length,
pendingOrders: myOrders.filter(o => o.status === 'pending').length,
paidOrders: myOrders.filter(o => o.status === 'paid').length,
totalSales: myOrders
.filter(o => o.status === 'paid' && o.createdAt > thirtyDaysAgo)
.reduce((sum, o) => sum + o.total, 0),
totalProducts: 0, // TODO: Implement product management
activeProducts: 0, // TODO: Implement product management
satisfaction: 95, // TODO: Implement review system
satisfaction: userHasStore.value ? 95 : 0, // TODO: Implement review system
totalReviews: 0 // TODO: Implement review system
}
})
@ -527,6 +576,11 @@ const addProduct = () => {
console.log('Adding new product')
}
const createStore = () => {
// TODO: Implement store creation flow
console.log('Create store functionality to be implemented')
}
const navigateToMarket = () => router.push('/market')
const viewAllOrders = () => router.push('/market-dashboard?tab=orders')
const generateBulkInvoices = () => console.log('Generate bulk invoices')

View file

@ -278,7 +278,15 @@ const statusFilter = ref('')
const sortBy = ref('createdAt')
// Computed properties
const allOrders = computed(() => Object.values(marketStore.orders))
const allOrders = computed(() => {
// Filter orders to only show those where the current user is the buyer
const currentUserPubkey = auth.currentUser?.value?.pubkey
if (!currentUserPubkey) return []
return Object.values(marketStore.orders).filter(order =>
order.buyerPubkey === currentUserPubkey
)
})
const filteredOrders = computed(() => {
if (!statusFilter.value) return allOrders.value