Enhance ReceiveDialog.vue with UI improvements and responsive design
- Updated styling for various components to improve visual hierarchy and responsiveness, including adjustments to padding, font sizes, and element spacing. - Enhanced form field labels and descriptions for better clarity and accessibility. - Improved error message display and button sizes for a more consistent user experience. - Refined layout for invoice details and payment status messages to ensure better readability across different screen sizes. These changes enhance the overall user experience by providing a more polished and responsive interface for managing Bitcoin payments.
This commit is contained in:
parent
7b762a1e4b
commit
ef818baed6
1 changed files with 77 additions and 61 deletions
|
|
@ -181,65 +181,72 @@ function formatExpiry(seconds: number): string {
|
|||
|
||||
<template>
|
||||
<Dialog :open="props.open" @update:open="onOpenChange">
|
||||
<DialogContent class="sm:max-w-2xl max-h-[90vh] overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<DialogTitle class="flex items-center gap-2">
|
||||
<QrCode class="h-5 w-5" />
|
||||
<DialogContent class="sm:max-w-2xl max-h-[95vh] overflow-y-auto p-4 sm:p-6">
|
||||
<DialogHeader class="pb-2 sm:pb-4">
|
||||
<DialogTitle class="flex items-center gap-2 text-lg sm:text-xl">
|
||||
<QrCode class="h-4 w-4 sm:h-5 sm:w-5" />
|
||||
Receive Bitcoin
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
<DialogDescription class="text-sm sm:text-base">
|
||||
Create a Lightning invoice to receive Bitcoin payments.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<!-- Invoice Creation Form -->
|
||||
<div v-if="!createdInvoice" class="space-y-4">
|
||||
<form @submit="onSubmit" class="space-y-4">
|
||||
<div v-if="!createdInvoice" class="space-y-3 sm:space-y-4">
|
||||
<form @submit="onSubmit" class="space-y-3 sm:space-y-4">
|
||||
<FormField v-slot="{ componentField }" name="amount">
|
||||
<FormItem>
|
||||
<FormLabel>Amount (sats) *</FormLabel>
|
||||
<FormLabel class="text-sm font-medium">Amount (sats) *</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
type="number"
|
||||
min="1"
|
||||
max="10000000"
|
||||
placeholder="Enter amount in sats"
|
||||
class="h-9 sm:h-10"
|
||||
v-bind="componentField"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormDescription>Amount to request in satoshis</FormDescription>
|
||||
<FormDescription class="text-xs sm:text-sm">Amount to request in satoshis</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
|
||||
<FormField v-slot="{ componentField }" name="memo">
|
||||
<FormItem>
|
||||
<FormLabel>Description</FormLabel>
|
||||
<FormLabel class="text-sm font-medium">Description</FormLabel>
|
||||
<FormControl>
|
||||
<Textarea
|
||||
placeholder="e.g., Payment for services (optional)"
|
||||
class="min-h-[60px] sm:min-h-[80px] text-sm resize-none"
|
||||
v-bind="componentField"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormDescription>What is this payment for? (optional)</FormDescription>
|
||||
<FormDescription class="text-xs sm:text-sm">What is this payment for? (optional)</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
|
||||
<div v-if="error" class="text-destructive text-sm">
|
||||
<div v-if="error" class="text-destructive text-xs sm:text-sm p-2 sm:p-3 bg-destructive/10 rounded-md">
|
||||
{{ error }}
|
||||
</div>
|
||||
|
||||
<div class="flex gap-2 pt-4">
|
||||
<div class="flex gap-2 pt-2 sm:pt-4">
|
||||
<Button
|
||||
type="submit"
|
||||
:disabled="!isFormValid || isCreating"
|
||||
class="flex-1"
|
||||
class="flex-1 h-9 sm:h-10 text-sm sm:text-base"
|
||||
>
|
||||
<Loader2 v-if="isCreating" class="w-4 h-4 mr-2 animate-spin" />
|
||||
{{ isCreating ? 'Creating Invoice...' : 'Create Invoice' }}
|
||||
<Loader2 v-if="isCreating" class="w-3 h-3 sm:w-4 sm:h-4 mr-2 animate-spin" />
|
||||
{{ isCreating ? 'Creating...' : 'Create Invoice' }}
|
||||
</Button>
|
||||
<Button type="button" variant="outline" @click="closeDialog">
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
@click="closeDialog"
|
||||
class="h-9 sm:h-10 px-3 sm:px-4 text-sm sm:text-base"
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
</div>
|
||||
|
|
@ -247,91 +254,92 @@ function formatExpiry(seconds: number): string {
|
|||
</div>
|
||||
|
||||
<!-- Created Invoice Display -->
|
||||
<div v-else class="space-y-6">
|
||||
<div v-else class="space-y-4 sm:space-y-6">
|
||||
<!-- Invoice Details -->
|
||||
<div class="bg-muted/50 rounded-lg p-4 space-y-3">
|
||||
<div class="bg-muted/50 rounded-lg p-3 sm:p-4 space-y-2 sm:space-y-3">
|
||||
<div class="flex items-center justify-between">
|
||||
<h4 class="font-medium">Invoice Details</h4>
|
||||
<div class="text-sm text-muted-foreground">
|
||||
<h4 class="font-medium text-sm sm:text-base">Invoice Details</h4>
|
||||
<div class="text-xs sm:text-sm text-muted-foreground">
|
||||
Expires in {{ formatExpiry(createdInvoice.expiry || 3600) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-2 gap-4 text-sm">
|
||||
<div>
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-2 sm:gap-4 text-sm">
|
||||
<div class="flex justify-between sm:block">
|
||||
<span class="text-muted-foreground">Amount:</span>
|
||||
<span class="font-medium ml-2">{{ createdInvoice.amount }} sats</span>
|
||||
<span class="font-medium sm:ml-2">{{ createdInvoice.amount }} sats</span>
|
||||
</div>
|
||||
<div>
|
||||
<div class="flex justify-between sm:block">
|
||||
<span class="text-muted-foreground">Status:</span>
|
||||
<span class="font-medium ml-2" :class="statusColor">{{ statusText }}</span>
|
||||
<span class="font-medium sm:ml-2" :class="statusColor">{{ statusText }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span class="text-muted-foreground text-sm">Description:</span>
|
||||
<p class="font-medium">{{ createdInvoice.memo }}</p>
|
||||
<span class="text-muted-foreground text-xs sm:text-sm">Description:</span>
|
||||
<p class="font-medium text-sm break-words">{{ createdInvoice.memo }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- QR Code Display -->
|
||||
<div v-if="paymentStatus === 'pending'" class="flex flex-col items-center space-y-4">
|
||||
<div v-if="isLoadingQR" class="w-64 h-64 flex items-center justify-center bg-muted rounded-lg">
|
||||
<Loader2 class="h-8 w-8 animate-spin text-muted-foreground" />
|
||||
<div v-if="paymentStatus === 'pending'" class="flex flex-col items-center space-y-3 sm:space-y-4">
|
||||
<div v-if="isLoadingQR" class="w-48 h-48 sm:w-64 sm:h-64 flex items-center justify-center bg-muted rounded-lg">
|
||||
<Loader2 class="h-6 w-6 sm:h-8 sm:w-8 animate-spin text-muted-foreground" />
|
||||
</div>
|
||||
<div v-else-if="qrCode" class="bg-white p-4 rounded-lg">
|
||||
<div v-else-if="qrCode" class="bg-white p-2 sm:p-4 rounded-lg">
|
||||
<img
|
||||
:src="qrCode"
|
||||
alt="Lightning Invoice QR Code"
|
||||
class="w-64 h-64"
|
||||
class="w-48 h-48 sm:w-64 sm:h-64"
|
||||
/>
|
||||
</div>
|
||||
<div v-else class="w-64 h-64 flex items-center justify-center bg-muted rounded-lg">
|
||||
<QrCode class="h-12 w-12 text-muted-foreground opacity-50" />
|
||||
<div v-else class="w-48 h-48 sm:w-64 sm:h-64 flex items-center justify-center bg-muted rounded-lg">
|
||||
<QrCode class="h-8 w-8 sm:h-12 sm:w-12 text-muted-foreground opacity-50" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Payment Success Message -->
|
||||
<div v-else-if="paymentStatus === 'confirmed'" class="flex flex-col items-center space-y-4">
|
||||
<div class="w-64 h-64 flex flex-col items-center justify-center bg-green-50 dark:bg-green-950/20 rounded-lg border border-green-200 dark:border-green-800">
|
||||
<Check class="h-16 w-16 text-green-600 dark:text-green-400 mb-4" />
|
||||
<div class="text-center">
|
||||
<p class="text-lg font-semibold text-green-800 dark:text-green-200">Payment Received!</p>
|
||||
<div v-else-if="paymentStatus === 'confirmed'" class="flex flex-col items-center space-y-3 sm:space-y-4">
|
||||
<div class="w-48 h-48 sm:w-64 sm:h-64 flex flex-col items-center justify-center bg-green-50 dark:bg-green-950/20 rounded-lg border border-green-200 dark:border-green-800">
|
||||
<Check class="h-12 w-12 sm:h-16 sm:w-16 text-green-600 dark:text-green-400 mb-2 sm:mb-4" />
|
||||
<div class="text-center px-2">
|
||||
<p class="text-base sm:text-lg font-semibold text-green-800 dark:text-green-200">Payment Received!</p>
|
||||
<p class="text-sm text-green-600 dark:text-green-400 mt-1">{{ createdInvoice.amount }} sats</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Payment Failed Message -->
|
||||
<div v-else-if="paymentStatus === 'failed'" class="flex flex-col items-center space-y-4">
|
||||
<div class="w-64 h-64 flex flex-col items-center justify-center bg-red-50 dark:bg-red-950/20 rounded-lg border border-red-200 dark:border-red-800">
|
||||
<svg class="h-16 w-16 text-red-600 dark:text-red-400 mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<div v-else-if="paymentStatus === 'failed'" class="flex flex-col items-center space-y-3 sm:space-y-4">
|
||||
<div class="w-48 h-48 sm:w-64 sm:h-64 flex flex-col items-center justify-center bg-red-50 dark:bg-red-950/20 rounded-lg border border-red-200 dark:border-red-800">
|
||||
<svg class="h-12 w-12 sm:h-16 sm:w-16 text-red-600 dark:text-red-400 mb-2 sm:mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
|
||||
</svg>
|
||||
<div class="text-center">
|
||||
<p class="text-lg font-semibold text-red-800 dark:text-red-200">Payment Failed</p>
|
||||
<p class="text-sm text-red-600 dark:text-red-400 mt-1">Invoice has expired or failed</p>
|
||||
<div class="text-center px-2">
|
||||
<p class="text-base sm:text-lg font-semibold text-red-800 dark:text-red-200">Payment Failed</p>
|
||||
<p class="text-xs sm:text-sm text-red-600 dark:text-red-400 mt-1">Invoice has expired or failed</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Lightning Invoice (BOLT11) -->
|
||||
<div class="space-y-2">
|
||||
<Label>Lightning Invoice (BOLT11)</Label>
|
||||
<div class="flex gap-2">
|
||||
<div class="space-y-1 sm:space-y-2">
|
||||
<Label class="text-sm font-medium">Lightning Invoice (BOLT11)</Label>
|
||||
<div class="flex gap-1 sm:gap-2">
|
||||
<Input
|
||||
:key="`bolt11-${createdInvoice?.payment_hash}`"
|
||||
:model-value="createdInvoice?.payment_request || createdInvoice?.bolt11 || ''"
|
||||
readonly
|
||||
class="font-mono text-xs"
|
||||
class="font-mono text-xs h-8 sm:h-9"
|
||||
/>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
@click="copyToClipboard(createdInvoice.payment_request || createdInvoice.bolt11, 'bolt11')"
|
||||
class="h-8 w-8 sm:h-9 sm:w-auto sm:px-3 p-0 sm:p-2"
|
||||
>
|
||||
<Check v-if="copiedField === 'bolt11'" class="h-4 w-4 text-green-600" />
|
||||
<Copy v-else class="h-4 w-4" />
|
||||
<Check v-if="copiedField === 'bolt11'" class="h-3 w-3 sm:h-4 sm:w-4 text-green-600" />
|
||||
<Copy v-else class="h-3 w-3 sm:h-4 sm:w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
<p class="text-xs text-muted-foreground">
|
||||
|
|
@ -340,32 +348,40 @@ function formatExpiry(seconds: number): string {
|
|||
</div>
|
||||
|
||||
<!-- Payment Hash -->
|
||||
<div class="space-y-2">
|
||||
<Label>Payment Hash</Label>
|
||||
<div class="flex gap-2">
|
||||
<div class="space-y-1 sm:space-y-2">
|
||||
<Label class="text-sm font-medium">Payment Hash</Label>
|
||||
<div class="flex gap-1 sm:gap-2">
|
||||
<Input
|
||||
:key="`hash-${createdInvoice?.payment_hash}`"
|
||||
:model-value="createdInvoice?.payment_hash || ''"
|
||||
readonly
|
||||
class="font-mono text-xs"
|
||||
class="font-mono text-xs h-8 sm:h-9"
|
||||
/>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
@click="copyToClipboard(createdInvoice.payment_hash, 'hash')"
|
||||
class="h-8 w-8 sm:h-9 sm:w-auto sm:px-3 p-0 sm:p-2"
|
||||
>
|
||||
<Check v-if="copiedField === 'hash'" class="h-4 w-4 text-green-600" />
|
||||
<Copy v-else class="h-4 w-4" />
|
||||
<Check v-if="copiedField === 'hash'" class="h-3 w-3 sm:h-4 sm:w-4 text-green-600" />
|
||||
<Copy v-else class="h-3 w-3 sm:h-4 sm:w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex gap-2 pt-4">
|
||||
<Button @click="createAnother" variant="outline" class="flex-1">
|
||||
<div class="flex gap-2 pt-3 sm:pt-4">
|
||||
<Button
|
||||
@click="createAnother"
|
||||
variant="outline"
|
||||
class="flex-1 h-9 sm:h-10 text-sm sm:text-base"
|
||||
>
|
||||
Create Another
|
||||
</Button>
|
||||
<Button @click="closeDialog" class="flex-1">
|
||||
<Button
|
||||
@click="closeDialog"
|
||||
class="flex-1 h-9 sm:h-10 text-sm sm:text-base"
|
||||
>
|
||||
Done
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue