webapp/src/modules/market/components/MarketSettings.vue
padreug 17c07c37a0 Refactor chat and market modules for improved integration and maintainability
- Remove deprecated Nostr chat and relay hub components, transitioning to a modular chat service for better encapsulation.
- Update App.vue and Navbar.vue to utilize the new chat module, enhancing user experience with automatic peer management.
- Simplify event handling and connection logic in ChatComponent.vue, ensuring compatibility with the new chat service architecture.
- Adjust market settings and order history components to reflect changes in the chat module, improving overall coherence in the application structure.
- Clean up unused imports and streamline configuration access for better performance and maintainability.
2025-09-05 01:44:15 +02:00

332 lines
12 KiB
Vue

<template>
<div class="space-y-6">
<!-- Header -->
<div>
<h2 class="text-2xl font-bold text-foreground">Market Settings</h2>
<p class="text-muted-foreground mt-1">Configure your store and market preferences</p>
</div>
<!-- Settings Tabs -->
<div class="border-b border-border">
<nav class="flex space-x-8">
<button
v-for="tab in settingsTabs"
:key="tab.id"
@click="activeSettingsTab = tab.id"
:class="[
'py-2 px-1 border-b-2 font-medium text-sm transition-colors',
activeSettingsTab === tab.id
? 'border-primary text-primary'
: 'border-transparent text-muted-foreground hover:text-foreground hover:border-muted-foreground'
]"
>
{{ tab.name }}
</button>
</nav>
</div>
<!-- Settings Content -->
<div class="min-h-[500px]">
<!-- Store Settings Tab -->
<div v-if="activeSettingsTab === 'store'" class="space-y-6">
<div class="bg-card p-6 rounded-lg border shadow-sm">
<h3 class="text-lg font-semibold text-foreground mb-4">Store Information</h3>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label class="block text-sm font-medium text-foreground mb-2">Store Name</label>
<Input v-model="storeSettings.name" placeholder="Enter store name" />
</div>
<div>
<label class="block text-sm font-medium text-foreground mb-2">Store Description</label>
<Input v-model="storeSettings.description" placeholder="Enter store description" />
</div>
<div>
<label class="block text-sm font-medium text-foreground mb-2">Contact Email</label>
<Input v-model="storeSettings.contactEmail" type="email" placeholder="Enter contact email" />
</div>
<div>
<label class="block text-sm font-medium text-foreground mb-2">Store Category</label>
<select v-model="storeSettings.category" class="w-full px-3 py-2 border border-input rounded-md focus:outline-none focus:ring-2 focus:ring-ring focus:border-ring bg-background text-foreground">
<option value="">Select category</option>
<option value="electronics">Electronics</option>
<option value="clothing">Clothing</option>
<option value="books">Books</option>
<option value="food">Food & Beverages</option>
<option value="services">Services</option>
<option value="other">Other</option>
</select>
</div>
</div>
<div class="mt-6">
<Button @click="saveStoreSettings" variant="default">
Save Store Settings
</Button>
</div>
</div>
</div>
<!-- Payment Settings Tab -->
<div v-else-if="activeSettingsTab === 'payment'" class="space-y-6">
<div class="bg-card p-6 rounded-lg border shadow-sm">
<h3 class="text-lg font-semibold text-foreground mb-4">Payment Configuration</h3>
<div class="space-y-4">
<div>
<label class="block text-sm font-medium text-foreground mb-2">Default Currency</label>
<select v-model="paymentSettings.defaultCurrency" class="w-full px-3 py-2 border border-input rounded-md focus:outline-none focus:ring-2 focus:ring-ring focus:border-ring bg-background text-foreground">
<option value="sat">Satoshi (sats)</option>
<option value="btc">Bitcoin (BTC)</option>
<option value="usd">US Dollar (USD)</option>
<option value="eur">Euro (EUR)</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-foreground mb-2">Invoice Expiry (minutes)</label>
<Input v-model="paymentSettings.invoiceExpiry" type="number" min="5" max="1440" placeholder="60" />
</div>
<div>
<label class="block text-sm font-medium text-foreground mb-2">Auto-generate Invoices</label>
<div class="flex items-center">
<input
v-model="paymentSettings.autoGenerateInvoices"
type="checkbox"
class="h-4 w-4 text-primary focus:ring-primary border-input rounded"
/>
<label class="ml-2 text-sm text-foreground">
Automatically generate Lightning invoices for new orders
</label>
</div>
</div>
</div>
<div class="mt-6">
<Button @click="savePaymentSettings" variant="default">
Save Payment Settings
</Button>
</div>
</div>
</div>
<!-- Nostr Settings Tab -->
<div v-else-if="activeSettingsTab === 'nostr'" class="space-y-6">
<div class="bg-card p-6 rounded-lg border shadow-sm">
<h3 class="text-lg font-semibold text-foreground mb-4">Nostr Network Configuration</h3>
<div class="space-y-4">
<div>
<label class="block text-sm font-medium text-foreground mb-2">Relay Connections</label>
<div class="space-y-2">
<div v-for="relay in nostrSettings.relays" :key="relay" class="flex items-center gap-2">
<Input :value="relay" readonly class="flex-1" />
<Button @click="removeRelay(relay)" variant="outline" size="sm">
<X class="w-4 h-4" />
</Button>
</div>
<div class="flex gap-2">
<Input v-model="newRelay" placeholder="wss://relay.example.com" class="flex-1" />
<Button @click="addRelay" variant="outline">
Add Relay
</Button>
</div>
</div>
</div>
<div>
<label class="block text-sm font-medium text-foreground mb-2">Nostr Public Key</label>
<Input :value="nostrSettings.pubkey" readonly class="font-mono text-sm" />
<p class="text-xs text-muted-foreground mt-1">Your Nostr public key for receiving orders</p>
</div>
<div>
<label class="block text-sm font-medium text-foreground mb-2">Connection Status</label>
<div class="flex items-center gap-2">
<div
class="w-3 h-3 rounded-full"
:class="orderEvents.isSubscribed ? 'bg-green-500' : 'bg-yellow-500'"
></div>
<span class="text-sm text-muted-foreground">
{{ orderEvents.isSubscribed ? 'Connected to Nostr network' : 'Connecting to Nostr network...' }}
</span>
</div>
</div>
</div>
<div class="mt-6">
<Button @click="saveNostrSettings" variant="default">
Save Nostr Settings
</Button>
</div>
</div>
</div>
<!-- Shipping Settings Tab -->
<div v-else-if="activeSettingsTab === 'shipping'" class="space-y-6">
<div class="bg-card p-6 rounded-lg border shadow-sm">
<h3 class="text-lg font-semibold text-foreground mb-4">Shipping Zones</h3>
<div class="space-y-4">
<div v-for="zone in shippingSettings.zones" :key="zone.id" class="border border-border rounded-lg p-4">
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<div>
<label class="block text-sm font-medium text-foreground mb-1">Zone Name</label>
<Input v-model="zone.name" placeholder="Zone name" />
</div>
<div>
<label class="block text-sm font-medium text-foreground mb-1">Cost</label>
<Input v-model="zone.cost" type="number" min="0" step="0.01" placeholder="0.00" />
</div>
<div>
<label class="block text-sm font-medium text-foreground mb-1">Currency</label>
<select v-model="zone.currency" class="w-full px-3 py-2 border border-input rounded-md focus:outline-none focus:ring-2 focus:ring-ring focus:border-ring bg-background text-foreground">
<option value="sat">Satoshi (sats)</option>
<option value="btc">Bitcoin (BTC)</option>
<option value="usd">US Dollar (USD)</option>
</select>
</div>
</div>
<div class="mt-3 flex justify-end">
<Button @click="removeShippingZone(zone.id)" variant="outline" size="sm">
Remove Zone
</Button>
</div>
</div>
<Button @click="addShippingZone" variant="outline">
<Plus class="w-4 h-4 mr-2" />
Add Shipping Zone
</Button>
</div>
<div class="mt-6">
<Button @click="saveShippingSettings" variant="default">
Save Shipping Settings
</Button>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
// import { useOrderEvents } from '@/composables/useOrderEvents' // TODO: Move to market module
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Plus, X } from 'lucide-vue-next'
// const marketStore = useMarketStore()
// const orderEvents = useOrderEvents() // TODO: Move to market module
const orderEvents = { isSubscribed: ref(false) } // Temporary mock
// Local state
const activeSettingsTab = ref('store')
const newRelay = ref('')
// Settings data
const storeSettings = ref({
name: 'My Store',
description: 'A great place to shop',
contactEmail: 'store@example.com',
category: 'other'
})
const paymentSettings = ref({
defaultCurrency: 'sat',
invoiceExpiry: 60,
autoGenerateInvoices: true
})
const nostrSettings = ref({
relays: [
'wss://relay.damus.io',
'wss://relay.snort.social',
'wss://nostr-pub.wellorder.net'
],
pubkey: 'npub1...' // TODO: Get from auth
})
const shippingSettings = ref({
zones: [
{
id: '1',
name: 'Local',
cost: 0,
currency: 'sat',
estimatedDays: '1-2 days'
},
{
id: '2',
name: 'Domestic',
cost: 1000,
currency: 'sat',
estimatedDays: '3-5 days'
},
{
id: '3',
name: 'International',
cost: 5000,
currency: 'sat',
estimatedDays: '7-14 days'
}
]
})
// Settings tabs
const settingsTabs = [
{ id: 'store', name: 'Store Settings' },
{ id: 'payment', name: 'Payment Settings' },
{ id: 'nostr', name: 'Nostr Network' },
{ id: 'shipping', name: 'Shipping Zones' }
]
// Methods
const saveStoreSettings = () => {
// TODO: Save store settings
console.log('Saving store settings:', storeSettings.value)
}
const savePaymentSettings = () => {
// TODO: Save payment settings
console.log('Saving payment settings:', paymentSettings.value)
}
const saveNostrSettings = () => {
// TODO: Save Nostr settings
console.log('Saving Nostr settings:', nostrSettings.value)
}
const saveShippingSettings = () => {
// TODO: Save shipping settings
console.log('Saving shipping settings:', shippingSettings.value)
}
const addRelay = () => {
if (newRelay.value && !nostrSettings.value.relays.includes(newRelay.value)) {
nostrSettings.value.relays.push(newRelay.value)
newRelay.value = ''
}
}
const removeRelay = (relay: string) => {
const index = nostrSettings.value.relays.indexOf(relay)
if (index > -1) {
nostrSettings.value.relays.splice(index, 1)
}
}
const addShippingZone = () => {
const newZone = {
id: Date.now().toString(),
name: 'New Zone',
cost: 0,
currency: 'sat',
estimatedDays: '3-5 days'
}
shippingSettings.value.zones.push(newZone)
}
const removeShippingZone = (zoneId: string) => {
const index = shippingSettings.value.zones.findIndex(z => z.id === zoneId)
if (index > -1) {
shippingSettings.value.zones.splice(index, 1)
}
}
// Lifecycle
onMounted(() => {
console.log('Market Settings component loaded')
})
</script>