Skip to content
This repository has been archived by the owner on Aug 15, 2023. It is now read-only.

Commit

Permalink
feat: implement nav menu and contacts screens (#52)
Browse files Browse the repository at this point in the history
* fix: fix initial display of recent transactions

* feat: add contacts placeholder components and refactor routes

* feat: implement nav menu and contacts screens

* chore: upgrade dependencies

Co-authored-by: Samer Buna <[email protected]>
  • Loading branch information
samerbuna and samerbuna authored Feb 9, 2022
1 parent 7db0e7f commit 7591d4d
Show file tree
Hide file tree
Showing 20 changed files with 907 additions and 483 deletions.
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"tsc:check": "tsc --pretty --noEmit --skipLibCheck"
},
"dependencies": {
"@galoymoney/client": "^0.0.19",
"@galoymoney/client": "^0.0.20",
"@galoymoney/react": "^0.0.15",
"@testing-library/jest-dom": "^5.16.2",
"@testing-library/react": "^12.1.2",
Expand Down Expand Up @@ -75,14 +75,14 @@
"webpack-cli": "^4.9.1"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.10.2",
"@typescript-eslint/parser": "^5.10.2",
"babel-jest": "^27.5.0",
"@typescript-eslint/eslint-plugin": "^5.11.0",
"@typescript-eslint/parser": "^5.11.0",
"babel-jest": "^27.5.1",
"eslint": "^8.7.0",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-react": "^7.28.0",
"eslint-plugin-react-hooks": "^4.3.0",
"jest": "^27.5.0",
"jest": "^27.5.1",
"prettier": "^2.5.1",
"ts-jest": "^27.1.3",
"ts-node-dev": "^1.1.8",
Expand Down
25 changes: 23 additions & 2 deletions src/components/__snapshots__/root.spec.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ exports[`Root renders Home and matches snapshot 1`] = `
class="home"
>
<div
class="header-container home-page"
class="header-container home-header"
>
<div
class="header"
Expand Down Expand Up @@ -47,8 +47,29 @@ exports[`Root renders Home and matches snapshot 1`] = `
<a
href="/login"
>
Login
<i
aria-hidden="true"
class="fas fa-sign-in-alt"
/>
<span
class="name"
>
Login
</span>
</a>
<div
class="separator"
>
|
</div>
<div
class="menu-icon"
>
<i
aria-hidden="true"
class="fas fa-bars"
/>
</div>
</div>
</div>
<div
Expand Down
63 changes: 63 additions & 0 deletions src/components/contacts/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { translate, useQuery } from "@galoymoney/client"
import { Spinner } from "@galoymoney/react"
import { history } from "../../store"
import ErrorMessage from "../error-message"
import Header from "../header"

const nameDisplay = (name: string): string => {
if (name.length > 15) {
return name.substring(0, 15) + "..."
}

return name
}

const Contacts = () => {
const { loading, errorsMessage, data } = useQuery.contacts()

const handleSendBitcoin = (contactUsername: string) => {
history.push(`/send?to=${contactUsername}`)
}

const showContactDetails = (contactUsername: string) => {
history.push(`/transactions?username=${contactUsername}`)
}

return (
<div className="contacts">
<Header page="contacts" />

<div className="page-title">{translate("Contacts")}</div>
<div className="list">
{loading && <Spinner size="big" />}

{errorsMessage && <ErrorMessage message={errorsMessage} />}

{data?.me?.contacts.map((contact) => {
return (
<div key={contact.username} className="contact">
<i aria-hidden className="fas fa-user-alt" />
<div className="name">{nameDisplay(contact.alias ?? contact.username)}</div>
<div className="actions">
<div
title={translate("Transaction List")}
onClick={() => showContactDetails(contact.username)}
>
<i aria-hidden className="fas fa-list" />
</div>
<div
title={translate("Send Bitcoin")}
onClick={() => handleSendBitcoin(contact.username)}
>
<i aria-hidden className="fas fa-paper-plane" />
</div>
</div>
</div>
)
})}
</div>
</div>
)
}

export default Contacts
11 changes: 11 additions & 0 deletions src/components/error-message.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { translate } from "@galoymoney/client"

const ErrorMessage = ({ message = "Not able to generate invoice." }) => (
<div className="error">
{translate(message as never)}
<br />
{translate("Please try again later.")}
</div>
)

export default ErrorMessage
63 changes: 56 additions & 7 deletions src/components/header.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { translate } from "@galoymoney/client"
import { useState } from "react"

import useMainQuery from "../hooks/use-main-query"
import { useAuthContext } from "../store/use-auth-context"
Expand All @@ -7,47 +8,95 @@ import Balance from "./balance"
import Link from "./link"
import Logout from "./logout"

const LoginLink = () => (
<Link to="/login">
<i aria-hidden className="fas fa-sign-in-alt" />
<span className="name">{translate("Login")}</span>
</Link>
)

type Props = {
page?: "send-bitcoin" | "receive-bitcoin" | "home"
page?: "home" | "send-bitcoin" | "receive-bitcoin" | "contacts" | "transactions"
}

const Header = ({ page }: Props) => {
const { isAuthenticated } = useAuthContext()
const { btcWalletBalance } = useMainQuery()

const [showMenu, setShowMenu] = useState(false)

const handleMenuClick: React.MouseEventHandler<HTMLDivElement> = (event) => {
event.preventDefault()
setShowMenu((menuStatus) => !menuStatus)
}

const handleMenuClose: React.MouseEventHandler<HTMLDivElement> = (event) => {
event.preventDefault()
setShowMenu(false)
}

const showHeaderNav = page && ["home", "send-bitcoin", "recevei-bitcoin"].includes(page)

return (
<div className={`header-container ${page}-page`}>
<div className={`header-container ${page}-header`}>
<div className="header">
<Balance balance={btcWalletBalance} />
<div className="links">
{page !== "home" && (
<>
<Link to="/">{translate("Home")}</Link>
<Link to="/">
<i aria-hidden className="fas fa-home" />
<span className="name">{translate("Home")}</span>
</Link>
<div className="separator">|</div>
</>
)}
{isAuthenticated ? <Logout /> : <Link to="/login">{translate("Login")}</Link>}
{isAuthenticated ? <Logout /> : <LoginLink />}
<div className="separator">|</div>
<div className="menu-icon" onClick={handleMenuClick}>
<i aria-hidden className="fas fa-bars" />
</div>
</div>
</div>
{page && (
{showHeaderNav && (
<div className="header-nav">
<Link to="/scan">
<i aria-hidden className="fas fa-qrcode" />
{translate("Scan QR code")}
</Link>
<Link to="/send" className={`${page === "send-bitcoin" ? "active" : "link"}`}>
<i aria-hidden className="fas fa-paper-plane"></i>
<i aria-hidden className="fas fa-paper-plane" />
{translate("Send Bitcoin")}
</Link>
<Link
to="/receive"
className={`${page === "receive-bitcoin" ? "active" : "link"}`}
>
<i aria-hidden className="far fa-dot-circle"></i>
<i aria-hidden className="far fa-dot-circle" />
{translate("Receive Bitcoin")}
</Link>
</div>
)}

{showMenu && (
<div className="menu">
<div className="close" onClick={handleMenuClose}>
<i aria-hidden className="fas fa-times" />
</div>

<Link to="/">
<i aria-hidden className="fas fa-home" />
{translate("Home")}
</Link>

<Link to="/contacts">
<i aria-hidden className="fas fa-user-friends" />
{translate("Contacts")}
</Link>

{isAuthenticated ? <Logout /> : <LoginLink />}
</div>
)}
</div>
)
}
Expand Down
3 changes: 2 additions & 1 deletion src/components/logout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ const Logout = () => {

return (
<a href="/logout" onClick={handleLogout}>
{translate("Logout")}
<i aria-hidden className="fas fa-sign-out-alt" />
<span className="name">{translate("Logout")}</span>
</a>
)
}
Expand Down
4 changes: 2 additions & 2 deletions src/components/pages/receive.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const Receive = () => {
satsForInvoice: Math.round(usdToSats(input.amount as number)),
}))
}
}, [input.currency, input.amount, shouldUpdateSatsForInvoice, usdToSats])
}, [input.currency, input.amount, input.memo, shouldUpdateSatsForInvoice, usdToSats])

