Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(pay): ui improvements #4048

Merged
merged 14 commits into from
Feb 28, 2024
Merged
1 change: 1 addition & 0 deletions apps/pay/BUCK
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ filegroup(
name = "src",
srcs = glob([
"app/**",
"context/**",
"theme/**",
"services/**",
"components/**",
Expand Down
69 changes: 61 additions & 8 deletions apps/pay/app/[username]/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,72 @@
import React from "react"

import Link from "next/link"

import { ApolloQueryResult } from "@apollo/client"

import { getClient } from "../ssr-client"

import { defaultCurrencyMetadata } from "../currency-metadata"

import styles from "./username.module.css"

import UsernameLayoutContainer from "@/components/layouts/username-layout"
import { InvoiceProvider } from "@/context/invoice-context"
import {
AccountDefaultWalletsDocument,
AccountDefaultWalletsQuery,
} from "@/lib/graphql/generated"

export default function UsernameLayout({
children,
params,
}: {
type Props = {
children: React.ReactNode
params: {
username: string
}
}) {
}

export default async function UsernameLayout({ children, params }: Props) {
let response: ApolloQueryResult<AccountDefaultWalletsQuery> | { errorMessage: string }
try {
response = await getClient().query<AccountDefaultWalletsQuery>({
query: AccountDefaultWalletsDocument,
variables: { username: params.username },
})
} catch (err) {
console.error("error in username-layout.tsx", err)
if (err instanceof Error) {
response = { errorMessage: err.message }
} else {
console.error("Unknown error")
response = { errorMessage: "An unknown error occurred" }
}
}

if ("errorMessage" in response) {
return (
<div className={styles.error}>
<p>{`${response.errorMessage}.`}</p>
<p>Please check the username in your browser URL and try again.</p>
<Link href={"/"}>Go back</Link>
</div>
)
}

const initialState = {
currentAmount: "0",
createdInvoice: false,
walletCurrency: response?.data?.accountDefaultWallet.walletCurrency,
walletId: response?.data?.accountDefaultWallet.id,
username: params.username,
pinnedToHomeScreenModalVisible: false,
memo: "",
displayCurrencyMetaData: defaultCurrencyMetadata,
}
siddhart1o1 marked this conversation as resolved.
Show resolved Hide resolved

return (
<UsernameLayoutContainer username={params.username}>
{children}
</UsernameLayoutContainer>
<InvoiceProvider initialState={initialState}>
<UsernameLayoutContainer username={params.username}>
{children}
</UsernameLayoutContainer>
</InvoiceProvider>
)
}
160 changes: 40 additions & 120 deletions apps/pay/app/[username]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,20 @@
"use client"
import Link from "next/link"
import React from "react"
import React, { useEffect } from "react"
import Container from "react-bootstrap/Container"
import Image from "react-bootstrap/Image"

import Head from "next/head"

import { gql } from "@apollo/client"

import { useSearchParams } from "next/navigation"

import ParsePayment from "../../components/parse-pos-payment"
import PinToHomescreen from "../../components/pin-to-homescreen"

import CurrencyDropdown from "../../components/currency/currency-dropdown"

import { useAccountDefaultWalletsQuery } from "../../lib/graphql/generated"

import reducer, { ACTIONS } from "../reducer"
import { ACTIONS } from "../reducer"

import styles from "./username.module.css"

import LoadingComponent from "@/components/loading"
import { extractSearchParams } from "@/utils/utils"
import { useInvoiceContext } from "@/context/invoice-context"

gql`
query accountDefaultWallets($username: Username!) {
Expand All @@ -35,71 +27,30 @@ gql`
`

type Props = {
params: {
username: string
searchParams: {
memo: string
amount: string
}
}

function updateCurrencyAndReload(newDisplayCurrency: string): void {
localStorage.setItem("display", newDisplayCurrency)

const currentURL = new URL(window.location.toString())
const searchParams = new URLSearchParams(window.location.search)
searchParams.set("display", newDisplayCurrency)
currentURL.search = searchParams.toString()

window.history.pushState({}, "", currentURL.toString())
setTimeout(() => {
window.location.reload()
}, 100)
}
function ReceivePayment({ searchParams }: Props) {
const { memo, amount } = searchParams
const { state, dispatch } = useInvoiceContext()
const { username } = state

function ReceivePayment({ params }: Props) {
const searchParams = useSearchParams()
const { memo } = extractSearchParams(searchParams)

const { username } = params
const manifestParams = new URLSearchParams()

let accountUsername: string
if (!username) {
accountUsername = ""
} else {
accountUsername = username.toString()
}
useEffect(() => {
dispatch({
type: ACTIONS.SET_AMOUNT_FROM_PARAMS,
payload: amount ?? "0",
})
}, [])

const manifestParams = new URLSearchParams()
if (memo) {
manifestParams.set("memo", memo.toString())
}

const {
data,
error: usernameError,
loading: usernameLoading,
} = useAccountDefaultWalletsQuery({
variables: { username: accountUsername },
skip: !accountUsername,
})

const [state, dispatch] = React.useReducer(reducer, {
currentAmount: "",
createdInvoice: false,
walletCurrency: data?.accountDefaultWallet.walletCurrency,
username: accountUsername,
pinnedToHomeScreenModalVisible: false,
})

React.useEffect(() => {
if (state.walletCurrency === data?.accountDefaultWallet.walletCurrency) {
return
}
dispatch({
type: ACTIONS.UPDATE_WALLET_CURRENCY,
payload: data?.accountDefaultWallet.walletCurrency,
})
dispatch({ type: ACTIONS.UPDATE_USERNAME, payload: username })
}, [state, username, data])

return username ? (
<Container className={styles.payment_container}>
<Head>
Expand All @@ -109,61 +60,30 @@ function ReceivePayment({ params }: Props) {
id="manifest"
/>
</Head>
{usernameError ? (
<div className={styles.error}>
<p>{`${usernameError.message}.`}</p>
<p>Please check the username in your browser URL and try again.</p>
<Link href={"/setuppwa"} onClick={() => localStorage.removeItem("username")}>
Back
</Link>
</div>
) : (
<>
<PinToHomescreen
pinnedToHomeScreenModalVisible={state.pinnedToHomeScreenModalVisible}
dispatch={dispatch}
/>
<div className={styles.username_container}>
{state.createdInvoice && (
<button onClick={() => dispatch({ type: ACTIONS.BACK })}>
<Image
src="/icons/chevron-left-icon.svg"
alt="back button"
width="10px"
height="12px"
/>
</button>
)}
<p className={styles.username}>{`Pay ${username}`}</p>
<div style={{ marginLeft: "12px", marginTop: "9px" }}>
<CurrencyDropdown
style={{
border: "none",
outline: "none",
width: "56px",
height: "42px",
fontSize: "18px",
backgroundColor: "white",
textAlign: "center",
verticalAlign: "middle",
}}
showOnlyFlag={true}
onSelectedDisplayCurrencyChange={updateCurrencyAndReload}
/>
</div>
</div>
{data && !usernameLoading && accountUsername && state ? (
<ParsePayment
state={state}
dispatch={dispatch}
defaultWalletCurrency={data?.accountDefaultWallet.walletCurrency}
walletId={data?.accountDefaultWallet.id}
username={accountUsername}

<div className={styles.username_container}>
{state.createdInvoice && (
<button onClick={() => dispatch({ type: ACTIONS.BACK })}>
<Image
src="/icons/chevron-left-icon.svg"
alt="back button"
width="10px"
height="12px"
/>
) : (
<LoadingComponent />
)}
</>
</button>
)}
<p className={styles.username}>{`Pay ${username}`}</p>
</div>
{username && state ? (
<ParsePayment
state={state}
dispatch={dispatch}
defaultWalletCurrency={state.walletCurrency}
walletId={state?.walletId}
username={username}
/>
) : (
<LoadingComponent />
)}
</Container>
) : null
Expand Down
15 changes: 11 additions & 4 deletions apps/pay/app/[username]/print/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,16 @@ export default function Print({
<br />
<Row className="justify-content-md-center">
<Col md="auto">
<Card className="text-center">
<div className="text-center mt-4">
<Card.Body>
<Card.Text>
<Card.Text
style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
}}
>
<span className="user-header">{userHeader}</span>
<p>
{`Display this static QR code online or in person to allow anybody to
Expand All @@ -96,12 +103,12 @@ export default function Print({
create a fresh invoice for paying from any Lightning wallet.
</Card.Text>
</Card.Body>
</Card>
</div>
</Col>
</Row>
<br />
</Container>
<Row className="justify-content-center">
<Row className="justify-content-center ">
<ReactToPrint
trigger={() => (
<button data-testid="print-btn" className="print-paycode-button">
Expand Down
15 changes: 12 additions & 3 deletions apps/pay/app/[username]/username.module.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
.payment_container {
height: 100%;
padding-left: 0;
padding-right: 0;
box-shadow: rgba(0, 0, 0, 0.05) 0px 0px 0px 1px,
rgb(209, 213, 219) 0px 0px 0px 1px inset;
border-radius: 1em;
padding: 2em;
}

.pin_btn {
Expand Down Expand Up @@ -65,3 +66,11 @@
.error > p:last-child {
color: rgb(45, 43, 43);
}

@media (max-width: 768px) {
.payment_container {
padding: 0em;
box-shadow: none;
border-radius: 0;
}
}
10 changes: 10 additions & 0 deletions apps/pay/app/currency-metadata.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Currency } from "@/lib/graphql/generated"

export const defaultCurrencyMetadata: Currency = {
id: "USD",
flag: "🇺🇸",
name: "US Dollar",
symbol: "$",
fractionDigits: 2,
__typename: "Currency",
}
Loading
Loading