diff --git a/src/components/card/Card.tsx b/src/components/card/Card.tsx index dfe6d127..89065b97 100644 --- a/src/components/card/Card.tsx +++ b/src/components/card/Card.tsx @@ -96,8 +96,8 @@ export default function Card() { if (isRevealing) return; if (!passkey) return; try { - const { isSuccess, data } = await refetchCard(); - if (isSuccess && data.url) { + const { isSuccess } = await refetchCard(); + if (isSuccess) { setCardDetailsOpen(true); return; } @@ -105,7 +105,7 @@ export default function Card() { if (result === "ok") { await createCard(); const { data: card } = await refetchCard(); - if (card?.url) setCardDetailsOpen(true); + if (card) setCardDetailsOpen(true); } else { resumeInquiry(result.inquiryId, result.sessionToken).catch(handleError); } @@ -206,7 +206,6 @@ export default function Card() { { setCardDetailsOpen(false); diff --git a/src/components/card/CardDetails.tsx b/src/components/card/CardDetails.tsx index c18329bc..7258441b 100644 --- a/src/components/card/CardDetails.tsx +++ b/src/components/card/CardDetails.tsx @@ -1,13 +1,15 @@ -import { Snowflake, X } from "@tamagui/lucide-icons"; +import { Copy, Snowflake, X } from "@tamagui/lucide-icons"; +import { useToastController } from "@tamagui/toast"; import { useMutation, useQuery } from "@tanstack/react-query"; +import { setStringAsync } from "expo-clipboard"; import React from "react"; import { ms } from "react-native-size-matters"; -import { ScrollView, Sheet, Spinner, Square, Switch, XStack } from "tamagui"; -import { nonEmpty, pipe, safeParse, string, url } from "valibot"; +import { ScrollView, Sheet, Spinner, Square, Switch, XStack, YStack } from "tamagui"; import CardBack from "./CardBack"; import DismissableAlert from "./DismissableAlert"; import handleError from "../../utils/handleError"; +import { decryptSecret } from "../../utils/panda"; import queryClient from "../../utils/queryClient"; import { getCard, setCardStatus } from "../../utils/server"; import Button from "../shared/Button"; @@ -15,9 +17,9 @@ import SafeView from "../shared/SafeView"; import Text from "../shared/Text"; import View from "../shared/View"; -export default function CardDetails({ open, onClose, uri }: { open: boolean; onClose: () => void; uri?: string }) { +export default function CardDetails({ open, onClose }: { open: boolean; onClose: () => void }) { const { data: alertShown } = useQuery({ queryKey: ["settings", "alertShown"] }); - const { success, output } = safeParse(pipe(string(), nonEmpty("empty url"), url("bad url")), uri); + const toast = useToastController(); const { data: card, isFetching: isFetchingCard } = useQuery({ queryKey: ["card", "details"], queryFn: getCard }); const { mutateAsync: changeCardStatus, @@ -31,6 +33,10 @@ export default function CardDetails({ open, onClose, uri }: { open: boolean; onC }, }); const displayStatus = isSettingCardStatus ? optimisticCardStatus : card?.status; + const cardNumber = + card && card.provider === "panda" + ? decryptSecret(card.encryptedPan.data, card.encryptedPan.iv, card.secretKey) + : ""; return ( - {success && } + {card && card.provider === "cryptomate" && } + {card && card.provider === "panda" && ( + + + + {cardNumber.match(/.{1,4}/g)?.join(" ") ?? ""} + + { + setStringAsync(cardNumber).catch(handleError); + toast.show("Copied to clipboard!"); + }} + /> + + + + + Expires + + + {`${card.expirationMonth}/${card.expirationYear}`} + + + + + CVV  + + + {decryptSecret(card.encryptedCvc.data, card.encryptedCvc.iv, card.secretKey)} + + + + + + {card.displayName} + + + + )} - - - {success && alertShown && ( + {card && card.provider === "cryptomate" && alertShown && ( { @@ -111,7 +166,6 @@ export default function CardDetails({ open, onClose, uri }: { open: boolean; onC }} /> )} -