useEffect(() => {
if (input.currency === "SATS" && shouldUpdateSatsForInvoice) {
Expand All @@ -61,7 +61,7 @@ const Receive = () => {
satsForInvoice: input.amount as number,
}))
}
}, [input.currency, input.amount, shouldUpdateSatsForInvoice])
}, [input.currency, input.amount, input.memo, shouldUpdateSatsForInvoice])

useEffect(() => {
if (input.layer === "onchain" && btcWalletId) {
Expand Down
12 changes: 8 additions & 4 deletions src/components/pages/send.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,19 @@ import Header from "../header"
import { ButtonLink } from "../link"
import SendAction from "../send/send-action"

const Send = () => {
type Props = {
to?: string
}

const Send = ({ to }: Props) => {
const dispatch = useAppDispatcher()
const { pubKey, btcWalletId, btcWalletBalance, username } = useMainQuery()
const { satsToUsd, usdToSats } = useMyUpdates()

const [input, setInput] = useState<InvoiceInput>({
currency: "USD",
amount: "",
destination: "",
destination: to ?? "",
memo: "",
})

Expand All @@ -51,7 +55,7 @@ const Send = () => {
satAmount: newSatAmount,
}))
}
}, [input.amount, input.currency, usdToSats])
}, [input.currency, input.amount, usdToSats])

useEffect(() => {
if (input.currency === "SATS" && typeof input.amount === "number") {
Expand All @@ -60,7 +64,7 @@ const Send = () => {
satAmount: input.amount as number,
}))
}
}, [input.amount, input.currency])
}, [input.currency, input.amount])

const setInputFromParsedDestination = useCallback(
async (parsedDestination: ValidPaymentReponse) => {
Expand Down
Loading

0 comments on commit 7591d4d

Please sign in to comment.