Remove dangling PaymentRequestDialog component (may contain confusing legacy code)
This commit is contained in:
parent
fb5c5088d5
commit
16a96ebfc9
1 changed files with 0 additions and 287 deletions
|
|
@ -1,287 +0,0 @@
|
||||||
<template>
|
|
||||||
<Dialog :open="modelValue" @update:open="updateOpen">
|
|
||||||
<DialogContent class="sm:max-w-md">
|
|
||||||
<DialogHeader>
|
|
||||||
<DialogTitle>Payment Request</DialogTitle>
|
|
||||||
<DialogDescription>
|
|
||||||
Complete your payment to finalize your order
|
|
||||||
</DialogDescription>
|
|
||||||
</DialogHeader>
|
|
||||||
|
|
||||||
<div v-if="paymentRequest" class="space-y-4">
|
|
||||||
<!-- Order Details -->
|
|
||||||
<div class="space-y-2">
|
|
||||||
<h4 class="text-sm font-medium">Order Details</h4>
|
|
||||||
<div class="text-xs text-muted-foreground">
|
|
||||||
Order ID: {{ paymentRequest.id }}
|
|
||||||
</div>
|
|
||||||
<div v-if="paymentRequest.message" class="text-sm">
|
|
||||||
{{ paymentRequest.message }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Payment Options -->
|
|
||||||
<div class="space-y-2">
|
|
||||||
<h4 class="text-sm font-medium">Payment Options</h4>
|
|
||||||
<div v-for="option in paymentRequest.payment_options" :key="option.type" class="space-y-2">
|
|
||||||
<Card>
|
|
||||||
<CardContent class="p-4">
|
|
||||||
<div class="flex items-center justify-between">
|
|
||||||
<div class="flex-1">
|
|
||||||
<div class="font-medium">{{ getPaymentTypeLabel(option.type) }}</div>
|
|
||||||
<div class="text-xs text-muted-foreground truncate">{{ option.link }}</div>
|
|
||||||
</div>
|
|
||||||
<div class="ml-4">
|
|
||||||
<Button
|
|
||||||
:variant="option.type === 'ln' ? 'default' : 'outline'"
|
|
||||||
size="sm"
|
|
||||||
@click="handlePayment(option)"
|
|
||||||
>
|
|
||||||
<component :is="getPaymentTypeIcon(option.type)" class="h-4 w-4" />
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Lightning Invoice QR Code -->
|
|
||||||
<div v-if="lightningInvoice" class="space-y-4">
|
|
||||||
<h4 class="text-sm font-medium">Lightning Invoice</h4>
|
|
||||||
<div class="flex justify-center">
|
|
||||||
<div class="bg-white p-4 rounded-lg border">
|
|
||||||
<div v-if="qrCodeLoading" class="w-48 h-48 flex items-center justify-center">
|
|
||||||
<div class="animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900"></div>
|
|
||||||
</div>
|
|
||||||
<img
|
|
||||||
v-else-if="qrCodeDataUrl"
|
|
||||||
:src="qrCodeDataUrl"
|
|
||||||
alt="Lightning payment QR code"
|
|
||||||
class="w-48 h-48"
|
|
||||||
/>
|
|
||||||
<div v-else-if="qrCodeError" class="w-48 h-48 flex items-center justify-center text-red-500 text-sm">
|
|
||||||
{{ qrCodeError }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex justify-center space-x-2">
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
@click="copyInvoice"
|
|
||||||
>
|
|
||||||
Copy Invoice
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
@click="payWithWallet"
|
|
||||||
>
|
|
||||||
Pay with Wallet
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-else class="text-center text-muted-foreground py-8">
|
|
||||||
No payment request available
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<DialogFooter>
|
|
||||||
<Button variant="outline" @click="updateOpen(false)">
|
|
||||||
Close
|
|
||||||
</Button>
|
|
||||||
</DialogFooter>
|
|
||||||
</DialogContent>
|
|
||||||
</Dialog>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { computed, ref, watch } from 'vue'
|
|
||||||
import { toast } from 'vue-sonner'
|
|
||||||
import QRCode from 'qrcode'
|
|
||||||
import { useAuth } from '@/composables/useAuthService'
|
|
||||||
import type { NostrmarketPaymentRequest } from '../services/nostrmarketService'
|
|
||||||
import {
|
|
||||||
Dialog,
|
|
||||||
DialogContent,
|
|
||||||
DialogDescription,
|
|
||||||
DialogFooter,
|
|
||||||
DialogHeader,
|
|
||||||
DialogTitle,
|
|
||||||
} from '@/components/ui/dialog'
|
|
||||||
import { Button } from '@/components/ui/button'
|
|
||||||
import { Card, CardContent } from '@/components/ui/card'
|
|
||||||
import { Zap, Bitcoin, Link, QrCode, CreditCard } from 'lucide-vue-next'
|
|
||||||
|
|
||||||
// Props
|
|
||||||
interface Props {
|
|
||||||
modelValue: boolean
|
|
||||||
paymentRequest?: NostrmarketPaymentRequest
|
|
||||||
}
|
|
||||||
|
|
||||||
const props = defineProps<Props>()
|
|
||||||
|
|
||||||
// Emits
|
|
||||||
const emit = defineEmits<{
|
|
||||||
'update:modelValue': [value: boolean]
|
|
||||||
'payment-completed': [orderId: string]
|
|
||||||
}>()
|
|
||||||
|
|
||||||
// Auth
|
|
||||||
const auth = useAuth()
|
|
||||||
|
|
||||||
// Computed
|
|
||||||
const lightningInvoice = computed(() => {
|
|
||||||
if (!props.paymentRequest) return null
|
|
||||||
|
|
||||||
const lightningOption = props.paymentRequest.payment_options.find(opt => opt.type === 'ln')
|
|
||||||
return lightningOption?.link || null
|
|
||||||
})
|
|
||||||
|
|
||||||
// QR Code generation
|
|
||||||
const qrCodeDataUrl = ref<string | null>(null)
|
|
||||||
const qrCodeLoading = ref(false)
|
|
||||||
const qrCodeError = ref<string | null>(null)
|
|
||||||
|
|
||||||
const generateQRCode = async (paymentRequest: string) => {
|
|
||||||
try {
|
|
||||||
qrCodeLoading.value = true
|
|
||||||
qrCodeError.value = null
|
|
||||||
|
|
||||||
const dataUrl = await QRCode.toDataURL(paymentRequest, {
|
|
||||||
width: 200,
|
|
||||||
margin: 2,
|
|
||||||
color: {
|
|
||||||
dark: '#000000',
|
|
||||||
light: '#FFFFFF'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
qrCodeDataUrl.value = dataUrl
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to generate QR code:', error)
|
|
||||||
qrCodeError.value = 'Failed to generate QR code'
|
|
||||||
qrCodeDataUrl.value = null
|
|
||||||
} finally {
|
|
||||||
qrCodeLoading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Watch for lightning invoice changes and generate QR code
|
|
||||||
watch(lightningInvoice, (newInvoice) => {
|
|
||||||
if (newInvoice) {
|
|
||||||
generateQRCode(newInvoice)
|
|
||||||
} else {
|
|
||||||
qrCodeDataUrl.value = null
|
|
||||||
}
|
|
||||||
}, { immediate: true })
|
|
||||||
|
|
||||||
// Methods
|
|
||||||
const updateOpen = (open: boolean) => {
|
|
||||||
emit('update:modelValue', open)
|
|
||||||
}
|
|
||||||
|
|
||||||
const getPaymentTypeLabel = (type: string): string => {
|
|
||||||
switch (type) {
|
|
||||||
case 'ln':
|
|
||||||
return 'Lightning Network'
|
|
||||||
case 'btc':
|
|
||||||
return 'Bitcoin On-Chain'
|
|
||||||
case 'url':
|
|
||||||
return 'Payment URL'
|
|
||||||
case 'lnurl':
|
|
||||||
return 'LNURL-Pay'
|
|
||||||
default:
|
|
||||||
return type.toUpperCase()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const getPaymentTypeIcon = (type: string) => {
|
|
||||||
switch (type) {
|
|
||||||
case 'ln':
|
|
||||||
return Zap
|
|
||||||
case 'btc':
|
|
||||||
return Bitcoin
|
|
||||||
case 'url':
|
|
||||||
return Link
|
|
||||||
case 'lnurl':
|
|
||||||
return QrCode
|
|
||||||
default:
|
|
||||||
return CreditCard
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handlePayment = async (option: { type: string; link: string }) => {
|
|
||||||
try {
|
|
||||||
switch (option.type) {
|
|
||||||
case 'ln':
|
|
||||||
// For Lightning invoices, we can either show QR code or pay directly
|
|
||||||
if (lightningInvoice.value) {
|
|
||||||
await payWithWallet()
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case 'url':
|
|
||||||
// Open payment URL in new tab
|
|
||||||
window.open(option.link, '_blank')
|
|
||||||
break
|
|
||||||
case 'btc':
|
|
||||||
// Copy Bitcoin address
|
|
||||||
await navigator.clipboard.writeText(option.link)
|
|
||||||
toast.success('Bitcoin address copied to clipboard')
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
console.warn('Unknown payment type:', option.type)
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Payment handling error:', error)
|
|
||||||
toast.error('Failed to process payment')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const copyInvoice = async () => {
|
|
||||||
if (!lightningInvoice.value) return
|
|
||||||
|
|
||||||
try {
|
|
||||||
await navigator.clipboard.writeText(lightningInvoice.value)
|
|
||||||
toast.success('Lightning invoice copied to clipboard')
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to copy invoice:', error)
|
|
||||||
toast.error('Failed to copy invoice')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const payWithWallet = async () => {
|
|
||||||
if (!lightningInvoice.value) return
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Import the payment API
|
|
||||||
const { payInvoiceWithWallet } = await import('@/lib/api/events')
|
|
||||||
|
|
||||||
if (!auth.currentUser.value?.wallets?.[0]?.id || !auth.currentUser.value?.wallets?.[0]?.adminkey) {
|
|
||||||
toast.error('Please connect your wallet to pay')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pay the invoice
|
|
||||||
const result = await payInvoiceWithWallet(
|
|
||||||
lightningInvoice.value,
|
|
||||||
auth.currentUser.value.wallets[0].id,
|
|
||||||
auth.currentUser.value.wallets[0].adminkey
|
|
||||||
)
|
|
||||||
|
|
||||||
console.log('Payment result:', result)
|
|
||||||
|
|
||||||
toast.success('Payment successful!')
|
|
||||||
|
|
||||||
// Emit payment completed event
|
|
||||||
if (props.paymentRequest) {
|
|
||||||
emit('payment-completed', props.paymentRequest.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close the dialog
|
|
||||||
updateOpen(false)
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Payment failed:', error)
|
|
||||||
toast.error('Payment failed: ' + (error instanceof Error ? error.message : 'Unknown error'))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue