feat(machine): add optimized BitcoinIcon component

SVGO-optimized bitcoin.svg (62% smaller) as a reusable Vue component
with configurable size prop. Used in CashInView balance limit message
instead of dollar-sign emoji.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Patrick Mulligan 2026-02-16 17:26:15 -05:00
commit 3f0247313d
2 changed files with 36 additions and 2 deletions

View file

@ -0,0 +1,33 @@
<script setup lang="ts">
withDefaults(
defineProps<{
size?: number | string
}>(),
{ size: 48 }
)
</script>
<template>
<svg
:width="size"
:height="size"
viewBox="0 0 47.839 47.58"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g transform="translate(-55.192 -74.568)">
<ellipse cx="79.111" cy="98.358" rx="23.92" ry="23.79" fill="#F7B83C" />
<ellipse cx="79.111" cy="98.358" rx="20.855" ry="20.742" fill="#FFCD55" />
<path
d="M405.155 248.922q-19.769-21.389-59.66-29.374c33.866-14.453 48.749-38.983 44.663-73.595-1.366-12.55-5.512-23.428-12.447-32.648-6.94-9.222-17.243-18.926-29.569-26.733-21.74-11.155-48.27-14.722-48.8-14.765V-.071h-52.497v69.88q-13.636 0-41.588.571V-.07h-52.503v71.877q-11.253.287-33.07.288l-54.263-.288v46.778h10.827q25.91.001 30.34 19.395c1.618 67.952 0 127.061 0 196.807q-2.722 14.546-19.77 14.548H57.984l-10.57 52.198h68.184c4.319 0 10.565.048 18.75.134q12.27.144 18.407.144v72.732h52.512v-71.877c9.543.195 23.406.287 41.588.287v71.59h52.497V401.81c31.043-1.995 59.86-8.88 85.166-26.174 8.867-6.65 19.091-19.75 24.897-30.02 5.786-10.27 9.484-22.155 11.07-35.659 2.967-26.424-2.15-46.772-15.33-61.036m-207.881-118.72c1.591 0 15.084-.047 22.47-.143q11.083-.146 18.41-.288c4.888-.094 15.724-.208 23.825.166 49.799 11.727 42.177 67.725.3 70.12-7.502.284-24.518.782-28.38.876q-5.796.141-15.855 0c-6.708-.094-19.628-.144-20.767-.144zm74.252 211.366c-3.761 1.411-8.526 1.915-16.036 2.211-7.725.28-14.273.573-18.59.573-4.319 0-9.775-.052-16.366-.145-6.595-.089-24.264.295-26.084.295l-.498-87.458s20.683-.524 29.662-.718c8.981-.192 16.307-.281 21.99-.281 5.68 0 14.835-.197 23.528.855 45.613 10.538 51.667 67.27 2.394 84.668"
fill="#EEB94F"
transform="matrix(.05942 0 0 .06234 64.98 83.733)"
/>
<path
d="M402.687 246.861c-8.425-10.866-30.598-21.99-57.192-27.313 33.866-14.453 48.749-38.983 44.663-73.594-1.366-12.551-5.512-23.429-12.447-32.649-6.94-9.222-17.243-18.926-29.569-26.733-21.74-11.155-48.27-14.722-48.8-14.765V-.071h-52.497v69.88q-13.636 0-41.588.571V-.07h-52.503v71.877q-11.253.287-33.07.288l-54.263-.288v46.778h10.827q25.91.001 30.34 19.395c1.618 67.952 0 127.061 0 196.807q-2.722 14.546-19.77 14.548H57.984l-10.57 52.198h68.184c4.319 0 10.565.048 18.75.134q12.27.144 18.407.144v72.732h52.512v-71.877c9.543.195 23.406.287 41.588.287v71.59h52.497V401.81c31.043-1.995 57.532-3.263 80.042-18.69 30.422-19.42 40.135-45.215 39.96-77.79-.766-28.49-6.327-46.713-16.668-58.47M197.274 130.203c1.591 0 15.084-.048 22.47-.144q11.083-.146 18.41-.288c4.888-.094 15.724-.208 23.825.166 49.799 11.727 42.177 67.725.3 70.12-7.502.284-24.518.782-28.38.876q-5.796.141-15.855 0c-6.708-.094-19.628-.144-20.767-.144zm74.252 211.365c-3.761 1.411-8.526 1.915-16.036 2.211-7.725.28-14.273.573-18.59.573-4.319 0-9.775-.052-16.366-.145-6.595-.089-24.264.295-26.084.295l-.498-87.458s20.683-.524 29.662-.718c8.981-.192 16.307-.281 21.99-.281 5.68 0 14.835-.197 23.528.855 45.613 10.538 51.667 67.27 2.394 84.668"
fill="#fff"
transform="matrix(.05942 0 0 .06234 65.509 83.733)"
/>
</g>
</svg>
</template>

View file

@ -9,6 +9,7 @@ import { Alert, AlertDescription } from '@/components/ui/alert'
import { Skeleton } from '@/components/ui/skeleton' import { Skeleton } from '@/components/ui/skeleton'
import { Input } from '@/components/ui/input' import { Input } from '@/components/ui/input'
import QRCode from '@/components/QRCode.vue' import QRCode from '@/components/QRCode.vue'
import BitcoinIcon from '@/components/BitcoinIcon.vue'
const router = useRouter() const router = useRouter()
const atmStore = useAtmStore() const atmStore = useAtmStore()
@ -237,8 +238,8 @@ const isProcessing = computed(() => atmStore.isPayingInvoice || atmStore.isReque
<!-- Bill Acceptor Visual --> <!-- Bill Acceptor Visual -->
<div class="rounded-lg border-2 border-dashed border-white/20 p-6 text-center"> <div class="rounded-lg border-2 border-dashed border-white/20 p-6 text-center">
<div v-if="balanceLimitReached"> <div v-if="balanceLimitReached" class="flex flex-col items-center">
<div class="mb-2 text-4xl">💰</div> <BitcoinIcon :size="48" class="mb-2 grayscale opacity-40" />
<p class="text-sm text-muted-foreground"> <p class="text-sm text-muted-foreground">
Maximum amount reached — press Done to continue Maximum amount reached — press Done to continue
</p> </p>