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:
padreug 2025-09-04 22:39:02 +02:00
parent 2f0024478d
commit a551f46c90
16 changed files with 7 additions and 1488 deletions

View file

@ -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>

View file

@ -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'

View file

@ -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'

View file

@ -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>

View file

@ -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>

View file

@ -1,5 +1,4 @@
// Notification manager for push notifications
// import type { NotificationPayload } from './push'
export interface NotificationOptions {

View file

@ -1,201 +0,0 @@
/**
* Test file for formatting utility functions
* This file can be run with a test runner or used for manual verification
*/
import {
formatNumber,
formatSats,
formatMsats,
formatCurrency,
formatEventPrice,
formatWalletBalance
} from './formatting.js'
// Test data
const testNumbers = [
0,
1,
999,
1000,
1001,
9999,
10000,
10001,
99999,
100000,
100001,
999999,
1000000,
1000001,
1234567,
9999999,
10000000
]
const testSats = [
0,
1,
999,
1000,
1001,
9999,
10000,
10001,
99999,
100000,
100001,
999999,
1000000,
1000001,
1234567,
9999999,
10000000
]
const testMsats = [
0,
1000,
999000,
1000000,
1001000,
9999000,
10000000,
10001000,
99999000,
100000000,
100001000,
999999000,
1000000000,
1000001000,
1234567000,
9999999000,
10000000000
]
const testCurrencies = [
{ amount: 0, currency: 'USD' },
{ amount: 1.99, currency: 'USD' },
{ amount: 999.99, currency: 'USD' },
{ amount: 1000, currency: 'USD' },
{ amount: 1001.50, currency: 'USD' },
{ amount: 9999.99, currency: 'USD' },
{ amount: 10000, currency: 'USD' },
{ amount: 0, currency: 'EUR' },
{ amount: 1.99, currency: 'EUR' },
{ amount: 999.99, currency: 'EUR' },
{ amount: 1000, currency: 'EUR' }
]
const testEventPrices = [
{ price: 0, currency: 'sats' },
{ price: 1, currency: 'sats' },
{ price: 999, currency: 'sats' },
{ price: 1000, currency: 'sats' },
{ price: 1001, currency: 'sats' },
{ price: 9999, currency: 'sats' },
{ price: 10000, currency: 'sats' },
{ price: 0, currency: 'USD' },
{ price: 1.99, currency: 'USD' },
{ price: 999.99, currency: 'USD' },
{ price: 1000, currency: 'USD' },
{ price: 0, currency: 'EUR' },
{ price: 1.99, currency: 'EUR' },
{ price: 999.99, currency: 'EUR' },
{ price: 1000, currency: 'EUR' }
]
// Test functions
function testFormatNumber() {
console.log('Testing formatNumber function:')
testNumbers.forEach(num => {
const formatted = formatNumber(num)
console.log(`${num} -> "${formatted}"`)
})
console.log('')
}
function testFormatSats() {
console.log('Testing formatSats function:')
testSats.forEach(sats => {
const formatted = formatSats(sats)
console.log(`${sats} sats -> "${formatted}"`)
})
console.log('')
}
function testFormatMsats() {
console.log('Testing formatMsats function:')
testMsats.forEach(msats => {
const formatted = formatMsats(msats)
console.log(`${msats} msats -> "${formatted}"`)
})
console.log('')
}
function testFormatCurrency() {
console.log('Testing formatCurrency function:')
testCurrencies.forEach(({ amount, currency }) => {
const formatted = formatCurrency(amount, currency)
console.log(`${amount} ${currency} -> "${formatted}"`)
})
console.log('')
}
function testFormatEventPrice() {
console.log('Testing formatEventPrice function:')
testEventPrices.forEach(({ price, currency }) => {
const formatted = formatEventPrice(price, currency)
console.log(`${price} ${currency} -> "${formatted}"`)
})
console.log('')
}
function testFormatWalletBalance() {
console.log('Testing formatWalletBalance function:')
testMsats.forEach(msats => {
const formatted = formatWalletBalance(msats)
console.log(`${msats} msats -> "${formatted}"`)
})
console.log('')
}
// Run all tests
function runAllTests() {
console.log('=== FORMATTING UTILITY TESTS ===\n')
testFormatNumber()
testFormatSats()
testFormatMsats()
testFormatCurrency()
testFormatEventPrice()
testFormatWalletBalance()
console.log('=== TESTS COMPLETED ===')
}
// Export for manual testing
export {
runAllTests,
testFormatNumber,
testFormatSats,
testFormatMsats,
testFormatCurrency,
testFormatEventPrice,
testFormatWalletBalance
}
// Run tests if this file is executed directly
if (typeof window !== 'undefined') {
// Browser environment - add to window for console testing
(window as any).formattingTests = {
runAllTests,
testFormatNumber,
testFormatSats,
testFormatMsats,
testFormatCurrency,
testFormatEventPrice,
testFormatWalletBalance
}
console.log('Formatting tests available at window.formattingTests')
}

View file

@ -1,187 +0,0 @@
<template>
<div class="min-h-screen flex items-center justify-center px-4 sm:px-6 lg:px-8 xl:px-12 2xl:px-16 py-8">
<div class="flex flex-col items-center justify-center space-y-8 max-w-4xl mx-auto w-full">
<!-- Welcome Section -->
<div class="text-center space-y-4">
<div class="flex justify-center">
<img src="@/assets/logo.png" alt="Logo" class="h-36 w-36 sm:h-48 sm:w-48 md:h-60 md:w-60" />
</div>
<h1 class="text-4xl font-bold tracking-tight">Welcome to the Virtual Realm</h1>
<p class="text-xl text-muted-foreground max-w-md">
Your secure platform for events and community management
</p>
</div>
<!-- Login Card -->
<Card v-if="!showRegister" class="w-full max-w-md">
<CardHeader>
<CardTitle class="text-center">Sign In</CardTitle>
<CardDescription class="text-center">
Enter your credentials to access your account
</CardDescription>
</CardHeader>
<CardContent class="space-y-4">
<div class="space-y-2">
<Label for="username">Username or Email</Label>
<Input id="username" v-model="loginForm.username" placeholder="Enter your username or email"
@keydown.enter="handleLogin" />
</div>
<div class="space-y-2">
<Label for="password">Password</Label>
<Input id="password" type="password" v-model="loginForm.password" placeholder="Enter your password"
@keydown.enter="handleLogin" />
</div>
<p v-if="error" class="text-sm text-destructive text-center">
{{ error }}
</p>
<Button @click="handleLogin" :disabled="isLoading || !canLogin" class="w-full">
<span v-if="isLoading" class="animate-spin text-xl text-stone-700"></span>
Sign In
</Button>
<div class="text-center">
<p class="text-sm text-muted-foreground">
Don't have an account?
<Button variant="link" @click="showRegister = true" class="p-0 h-auto">
Create one
</Button>
</p>
</div>
</CardContent>
</Card>
<!-- Register Card -->
<Card v-else class="w-full max-w-md">
<CardHeader>
<CardTitle class="text-center">Create Account</CardTitle>
<CardDescription class="text-center">
Create a new account to get started
</CardDescription>
</CardHeader>
<CardContent class="space-y-4">
<div class="space-y-2">
<Label for="reg-username">Username</Label>
<Input id="reg-username" v-model="registerForm.username" placeholder="Choose a username"
@keydown.enter="handleRegister" />
</div>
<div class="space-y-2">
<Label for="reg-email">Email (optional)</Label>
<Input id="reg-email" type="email" v-model="registerForm.email" placeholder="Enter your email"
@keydown.enter="handleRegister" />
</div>
<div class="space-y-2">
<Label for="reg-password">Password</Label>
<Input id="reg-password" type="password" v-model="registerForm.password" placeholder="Choose a password"
@keydown.enter="handleRegister" />
</div>
<div class="space-y-2">
<Label for="reg-password-repeat">Confirm Password</Label>
<Input id="reg-password-repeat" type="password" v-model="registerForm.password_repeat"
placeholder="Confirm your password" @keydown.enter="handleRegister" />
</div>
<p v-if="error" class="text-sm text-destructive text-center">
{{ error }}
</p>
<Button @click="handleRegister" :disabled="isLoading || !canRegister" class="w-full">
<span v-if="isLoading" class="animate-spin mr-2"></span>
Create Account
</Button>
<div class="text-center">
<p class="text-sm text-muted-foreground">
Already have an account?
<Button variant="link" @click="showRegister = false" class="p-0 h-auto">
Sign in
</Button>
</p>
</div>
</CardContent>
</Card>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { useRouter } from 'vue-router'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { auth } from '@/composables/useAuth'
import { toast } from 'vue-sonner'
const router = useRouter()
const showRegister = ref(false)
const isLoading = ref(false)
const error = ref('')
// Login form
const loginForm = ref({
username: '',
password: ''
})
// Register form
const registerForm = ref({
username: '',
email: '',
password: '',
password_repeat: ''
})
const canLogin = computed(() => {
return loginForm.value.username.trim() && loginForm.value.password.trim()
})
const canRegister = computed(() => {
const { username, password, password_repeat } = registerForm.value
return username.trim() && password.trim() && password === password_repeat && password.length >= 6
})
async function handleLogin() {
if (!canLogin.value) return
try {
isLoading.value = true
error.value = ''
await auth.login({
username: loginForm.value.username,
password: loginForm.value.password
})
toast.success('Login successful!')
// Redirect to home page after successful login
router.push('/')
} catch (err) {
error.value = err instanceof Error ? err.message : 'Login failed'
toast.error('Login failed. Please check your credentials.')
} finally {
isLoading.value = false
}
}
async function handleRegister() {
if (!canRegister.value) return
try {
isLoading.value = true
error.value = ''
await auth.register({
username: registerForm.value.username,
email: registerForm.value.email || undefined,
password: registerForm.value.password,
password_repeat: registerForm.value.password_repeat
})
toast.success('Registration successful!')
// Redirect to home page after successful registration
router.push('/')
} catch (err) {
error.value = err instanceof Error ? err.message : 'Registration failed'
toast.error('Registration failed. Please try again.')
} finally {
isLoading.value = false
}
}
</script>

View file

@ -60,7 +60,6 @@
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
// import { useAuth } from '@/composables/useAuth'
import { useMarketStore } from '@/stores/market'
import { Badge } from '@/components/ui/badge'
import {