From cd4ead2bb6de04fcaf951c551f7f83c1ddf037b5 Mon Sep 17 00:00:00 2001 From: Michael Gingras Date: Tue, 29 Oct 2024 15:49:25 -0600 Subject: [PATCH] Adds better loading state on voter page --- src/app/api/common/citizens/getCitizens.ts | 10 +- src/app/api/common/delegates/getDelegates.ts | 2 +- src/app/delegates/page.jsx | 96 +----------- .../DelegateCardList/CitzenCardList.tsx | 6 +- .../DelegateCardList/DelegateCardWrapper.tsx | 137 ++++++++++++++++++ tsconfig.json | 3 +- 6 files changed, 155 insertions(+), 99 deletions(-) create mode 100644 src/components/Delegates/DelegateCardList/DelegateCardWrapper.tsx diff --git a/src/app/api/common/citizens/getCitizens.ts b/src/app/api/common/citizens/getCitizens.ts index e3646f136..264e4da9c 100644 --- a/src/app/api/common/citizens/getCitizens.ts +++ b/src/app/api/common/citizens/getCitizens.ts @@ -15,7 +15,7 @@ async function getCitizens({ sort = "shuffle", seed, }: { - pagination: PaginationParams; + pagination?: PaginationParams; sort: string; seed?: number; }): Promise> { @@ -26,7 +26,7 @@ async function getCitizens({ if (sort === "shuffle") { return prisma.$queryRawUnsafe( ` - SELECT + SELECT citizens.address AS delegate, delegate.voting_power, advanced_vp, @@ -54,7 +54,7 @@ async function getCitizens({ WHERE citizens.retro_funding_round = (SELECT MAX(retro_funding_round) FROM agora.citizens) ORDER BY md5(CAST(citizens.address AS TEXT) || CAST($2 AS TEXT)) OFFSET $3 - LIMIT $4; + LIMIT $4; `, slug, seed, @@ -64,7 +64,7 @@ async function getCitizens({ } else { return prisma.$queryRawUnsafe( ` - SELECT + SELECT citizens.address AS delegate, delegate.voting_power, direct_vp, @@ -92,7 +92,7 @@ async function getCitizens({ AND citizens.dao_slug = $1::config.dao_slug WHERE citizens.retro_funding_round = (SELECT MAX(retro_funding_round) FROM agora.citizens) ORDER BY COALESCE(delegate.voting_power, 0) DESC, - citizens.address ASC + citizens.address ASC OFFSET $2 LIMIT $3; `, diff --git a/src/app/api/common/delegates/getDelegates.ts b/src/app/api/common/delegates/getDelegates.ts index 37a1fd774..6ae0587c0 100644 --- a/src/app/api/common/delegates/getDelegates.ts +++ b/src/app/api/common/delegates/getDelegates.ts @@ -34,7 +34,7 @@ async function getDelegates({ seed, filters, }: { - pagination: PaginationParams; + pagination?: PaginationParams; sort: string; seed?: number; filters?: { diff --git a/src/app/delegates/page.jsx b/src/app/delegates/page.jsx index c4c3ab5d6..96dd1a204 100644 --- a/src/app/delegates/page.jsx +++ b/src/app/delegates/page.jsx @@ -1,32 +1,9 @@ -import { fetchCitizens as apiFetchCitizens } from "@/app/api/common/citizens/getCitizens"; -import { fetchDelegates as apiFetchDelegates } from "@/app/api/common/delegates/getDelegates"; -import { fetchCurrentDelegators as apiFetchCurrentDelegators } from "@/app/api/common/delegations/getDelegations"; -import DelegateCardList from "@/components/Delegates/DelegateCardList/DelegateCardList"; -import CitizenCardList from "@/components/Delegates/DelegateCardList/CitzenCardList"; -import DelegateTabs from "@/components/Delegates/DelegatesTabs/DelegatesTabs"; -import Hero from "@/components/Hero/Hero"; -import { TabsContent } from "@/components/ui/tabs"; -import { citizensFilterOptions, delegatesFilterOptions } from "@/lib/constants"; import Tenant from "@/lib/tenant/tenant"; -import React from "react"; - -async function fetchCitizens(sort, seed, pagination) { - "use server"; - - return apiFetchCitizens({ pagination, seed, sort }); -} - -async function fetchDelegates(sort, seed, filters, pagination) { - "use server"; - - return apiFetchDelegates({ pagination, seed, sort, filters }); -} - -async function fetchDelegators(address) { - "use server"; - - return apiFetchCurrentDelegators(address); -} +import React, { Suspense } from "react"; +import DelegateCardWrapper, { + DelegateCardLoadingState, +} from "@/components/Delegates/DelegateCardList/DelegateCardWrapper"; +import Hero from "@/components/Hero/Hero"; export async function generateMetadata({}, parent) { const { ui } = Tenant.current(); @@ -58,69 +35,12 @@ export async function generateMetadata({}, parent) { } export default async function Page({ searchParams }) { - const { ui } = Tenant.current(); - - const sort = - delegatesFilterOptions[searchParams.orderBy]?.sort || - delegatesFilterOptions.weightedRandom.sort; - const citizensSort = - citizensFilterOptions[searchParams.citizensOrderBy]?.value || - citizensFilterOptions.shuffle.sort; - - const filters = { - ...(searchParams.delegateeFilter && { - delegatee: searchParams.delegateeFilter, - }), - ...(searchParams.issueFilter && { issues: searchParams.issueFilter }), - ...(searchParams.stakeholderFilter && { - stakeholders: searchParams.stakeholderFilter, - }), - }; - - const endorsedToggle = ui.toggle("delegates/endorsed-filter"); - if (endorsedToggle?.enabled) { - const defaultFilter = endorsedToggle.config.defaultFilter; - filters.endorsed = - searchParams?.endorsedFilter === undefined - ? defaultFilter - : searchParams.endorsedFilter === "true"; - } - - const tab = searchParams.tab; - const seed = Math.random(); - const delegates = - tab === "citizens" - ? await fetchCitizens(citizensSort, seed) - : await fetchDelegates(sort, seed, filters); - return (
- - - { - "use server"; - return apiFetchDelegates({ pagination, seed, sort, filters }); - }} - fetchDelegators={fetchDelegators} - /> - - - { - "use server"; - - return apiFetchCitizens({ pagination, seed, sort: citizensSort }); - }} - fetchDelegators={fetchDelegators} - />{" "} - - + }> + +
); } diff --git a/src/components/Delegates/DelegateCardList/CitzenCardList.tsx b/src/components/Delegates/DelegateCardList/CitzenCardList.tsx index 5615fd13e..511b886a7 100644 --- a/src/components/Delegates/DelegateCardList/CitzenCardList.tsx +++ b/src/components/Delegates/DelegateCardList/CitzenCardList.tsx @@ -12,15 +12,15 @@ import useConnectedDelegate from "@/hooks/useConnectedDelegate"; import { cn } from "@/lib/utils"; import { useAgoraContext } from "@/contexts/AgoraContext"; import { PaginatedResult, PaginationParams } from "@/app/lib/pagination"; -import { Delegate } from "@/app/api/common/delegates/delegate"; +import { DelegateChunk } from "@/app/api/common/delegates/delegate"; interface Props { isDelegatesCitizensFetching: boolean; - initialDelegates: PaginatedResult; + initialDelegates: PaginatedResult; fetchDelegates: ( pagination: PaginationParams, seed: number - ) => Promise>; + ) => Promise>; fetchDelegators: (addressOrENSName: string) => Promise; } diff --git a/src/components/Delegates/DelegateCardList/DelegateCardWrapper.tsx b/src/components/Delegates/DelegateCardList/DelegateCardWrapper.tsx new file mode 100644 index 000000000..24e67a853 --- /dev/null +++ b/src/components/Delegates/DelegateCardList/DelegateCardWrapper.tsx @@ -0,0 +1,137 @@ +import { fetchCitizens as apiFetchCitizens } from "@/app/api/common/citizens/getCitizens"; +import { fetchDelegates as apiFetchDelegates } from "@/app/api/common/delegates/getDelegates"; +import { fetchCurrentDelegators as apiFetchCurrentDelegators } from "@/app/api/common/delegations/getDelegations"; +import DelegateCardList from "@/components/Delegates/DelegateCardList/DelegateCardList"; +import CitizenCardList from "@/components/Delegates/DelegateCardList/CitzenCardList"; +import DelegateTabs from "@/components/Delegates/DelegatesTabs/DelegatesTabs"; +import { TabsContent } from "@/components/ui/tabs"; +import { citizensFilterOptions, delegatesFilterOptions } from "@/lib/constants"; +import Tenant from "@/lib/tenant/tenant"; +import React from "react"; +import { PaginationParams } from "@/app/lib/pagination"; +import { UIEndorsedConfig } from "@/lib/tenant/tenantUI"; + +async function fetchCitizens( + sort: string, + seed: number, + pagination?: PaginationParams +) { + "use server"; + + return apiFetchCitizens({ pagination, seed, sort }); +} + +async function fetchDelegates( + sort: string, + seed: number, + filters: any, + pagination?: PaginationParams +) { + "use server"; + + return apiFetchDelegates({ pagination, seed, sort, filters }); +} + +async function fetchDelegators(address: string) { + "use server"; + + return apiFetchCurrentDelegators(address); +} + +const DelegateCardWrapper = async ({ searchParams }: { searchParams: any }) => { + const { ui } = Tenant.current(); + + const sort = + delegatesFilterOptions[ + searchParams.orderBy as keyof typeof delegatesFilterOptions + ]?.sort || delegatesFilterOptions.weightedRandom.sort; + const citizensSort = + citizensFilterOptions[ + searchParams.citizensOrderBy as keyof typeof citizensFilterOptions + ]?.value || citizensFilterOptions.shuffle.sort; + + const filters = { + ...(searchParams.delegateeFilter && { + delegatee: searchParams.delegateeFilter, + }), + ...(searchParams.issueFilter && { issues: searchParams.issueFilter }), + ...(searchParams.stakeholderFilter && { + stakeholders: searchParams.stakeholderFilter, + }), + }; + + const endorsedToggle = ui.toggle("delegates/endorsed-filter"); + if (endorsedToggle?.enabled) { + const defaultFilter = (endorsedToggle.config as UIEndorsedConfig) + .defaultFilter; + filters.endorsed = + searchParams?.endorsedFilter === undefined + ? defaultFilter + : searchParams.endorsedFilter === "true"; + } + + const tab = searchParams.tab; + const seed = Math.random(); + const delegates = + tab === "citizens" + ? await fetchCitizens(citizensSort, seed) + : await fetchDelegates(sort, seed, filters); + + return ( + + + { + "use server"; + return apiFetchDelegates({ pagination, seed, sort, filters }); + }} + // @ts-ignore + fetchDelegators={fetchDelegators} + /> + + + { + "use server"; + + return apiFetchCitizens({ pagination, seed, sort: citizensSort }); + }} + // @ts-ignore + fetchDelegators={fetchDelegators} + />{" "} + + + ); +}; + +export const DelegateCardLoadingState = () => { + return ( +
+
+

Delegates

+
+ + + +
+
+
+ + + + + + + + + +
+
+ ); +}; + +export default DelegateCardWrapper; diff --git a/tsconfig.json b/tsconfig.json index 6dd90777f..55c7591a2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -30,8 +30,7 @@ "**/*.tsx", "**/*.jsx", "**/*.js", - ".next/types/**/*.ts", - "src/components/Dialogs/UndelegateDialog" + ".next/types/**/*.ts" ], "exclude": ["node_modules"] }