aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/InvoiceData.svelte
blob: 847d6f624c3f7cc47da1738627a9ba9f247dc88f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<script lang="ts">
  import PhWarningBold from "virtual:icons/ph/warning-bold";
  import PhCopyBold from "virtual:icons/ph/copy-bold";
  import Amount from "$comp/Amount.svelte";

  import { btc, copy, f, sat, sats, types } from "$lib/utils";
  import { fiat } from "$lib/store";
  let {
    showQr,
    link,
    txt,
    invoice,
    amount,
    amountFiat,
    currency,
    locale,
    tip,
    rate,
    align = "",
    qrDataUrl,
    t,
  }: any = $props();

  let expanded = $state(false);
  let { memo } = $derived(invoice);

  let qrSrc = $derived(`/qr/${encodeURIComponent(invoice.text)}/raw`);
  let srcs: string[] = $state([]);
  let lastDataUrl: string | undefined;

  $effect(() => {
    // Update if the server-provided data URL changed (e.g. new invoice)
    if (qrDataUrl && qrDataUrl !== lastDataUrl) {
      lastDataUrl = qrDataUrl;
      srcs = [qrDataUrl];
      return;
    }
    if (qrDataUrl && srcs.length) return;
    const next = qrSrc;
    if (!srcs.length) {
      srcs = [next];
    } else if (next !== srcs[srcs.length - 1]) {
      srcs = [...srcs, next];
    }
  });

  let onLoaded = (src: string) => {
    const idx = srcs.indexOf(src);
    if (idx > 0) srcs = srcs.slice(idx);
  };
</script>

{#if showQr}
  <div class="max-w-[280px] w-full mx-auto aspect-square relative">
    {#each srcs as src, i (src)}
      <a href={link} class="absolute inset-0" style:z-index={i}>
        <img
          {src}
          alt={txt}
          onload={srcs.length > 1 ? () => onLoaded(src) : undefined}
        />
      </a>
    {/each}
  </div>
{/if}

{#if invoice.type === types.liquid}
  <div class="flex justify-center p-4 shadow items-center gap-2">
    <PhWarningBold width="48" class="text-warning" />
    <div>
      <div class="my-auto text-xl text-center text-secondary">
        {t("payments.onlyLbtc")}
        <span class="text-teal-500 font-bold">L-BTC</span>
        &mdash; {t("payments.dontDeposit")}
      </div>
    </div>
  </div>
{/if}

  <button
    data-testid="invoice-text"
    onclick={() => { copy(txt); expanded = !expanded; }}
    aria-label="Copy invoice"
    class="w-full text-center text-secondary text-xl flex gap-1 items-center justify-center cursor-pointer hover:opacity-70"
  >
    <span class:truncate={!expanded} class="break-all">{txt}</span>
    <PhCopyBold width="32" class="shrink-0" />
  </button>

{#each invoice.items as i}
  {@const itemTotal = i.price * i.quantity}
  <div class="grid grid-cols-12 text-xl">
    <div class="col-span-1 my-auto">{i.quantity}</div>
    <div class="mr-auto grow col-span-7 my-auto">{i.name}</div>
    <div class="col-span-4 font-semibold text-right my-auto" class:hidden={!$fiat}>{f(itemTotal, currency)}</div>
    <div class="col-span-4 font-semibold text-right my-auto" class:hidden={$fiat}>{sat(btc(itemTotal, rate))}</div>
  </div>
{/each}

{#if amount > 0}
  <Amount {amount} {currency} {rate} {locale} {tip} />
{/if}

{#if memo}
  <div class="text-xl text-center">{memo}</div>
{/if}