Skip to content

Commit

Permalink
fix: fetch results cached st not getting latest data
Browse files Browse the repository at this point in the history
  • Loading branch information
kittybest committed Jul 23, 2024
1 parent 20b01b3 commit 7b6c655
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 58 deletions.
20 changes: 16 additions & 4 deletions src/features/applications/components/AdminButtonsBar.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,35 @@
import { useCallback } from "react";
import { useCallback, useEffect } from "react";

import { Button } from "~/components/ui/Button";
import { Spinner } from "~/components/ui/Spinner";
import { useIsAdmin } from "~/hooks/useIsAdmin";
import { useIsCorrectNetwork } from "~/hooks/useIsCorrectNetwork";

import { useApproveApplication } from "../hooks/useApproveApplication";

interface IAdminButtonsBarProps {
projectId: string;
onSuccess: () => void;
}

export const AdminButtonsBar = ({ projectId }: IAdminButtonsBarProps): JSX.Element => {
export const AdminButtonsBar = ({ projectId, onSuccess }: IAdminButtonsBarProps): JSX.Element => {
const isAdmin = useIsAdmin();
const { isCorrectNetwork, correctNetwork } = useIsCorrectNetwork();

const approve = useApproveApplication({});
const approve = useApproveApplication({
onSuccess,
});

const onClick = useCallback(() => {
approve.mutate([projectId]);
}, [approve, projectId]);

useEffect(() => {
if (approve.isSuccess) {
onSuccess();
}
}, [approve.isSuccess, onSuccess]);

return (
<div className="my-3 flex justify-end gap-2">
<Button
Expand All @@ -29,7 +39,9 @@ export const AdminButtonsBar = ({ projectId }: IAdminButtonsBarProps): JSX.Eleme
variant="primary"
onClick={onClick}
>
{!isCorrectNetwork ? `Connect to ${correctNetwork.name}` : "Approve application"}
{approve.isPending && <Spinner className="mr-2 h-4 w-4" />}

{!approve.isPending && !isCorrectNetwork ? `Connect to ${correctNetwork.name}` : "Approve application"}
</Button>
</div>
);
Expand Down
18 changes: 13 additions & 5 deletions src/features/applications/components/ApplicationsToApprove.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ClockIcon } from "lucide-react";
import Link from "next/link";
import { useMemo } from "react";
import { useMemo, useEffect } from "react";
import { useFormContext } from "react-hook-form";
import { FiAlertCircle } from "react-icons/fi";
import { z } from "zod";
Expand All @@ -21,7 +21,7 @@ import { type Attestation } from "~/utils/fetchAttestations";
import { formatDate } from "~/utils/time";

import { useApproveApplication } from "../hooks/useApproveApplication";
import { useApprovedApplications } from "../hooks/useApprovedApplications";
import { useLatestApprovedApplications } from "../hooks/useApprovedApplications";

export interface IApplicationItemProps extends Attestation {
isApproved?: boolean;
Expand Down Expand Up @@ -130,7 +130,9 @@ export const ApplicationItem = ({
</div>

<div className="flex-[2]">
{isApproved ? <Badge variant="success">Approved</Badge> : <Badge variant="pending">Pending</Badge>}
{isApproved && <Badge variant="success">Approved</Badge>}

{!isApproved && <Badge variant="pending">Pending</Badge>}
</div>
</div>
</Link>
Expand All @@ -145,8 +147,8 @@ type TApplicationsToApprove = z.infer<typeof ApplicationsToApproveSchema>;

export const ApplicationsToApprove = (): JSX.Element => {
const applications = useApplications();
const approved = useApprovedApplications();
const approve = useApproveApplication({});
const approved = useLatestApprovedApplications();
const approve = useApproveApplication();

const approvedById = useMemo(
() =>
Expand All @@ -159,6 +161,12 @@ export const ApplicationsToApprove = (): JSX.Element => {

const applicationsToApprove = applications.data?.filter((application) => !approvedById?.get(application.id));

useEffect(() => {
if (approve.isSuccess) {
approved.refetch();
}
}, [approve.isSuccess, approved]);

return (
<div className="flex w-full justify-center dark:text-white">
<div className="flex flex-col gap-4 md:max-w-screen-sm lg:max-w-screen-md xl:max-w-screen-lg">
Expand Down
41 changes: 0 additions & 41 deletions src/features/applications/components/ApproveButton.tsx

This file was deleted.

12 changes: 8 additions & 4 deletions src/features/applications/components/ReviewBar.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { useMemo } from "react";
import { useMemo, useCallback } from "react";
import { FiAlertCircle } from "react-icons/fi";

import { StatusBar } from "~/components/StatusBar";
import { useIsAdmin } from "~/hooks/useIsAdmin";

import { useApprovedApplications } from "../hooks/useApprovedApplications";
import { useLatestApprovedApplications } from "../hooks/useApprovedApplications";

import { AdminButtonsBar } from "./AdminButtonsBar";

Expand All @@ -14,10 +14,14 @@ interface IReviewBarProps {

export const ReviewBar = ({ projectId }: IReviewBarProps): JSX.Element => {
const isAdmin = useIsAdmin();
const rawReturn = useApprovedApplications([projectId]);
const rawReturn = useLatestApprovedApplications([projectId]);

const approved = useMemo(() => rawReturn.data && rawReturn.data.length > 0, [rawReturn]);

const handleOnSuccess = useCallback(() => {
rawReturn.refetch();
}, [rawReturn]);

return (
<div className="mb-4 w-full">
{approved && <StatusBar content="The project has been approved." status="approved" />}
Expand All @@ -39,7 +43,7 @@ export const ReviewBar = ({ projectId }: IReviewBarProps): JSX.Element => {
/>
)}

{isAdmin && !approved && <AdminButtonsBar projectId={projectId} />}
{isAdmin && !approved && <AdminButtonsBar projectId={projectId} onSuccess={handleOnSuccess} />}
</div>
);
};
4 changes: 4 additions & 0 deletions src/features/applications/hooks/useApprovedApplications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@ import type { Attestation } from "~/utils/fetchAttestations";
export function useApprovedApplications(ids?: string[]): UseTRPCQueryResult<Attestation[], unknown> {
return api.applications.approvals.useQuery({ ids });
}

export function useLatestApprovedApplications(ids?: string[]): UseTRPCQueryResult<Attestation[], unknown> {
return api.applications.latestApprovals.useQuery({ ids });
}
6 changes: 5 additions & 1 deletion src/features/projects/components/ProjectDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { ProjectAvatar } from "~/features/projects/components/ProjectAvatar";
import { ProjectBanner } from "~/features/projects/components/ProjectBanner";
import { VotingWidget } from "~/features/projects/components/VotingWidget";
import { type Attestation } from "~/utils/fetchAttestations";
import { useAppState } from "~/utils/state";
import { EAppState } from "~/utils/types";

import { useProjectMetadata } from "../hooks/useProjects";

Expand All @@ -30,6 +32,8 @@ const ProjectDetails = ({
const { bio, websiteUrl, payoutAddress, github, twitter, fundingSources, profileImageUrl, bannerImageUrl } =
metadata.data ?? {};

const appState = useAppState();

return (
<div className={clsx("relative dark:text-white", disabled && "opacity-30")}>
<div className="mb-7">
Expand All @@ -47,7 +51,7 @@ const ProjectDetails = ({
<div className="flex items-center justify-between">
<h3>{attestation?.name}</h3>

<VotingWidget projectId={projectId} />
{appState === EAppState.VOTING && <VotingWidget projectId={projectId} />}
</div>

<ProjectContacts author={payoutAddress} github={github} twitter={twitter} website={websiteUrl} />
Expand Down
4 changes: 2 additions & 2 deletions src/pages/projects/[projectId]/Project.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { type GetServerSideProps } from "next";
import { useMemo } from "react";

import { ReviewBar } from "~/features/applications/components/ReviewBar";
import { useApprovedApplications } from "~/features/applications/hooks/useApprovedApplications";
import { useLatestApprovedApplications } from "~/features/applications/hooks/useApprovedApplications";
import ProjectDetails from "~/features/projects/components/ProjectDetails";
import { useProjectById } from "~/features/projects/hooks/useProjects";
import { LayoutWithSidebar } from "~/layouts/DefaultLayout";
Expand All @@ -15,7 +15,7 @@ export interface IProjectDetailsProps {

const ProjectDetailsPage = ({ projectId = "" }: IProjectDetailsProps): JSX.Element => {
const projects = useProjectById(projectId);
const approved = useApprovedApplications();
const approved = useLatestApprovedApplications();
const { name } = projects.data?.[0] ?? {};
const appState = useAppState();

Expand Down
11 changes: 10 additions & 1 deletion src/server/api/routers/applications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { z } from "zod";

import { config, eas } from "~/config";
import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";
import { createDataFilter, fetchAttestations } from "~/utils/fetchAttestations";
import { createDataFilter, fetchAttestations, fetchAttestationsWithoutCache } from "~/utils/fetchAttestations";

export const FilterSchema = z.object({
limit: z.number().default(3 * 8),
Expand All @@ -19,6 +19,15 @@ export const applicationsRouter = createTRPCRouter({
},
}),
),
latestApprovals: publicProcedure.input(z.object({ ids: z.array(z.string()).optional() })).query(async ({ input }) =>
fetchAttestationsWithoutCache([eas.schemas.approval], {
where: {
attester: { equals: config.admin },
refUID: input.ids ? { in: input.ids } : undefined,
AND: [createDataFilter("type", "bytes32", "application"), createDataFilter("round", "bytes32", config.roundId)],
},
}),
),
list: publicProcedure.input(FilterSchema).query(async () =>
fetchAttestations([eas.schemas.metadata], {
orderBy: [{ time: "desc" }],
Expand Down
25 changes: 25 additions & 0 deletions src/utils/fetchAttestations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { createCachedFetch } from "./fetch";

const cachedFetch = createCachedFetch({ ttl: 1000 * 60 * 10 });

const uncachedFetch = createCachedFetch({ ttl: 0 });

export interface AttestationWithMetadata {
id: string;
refUID: string;
Expand Down Expand Up @@ -85,6 +87,29 @@ export async function fetchAttestations(schema: string[], filter?: AttestationsF
}).then((r) => r.data.attestations.map(parseAttestation));
}

export async function fetchAttestationsWithoutCache(
schema: string[],
filter?: AttestationsFilter,
): Promise<Attestation[]> {
const startsAt = config.startsAt && Math.floor(+config.startsAt / 1000);

return uncachedFetch<{ attestations: AttestationWithMetadata[] }>(eas.url, {
method: "POST",
body: JSON.stringify({
query: AttestationsQuery,
variables: {
...filter,
where: {
schemaId: { in: schema },
revoked: { equals: false },
time: { gte: startsAt },
...filter?.where,
},
},
}),
}).then((r) => r.data.attestations.map(parseAttestation));
}

export async function fetchApprovedVoter(address: string): Promise<boolean | number> {
if (config.skipApprovedVoterCheck) {
return true;
Expand Down

0 comments on commit 7b6c655

Please sign in to comment.