Skip to content

Commit 8a2f4e3

Browse files
committed
React query, refetch on window focus
1 parent a1335b2 commit 8a2f4e3

File tree

7 files changed

+85
-42
lines changed

7 files changed

+85
-42
lines changed

apps/web/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"@astrojs/react": "^4.2.1",
1414
"@repo/shared": "workspace:*",
1515
"@tailwindcss/vite": "^4.0.14",
16+
"@tanstack/react-query": "^5.71.1",
1617
"astro": "^5.5.3",
1718
"axios": "^1.8.3",
1819
"bech32": "^2.0.0",

apps/web/src/containers/Claim.tsx

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,49 @@
1-
import { ClaimStatus, type Claims } from "@repo/shared";
1+
import { ClaimStatus } from "@repo/shared";
2+
import { QueryClient, QueryClientProvider, useQuery } from "@tanstack/react-query";
23
import { bech32 } from "bech32";
34
import { Layers } from "lucide-react";
45
import queryString from "query-string";
5-
import { useEffect, useState } from "react";
6+
import { useEffect, useMemo } from "react";
67
import { getClaimsByIds } from "../api/claims";
78
import { PaymentInfo } from "../components/PaymentInfo";
89
import { PaymentWait } from "../components/PaymentWait";
910
import { getBitcoinFiatValue } from "../utils/getBitcoinFiatValue";
1011
import { formatCurrency, formatNumber } from "../utils/numbers";
12+
import { QUERY_KEYS } from "../utils/queryKeys";
1113
import { subscribeSSE } from "../utils/sse";
1214
import { useBitcoinExchangeRate } from "../utils/useBitcoinExchangeRate";
1315
import { SuccessIcon } from "./SuccessIcon";
1416
import { WaitIcon } from "./WaitIcon";
1517

18+
const queryClient = new QueryClient();
19+
1620
export const Claim = () => {
21+
return (
22+
<QueryClientProvider client={queryClient}>
23+
<ClaimComponent />
24+
</QueryClientProvider>
25+
);
26+
};
27+
28+
export const ClaimComponent = () => {
1729
const id = queryString.parse(window.location.search).id as string | undefined;
18-
const [claim, setClaim] = useState<Claims | null>(null);
1930
const { usdExchangeRate, fetchExchangeRate } = useBitcoinExchangeRate();
2031

32+
const { data: claims = [], refetch } = useQuery({
33+
queryKey: [QUERY_KEYS.GET_CLAIMS, [id]],
34+
queryFn: () => getClaimsByIds([id as string]),
35+
enabled: !!id,
36+
refetchOnWindowFocus: true,
37+
});
38+
39+
const claim = useMemo(() => claims[0], [claims]);
40+
2141
const withdrawLink = `https://stackorange.com/api/payments/withdraw/${id}`;
42+
2243
const withdrawLinkLnurl = bech32
2344
.encode("lnurl", bech32.toWords(Buffer.from(withdrawLink, "utf8")), 1023)
2445
.toUpperCase();
2546

26-
useEffect(() => {
27-
if (!id) {
28-
return;
29-
}
30-
31-
getClaimsByIds([id]).then((claims) => {
32-
setClaim(claims[0]);
33-
});
34-
}, [id]);
35-
3647
useEffect(() => {
3748
if (!claim || claim.status !== ClaimStatus.PAID) {
3849
return;
@@ -44,15 +55,15 @@ export const Claim = () => {
4455
`${import.meta.env.PUBLIC_API_URL || ""}/api/payments/${claim.id}`,
4556
({ paymentId }) => {
4657
if (paymentId === claim.id) {
47-
setClaim((prev) => (prev ? { ...prev, status: ClaimStatus.CLAIMED } : null));
58+
refetch();
4859
}
4960
},
5061
);
5162

5263
return () => {
5364
eventSource.close();
5465
};
55-
}, [claim, fetchExchangeRate]);
66+
}, [claim, fetchExchangeRate, refetch]);
5667

