diff options
| author | Adrien Hopkins <[email protected]> | 2022-08-02 13:13:27 -0500 |
|---|---|---|
| committer | Adrien Hopkins <[email protected]> | 2022-08-02 13:13:27 -0500 |
| commit | c21ee41b206db79b2157d8743b0473a094448dfb (patch) | |
| tree | fac1a595e451c0b32ceedfe4fb70855270456377 /src/components | |
| parent | 3b216dd6c170a7d71d21a391098c554008c8bdb4 (diff) | |
| parent | 05f5001fc7d325e31d9c777be11343604c72fbfd (diff) | |
| download | coinos-ui-c21ee41b206db79b2157d8743b0473a094448dfb.tar.gz coinos-ui-c21ee41b206db79b2157d8743b0473a094448dfb.zip | |
Merge branch 'master' into i18n
Diffstat (limited to 'src/components')
| -rw-r--r-- | src/components/404.svelte | 16 | ||||
| -rw-r--r-- | src/components/About.svelte | 73 | ||||
| -rw-r--r-- | src/components/AppHeader.svelte | 88 | ||||
| -rw-r--r-- | src/components/Footer.svelte | 39 | ||||
| -rw-r--r-- | src/components/LandingHeader.svelte | 106 | ||||
| -rw-r--r-- | src/components/LandingHero.svelte | 21 | ||||
| -rw-r--r-- | src/components/LoadingSplash.svelte | 7 | ||||
| -rw-r--r-- | src/components/RegisterOrLogin.svelte | 43 | ||||
| -rw-r--r-- | src/components/index.js | 4 |
9 files changed, 343 insertions, 54 deletions
diff --git a/src/components/404.svelte b/src/components/404.svelte new file mode 100644 index 00000000..503316bb --- /dev/null +++ b/src/components/404.svelte @@ -0,0 +1,16 @@ +<script> + import { Icon } from '$comp'; +</script> + +<div class="flex justify-center items-center mt-20"> + <div class="space-y-5 text-center"> + <a href="/"> + <Icon icon="logo" /> + </a> + + <Icon icon="question" style="mx-auto w-full" /> + + <h1 class="font-bold text-5xl">404</h1> + <p>Page not found.</p> + </div> +</div> diff --git a/src/components/About.svelte b/src/components/About.svelte new file mode 100644 index 00000000..3731bf9b --- /dev/null +++ b/src/components/About.svelte @@ -0,0 +1,73 @@ +<script> + import { Image, Icon } from '$comp'; + + const aboutAdam = [ + 'Running Bitcoin since 2011', + '20+ years web development experience in government and industry', + 'Early Bitcoin Vancouver meetup organizer', + 'Founder of The Bitcoin Co-op and early supporter of Decentral Vancouver', + 'Yogi, permaculturist, anarchist, decentralist', + 'Husband, father, brother, son' + ]; +</script> + +<h3 class="text-5xl font-medium mb-10 text-center">About</h3> +<div + class="md:px-10 lg:px-0 block lg:flex justify-center text-secondary text-xl lg:space-x-20 mx-auto max-w-7xl relative" +> + <p class="w-full lg:w-5/12"> + <strong>CoinOS is</strong> an <strong>open source</strong> bitcoin web wallet, point of sale, + ecommerce marketplace and exchange platform. Development started in Vancouver in September 2012 + as a way to provide local merchants with a convenient way to accept bitcoin payments. + <br /><br /> + The feature set has grown over the years to accomodate a wide variety of use cases with the goal + of making it as easy as possible for anyone to get started using Bitcoin quickly, cheaply, and securely. + <br /><br /> + </p> + <p class="w-full lg:w-5/12"> + Anyone can download the source code and host their own instance of the platform backed by their + own bitcoin, liquid or lightning nodes, or reach out and we'll gladly set this up for you. + <br /><br /> + Intra-account transfers between custodial wallets of different users on our server are completely + free, instant, and unlimited. + </p> + <Image image="swoosh" style="w-32 absolute -bottom-20 lg:bottom-0 right-0 md:right-10" /> +</div> + +<div class="px-5 block lg:flex justify-center lg:space-x-32 items-center mt-40 lg:mt-20"> + <div class="space-y-5 mb-5 lg:mb-0"> + <h3 class="text-5xl font-medium mb-10 text-center lg:text-right">The Founder</h3> + + <Image image="adam" style="rounded-full mx-auto lg:mx-0 lg:ml-auto w-40" /> + + <div class="space-y-2"> + <span class="text-2xl text-center font-semibold block lg:text-right">Adam Soltys</span> + <span class="text-xl text-center text-secondary block lg:text-right" + >Chief Technical Officer</span + > + </div> + + <div class="flex justify-center lg:justify-end items-center space-x-5"> + <a + href="https://twitter.com/adamsoltys" + target="_blank" + rel="noreferrer" + class="rounded-full p-2 bg-[#1D9BF0]"><Icon icon="twitter" style="w-6" /></a + > + <a + href="https://github.com/asoltys" + target="_blank" + rel="noreferrer" + class="rounded-full p-2 bg-gray-800"><Icon icon="github" style="w-6" /></a + > + </div> + </div> + + <ul + class="w-full mx-auto md:w-[700px] lg:w-[500px] xl:w-auto text-secondary px-1 md:px-10 text-xl list-disc space-y-5" + > + {#each aboutAdam as about} + <li>{about}</li> + {/each} + </ul> +</div> diff --git a/src/components/AppHeader.svelte b/src/components/AppHeader.svelte index 249e2826..242e6924 100644 --- a/src/components/AppHeader.svelte +++ b/src/components/AppHeader.svelte @@ -1,32 +1,88 @@ <script> // we will want to dynamically use the users avatar on this screen if they have uploaded one + import { user } from '$lib/store'; import { goto } from '$app/navigation'; import { Icon, LocaleSelector } from '$comp'; - import { locale, locales } from 'svelte-i18n'; + export let avatarPosition = 'left-[calc(50vw-48px)]'; + + const menuButtons = [ + { title: 'Customers', icon: 'customers', goto: 'customers' }, + { title: 'Dashboard', icon: 'dash', goto: 'dashboard' }, + { title: 'Settings', icon: 'settings', goto: 'settings' }, + { title: 'Support', icon: 'support', goto: 'support' }, + { title: 'Sign out', icon: 'logout', goto: 'logout' } + ]; + + let showMenu = false; + + const handleMenuItemClick = (item) => { + if (item === 'logout') { + goto('/logout'); + } else { + goto(`/${$user.username + '/' + item}`); + } + }; </script> -<header class="bg-gradient-to-r from-primary to-gradient h-[20vh] w-full relative"> +<header class="bg-gradient-to-r from-primary to-gradient h-[175px] w-full relative"> <nav class="flex justify-end items-center space-x-4 p-5"> <LocaleSelector /> - - <button class="bg-white p-2 rounded-full w-12 h-12" on:click={() => goto('/receive')} - ><Icon icon="numpad" style="mx-auto" /></button - > - <button class="bg-white p-2 rounded-full w-12 h-12" - ><Icon icon="clock" style="mx-auto" /></button - > - <button class="bg-white p-2 rounded-full w-12 h-12" - ><Icon icon="menu" style="mx-auto" /></button - > - <button class="bg-white p-2 rounded-full w-12 h-12" - ><Icon icon="profile" style="mx-auto" /></button - > + {#if $user} + <a href={`/${$user.username}/receive`}> + <button class="bg-white p-2 rounded-full w-12 h-12" + ><Icon icon="numpad" style="mx-auto" /> + </button> + </a> + <a href={`/${$user.username}/transactions`}> + <button class="bg-white p-2 rounded-full w-12 h-12" + ><Icon icon="clock" style="mx-auto" /> + </button> + </a> + <a href={`/${$user.username}`}> + <button class="bg-white p-2 rounded-full w-12 h-12" + ><Icon icon="profile" style="mx-auto" /> + </button> + </a> + <div class="relative"> + <button class="bg-white p-2 rounded-full w-12 h-12" on:click={() => (showMenu = !showMenu)} + ><Icon icon="menu" style="mx-auto" /> + </button> + <div + class="{showMenu + ? 'block' + : 'hidden'} absolute top-14 right-0 bg-white rounded-3xl p-8 shadow-xl z" + > + <ul class="space-y-5 w-32"> + {#each menuButtons as button} + <li> + <button + class="flex justify-center items-center font-semibold text-sm" + on:click={() => handleMenuItemClick(button.goto)} + ><Icon icon={button.icon} style="mr-1" /> {button.title} + </button> + </li> + {/each} + </ul> + </div> + </div> + {:else} + <a href="/login"> + <button class="bg-white px-5 py-2 rounded-xl font-semibold text-sm">Sign in </button> + </a> + {/if} +>>>>>>> master </nav> <div - class="absolute top-[calc(20vh-48px)] left-[calc(50vw-48px)] rounded-full border-4 border-white p-4 bg-gradient-to-r from-primary to-gradient w-24 h-24" + class="absolute top-[calc(175px-48px)] {avatarPosition} rounded-full border-4 border-white p-4 bg-gradient-to-r from-primary to-gradient w-24 h-24" > <Icon icon="logo-symbol-white" style="mx-auto" /> </div> </header> + +<style> + .z { + z-index: 100; + } +</style> diff --git a/src/components/Footer.svelte b/src/components/Footer.svelte new file mode 100644 index 00000000..0c682179 --- /dev/null +++ b/src/components/Footer.svelte @@ -0,0 +1,39 @@ +<script> + import { Icon } from '$comp'; + + const followLinks = [ + { url: 'https://twitter.com/coinoswallet', title: 'Twitter' }, + { url: 'https://github.com/coinos', title: 'GitHub' }, + { url: 'https://t.me/coinos', title: 'Telegram' } + ]; + + const companyLinks = [ + { url: 'mailto:[email protected]', title: 'Support' }, + { url: '/community', title: 'Community' }, + { url: '/jobs', title: 'Jobs' } + ]; +</script> + +<footer class="space-y-10 md:space-y-0 text-xl block md:flex justify-around items-center mb-20"> + <Icon icon="logo" style="w-48 mx-auto md:mx-0" /> + + <div class="text-center md:text-left"> + <p class="font-semibold">Follow Us</p> + <ul class="mt-5 text-secondary space-y-3 font-medium"> + {#each followLinks as link} + <li><a href={link.url} target="_blank" rel="noreferrer">{link.title}</a></li> + {/each} + </ul> + </div> + + <div class="text-center md:text-left"> + <p class="font-semibold">Company</p> + <ul class="mt-5 text-secondary space-y-3"> + {#each companyLinks as link} + <li><a href={link.url}>{link.title}</a></li> + {/each} + </ul> + </div> + + <Icon icon="shield" style="mx-auto md:mx-0" /> +</footer> diff --git a/src/components/LandingHeader.svelte b/src/components/LandingHeader.svelte index ca9d431e..352b200c 100644 --- a/src/components/LandingHeader.svelte +++ b/src/components/LandingHeader.svelte @@ -2,34 +2,112 @@ import { goto } from '$app/navigation'; import { scroll } from '$lib/utils'; import { Icon, LocaleSelector } from '$comp'; - - import { _, locale, locales } from 'svelte-i18n'; + import { user } from '$lib/store'; + import { _ } from 'svelte-i18n'; export let howItWorks; export let faq; + export let about; + + let showMobileMenu = false; + const mobileMenuButtonClick = (section) => { + showMobileMenu = false; + scroll(section); + }; </script> -<header class="w-full lg:w-5/6 pt-10 mx-auto"> +<header + class="w-full lg:w-5/6 py-5 xl:pb-0 xl:pt-10 mx-auto fixed md:sticky z-10 top-0 bg-white/90" +> <nav class="block xl:flex flex-wrap justify-between items-center"> - <a href="/"> + <a href="/" class="hidden md:block"> <Icon icon="logo" style="mx-auto mb-5 xl:mb-0" /> </a> + <Icon icon="logo" style="block md:hidden ml-5 w-48" /> <LocaleSelector /> + <!-- desktop nav --> <div class="hidden space-x-10 md:flex flex-wrap justify-center items-center font-bold"> <button on:click={() => scroll(howItWorks)}>{$_('howItWorks')}</button> <button on:click={() => scroll(faq)}>{$_('FAQ')}</button> - <button>{$_('about')}</button> - <button class="border rounded-full px-6 py-2 font-bold" on:click={() => goto('/register')} - >{$_('startInSeconds')}</button - > - <button - class="bg-black text-white border rounded-full px-6 py-2 font-bold" - on:click={() => goto('/login')} - > - {$_('signIn')} - </button> + <button on:click={() => scroll(about)}>{$_('about')}</button> + {#if !$user} + <button class="border rounded-full px-6 py-2 font-bold" on:click={() => goto('/register')} + >{$_('startInSeconds')} + </button> + <button + class="bg-black text-white border rounded-full px-6 py-2 font-bold" + on:click={() => goto('/login')} + > + {$_('signIn')} + </button> + {:else} + <button + class="border rounded-full px-6 py-2 font-bold" + on:click={() => goto(`/${$user.username}/dashboard`)} + >Account + </button> + <button + class="bg-black text-white border rounded-full px-6 py-2 font-bold" + on:click={() => goto('/logout')} + > + Sign out + </button> + {/if} + </div> + + <!-- mobile nav --> + <button + class="block md:hidden absolute top-[34.5px] right-10 z" + on:click={() => (showMobileMenu = !showMobileMenu)} + ><Icon icon={!showMobileMenu ? 'menu' : 'close'} /> + </button> + + <div + class="block md:hidden absolute top-0 {showMobileMenu + ? 'right-0' + : 'right-[-100%]'} transition-all ease-in-out duration-300 h-[100vh] w-full bg-white" + > + <div class="space-y-8 mt-24 ml-10 font-bold text-xl"> + <button on:click={() => mobileMenuButtonClick(howItWorks)} class="block" + >{$_('howItWorks')}</button + > + <button on:click={() => mobileMenuButtonClick(faq)} class="block">{$_('FAQ')}</button> + <button on:click={() => mobileMenuButtonClick(about)} class="block">{$_('about')}</button> + {#if !$user} + <button + class="border rounded-full px-6 py-2 font-bold block" + on:click={() => goto('/register')} + >{$_('startInSeconds')} + </button> + <button + class="bg-black text-white border rounded-full px-6 py-2 font-bold block" + on:click={() => goto('/login')} + > + {$_('startInSeconds')} + </button> + {:else} + <button + class="border rounded-full px-6 py-2 font-bold block" + on:click={() => goto(`/${$user.username}/dashboard`)} + >Account + </button> + <button + class="bg-black text-white border rounded-full px-6 py-2 font-bold block" + on:click={() => goto('/logout')} + > + Sign out + </button> + {/if} + </div> +>>>>>>> master </div> </nav> </header> + +<style> + .z { + z-index: 100; + } +</style> diff --git a/src/components/LandingHero.svelte b/src/components/LandingHero.svelte index 2c2e1ab5..93bea8c2 100644 --- a/src/components/LandingHero.svelte +++ b/src/components/LandingHero.svelte @@ -1,9 +1,10 @@ <script> import { goto } from '$app/navigation'; import { Icon, Image } from '$comp'; + import { user } from '$lib/store'; </script> -<div> +<div class="mt-[96.88px] md:mt-0"> <div class="space-y-10"> <h1 class="text-5xl md:text-6xl lg:text-7xl 2xl:text-8xl font-medium text-center w-full md:w-3/4 lg:w-1/2 max-w-7xl mx-auto leading-tight" @@ -19,14 +20,16 @@ Grow your customer base and revenue by accepting Bitcoin with an easy-to-use and managed Point of Sale. No software or hardware required. </h2> - <div class="flex justify-center"> - <button - class="bg-black text-white border rounded-full px-6 py-2 font-bold" - on:click={() => goto('/register')} - > - Start in Seconds - </button> - </div> + {#if !$user} + <div class="flex justify-center"> + <button + class="bg-black text-white border rounded-full px-6 py-2 font-bold" + on:click={() => goto('/register')} + > + Start in Seconds + </button> + </div> + {/if} </div> <!-- hero image --> diff --git a/src/components/LoadingSplash.svelte b/src/components/LoadingSplash.svelte new file mode 100644 index 00000000..2ab4c739 --- /dev/null +++ b/src/components/LoadingSplash.svelte @@ -0,0 +1,7 @@ +<script> + import { Icon } from '$comp'; +</script> + +<div class="flex justify-center items-center"> + <Icon icon="logo" style="mt-[calc(50vh-72px)]" /> +</div> diff --git a/src/components/RegisterOrLogin.svelte b/src/components/RegisterOrLogin.svelte index 7cc41709..157c2821 100644 --- a/src/components/RegisterOrLogin.svelte +++ b/src/components/RegisterOrLogin.svelte @@ -1,13 +1,15 @@ <script> + import { toast } from '@zerodevx/svelte-toast'; import { Icon } from '$comp'; import { post } from '$lib/utils'; - import { token } from '$lib/store'; - import { connect } from '$lib/socket'; + import { user, token } from '$lib/store'; + import { auth } from '$lib/socket'; import { goto } from '$app/navigation'; export let page; - let username, password; + let username = 'bob', + password = 'pw'; let revealPassword = false; @@ -16,20 +18,27 @@ 'Sign in': '/login' }[page]; - let submit = () => - post(url, { username, password }).then((r) => - r.json().then((r) => { - $token = r.token; - connect(); - goto('/receive'); - }) - ); + let submit = async () => { + try { + let r = await post(url, { username, password }); + if (!r.token) r = await post('/login', { username, password }); + $token = r.token; + auth(); + } catch (e) { + if (!e.message) e.message = 'Login failed'; + toast.push(e.message); + } + }; + + $: if ($user) goto(`/${username}/receive`); </script> <div class="pt-10"> - <a href="/"> - <Icon icon="logo" style="mx-auto mb-10" /> - </a> + <div class="w-[243px] mx-auto mb-10"> + <a href="/"> + <Icon icon="logo" /> + </a> + </div> <div class="flex justify-center items-center"> <div class="shadow-xl rounded-3xl p-10 pb-12 space-y-5 w-full mx-5 md:mx-0 md:w-[400px]"> @@ -38,11 +47,13 @@ <form class="space-y-5" on:submit|preventDefault={submit}> <div> <label for="username" class="font-semibold">Username</label> + <!-- svelte-ignore a11y-autofocus --> <input type="text" required class="bg-primary p-4 rounded-2xl w-full" bind:value={username} + autofocus /> </div> @@ -78,7 +89,9 @@ </p> {:else} <div class="flex justify-end items-center"> - <a href="" class="underline underline-offset-4 text-black text-sm">Forgot Password?</a> + <a href="/forgot" class="underline underline-offset-4 text-black text-sm" + >Forgot Password?</a + > </div> {/if} diff --git a/src/components/index.js b/src/components/index.js index f0e86183..1d5b369d 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -8,3 +8,7 @@ export { default as Image } from './Image.svelte'; export { default as RegisterOrLogin } from './RegisterOrLogin.svelte'; export { default as AppHeader } from './AppHeader.svelte'; export { default as LocaleSelector } from './LocaleSelector.svelte'; +export { default as LoadingSplash } from './LoadingSplash.svelte'; +export { default as PageNotFound } from './404.svelte'; +export { default as About } from './About.svelte'; +export { default as Footer } from './Footer.svelte'; |
