fix(machine): responsive mobile layout for cash-in/cash-out views
- Push header below fixed status badges on mobile (pt-12) - Use w-full max-w-* instead of fixed widths so cards fit mobile screens - Make main content scrollable with overflow-auto - Reduce padding on mobile (p-4 vs p-8) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
1f312abcaf
commit
b6b544d45a
2 changed files with 56 additions and 25 deletions
|
|
@ -189,16 +189,18 @@ const isProcessing = computed(() => atmStore.isPayingInvoice || atmStore.isReque
|
||||||
<template>
|
<template>
|
||||||
<div class="flex flex-1 flex-col">
|
<div class="flex flex-1 flex-col">
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<header class="flex items-center bg-black/30 px-8 py-4">
|
<header class="flex items-center bg-black/30 px-4 pb-3 pt-12 sm:px-8 sm:py-4">
|
||||||
<Button variant="ghost" class="text-muted-foreground" @click="cancel">← Cancel</Button>
|
<Button variant="ghost" class="text-muted-foreground" @click="cancel">← Cancel</Button>
|
||||||
<h2 class="flex-1 text-center text-xl font-semibold">Buy Bitcoin</h2>
|
<h2 class="flex-1 text-center text-lg font-semibold sm:text-xl">Buy Bitcoin</h2>
|
||||||
<div class="w-20"></div>
|
<div class="w-20"></div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<!-- Content -->
|
<!-- Content -->
|
||||||
<main class="flex flex-1 items-center justify-center p-8">
|
<main
|
||||||
|
class="flex min-h-0 flex-1 items-start justify-center overflow-auto p-4 sm:items-center sm:p-8"
|
||||||
|
>
|
||||||
<!-- Fetching Rate -->
|
<!-- Fetching Rate -->
|
||||||
<Card v-if="nestedState === 'fetchingRate'" class="w-80 border-0 bg-white/5">
|
<Card v-if="nestedState === 'fetchingRate'" class="w-full max-w-80 border-0 bg-white/5">
|
||||||
<CardContent class="flex flex-col items-center gap-4 p-8">
|
<CardContent class="flex flex-col items-center gap-4 p-8">
|
||||||
<Skeleton class="h-10 w-10 rounded-full" />
|
<Skeleton class="h-10 w-10 rounded-full" />
|
||||||
<p class="text-muted-foreground">Fetching exchange rate...</p>
|
<p class="text-muted-foreground">Fetching exchange rate...</p>
|
||||||
|
|
@ -206,7 +208,10 @@ const isProcessing = computed(() => atmStore.isPayingInvoice || atmStore.isReque
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<!-- Inserting Bills -->
|
<!-- Inserting Bills -->
|
||||||
<Card v-else-if="nestedState === 'insertingBills'" class="w-96 border-0 bg-white/5">
|
<Card
|
||||||
|
v-else-if="nestedState === 'insertingBills'"
|
||||||
|
class="w-full max-w-96 border-0 bg-white/5"
|
||||||
|
>
|
||||||
<CardHeader class="text-center">
|
<CardHeader class="text-center">
|
||||||
<CardTitle>Insert Cash</CardTitle>
|
<CardTitle>Insert Cash</CardTitle>
|
||||||
<CardDescription v-if="context">
|
<CardDescription v-if="context">
|
||||||
|
|
@ -282,7 +287,10 @@ const isProcessing = computed(() => atmStore.isPayingInvoice || atmStore.isReque
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<!-- Generating NDebit -->
|
<!-- Generating NDebit -->
|
||||||
<Card v-else-if="nestedState === 'generatingNdebit'" class="w-80 border-0 bg-white/5">
|
<Card
|
||||||
|
v-else-if="nestedState === 'generatingNdebit'"
|
||||||
|
class="w-full max-w-80 border-0 bg-white/5"
|
||||||
|
>
|
||||||
<CardContent class="flex flex-col items-center gap-4 p-8">
|
<CardContent class="flex flex-col items-center gap-4 p-8">
|
||||||
<Skeleton class="h-10 w-10 rounded-full" />
|
<Skeleton class="h-10 w-10 rounded-full" />
|
||||||
<p class="text-muted-foreground">Preparing payment code...</p>
|
<p class="text-muted-foreground">Preparing payment code...</p>
|
||||||
|
|
@ -290,7 +298,10 @@ const isProcessing = computed(() => atmStore.isPayingInvoice || atmStore.isReque
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<!-- Display QR (unified lightning + clink) -->
|
<!-- Display QR (unified lightning + clink) -->
|
||||||
<Card v-else-if="nestedState === 'displayingQR'" class="w-[420px] border-0 bg-white/5">
|
<Card
|
||||||
|
v-else-if="nestedState === 'displayingQR'"
|
||||||
|
class="w-full max-w-[420px] border-0 bg-white/5"
|
||||||
|
>
|
||||||
<CardContent class="pt-6 space-y-5">
|
<CardContent class="pt-6 space-y-5">
|
||||||
<!-- Amount Display -->
|
<!-- Amount Display -->
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
|
|
@ -455,7 +466,7 @@ const isProcessing = computed(() => atmStore.isPayingInvoice || atmStore.isReque
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<!-- Ask for Receipt -->
|
<!-- Ask for Receipt -->
|
||||||
<Card v-else-if="nestedState === 'askForReceipt'" class="w-80 border-0 bg-white/5">
|
<Card v-else-if="nestedState === 'askForReceipt'" class="w-full max-w-80 border-0 bg-white/5">
|
||||||
<CardContent class="flex flex-col items-center gap-4 p-8">
|
<CardContent class="flex flex-col items-center gap-4 p-8">
|
||||||
<div class="text-6xl text-green-400">✅</div>
|
<div class="text-6xl text-green-400">✅</div>
|
||||||
<CardTitle>Payment Sent!</CardTitle>
|
<CardTitle>Payment Sent!</CardTitle>
|
||||||
|
|
@ -468,7 +479,10 @@ const isProcessing = computed(() => atmStore.isPayingInvoice || atmStore.isReque
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<!-- Sending Receipt -->
|
<!-- Sending Receipt -->
|
||||||
<Card v-else-if="nestedState === 'sendingReceipt'" class="w-80 border-0 bg-white/5">
|
<Card
|
||||||
|
v-else-if="nestedState === 'sendingReceipt'"
|
||||||
|
class="w-full max-w-80 border-0 bg-white/5"
|
||||||
|
>
|
||||||
<CardContent class="flex flex-col items-center gap-4 p-8">
|
<CardContent class="flex flex-col items-center gap-4 p-8">
|
||||||
<Skeleton class="h-10 w-10 rounded-full" />
|
<Skeleton class="h-10 w-10 rounded-full" />
|
||||||
<p class="text-muted-foreground">Sending receipt...</p>
|
<p class="text-muted-foreground">Sending receipt...</p>
|
||||||
|
|
@ -476,7 +490,7 @@ const isProcessing = computed(() => atmStore.isPayingInvoice || atmStore.isReque
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<!-- Complete -->
|
<!-- Complete -->
|
||||||
<Card v-else-if="nestedState === 'complete'" class="w-80 border-0 bg-green-900/30">
|
<Card v-else-if="nestedState === 'complete'" class="w-full max-w-80 border-0 bg-green-900/30">
|
||||||
<CardContent class="flex flex-col items-center gap-4 p-8 text-center">
|
<CardContent class="flex flex-col items-center gap-4 p-8 text-center">
|
||||||
<div class="text-6xl">🎉</div>
|
<div class="text-6xl">🎉</div>
|
||||||
<CardTitle class="text-green-400">Transaction Complete!</CardTitle>
|
<CardTitle class="text-green-400">Transaction Complete!</CardTitle>
|
||||||
|
|
@ -489,7 +503,7 @@ const isProcessing = computed(() => atmStore.isPayingInvoice || atmStore.isReque
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<!-- Error -->
|
<!-- Error -->
|
||||||
<Card v-else-if="nestedState === 'error'" class="w-80 border-0 bg-red-900/30">
|
<Card v-else-if="nestedState === 'error'" class="w-full max-w-80 border-0 bg-red-900/30">
|
||||||
<CardContent class="flex flex-col items-center gap-4 p-8 text-center">
|
<CardContent class="flex flex-col items-center gap-4 p-8 text-center">
|
||||||
<div class="text-6xl">⚠️</div>
|
<div class="text-6xl">⚠️</div>
|
||||||
<CardTitle class="text-red-400">Error</CardTitle>
|
<CardTitle class="text-red-400">Error</CardTitle>
|
||||||
|
|
@ -501,7 +515,7 @@ const isProcessing = computed(() => atmStore.isPayingInvoice || atmStore.isReque
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<!-- Fallback -->
|
<!-- Fallback -->
|
||||||
<Card v-else class="w-80 border-0 bg-white/5">
|
<Card v-else class="w-full max-w-80 border-0 bg-white/5">
|
||||||
<CardContent class="p-8 text-center">
|
<CardContent class="p-8 text-center">
|
||||||
<p class="text-muted-foreground">State: {{ nestedState }}</p>
|
<p class="text-muted-foreground">State: {{ nestedState }}</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|
|
||||||
|
|
@ -98,16 +98,18 @@ function formatFiat(cents: number): string {
|
||||||
<template>
|
<template>
|
||||||
<div class="flex flex-1 flex-col">
|
<div class="flex flex-1 flex-col">
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<header class="flex items-center bg-black/30 px-8 py-4">
|
<header class="flex items-center bg-black/30 px-4 pb-3 pt-12 sm:px-8 sm:py-4">
|
||||||
<Button variant="ghost" class="text-muted-foreground" @click="cancel">← Cancel</Button>
|
<Button variant="ghost" class="text-muted-foreground" @click="cancel">← Cancel</Button>
|
||||||
<h2 class="flex-1 text-center text-xl font-semibold">Sell Bitcoin</h2>
|
<h2 class="flex-1 text-center text-lg font-semibold sm:text-xl">Sell Bitcoin</h2>
|
||||||
<div class="w-20"></div>
|
<div class="w-20"></div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<!-- Content -->
|
<!-- Content -->
|
||||||
<main class="flex flex-1 items-center justify-center p-8">
|
<main
|
||||||
|
class="flex min-h-0 flex-1 items-start justify-center overflow-auto p-4 sm:items-center sm:p-8"
|
||||||
|
>
|
||||||
<!-- Fetching Rate -->
|
<!-- Fetching Rate -->
|
||||||
<Card v-if="nestedState === 'fetchingRate'" class="w-80 border-0 bg-white/5">
|
<Card v-if="nestedState === 'fetchingRate'" class="w-full max-w-80 border-0 bg-white/5">
|
||||||
<CardContent class="flex flex-col items-center gap-4 p-8">
|
<CardContent class="flex flex-col items-center gap-4 p-8">
|
||||||
<Skeleton class="h-10 w-10 rounded-full" />
|
<Skeleton class="h-10 w-10 rounded-full" />
|
||||||
<p class="text-muted-foreground">Fetching exchange rate...</p>
|
<p class="text-muted-foreground">Fetching exchange rate...</p>
|
||||||
|
|
@ -115,7 +117,10 @@ function formatFiat(cents: number): string {
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<!-- Selecting Amount - Main cash-out screen -->
|
<!-- Selecting Amount - Main cash-out screen -->
|
||||||
<Card v-else-if="nestedState === 'selectingAmount'" class="w-[520px] border-0 bg-white/5">
|
<Card
|
||||||
|
v-else-if="nestedState === 'selectingAmount'"
|
||||||
|
class="w-full max-w-[520px] border-0 bg-white/5"
|
||||||
|
>
|
||||||
<CardHeader class="text-center">
|
<CardHeader class="text-center">
|
||||||
<CardTitle>Select Cash Amount</CardTitle>
|
<CardTitle>Select Cash Amount</CardTitle>
|
||||||
<CardDescription v-if="context">
|
<CardDescription v-if="context">
|
||||||
|
|
@ -198,7 +203,10 @@ function formatFiat(cents: number): string {
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<!-- Generating Invoice -->
|
<!-- Generating Invoice -->
|
||||||
<Card v-else-if="nestedState === 'generatingInvoice'" class="w-80 border-0 bg-white/5">
|
<Card
|
||||||
|
v-else-if="nestedState === 'generatingInvoice'"
|
||||||
|
class="w-full max-w-80 border-0 bg-white/5"
|
||||||
|
>
|
||||||
<CardContent class="flex flex-col items-center gap-4 p-8">
|
<CardContent class="flex flex-col items-center gap-4 p-8">
|
||||||
<Skeleton class="h-10 w-10 rounded-full" />
|
<Skeleton class="h-10 w-10 rounded-full" />
|
||||||
<p class="text-muted-foreground">Creating invoice...</p>
|
<p class="text-muted-foreground">Creating invoice...</p>
|
||||||
|
|
@ -206,7 +214,10 @@ function formatFiat(cents: number): string {
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<!-- Displaying Invoice - Show QR for payment -->
|
<!-- Displaying Invoice - Show QR for payment -->
|
||||||
<Card v-else-if="nestedState === 'displayingInvoice'" class="w-[480px] border-0 bg-white/5">
|
<Card
|
||||||
|
v-else-if="nestedState === 'displayingInvoice'"
|
||||||
|
class="w-full max-w-[480px] border-0 bg-white/5"
|
||||||
|
>
|
||||||
<CardHeader class="text-center">
|
<CardHeader class="text-center">
|
||||||
<CardTitle>Scan to Pay</CardTitle>
|
<CardTitle>Scan to Pay</CardTitle>
|
||||||
<CardDescription v-if="context">
|
<CardDescription v-if="context">
|
||||||
|
|
@ -260,7 +271,10 @@ function formatFiat(cents: number): string {
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<!-- Dispensing Cash -->
|
<!-- Dispensing Cash -->
|
||||||
<Card v-else-if="nestedState === 'dispensingCash'" class="w-80 border-0 bg-white/5">
|
<Card
|
||||||
|
v-else-if="nestedState === 'dispensingCash'"
|
||||||
|
class="w-full max-w-80 border-0 bg-white/5"
|
||||||
|
>
|
||||||
<CardContent class="flex flex-col items-center gap-4 p-8">
|
<CardContent class="flex flex-col items-center gap-4 p-8">
|
||||||
<Skeleton class="h-10 w-10 rounded-full" />
|
<Skeleton class="h-10 w-10 rounded-full" />
|
||||||
<p class="text-muted-foreground">Dispensing cash...</p>
|
<p class="text-muted-foreground">Dispensing cash...</p>
|
||||||
|
|
@ -269,7 +283,10 @@ function formatFiat(cents: number): string {
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<!-- Cash Ready -->
|
<!-- Cash Ready -->
|
||||||
<Card v-else-if="nestedState === 'waitingForCashTaken'" class="w-80 border-0 bg-green-900/30">
|
<Card
|
||||||
|
v-else-if="nestedState === 'waitingForCashTaken'"
|
||||||
|
class="w-full max-w-80 border-0 bg-green-900/30"
|
||||||
|
>
|
||||||
<CardContent class="flex flex-col items-center gap-4 p-8 text-center">
|
<CardContent class="flex flex-col items-center gap-4 p-8 text-center">
|
||||||
<div class="text-6xl text-green-400">✅</div>
|
<div class="text-6xl text-green-400">✅</div>
|
||||||
<CardTitle class="text-green-400">Cash Ready!</CardTitle>
|
<CardTitle class="text-green-400">Cash Ready!</CardTitle>
|
||||||
|
|
@ -288,7 +305,7 @@ function formatFiat(cents: number): string {
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<!-- Ask for Receipt -->
|
<!-- Ask for Receipt -->
|
||||||
<Card v-else-if="nestedState === 'askForReceipt'" class="w-80 border-0 bg-white/5">
|
<Card v-else-if="nestedState === 'askForReceipt'" class="w-full max-w-80 border-0 bg-white/5">
|
||||||
<CardContent class="flex flex-col items-center gap-4 p-8">
|
<CardContent class="flex flex-col items-center gap-4 p-8">
|
||||||
<CardTitle>Would you like a receipt?</CardTitle>
|
<CardTitle>Would you like a receipt?</CardTitle>
|
||||||
<p class="text-sm text-muted-foreground">Scan your npub to receive a Nostr DM receipt</p>
|
<p class="text-sm text-muted-foreground">Scan your npub to receive a Nostr DM receipt</p>
|
||||||
|
|
@ -300,7 +317,7 @@ function formatFiat(cents: number): string {
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<!-- Complete -->
|
<!-- Complete -->
|
||||||
<Card v-else-if="nestedState === 'complete'" class="w-80 border-0 bg-green-900/30">
|
<Card v-else-if="nestedState === 'complete'" class="w-full max-w-80 border-0 bg-green-900/30">
|
||||||
<CardContent class="flex flex-col items-center gap-4 p-8 text-center">
|
<CardContent class="flex flex-col items-center gap-4 p-8 text-center">
|
||||||
<div class="text-6xl">🎉</div>
|
<div class="text-6xl">🎉</div>
|
||||||
<CardTitle class="text-green-400">Transaction Complete!</CardTitle>
|
<CardTitle class="text-green-400">Transaction Complete!</CardTitle>
|
||||||
|
|
@ -311,7 +328,7 @@ function formatFiat(cents: number): string {
|
||||||
<!-- Error -->
|
<!-- Error -->
|
||||||
<Card
|
<Card
|
||||||
v-else-if="nestedState === 'error' || nestedState === 'dispenseError'"
|
v-else-if="nestedState === 'error' || nestedState === 'dispenseError'"
|
||||||
class="w-80 border-0 bg-red-900/30"
|
class="w-full max-w-80 border-0 bg-red-900/30"
|
||||||
>
|
>
|
||||||
<CardContent class="flex flex-col items-center gap-4 p-8 text-center">
|
<CardContent class="flex flex-col items-center gap-4 p-8 text-center">
|
||||||
<div class="text-6xl">⚠️</div>
|
<div class="text-6xl">⚠️</div>
|
||||||
|
|
@ -324,7 +341,7 @@ function formatFiat(cents: number): string {
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<!-- Fallback -->
|
<!-- Fallback -->
|
||||||
<Card v-else class="w-80 border-0 bg-white/5">
|
<Card v-else class="w-full max-w-80 border-0 bg-white/5">
|
||||||
<CardContent class="p-8 text-center">
|
<CardContent class="p-8 text-center">
|
||||||
<p class="text-muted-foreground">State: {{ nestedState }}</p>
|
<p class="text-muted-foreground">State: {{ nestedState }}</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue