Skip to content
This repository has been archived by the owner on Sep 2, 2024. It is now read-only.

Commit

Permalink
feat: add transaction popup
Browse files Browse the repository at this point in the history
  • Loading branch information
im-adithya committed Jul 5, 2024
1 parent 46f4504 commit ed99efc
Show file tree
Hide file tree
Showing 6 changed files with 612 additions and 62 deletions.
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"swr": "^2.2.4",
"tailwind-merge": "^2.2.2",
"tailwindcss-animate": "^1.0.7",
"vaul": "^0.9.1",
"zustand": "^4.5.0"
},
"devDependencies": {
Expand Down
249 changes: 188 additions & 61 deletions frontend/src/components/TransactionsList.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,41 @@
import dayjs from "dayjs";
import { ArrowDownIcon, ArrowUpIcon, Drum } from "lucide-react";
import {
ArrowDownIcon,
ArrowUpIcon,
ChevronDown,
ChevronUp,
CopyIcon,
Drum,
} from "lucide-react";
import React from "react";
import EmptyState from "src/components/EmptyState";

import Loading from "src/components/Loading";
import {
Credenza,
CredenzaBody,
CredenzaContent,
CredenzaFooter,
CredenzaHeader,
CredenzaTitle,
CredenzaTrigger,
} from "src/components/ui/credenza";
import { toast } from "src/components/ui/use-toast";
import { useTransactions } from "src/hooks/useTransactions";
import { copyToClipboard } from "src/lib/clipboard";

function TransactionsList() {
const { data: transactions, isLoading } = useTransactions();
const [showDetails, setShowDetails] = React.useState(false);

if (isLoading) {
return <Loading />;
}

const copy = (text: string) => {
copyToClipboard(text);
toast({ title: "Copied to clipboard." });
};

return (
<div>
{!transactions?.length ? (
Expand All @@ -28,79 +52,182 @@ function TransactionsList() {
const type = tx.type;

return (
<div
<Credenza
key={`tx-${i}`}
className="p-3 mb-4 rounded-md"
// TODO: Add modal onclick to show payment details
onOpenChange={(open) => {
if (!open) {
setShowDetails(false);
}
}}
>
<div className="flex gap-3">
<div className="flex items-center">
{type == "outgoing" ? (
<div
className={
"flex justify-center items-center bg-orange-100 dark:bg-orange-950 rounded-full w-10 h-10 md:w-14 md:h-14"
}
>
<ArrowUpIcon
strokeWidth={3}
className="w-6 h-6 md:w-8 md:h-8 text-orange-400 dark:text-amber-600 stroke-orange-400 dark:stroke-amber-600"
/>
</div>
) : (
<div className="flex justify-center items-center bg-green-100 dark:bg-emerald-950 rounded-full w-10 h-10 md:w-14 md:h-14">
<ArrowDownIcon
strokeWidth={3}
className="w-6 h-6 md:w-8 md:h-8 text-green-500 dark:text-emerald-500 stroke-green-400 dark:stroke-emerald-500"
/>
<CredenzaTrigger
asChild
className="p-3 mb-4 hover:bg-gray-100 dark:hover:bg-surface-02dp cursor-pointer rounded-md slashed-zero"
>
<div className="flex gap-3">
<div className="flex items-center">
{type == "outgoing" ? (
<div
className={
"flex justify-center items-center bg-orange-100 dark:bg-orange-950 rounded-full w-10 h-10 md:w-14 md:h-14"
}
>
<ArrowUpIcon
strokeWidth={3}
className="w-6 h-6 md:w-8 md:h-8 text-orange-400 dark:text-amber-600 stroke-orange-400 dark:stroke-amber-600"
/>
</div>
) : (
<div className="flex justify-center items-center bg-green-100 dark:bg-emerald-950 rounded-full w-10 h-10 md:w-14 md:h-14">
<ArrowDownIcon
strokeWidth={3}
className="w-6 h-6 md:w-8 md:h-8 text-green-500 dark:text-emerald-500 stroke-green-400 dark:stroke-emerald-500"
/>
</div>
)}
</div>
<div className="overflow-hidden mr-3">
<div className="flex items-center gap-2 truncate dark:text-white">
<p className="text-lg md:text-xl font-semibold">
{type == "incoming" ? "Received" : "Sent"}
</p>
<p className="text-sm md:text-base truncate text-muted-foreground">
{dayjs(tx.settled_at * 1000).fromNow()}
</p>
</div>
)}
</div>
<div className="overflow-hidden mr-3">
<div className="flex items-center gap-2 truncate dark:text-white">
<p className="text-lg md:text-xl font-semibold">
{type == "incoming" ? "Received" : "Sent"}
</p>
<p className="text-sm md:text-base truncate text-muted-foreground">
{dayjs(tx.settled_at * 1000).fromNow()}
<p className="text-sm md:text-base text-muted-foreground">
{tx.description || "Lightning invoice"}
</p>
</div>
<p className="text-sm md:text-base text-muted-foreground">
{tx.description || "Lightning invoice"}
</p>
</div>
<div className="flex ml-auto text-right space-x-3 shrink-0 dark:text-white">
<div className="flex items-center gap-2 text-xl">
<p
className={`font-semibold ${
type == "incoming" &&
"text-green-600 dark:color-green-400"
}`}
>
{type == "outgoing" ? "-" : "+"}{" "}
{Math.floor(tx.amount / 1000)}
</p>
<p className="text-muted-foreground">sats</p>
<div className="flex ml-auto text-right space-x-3 shrink-0 dark:text-white">
<div className="flex items-center gap-2 text-xl">
<p
className={`font-semibold ${
type == "incoming" &&
"text-green-600 dark:color-green-400"
}`}
>
{type == "outgoing" ? "-" : "+"}{" "}
{Math.floor(tx.amount / 1000)}
</p>
<p className="text-muted-foreground">sats</p>

{/* {!!tx.totalAmountFiat && (
{/* {!!tx.totalAmountFiat && (
<p className="text-xs text-gray-400 dark:text-neutral-600">
~{tx.totalAmountFiat}
</p>
)} */}
</div>
</div>
</div>
</div>
</div>
</CredenzaTrigger>
<CredenzaContent className="slashed-zero">
<CredenzaHeader>
<CredenzaTitle>
{type == "outgoing" ? "Sent Bitcoin" : "Received Bitcoin"}
</CredenzaTitle>
</CredenzaHeader>
<CredenzaBody>
<div className="flex items-center mt-6">
{type == "outgoing" ? (
<div
className={
"flex justify-center items-center bg-orange-100 dark:bg-orange-950 rounded-full w-10 h-10 md:w-14 md:h-14"
}
>
<ArrowUpIcon
strokeWidth={3}
className="w-6 h-6 md:w-8 md:h-8 text-orange-400 dark:text-amber-600 stroke-orange-400 dark:stroke-amber-600"
/>
</div>
) : (
<div className="flex justify-center items-center bg-green-100 dark:bg-emerald-950 rounded-full w-10 h-10 md:w-14 md:h-14">
<ArrowDownIcon
strokeWidth={3}
className="w-6 h-6 md:w-8 md:h-8 text-green-500 dark:text-emerald-500 stroke-green-400 dark:stroke-emerald-500"
/>
</div>
)}
<div className="ml-4">
<p className="text-xl md:text-2xl font-semibold">
{Math.floor(tx.amount / 1000)}{" "}
{Math.floor(tx.amount / 1000) == 1 ? "sat" : "sats"}
</p>
{/* <p className="text-sm md:text-base text-gray-500">
Fiat Amount
</p> */}
</div>
</div>
<div className="mt-8">
<p className="dark:text-white">Date & Time</p>
<p className="text-muted-foreground">
{dayjs(tx.settled_at).toString()}
</p>
</div>
<div className="mt-6">
<p className="dark:text-white">Fee</p>
<p className="text-muted-foreground">
{tx.fees_paid} {tx.fees_paid == 1 ? "sat" : "sats"}
</p>
</div>
{tx.description && (
<div className="mt-6">
<p className="dark:text-white">Description</p>
<p className="text-muted-foreground">
{tx.description}
</p>
</div>
)}
</CredenzaBody>
<CredenzaFooter className="!justify-start mt-4 !flex-col">
<div
className="flex items-center gap-2 cursor-pointer"
onClick={() => setShowDetails(!showDetails)}
>
Details
{showDetails ? (
<ChevronUp className="w-4 h-4" />
) : (
<ChevronDown className="w-4 h-4" />
)}
</div>
{showDetails && (
<>
<div className="mt-6 !ml-0">
<p className="dark:text-white">Preimage</p>
<div className="flex items-center gap-4">
<p className="text-muted-foreground break-all">
{tx.preimage}
</p>
<CopyIcon
className="cursor-pointer text-muted-foreground w-6 h-6"
onClick={() => {
copy(tx.preimage);
}}
/>
</div>
</div>
<div className="mt-6 !ml-0">
<p className="dark:text-white">Hash</p>
<div className="flex items-center gap-4">
<p className="text-muted-foreground break-all">
{tx.payment_hash}
</p>
<CopyIcon
className="cursor-pointer text-muted-foreground w-6 h-6"
onClick={() => {
copy(tx.payment_hash);
}}
/>
</div>
</div>
</>
)}
</CredenzaFooter>
</CredenzaContent>
</Credenza>
);
})}
{/* {transaction && (
<TransactionModal
transaction={transaction}
isOpen={modalOpen}
onClose={() => {
setModalOpen(false);
}}
/>
)} */}
</>
)}
</div>
Expand Down
Loading

0 comments on commit ed99efc

Please sign in to comment.