Remove deprecated scripts and components related to Nostr functionality, including admin post debugging, VAPID key generation, and admin note sending. Clean up package dependencies by removing unused libraries and updating package-lock.json and package.json accordingly.
This commit is contained in:
parent
2f0024478d
commit
a551f46c90
16 changed files with 7 additions and 1488 deletions
|
|
@ -1,300 +0,0 @@
|
|||
<template>
|
||||
<div class="nostrmarket-publisher">
|
||||
<div class="publisher-header">
|
||||
<h3>Nostrmarket Integration</h3>
|
||||
<p>Publish your stalls and products to the nostrmarket network</p>
|
||||
</div>
|
||||
|
||||
<div class="publisher-status">
|
||||
<div class="status-item">
|
||||
<span class="label">Stalls:</span>
|
||||
<span class="value">{{ stallCount }}</span>
|
||||
</div>
|
||||
<div class="status-item">
|
||||
<span class="label">Products:</span>
|
||||
<span class="value">{{ productCount }}</span>
|
||||
</div>
|
||||
<div class="status-item">
|
||||
<span class="label">Published:</span>
|
||||
<span class="value">{{ publishedCount }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="publisher-actions">
|
||||
<button
|
||||
@click="publishCatalog"
|
||||
:disabled="isPublishing || !canPublish"
|
||||
class="publish-btn"
|
||||
:class="{ 'publishing': isPublishing }"
|
||||
>
|
||||
<span v-if="isPublishing">Publishing...</span>
|
||||
<span v-else>Publish to Nostrmarket</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
@click="refreshStatus"
|
||||
:disabled="isRefreshing"
|
||||
class="refresh-btn"
|
||||
>
|
||||
<span v-if="isRefreshing">Refreshing...</span>
|
||||
<span v-else>Refresh Status</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-if="lastResult" class="publish-result">
|
||||
<h4>Last Publication Result:</h4>
|
||||
<div class="result-details">
|
||||
<div class="result-section">
|
||||
<h5>Stalls Published:</h5>
|
||||
<ul>
|
||||
<li v-for="(eventId, stallId) in lastResult.stalls" :key="stallId">
|
||||
{{ getStallName(String(stallId)) }}: {{ eventId }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="result-section">
|
||||
<h5>Products Published:</h5>
|
||||
<ul>
|
||||
<li v-for="(eventId, productId) in lastResult.products" :key="productId">
|
||||
{{ getProductName(String(productId)) }}: {{ eventId }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="error" class="error-message">
|
||||
<p>Error: {{ error }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { useMarketStore } from '@/stores/market'
|
||||
|
||||
const marketStore = useMarketStore()
|
||||
|
||||
// State
|
||||
const isPublishing = ref(false)
|
||||
const isRefreshing = ref(false)
|
||||
const lastResult = ref<any>(null)
|
||||
const error = ref<string | null>(null)
|
||||
|
||||
// Computed
|
||||
const stallCount = computed(() => marketStore.stalls.length)
|
||||
const productCount = computed(() => marketStore.products.length)
|
||||
const publishedCount = computed(() => {
|
||||
const publishedStalls = marketStore.stalls.filter(s => s.nostrEventId).length
|
||||
const publishedProducts = marketStore.products.filter(p => p.nostrEventId).length
|
||||
return publishedStalls + publishedProducts
|
||||
})
|
||||
|
||||
const canPublish = computed(() => {
|
||||
return stallCount.value > 0 && productCount.value > 0
|
||||
})
|
||||
|
||||
// Methods
|
||||
const publishCatalog = async () => {
|
||||
if (!canPublish.value) return
|
||||
|
||||
isPublishing.value = true
|
||||
error.value = null
|
||||
|
||||
try {
|
||||
const result = await marketStore.publishToNostrmarket()
|
||||
lastResult.value = result
|
||||
console.log('Catalog published successfully:', result)
|
||||
} catch (err) {
|
||||
error.value = err instanceof Error ? err.message : 'Unknown error occurred'
|
||||
console.error('Failed to publish catalog:', err)
|
||||
} finally {
|
||||
isPublishing.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const refreshStatus = async () => {
|
||||
isRefreshing.value = true
|
||||
|
||||
try {
|
||||
// Force a refresh of the store data
|
||||
await new Promise(resolve => setTimeout(resolve, 100))
|
||||
} catch (err) {
|
||||
console.error('Failed to refresh status:', err)
|
||||
} finally {
|
||||
isRefreshing.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const getStallName = (stallId: string) => {
|
||||
const stall = marketStore.stalls.find(s => s.id === stallId)
|
||||
return stall?.name || stallId
|
||||
}
|
||||
|
||||
const getProductName = (productId: string) => {
|
||||
const product = marketStore.products.find(p => p.id === productId)
|
||||
return product?.name || productId
|
||||
}
|
||||
|
||||
// Initialize
|
||||
onMounted(() => {
|
||||
refreshStatus()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.nostrmarket-publisher {
|
||||
padding: 1.5rem;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 0.5rem;
|
||||
background: white;
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.publisher-header h3 {
|
||||
margin: 0 0 0.5rem 0;
|
||||
color: #1f2937;
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.publisher-header p {
|
||||
margin: 0 0 1.5rem 0;
|
||||
color: #6b7280;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.publisher-status {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 1rem;
|
||||
margin-bottom: 1.5rem;
|
||||
padding: 1rem;
|
||||
background: #f9fafb;
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
|
||||
.status-item {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.status-item .label {
|
||||
display: block;
|
||||
font-size: 0.75rem;
|
||||
color: #6b7280;
|
||||
text-transform: uppercase;
|
||||
font-weight: 500;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.status-item .value {
|
||||
display: block;
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.publisher-actions {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.publish-btn, .refresh-btn {
|
||||
padding: 0.75rem 1.5rem;
|
||||
border: none;
|
||||
border-radius: 0.375rem;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.publish-btn {
|
||||
background: #3b82f6;
|
||||
color: white;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.publish-btn:hover:not(:disabled) {
|
||||
background: #2563eb;
|
||||
}
|
||||
|
||||
.publish-btn:disabled {
|
||||
background: #9ca3af;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.publish-btn.publishing {
|
||||
background: #059669;
|
||||
}
|
||||
|
||||
.refresh-btn {
|
||||
background: #f3f4f6;
|
||||
color: #374151;
|
||||
border: 1px solid #d1d5db;
|
||||
}
|
||||
|
||||
.refresh-btn:hover:not(:disabled) {
|
||||
background: #e5e7eb;
|
||||
}
|
||||
|
||||
.refresh-btn:disabled {
|
||||
background: #f9fafb;
|
||||
color: #9ca3af;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.publish-result {
|
||||
margin-top: 1.5rem;
|
||||
padding: 1rem;
|
||||
background: #f0fdf4;
|
||||
border: 1px solid #bbf7d0;
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
|
||||
.publish-result h4 {
|
||||
margin: 0 0 1rem 0;
|
||||
color: #166534;
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.result-details {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.result-section h5 {
|
||||
margin: 0 0 0.5rem 0;
|
||||
color: #166534;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.result-section ul {
|
||||
margin: 0;
|
||||
padding-left: 1rem;
|
||||
font-size: 0.75rem;
|
||||
color: #166534;
|
||||
}
|
||||
|
||||
.result-section li {
|
||||
margin-bottom: 0.25rem;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
margin-top: 1rem;
|
||||
padding: 1rem;
|
||||
background: #fef2f2;
|
||||
border: 1px solid #fecaca;
|
||||
border-radius: 0.375rem;
|
||||
color: #dc2626;
|
||||
}
|
||||
|
||||
.error-message p {
|
||||
margin: 0;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -141,7 +141,6 @@
|
|||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
// import { useMarketStore } from '@/stores/market'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Shield } from 'lucide-vue-next'
|
||||
import type { ShippingZone } from '@/stores/market'
|
||||
|
|
|
|||
|
|
@ -201,7 +201,6 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
// import { useMarketStore } from '@/stores/market'
|
||||
import { useOrderEvents } from '@/composables/useOrderEvents'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Input } from '@/components/ui/input'
|
||||
|
|
|
|||
|
|
@ -1,80 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { LogOut, AlertTriangle } from 'lucide-vue-next'
|
||||
|
||||
// Define component name for better debugging
|
||||
defineOptions({
|
||||
name: 'LogoutConfirmDialog'
|
||||
})
|
||||
|
||||
interface Props {
|
||||
variant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link'
|
||||
size?: 'default' | 'sm' | 'lg' | 'icon'
|
||||
class?: string
|
||||
children?: any
|
||||
}
|
||||
|
||||
interface Emits {
|
||||
(e: 'confirm'): void
|
||||
}
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
variant: 'destructive',
|
||||
size: 'default'
|
||||
})
|
||||
|
||||
const emit = defineEmits<Emits>()
|
||||
const isOpen = ref(false)
|
||||
|
||||
const handleConfirm = () => {
|
||||
isOpen.value = false
|
||||
emit('confirm')
|
||||
}
|
||||
|
||||
const handleCancel = () => {
|
||||
isOpen.value = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Dialog v-model:open="isOpen">
|
||||
<DialogTrigger as-child>
|
||||
<slot>
|
||||
<Button :variant="variant" :size="size" :class="class">
|
||||
<LogOut class="h-4 w-4 mr-2" />
|
||||
Logout
|
||||
</Button>
|
||||
</slot>
|
||||
</DialogTrigger>
|
||||
|
||||
<DialogContent class="sm:max-w-md">
|
||||
<DialogHeader class="space-y-4">
|
||||
<div class="mx-auto w-12 h-12 rounded-full bg-gradient-to-br from-destructive to-destructive/80 p-0.5">
|
||||
<div class="w-full h-full rounded-full bg-background flex items-center justify-center">
|
||||
<AlertTriangle class="h-6 w-6 text-destructive" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center space-y-2">
|
||||
<DialogTitle class="text-xl font-semibold text-foreground">
|
||||
Confirm Logout
|
||||
</DialogTitle>
|
||||
<DialogDescription class="text-muted-foreground">
|
||||
Are you sure you want to logout? You will need to log in again to access your account.
|
||||
</DialogDescription>
|
||||
</div>
|
||||
</DialogHeader>
|
||||
|
||||
<DialogFooter class="flex flex-col sm:flex-row gap-2 sm:gap-3">
|
||||
<Button variant="ghost" @click="handleCancel" class="flex-1 sm:flex-none">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button variant="destructive" @click="handleConfirm" class="flex-1 sm:flex-none">
|
||||
<LogOut class="h-4 w-4 mr-2" />
|
||||
Logout
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { FuzzySearch, useFuzzySearch } from './index'
|
||||
|
||||
// Sample data for demonstration
|
||||
interface Product {
|
||||
id: number
|
||||
name: string
|
||||
description: string
|
||||
category: string
|
||||
price: number
|
||||
}
|
||||
|
||||
const products = ref<Product[]>([
|
||||
{ id: 1, name: 'Laptop', description: 'High-performance laptop for work and gaming', category: 'Electronics', price: 1200 },
|
||||
{ id: 2, name: 'Smartphone', description: 'Latest smartphone with advanced features', category: 'Electronics', price: 800 },
|
||||
{ id: 3, name: 'Headphones', description: 'Wireless noise-cancelling headphones', category: 'Audio', price: 200 },
|
||||
{ id: 4, name: 'Coffee Maker', description: 'Automatic coffee maker for home use', category: 'Kitchen', price: 150 },
|
||||
{ id: 5, name: 'Running Shoes', description: 'Comfortable running shoes for athletes', category: 'Sports', price: 120 },
|
||||
{ id: 6, name: 'Backpack', description: 'Durable backpack for travel and daily use', category: 'Travel', price: 80 },
|
||||
{ id: 7, name: 'Tablet', description: 'Portable tablet for entertainment and work', category: 'Electronics', price: 500 },
|
||||
{ id: 8, name: 'Blender', description: 'High-speed blender for smoothies and shakes', category: 'Kitchen', price: 100 },
|
||||
])
|
||||
|
||||
// Fuzzy search configuration
|
||||
const searchOptions = {
|
||||
fuseOptions: {
|
||||
keys: ['name', 'description', 'category'],
|
||||
threshold: 0.3,
|
||||
distance: 100,
|
||||
ignoreLocation: true,
|
||||
useExtendedSearch: false,
|
||||
minMatchCharLength: 1,
|
||||
shouldSort: true,
|
||||
findAllMatches: false,
|
||||
location: 0,
|
||||
isCaseSensitive: false,
|
||||
},
|
||||
resultLimit: 10,
|
||||
matchAllWhenSearchEmpty: true,
|
||||
minSearchLength: 1,
|
||||
}
|
||||
|
||||
// Use the fuzzy search composable
|
||||
const {
|
||||
searchQuery,
|
||||
results,
|
||||
filteredItems,
|
||||
isSearching,
|
||||
resultCount
|
||||
} = useFuzzySearch(products, searchOptions)
|
||||
|
||||
// Handle search results
|
||||
const handleSearchResults = (results: Product[]) => {
|
||||
console.log('Search results:', results)
|
||||
}
|
||||
|
||||
const handleSearch = (query: string) => {
|
||||
console.log('Search query:', query)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="p-6 max-w-4xl mx-auto">
|
||||
<h1 class="text-3xl font-bold mb-6">Fuzzy Search Demo</h1>
|
||||
|
||||
<!-- Fuzzy Search Component -->
|
||||
<div class="mb-8">
|
||||
<h2 class="text-xl font-semibold mb-4">Search Products</h2>
|
||||
<FuzzySearch
|
||||
:data="products"
|
||||
:options="searchOptions"
|
||||
placeholder="Search products by name, description, or category..."
|
||||
@search="handleSearch"
|
||||
@results="handleSearchResults"
|
||||
class="max-w-md"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Search Results -->
|
||||
<div class="mb-8">
|
||||
<h2 class="text-xl font-semibold mb-4">
|
||||
Results ({{ resultCount }} found)
|
||||
<span v-if="isSearching" class="text-sm font-normal text-muted-foreground">
|
||||
- Searching for "{{ searchQuery }}"
|
||||
</span>
|
||||
</h2>
|
||||
|
||||
<div v-if="filteredItems.length === 0 && isSearching" class="text-center py-8 text-muted-foreground">
|
||||
No products found matching your search.
|
||||
</div>
|
||||
|
||||
<div v-else class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
<div
|
||||
v-for="product in filteredItems"
|
||||
:key="product.id"
|
||||
class="border rounded-lg p-4 hover:shadow-md transition-shadow"
|
||||
>
|
||||
<h3 class="font-semibold text-lg">{{ product.name }}</h3>
|
||||
<p class="text-sm text-muted-foreground mb-2">{{ product.description }}</p>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-sm bg-secondary px-2 py-1 rounded">{{ product.category }}</span>
|
||||
<span class="font-semibold">${{ product.price }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Raw Results (for debugging) -->
|
||||
<div v-if="isSearching" class="mt-8 p-4 bg-muted rounded-lg">
|
||||
<h3 class="font-semibold mb-2">Raw Search Results (with scoring)</h3>
|
||||
<pre class="text-xs overflow-auto">{{ JSON.stringify(results, null, 2) }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
Loading…
Add table
Add a link
Reference in a new issue