- 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.
332 lines
12 KiB
Vue
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>
|
|
|