Skip to content

Commit

Permalink
feat: add receipt export and viewing on request scan (#142)
Browse files Browse the repository at this point in the history
  • Loading branch information
aimensahnoun authored Oct 3, 2024
1 parent 5eb3818 commit 20e1554
Show file tree
Hide file tree
Showing 13 changed files with 185 additions and 84 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@
// Utils
import { formatDate } from "@requestnetwork/shared-utils/formatDate";
import { calculateItemTotal } from "@requestnetwork/shared-utils/invoiceTotals";
import { exportToPDF } from "@requestnetwork/shared-utils/generateInvoice";
import { getCurrencyFromManager } from "@requestnetwork/shared-utils/getCurrency";
// Types
import type { WalletState } from "@requestnetwork/shared-types/web3Onboard";
import { onMount } from "svelte";
import { formatUnits } from "viem";
import { exportToPDF, walletClientToSigner } from "../../utils";
import { getCurrencyFromManager } from "../../utils/getCurrency";
import { walletClientToSigner } from "../../utils";
export let config;
export let wallet: WalletState | undefined;
Expand Down
10 changes: 6 additions & 4 deletions packages/invoice-dashboard/src/lib/view-requests.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,16 @@
// Utils
import { config as defaultConfig } from "@requestnetwork/shared-utils/config";
import { initializeCurrencyManager } from "@requestnetwork/shared-utils/initCurrencyManager";
import { exportToPDF } from "@requestnetwork/shared-utils/generateInvoice";
import { getCurrencyFromManager } from "@requestnetwork/shared-utils/getCurrency";
import { CurrencyManager } from "@requestnetwork/currency";
import type { RequestNetwork } from "@requestnetwork/request-client.js";
import { Types } from "@requestnetwork/request-client.js";
import { onMount } from "svelte";
import { formatUnits } from "viem";
import { capitalize, debounce, exportToPDF, formatAddress } from "../utils";
import { getCurrencyFromManager } from "../utils/getCurrency";
import { capitalize, debounce, formatAddress } from "../utils";
import { Drawer, InvoiceView } from "./dashboard";
export let config: IConfig;
Expand Down Expand Up @@ -515,8 +517,8 @@
<span
>{formatAddress(
currentTab === "Pay"
? (request.payee?.value ?? "")
: (request.payer?.value ?? "")
? request.payee?.value ?? ""
: request.payer?.value ?? ""
)}</span
>
<Copy
Expand Down
1 change: 0 additions & 1 deletion packages/invoice-dashboard/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export { debounce } from "./debounce";
export { formatAddress } from "./formatAddress";
export { exportToPDF } from "./generateInvoice";
export { publicClientToProvider, walletClientToSigner } from "./wallet-utils";
export { capitalize } from "./capitalize";
Original file line number Diff line number Diff line change
@@ -1,7 +1,42 @@
<script lang="ts">
import { fade } from "svelte/transition";
import { exportToPDF } from "@requestnetwork/shared-utils/generateInvoice";
import { getCurrencyFromManager } from "@requestnetwork/shared-utils/getCurrency";
import { initializeCurrencyManager } from "@requestnetwork/shared-utils/initCurrencyManager";
import Toaster from "@requestnetwork/shared-components/sonner.svelte";
import { toast } from "svelte-sonner";
export let createdRequest: any;
export let enablePdfReceipt: boolean = true;
export let enableRequestScanLink: boolean = true;
export let sellerLogo: string = "";
async function handleDownloadReceipt() {
if (createdRequest) {
try {
const currencyManager = initializeCurrencyManager([]);
const currencyData = createdRequest?.inMemoryInfo?.requestData;
await exportToPDF(
currencyData,
getCurrencyFromManager(currencyData.currencyInfo, currencyManager),
sellerLogo
);
} catch (error) {
toast.error(`Failed to export PDF`, {
description: `${error}`,
action: {
label: "X",
onClick: () => console.info("Close"),
},
});
}
}
}
</script>

<Toaster />
<div class="payment-complete" transition:fade={{ duration: 300 }}>
<div class="checkmark-container">
<svg
Expand All @@ -19,9 +54,26 @@
</div>
<h2>Payment Complete</h2>
<p>Thank you for your payment. Your transaction was successful.</p>

{#if enablePdfReceipt || (enableRequestScanLink && createdRequest)}
<div class="buttons-container">
{#if enablePdfReceipt}
<button on:click={handleDownloadReceipt}>Download Receipt</button>
{/if}
{#if enableRequestScanLink && createdRequest}
<a
target="_blank"
rel="noopener noreferrer"
href={`https://scan.request.network/request/${createdRequest.requestId}`}
>
View on Request Scan
</a>
{/if}
</div>
{/if}
</div>

<style>
<style lang="scss">
.payment-complete {
display: flex;
flex-direction: column;
Expand All @@ -41,6 +93,42 @@
border-radius: 50%;
}
.buttons-container {
display: flex;
gap: 16px;
margin-top: 24px;
button,
a {
padding: 10px 20px;
border-radius: 6px;
font-size: 14px;
font-weight: 500;
text-decoration: none;
transition: background-color 0.3s ease;
}
button {
background-color: #0bb489;
color: white;
border: none;
cursor: pointer;
&:hover {
background-color: darken(#0bb489, 10%);
}
}
a {
background-color: #f5f5f5;
color: #333;
&:hover {
background-color: darken(#f5f5f5, 10%);
}
}
}
h2 {
margin-top: 1rem;
font-size: 1.5rem;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
export let invoiceNumber: string | undefined;
export let feeAddress: string;
export let feeAmountInUSD: number;
export let createdRequest: any;
const COUNTDOWN_INTERVAL = 30;
Expand Down Expand Up @@ -275,6 +276,8 @@
persistRequest,
});

createdRequest = request;

if (onPaymentSuccess) {
onPaymentSuccess(request);
}
Expand Down
12 changes: 10 additions & 2 deletions packages/payment-widget/src/lib/payment-widget.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
export let invoiceNumber: string | undefined = undefined;
export let feeAddress: string = ethers.constants.AddressZero;
export let feeAmountInUSD: number = 0;
export let enablePdfReceipt: boolean = true;
export let enableRequestScanLink: boolean = true;
// State
let web3Modal: Web3Modal | null = null;
Expand All @@ -47,7 +49,7 @@
let selectedCurrency: Currency | null = null;
let connectionCheckInterval: ReturnType<typeof setInterval> | null = null;
let currentPaymentStep: PaymentStep = "currency";
let createdRequest: any;
let scrollPosition = 0;
// Effects
Expand Down Expand Up @@ -246,12 +248,18 @@
onPaymentError={onError}
bind:currentPaymentStep
bind:isConnected
bind:createdRequest
{sellerInfo}
buyerInfo={currentBuyerInfo}
{invoiceNumber}
/>
{:else}
<PaymentComplete />
<PaymentComplete
{createdRequest}
{enablePdfReceipt}
{enableRequestScanLink}
sellerLogo={sellerInfo.logo}
/>
{/if}
</Modal>
</section>
Expand Down
2 changes: 2 additions & 0 deletions packages/payment-widget/src/lib/react/PaymentWidget.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export interface PaymentWidgetProps {
invoiceNumber?: string;
feeAddress?: string;
feeAmountInUSD?: number;
enablePdfReceipt?: boolean;
enableRequestScanLink?: boolean;
}

/**
Expand Down
10 changes: 9 additions & 1 deletion packages/payment-widget/src/lib/utils/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ export const handleRequestPayment = async ({
skipPersistence: true,
});

const inMemoryRequest =
let inMemoryRequest =
await inMemoryRequestNetwork.createRequest(requestParameters);

const signer = await ethersProvider!.getSigner();
Expand Down Expand Up @@ -328,6 +328,14 @@ export const handleRequestPayment = async ({
await persistingRequestNetwork.persistRequest(inMemoryRequest);
}

if (inMemoryRequest?.inMemoryInfo?.requestData) {
inMemoryRequest.inMemoryInfo.requestData = {
...inMemoryRequest.inMemoryInfo.requestData,
payer: requestParameters.requestInfo.payer,
payee: requestParameters.requestInfo.payee,
};
}

return inMemoryRequest;
};

Expand Down
31 changes: 0 additions & 31 deletions shared/components/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -35,37 +35,6 @@

--radius: 0.5rem;
}

.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;

--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;

--popover: 222.2 84% 4.9%;
--popover-foreground: 210 40% 98%;

--card: 222.2 84% 4.9%;
--card-foreground: 210 40% 98%;

--border: 217.2 32.6% 17.5%;
--input: 217.2 32.6% 17.5%;

--primary: 210 40% 98%;
--primary-foreground: 222.2 47.4% 11.2%;

--secondary: 217.2 32.6% 17.5%;
--secondary-foreground: 210 40% 98%;

--accent: 217.2 32.6% 17.5%;
--accent-foreground: 210 40% 98%;

--destructive: 0 62.8% 30.6%;
--destructive-foreground: 210 40% 98%;

--ring: hsl(212.7, 26.8%, 83.9);
}
}

@layer base {
Expand Down
2 changes: 0 additions & 2 deletions shared/components/sonner.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@
Toaster as Sonner,
type ToasterProps as SonnerProps,
} from "svelte-sonner";
import { mode } from "mode-watcher";
type $$Props = SonnerProps;
import "./app.css";
</script>

<Sonner
theme={$mode}
class="toaster group"
toastOptions={{
classes: {
Expand Down
2 changes: 0 additions & 2 deletions shared/components/tailwind.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ import { fontFamily } from "tailwindcss/defaultTheme";
import type { Config } from "tailwindcss";

const config: Config = {
darkMode: ["class"],
content: ["./src/**/*.{html,js,svelte,ts}"],
safelist: ["dark"],
theme: {
container: {
center: true,
Expand Down
Loading

0 comments on commit 20e1554

Please sign in to comment.