5768
if (!claim) {
5869
return null;

apps/web/src/containers/CreateClaim.tsx

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,59 @@
1-
import { ClaimStatus, type Claims, LAST_UNPAID_CLAIM_ID_KEY } from "@repo/shared";
1+
import { ClaimStatus, LAST_ACTIVE_CLAIM_ID_KEY } from "@repo/shared";
2+
import { QueryClient, QueryClientProvider, useQuery } from "@tanstack/react-query";
23
import { motion } from "motion/react";
3-
import { useEffect, useState } from "react";
4+
import { useEffect, useMemo, useState } from "react";
45
import useLocalStorageState from "use-local-storage-state";
56
import { getClaimsByIds } from "../api/claims";
67
import { Steps } from "../components/Steps";
8+
import { QUERY_KEYS } from "../utils/queryKeys";
79
import { Form } from "./CreateClaimForm/Form";
810
import { Payment } from "./Payment";
911
import { PaymentSuccess } from "./PaymentSuccess";
1012

13+
const queryClient = new QueryClient();
14+
1115
export const CreateClaim = () => {
12-
const [unpaidClaimId, setUnpaidClaimId] = useLocalStorageState<string>(LAST_UNPAID_CLAIM_ID_KEY);
13-
const [claim, setClaim] = useState<Claims | null>(null);
16+
return (
17+
<QueryClientProvider client={queryClient}>
18+
<CreateClaimComponent />
19+
</QueryClientProvider>
20+
);
21+
};
22+
23+
export const CreateClaimComponent = () => {
24+
const [activeClaimId, setActiveClaimId] = useLocalStorageState<string>(LAST_ACTIVE_CLAIM_ID_KEY);
25+
26+
const { data: claims = [] } = useQuery({
27+
queryKey: [QUERY_KEYS.GET_CLAIMS, [activeClaimId]],
28+
queryFn: () => getClaimsByIds([activeClaimId as string]),
29+
enabled: !!activeClaimId,
30+
refetchOnWindowFocus: true,
31+
});
32+
1433
const [step, setStep] = useState(1);
1534

35+
const claim = useMemo(() => claims[0], [claims]);
36+
1637
useEffect(() => {
17-
if (!unpaidClaimId) {
38+
if (!claim) {
1839
return;
1940
}
2041

21-
getClaimsByIds([unpaidClaimId]).then((claims) => {
22-
const claim = claims[0];
23-
24-
if (!claim) {
25-
return;
26-
}
42+
if (claim.status !== ClaimStatus.AWAITING_PAYMENT) {
43+
setStep(4);
2744

28-
if (claim.status !== ClaimStatus.AWAITING_PAYMENT) {
29-
setClaim(claim);
30-
setStep(4);
31-
32-
return;
33-
}
45+
return;
46+
}
3447

35-
setClaim(claim);
36-
setStep(3);
37-
});
38-
}, [unpaidClaimId]);
48+
setStep(3);
49+
}, [claim]);
3950

4051
const handlePaymentSuccess = () => {
41-
setUnpaidClaimId("");
4252
setStep(4);
4353
};
4454

4555
const handlePaymentCancel = () => {
46-
setUnpaidClaimId("");
56+
setActiveClaimId("");
4757
setStep(1);
4858
};
4959

apps/web/src/containers/CreateClaimForm/Form.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ClaimChannel, HISTORY_CLAIM_IDS_KEY, LAST_UNPAID_CLAIM_ID_KEY } from "@repo/shared";
1+
import { ClaimChannel, HISTORY_CLAIM_IDS_KEY, LAST_ACTIVE_CLAIM_ID_KEY } from "@repo/shared";
22
import { motion } from "motion/react";
33
import type { Dispatch, SetStateAction } from "react";
44
import { FormProvider, type SubmitHandler, useForm } from "react-hook-form";
@@ -23,7 +23,7 @@ type Props = {
2323

2424
export const Form = ({ currentStep, setStep }: Props) => {
2525
const [__, setPastClaimIds] = useLocalStorageState<string[]>(HISTORY_CLAIM_IDS_KEY);
26-
const [_, setUnpaidClaimId] = useLocalStorageState<string>(LAST_UNPAID_CLAIM_ID_KEY);
26+
const [_, setActiveClaimId] = useLocalStorageState<string>(LAST_ACTIVE_CLAIM_ID_KEY);
2727

2828
const methods = useForm<FormValues>({
2929
defaultValues: { channel: ClaimChannel.EMAIL },
@@ -43,7 +43,7 @@ export const Form = ({ currentStep, setStep }: Props) => {
4343
}
4444

4545
setStep((step) => step + 1);
46-
setUnpaidClaimId(claim.id);
46+
setActiveClaimId(claim.id);
4747
setPastClaimIds((pastClaimIds) => [...(pastClaimIds || []), claim.id]);
4848
};
4949

apps/web/src/utils/queryKeys.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const QUERY_KEYS = {
2+
GET_CLAIMS: "GET_CLAIMS",
3+
};

packages/shared/src/constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
export const LAST_UNPAID_CLAIM_ID_KEY = "LAST_UNPAID_CLAIM_ID_KEY";
1+
export const LAST_ACTIVE_CLAIM_ID_KEY = "LAST_ACTIVE_CLAIM_ID_KEY";
22
export const HISTORY_CLAIM_IDS_KEY = "HISTORY_CLAIM_IDS_KEY";
33
export const ROUTING_FEE_PERCENT = 0.1;

pnpm-lock.yaml

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)