aboutsummaryrefslogtreecommitdiffstats
path: root/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'src/components')
-rw-r--r--src/components/About.svelte5
-rw-r--r--src/components/Account.svelte64
-rw-r--r--src/components/AppHeader.svelte33
-rw-r--r--src/components/Balance.svelte6
-rw-r--r--src/components/Footer.svelte2
-rw-r--r--src/components/Invoice.svelte2
-rw-r--r--src/components/Items.svelte246
-rw-r--r--src/components/LandingHeader.svelte16
-rw-r--r--src/components/LocationsMap.svelte12
-rw-r--r--src/components/Mnemonic.svelte14
-rw-r--r--src/components/Numpad.svelte2
-rw-r--r--src/components/Request.svelte39
-rw-r--r--src/components/WalletPass.svelte65
13 files changed, 430 insertions, 76 deletions
diff --git a/src/components/About.svelte b/src/components/About.svelte
index 1e60db72..01ff4c7c 100644
--- a/src/components/About.svelte
+++ b/src/components/About.svelte
@@ -91,14 +91,15 @@
{@html $t("about.locations.description")}
</p>
<!-- <LocationsMap {locations} /> -->
+
<a href="/map">
<div class="relative">
<img src="/map.png" class="mx-auto" />
<button
- class="bg-black text-white border rounded-full px-6 py-2 font-bold hover:opacity-80 absolute left-1/2 top-1/2 text-2xl"
+ class="bg-black text-white border border-4 rounded-full px-6 py-2 font-bold hover:bg-secondary absolute left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2 text-2xl"
>
- View map
+ {$t("about.locations.viewMap")}
</button>
</div>
</a>
diff --git a/src/components/Account.svelte b/src/components/Account.svelte
new file mode 100644
index 00000000..458f67c6
--- /dev/null
+++ b/src/components/Account.svelte
@@ -0,0 +1,64 @@
+<script>
+ import Icon from "$comp/Icon.svelte";
+ import Balance from "$comp/Balance.svelte";
+ import { t } from "$lib/translations";
+
+ export let user, rate, account;
+ let { name, seed, balance, id } = account;
+ $: type = seed ? "Savings" : "Cash";
+
+ $: refresh(account);
+ let refresh = (a) => ({ seed, balance, id } = a);
+
+ let setAccount = () => (document.cookie = `aid=${id}; path=/; max-age=86400`);
+</script>
+
+<a href={`/payments`} class="block" on:click={setAccount}>
+ <div class="py-4 px-2 space-y-5 bg-primary rounded-2xl border">
+ <div class="flex">
+ <Balance {balance} {user} {rate} />
+ {#if seed}
+ <a href={`/account/${id}`} class="contents">
+ <button class="ml-auto flex gap-1 mb-auto pb-4 pl-4">
+ <Icon icon="settings" style="w-8 my-auto" />
+ </button>
+ </a>
+ {/if}
+ </div>
+
+ <div class="flex gap-1 justify-center w-full text-xl">
+ <a href={`/invoice`} class="contents" on:click={setAccount}>
+ <button
+ class="rounded-2xl border py-5 px-4 hover:opacity-80 flex grow bg-white"
+ >
+ <div class="mx-auto flex gap-2">
+ <Icon icon="receive" style="w-8" />
+ <div class="my-auto">{$t("user.dashboard.receive")}</div>
+ </div>
+ </button>
+ </a>
+
+ <a href={`/scan`} class="contents" on:click={setAccount}>
+ <button
+ class="rounded-2xl border py-5 px-4 hover:opacity-80 flex shrink bg-white"
+ >
+ <div class="mx-auto flex gap-2">
+ <Icon icon="camera" style="w-8" />
+ </div>
+ </button>
+ </a>
+
+ <a href={`/send`} class="contents grow" on:click={setAccount}>
+ <button
+ type="button"
+ class="rounded-2xl border py-5 px-6 hover:opacity-80 flex bg-white grow"
+ >
+ <div class="mx-auto flex gap-1">
+ <Icon icon="send" style="w-8" />
+ <div class="my-auto">{$t("user.dashboard.send")}</div>
+ </div>
+ </button>
+ </a>
+ </div>
+ </div>
+</a>
diff --git a/src/components/AppHeader.svelte b/src/components/AppHeader.svelte
index 3b0303a8..cc521e93 100644
--- a/src/components/AppHeader.svelte
+++ b/src/components/AppHeader.svelte
@@ -7,11 +7,7 @@
import { loading, t } from "$lib/translations";
import { page } from "$app/stores";
- export let data;
-
- let { subject, user } = data;
- $: update(data);
- let update = (data) => ({ subject, user } = data);
+ export let user, subject;
let menuButtons;
$: if (user)
@@ -19,15 +15,15 @@
{
key: "nav.settings",
icon: "settings",
- href: `/${user.username}/settings`,
+ href: `/settings`,
},
{ key: "nav.support", icon: "support", href: `/support` },
- { key: "nav.map", icon: "map", href: `/${user.username}/map` },
- {
- key: "nav.messages",
- icon: "message",
- href: `/${user.username}/messages`,
- },
+ { key: "nav.map", icon: "map", href: `/map` },
+ // {
+ // key: "nav.messages",
+ // icon: "message",
+ // href: `/messages`,
+ // },
{ key: "nav.merch", icon: "shop", href: `https://coinosmerch.com` },
{ key: "nav.signOut", icon: "logout", href: `/logout` },
];
@@ -60,19 +56,19 @@
><Icon icon="home" style="mx-auto w-6 sm:w-8" />
</button>
</a>
- <a href={`/${user.username}/receive`}>
+ <a href={`/invoice`}>
<button
class="bg-white p-2 rounded-full w-12 h-12 sm:w-16 sm:h-16 drop-shadow-xl border border-black/10 {$page
- .url.pathname === `/${user.username}/receive`
+ .url.pathname.includes('invoice')
? 'opacity-100'
: 'opacity-70 hover:opacity-80'}"
><Icon icon="receive" style="mx-auto w-6 sm:w-8" />
</button>
</a>
- <a href={`/${user.username}/payments`}>
+ <a href={`/payments`}>
<button
class="bg-white p-2 rounded-full w-12 h-12 sm:w-16 sm:h-16 drop-shadow-xl border border-black/10 {$page
- .url.pathname === `/${user.username}/payments`
+ .url.pathname === `/payments`
? 'opacity-100'
: 'opacity-70 hover:opacity-80'} relative"
><Icon icon="clock" style="mx-auto w-6 sm:w-8" />
@@ -102,9 +98,8 @@
<div class="relative">
<OutClick on:outclick={() => (showMenu = false)}>
<button
- class="bg-white p-2 rounded-full w-12 h-12 sm:w-16 sm:h-16 drop-shadow-xl border border-black/10 {$page
- .url.pathname === `/${user.username}` ||
- $page.url.pathname === `/${user.username}/settings` ||
+ class="bg-white p-2 rounded-full w-12 h-12 sm:w-16 sm:h-16 drop-shadow-xl border border-black/10 {
+ $page.url.pathname === `/settings` ||
$page.url.pathname === `/support`
? 'opacity-100'
: `opacity-70 hover:opacity-80 ${
diff --git a/src/components/Balance.svelte b/src/components/Balance.svelte
index 4d5ac6bd..51c56555 100644
--- a/src/components/Balance.svelte
+++ b/src/components/Balance.svelte
@@ -6,7 +6,7 @@
import { t } from "$lib/translations";
let show;
- export let user, rate;
+ export let user, rate, balance;
</script>
{#if show && user.haspin && $pin?.length !== 6}
@@ -27,12 +27,12 @@
{#if isNaN(rate)}
<div class="text-gray-200">&mdash;</div>
{:else}
- {f((user.balance * rate) / sats, user.currency)}
+ {f((balance * rate) / sats, user.currency)}
{/if}
</div>
<div class="text-secondary text-2xl">
- ⚡️{s(user.balance)}
+ ⚡️{s(balance)}
</div>
{/if}
</div>
diff --git a/src/components/Footer.svelte b/src/components/Footer.svelte
index d70c013c..067e185e 100644
--- a/src/components/Footer.svelte
+++ b/src/components/Footer.svelte
@@ -4,7 +4,7 @@
import { t } from "$lib/translations";
const followLinks = [
- { url: "https://twitter.com/coinoswallet", titleID: "twitter" },
+ { url: "nostr:nprofile1qqst4qyeqenw7zm0fwjsty68h6cnys5jre2xd8ngqpjv5a2j26s78fspz4mhxue69uhhyetvv9ujucm0d9hx7uewd9hsgwx239", titleID: "nostr" },
{ url: "https://t.me/coinoswallet", titleID: "telegram" },
{ url: "https://linktr.ee/coinos.io", titleID: "linktree" },
];
diff --git a/src/components/Invoice.svelte b/src/components/Invoice.svelte
index ba436649..563a2fee 100644
--- a/src/components/Invoice.svelte
+++ b/src/components/Invoice.svelte
@@ -27,7 +27,7 @@
</div>
</div>
<div class="mx-auto my-auto flex gap-2">
- <a href={`/${invoice.user.username}/invoice/${$invoice.id}/tip`}>
+ <a href={`/invoice/${$invoice.id}/tip`}>
<button
class="rounded-full border py-2 px-4 font-bold hover:opacity-80 w-32"
>
diff --git a/src/components/Items.svelte b/src/components/Items.svelte
new file mode 100644
index 00000000..2916721d
--- /dev/null
+++ b/src/components/Items.svelte
@@ -0,0 +1,246 @@
+<script>
+ import { t } from "$lib/translations";
+ import { btc, f, sat, post } from "$lib/utils";
+ import { browser } from "$app/environment";
+ import { goto, invalidate } from "$app/navigation";
+ import { fade } from "svelte/transition";
+ import { cubicIn } from "svelte/easing";
+ import { flip } from "svelte/animate";
+ import {
+ dndzone,
+ SHADOW_ITEM_MARKER_PROPERTY_NAME,
+ SOURCES,
+ TRIGGERS,
+ } from "svelte-dnd-action";
+ import DeleteItem from "$comp/DeleteItem.svelte";
+ import Icon from "$comp/Icon.svelte";
+
+ export let subject, user, items, rate, currency, total;
+
+ let flipDurationMs = 200;
+ let dropTargetStyle = {};
+
+ let dragDisabled =
+ subject?.id !== user?.id || (browser && window.innerWidth < 768);
+
+ let deleting;
+ let del = (item) => {
+ deleting = item;
+ };
+
+ function handleConsider(e) {
+ const {
+ items: newItems,
+ info: { source, trigger },
+ } = e.detail;
+ items = newItems;
+ if (source === SOURCES.KEYBOARD && trigger === TRIGGERS.DRAG_STOPPED)
+ reset();
+ }
+
+ async function handleFinalize(e) {
+ const {
+ items: newItems,
+ info: { source },
+ } = e.detail;
+ items = newItems;
+ if (source === SOURCES.POINTER) reset();
+
+ if (subject?.id === user?.id) {
+ await post("/api/items/sort", { items });
+ invalidate("app:items");
+ }
+ }
+
+ function startDrag(e) {
+ e.preventDefault();
+ dragDisabled = false;
+ }
+
+ function handleKeyDown(e) {
+ if ((e.key === "Enter" || e.key === " ") && dragDisabled)
+ dragDisabled = false;
+ }
+
+ $: if (total > 0 && browser) {
+ let payButton = document.querySelector("#payButton");
+ if (payButton) payButton.addEventListener("click", checkout);
+ }
+
+ let checkout = async () => {
+ let invoice = {
+ type: "lightning",
+ amount: btc(total, rate),
+ currency,
+ items: items.filter((i) => i.quantity > 0),
+ prompt: subject.prompt,
+ memoPrompt: subject.memoPrompt,
+ rate,
+ };
+
+ let { id } = await post(`/invoice`, {
+ invoice,
+ user: { username: subject.username },
+ });
+
+ if (invoice.memoPrompt) {
+ return goto(`/invoice/${id}/memo`);
+ }
+ goto(`/invoice/${id}`);
+ };
+
+ let reset = () =>
+ (dragDisabled =
+ user?.username !== subject?.username || window.innerWidth < 768);
+</script>
+
+<svelte:window on:resize={reset} />
+
+{#if deleting}
+ <DeleteItem bind:item={deleting} />
+{/if}
+
+{#if items.length}
+ <h2 class="text-2xl font-bold">Select items</h2>
+{/if}
+<div
+ class="grid sm:grid-cols-2 gap-4 pb-20"
+ use:dndzone={{ items, flipDurationMs, dropTargetStyle, dragDisabled }}
+ on:consider={handleConsider}
+ on:finalize={handleFinalize}
+>
+ {#each items as i (i.id)}
+ <button
+ type="button"
+ class="w-full text-center cursor-pointer hover:opacity-80 mb-auto"
+ on:click={() => i.quantity++}
+ >
+ <div class="relative w-full h-64 overflow-hidden rounded-xl">
+ {#if i[SHADOW_ITEM_MARKER_PROPERTY_NAME]}
+ <div
+ in:fade={{ duration: 200, easing: cubicIn }}
+ class="custom-shadow-item"
+ />
+ {:else if i.image}
+ <img
+ src={`/api/public/${i.image}.webp`}
+ alt={i.name}
+ class="mx-auto object-cover h-full w-full"
+ />
+ {:else}
+ <div
+ class="bg-gradient-to-r from-primary to-gradient mb-4 cursor-pointer hover:opacity-80 w-full h-full"
+ alt="Banner"
+ />
+ {/if}
+ {#if user?.username === subject.username}
+ <div class="flex gap-2 justify-center absolute top-2 right-2">
+ <button type="button" on:click|stopPropagation={() => {}}>
+ <a href={`/items/${i.id}`}>
+ <button
+ class="bg-black rounded-full w-12 h-12 bg-opacity-40 hover:bg-opacity-100"
+ >
+ <Icon icon="edit" style="w-8 mx-auto invert" />
+ </button>
+ </a>
+ </button>
+ <button
+ class="bg-black rounded-full w-12 h-12 bg-opacity-40 hover:bg-opacity-100"
+ on:click|stopPropagation={() => del(i)}
+ >
+ <Icon icon="trash" style="w-8 mx-auto invert" />
+ </button>
+ <button
+ type="button"
+ on:click|stopPropagation={() => {}}
+ class="sm:hidden"
+ on:mousedown={startDrag}
+ on:touchstart={startDrag}
+ on:keydown={handleKeyDown}
+ >
+ <a href={`/items/${i.id}`}>
+ <button
+ class="bg-black rounded-full w-12 h-12 bg-opacity-40 hover:bg-opacity-100"
+ >
+ <Icon icon="move" style="w-8 mx-auto invert" />
+ </button>
+ </a>
+ </button>
+ </div>
+ {/if}
+ </div>
+ <div class="bg-white rounded-xl py-2">
+ <div class="flex text-left gap-2">
+ <div class="overflow-hidden space-y-1">
+ <div class="text-2xl break-words">{i.name}</div>
+ <div class="flex gap-2">
+ <div class="font-semibold text-lg">
+ {f(i.price, currency)}
+ </div>
+ <div class="text-secondary my-auto">
+ {sat(btc(i.price, rate))}
+ </div>
+ </div>
+ </div>
+ <div class="flex gap-1 ml-auto mb-auto justify-around tabular-nums">
+ {#if i.quantity}
+ <button
+ type="button"
+ on:click|stopPropagation={() => i.quantity > 0 && i.quantity--}
+ >
+ <Icon icon="minus" style="w-10 min-w-10" />
+ </button>
+ {/if}
+ <div class="text-2xl my-auto text-center">
+ {#if i.quantity}{i.quantity}{:else}&mdash;{/if}
+ </div>
+ {#if i.quantity}
+ <button
+ type="button"
+ on:click|stopPropagation={() => i.quantity++}
+ >
+ <Icon icon="plus" style="w-10 min-w-10" />
+ </button>
+ {/if}
+ </div>
+ </div>
+ </div>
+ </button>
+ {/each}
+</div>
+
+<div
+ class="fixed inset-x-0 mx-auto flex bottom-16"
+ class:static={!items.length}
+>
+ {#if total > 0}
+ <button
+ class="rounded-2xl py-5 px-6 font-bold hover:bg-neutral-700 flex bg-black text-white mx-auto"
+ on:click={checkout}
+ >
+ <div class="mx-auto flex">
+ <div class="my-auto text-2xl">
+ {$t("user.dashboard.checkout")}
+ {f(total, currency)}
+ <span class="text-base">
+ {sat(btc(total, rate), currency)}
+ </span>
+ </div>
+ </div>
+ </button>
+ {/if}
+</div>
+
+<style>
+ .custom-shadow-item {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ visibility: visible;
+ background: #333;
+ opacity: 0.5;
+ margin: 0;
+ }
+</style>
diff --git a/src/components/LandingHeader.svelte b/src/components/LandingHeader.svelte
index d1094a1d..72913999 100644
--- a/src/components/LandingHeader.svelte
+++ b/src/components/LandingHeader.svelte
@@ -19,22 +19,22 @@
</script>
<header
- class="w-full lg:w-5/6 py-5 mx-auto fixed md:sticky z-10 top-0 bg-white/90"
+ class="w-full lg:w-5/6 py-5 mx-auto fixed sticky z-10 top-0 bg-white/90"
bind:this={header}
>
- <nav class="block xl:flex flex-wrap justify-between items-center">
+ <nav class="block lg:flex justify-between items-center">
<div
- class="flex justify-start md:justify-center items-center md:space-x-10"
+ class="flex justify-start lg:justify-center items-center lg:space-x-10"
>
<a href="/" on:click={() => scroll(header)}>
- <Icon icon="logo" style="hidden md:block mb-5 xl:mb-0" />
- <Icon icon="logo" style="block md:hidden ml-5 w-48" />
+ <Icon icon="logo" style="hidden lg:block mb-5 xl:mb-0" />
+ <Icon icon="logo" style="block lg:hidden ml-5 w-48" />
</a>
</div>
<!-- desktop nav -->
<div
- class="hidden space-x-10 md:flex flex-wrap justify-center items-center font-bold"
+ class="hidden space-x-10 lg:flex justify-center items-center font-bold"
>
{#if $page.url.pathname === "/"}
<button class="hover:opacity-80" on:click={() => scroll(howItWorks)}
@@ -76,13 +76,13 @@
<!-- mobile nav -->
<button
- class="block md:hidden absolute top-[34.5px] right-10 z"
+ class="block lg:hidden absolute top-[34.5px] right-10 z"
on:click={() => (showMobileMenu = !showMobileMenu)}
><Icon icon={!showMobileMenu ? "menu" : "close"} />
</button>
<div
- class="container w-full px-10 md:hidden absolute top-0 {showMobileMenu
+ class="container w-full px-10 lg:hidden absolute top-0 {showMobileMenu
? 'right-0'
: 'right-[-100%]'} transition-all ease-in-out duration-300 h-[100vh] w-full bg-white"
>
diff --git a/src/components/LocationsMap.svelte b/src/components/LocationsMap.svelte
index 79ea4bf3..bd51b125 100644
--- a/src/components/LocationsMap.svelte
+++ b/src/components/LocationsMap.svelte
@@ -3,7 +3,7 @@
import { browser } from "$app/environment";
import Icon from "$comp/Icon.svelte";
import Popup from "$comp/Popup.svelte";
- import { shuffleArray } from "$lib/utils";
+ import { back, shuffleArray } from "$lib/utils";
import "maplibre-gl/dist/maplibre-gl.css";
@@ -220,8 +220,16 @@
class="mx-auto h-full w-full z-0"
bind:this={mapContainer}
/>
+ <div class="absolute flex top-2 left-2 gap-2">
+ <button
+ class="rounded-full border-2 border-black bg-white w-10 h-10"
+ on:click={back}
+ >
+ <Icon icon="arrow-left" style="w-4 m-auto" />
+ </button>
+ </div>
<div class="relative">
- <div class="flex absolute flex top-2 right-2 gap-2">
+ <div class="absolute flex top-2 right-2 gap-2">
<button
class="rounded-full border-2 border-black bg-white w-10 h-10"
on:click={toggle}
diff --git a/src/components/Mnemonic.svelte b/src/components/Mnemonic.svelte
new file mode 100644
index 00000000..5e834aed
--- /dev/null
+++ b/src/components/Mnemonic.svelte
@@ -0,0 +1,14 @@
+<script>
+ export let mnemonic;
+</script>
+
+<div
+ class="text-lg border p-4 rounded-2xl text-secondary grid grid-cols-3 gap-2 justify-center"
+>
+ {#each mnemonic.split(" ") as w, i}
+ <div>
+ <span class="select-none text-sm text-black">{i + 1}.</span>
+ <span>{@html w === "-" ? "&mdash;" : w}</span>
+ </div>
+ {/each}
+</div>
diff --git a/src/components/Numpad.svelte b/src/components/Numpad.svelte
index 88b5b899..78322ff5 100644
--- a/src/components/Numpad.svelte
+++ b/src/components/Numpad.svelte
@@ -1,7 +1,7 @@
<script>
import Left from "$comp/Left.svelte";
import Icon from "$comp/Icon.svelte";
- import { f, s, focus, post, warning, sat, sats } from "$lib/utils";
+ import { f, s, focus, warning, sat, sats } from "$lib/utils";
import { t } from "$lib/translations";
export let amount,
diff --git a/src/components/Request.svelte b/src/components/Request.svelte
deleted file mode 100644
index c085f9e2..00000000
--- a/src/components/Request.svelte
+++ /dev/null
@@ -1,39 +0,0 @@
-<script>
- import { t } from "$lib/translations";
- import { fly } from "svelte/transition";
-
- import Avatar from "$comp/Avatar.svelte";
- import Icon from "$comp/Icon.svelte";
-
- import { request, requestRedirect } from "$lib/store";
- import { page } from "$app/stores";
-
- export let user;
-
- $requestRedirect = $page.url.pathname;
-</script>
-
-{#if $request}
- <div class="fixed bottom-0 border-t w-full p-4 bg-white z-50" in:fly>
- <div class="flex flex-wrap md:flex-nowrap max-w-xl mx-auto gap-2">
- <div class="my-auto mx-auto">
- <div class="flex">
- <Avatar user={$request.requester} size={12} />
- <h1 class="my-auto">
- <b>{$request.requester.username}</b>
- {$t("payments.readyToPay")}
- </h1>
- </div>
- </div>
- <div class="mx-auto my-auto flex gap-2">
- <a href={`/${user.username}/receive/${$request.id}`}>
- <button
- class="rounded-full border py-2 px-4 font-bold hover:opacity-80 w-32"
- >
- {$t("payments.invoice")}
- </button>
- </a>
- </div>
- </div>
- </div>
-{/if}
diff --git a/src/components/WalletPass.svelte b/src/components/WalletPass.svelte
new file mode 100644
index 00000000..75c94f34
--- /dev/null
+++ b/src/components/WalletPass.svelte
@@ -0,0 +1,65 @@
+<script>
+ import { focus } from "$lib/utils";
+ import { t } from "$lib/translations";
+ import Icon from "$comp/Icon.svelte";
+ export let cancel, password, submit;
+ let revealPassword;
+</script>
+
+<div
+ class="fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full z-20"
+>
+ <div
+ class="relative top-1/3 mx-auto p-5 border w-96 shadow-lg rounded-md bg-white space-y-5"
+ >
+ <h1 class="text-center text-2xl font-semibold">
+ {$t("payments.enterWalletPass")}
+ </h1>
+ <form on:submit|preventDefault={submit}>
+ <div class="relative mb-5">
+ {#if revealPassword}
+ <input
+ name="password"
+ type="text"
+ required
+ bind:value={password}
+ autocapitalize="none"
+ use:focus
+ />
+ {:else}
+ <input
+ name="password"
+ type="password"
+ required
+ bind:value={password}
+ autocapitalize="none"
+ use:focus
+ />
+ {/if}
+ <button
+ type="button"
+ on:click={() => (revealPassword = !revealPassword)}
+ class="absolute right-5 top-1/2"
+ >
+ <Icon icon={revealPassword ? "eye" : "eye-off"} />
+ </button>
+ </div>
+ <div class="w-full flex justify-center gap-2">
+ <button
+ type="button"
+ class="border rounded-2xl font-semibold mx-auto py-5 px-6 hover:opacity-80 mx-auto grow"
+ on:click={cancel}
+ on:keydown={cancel}
+ >
+ <div class="my-auto">Cancel</div>
+ </button>
+ <button
+ type="submit"
+ class="border rounded-2xl font-semibold mx-auto py-5 px-6 hover:opacity-80 mx-auto grow"
+ >
+ <div class="my-auto">Submit</div>
+ </button>
+ </div>
+ </form>
+ </div>
+</div>