Skip to content

Commit

Permalink
feat: Implement random project donation
Browse files Browse the repository at this point in the history
& Update API client
  • Loading branch information
carina-akaia committed Jun 24, 2024
1 parent 8892ee8 commit 855c415
Show file tree
Hide file tree
Showing 8 changed files with 209 additions and 56 deletions.
23 changes: 2 additions & 21 deletions src/app/_components/Hero.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import Link from "next/link";

import { potlock } from "@/common/api/potlock";
import { Button } from "@/common/ui/components";
import useWallet from "@/modules/auth/hooks/useWallet";
import useRegistration from "@/modules/core/hooks/useRegistration";
import { useDonation } from "@/modules/donation";
import { DonationRandomButton } from "@/modules/donation";

const Hero = () => {
const wallet = useWallet();
Expand All @@ -13,15 +12,6 @@ const Hero = () => {
const { registration, loading } = useRegistration(accountId);
const isRegisteredProject = !!registration.id;

const { isLoading: isAccountListLoading, data: accountList } =
potlock.useAccounts();

const randomProjectAccountId = "unknown";

const { openDonationModal: openRandomDonationModal } = useDonation({
accountId: randomProjectAccountId ?? "unknown",
});

return (
<div className="relative flex w-full flex-col justify-center overflow-hidden rounded-xl border border-solid border-[#f8d3b0] bg-hero bg-cover bg-no-repeat">
<div className="relative z-[1] flex flex-col justify-center px-5 py-12 md:px-10 md:py-16">
Expand All @@ -33,16 +23,7 @@ const Hero = () => {
<br className="hidden md:block" /> participate in funding rounds.
</h1>
<div className="mt-6 flex items-center gap-4 text-sm max-md:flex-col md:mt-10 md:gap-8">
{isAccountListLoading
? null
: randomProjectAccountId && (
<Button
className="w-full md:w-[180px]"
onClick={openRandomDonationModal}
>
Donate Randomly
</Button>
)}
<DonationRandomButton />

{!loading && (
<Button
Expand Down
97 changes: 92 additions & 5 deletions src/common/api/potlock/generated/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,27 @@ import axios from "axios";
import type { AxiosError, AxiosRequestConfig, AxiosResponse } from "axios";
import useSwr from "swr";
import type { Key, SWRConfiguration } from "swr";
export type V1ListsRandomRegistrationRetrieveParams = {
/**
* Filter registrations by status
*/
status?: string;
};

export type V1DonorsRetrieveParams = {
/**
* Sort by field, e.g., most_donated_usd
*/
sort?: string;
};

export type V1AccountsPotApplicationsRetrieveParams = {
/**
* Filter pot applications by status
*/
status?: string;
};

export type V1AccountsActivePotsRetrieveParams = {
/**
* Filter by pot status
Expand Down Expand Up @@ -889,13 +903,23 @@ export const useV1AccountsPayoutsReceivedRetrieve = <TError = AxiosError<void>>(

export const v1AccountsPotApplicationsRetrieve = (
accountId: string,
params?: V1AccountsPotApplicationsRetrieveParams,
options?: AxiosRequestConfig,
): Promise<AxiosResponse<PaginatedPotApplicationsResponse>> => {
return axios.get(`/api/v1/accounts/${accountId}/pot_applications`, options);
return axios.get(`/api/v1/accounts/${accountId}/pot_applications`, {
...options,
params: { ...params, ...options?.params },
});
};

export const getV1AccountsPotApplicationsRetrieveKey = (accountId: string) =>
[`/api/v1/accounts/${accountId}/pot_applications`] as const;
export const getV1AccountsPotApplicationsRetrieveKey = (
accountId: string,
params?: V1AccountsPotApplicationsRetrieveParams,
) =>
[
`/api/v1/accounts/${accountId}/pot_applications`,
...(params ? [params] : []),
] as const;

export type V1AccountsPotApplicationsRetrieveQueryResult = NonNullable<
Awaited<ReturnType<typeof v1AccountsPotApplicationsRetrieve>>
Expand All @@ -904,6 +928,7 @@ export type V1AccountsPotApplicationsRetrieveQueryError = AxiosError<void>;

export const useV1AccountsPotApplicationsRetrieve = <TError = AxiosError<void>>(
accountId: string,
params?: V1AccountsPotApplicationsRetrieveParams,
options?: {
swr?: SWRConfiguration<
Awaited<ReturnType<typeof v1AccountsPotApplicationsRetrieve>>,
Expand All @@ -918,9 +943,11 @@ export const useV1AccountsPotApplicationsRetrieve = <TError = AxiosError<void>>(
const swrKey =
swrOptions?.swrKey ??
(() =>
isEnabled ? getV1AccountsPotApplicationsRetrieveKey(accountId) : null);
isEnabled
? getV1AccountsPotApplicationsRetrieveKey(accountId, params)
: null);
const swrFn = () =>
v1AccountsPotApplicationsRetrieve(accountId, axiosOptions);
v1AccountsPotApplicationsRetrieve(accountId, params, axiosOptions);

const query = useSwr<Awaited<ReturnType<typeof swrFn>>, TError>(
swrKey,
Expand Down Expand Up @@ -1109,6 +1136,66 @@ export const useV1ListsRetrieve2 = <TError = AxiosError<void>>(
};
};

export const v1ListsRandomRegistrationRetrieve = (
listId: number,
params?: V1ListsRandomRegistrationRetrieveParams,
options?: AxiosRequestConfig,
): Promise<AxiosResponse<ListRegistration>> => {
return axios.get(`/api/v1/lists/${listId}/random_registration`, {
...options,
params: { ...params, ...options?.params },
});
};

export const getV1ListsRandomRegistrationRetrieveKey = (
listId: number,
params?: V1ListsRandomRegistrationRetrieveParams,
) =>
[
`/api/v1/lists/${listId}/random_registration`,
...(params ? [params] : []),
] as const;

export type V1ListsRandomRegistrationRetrieveQueryResult = NonNullable<
Awaited<ReturnType<typeof v1ListsRandomRegistrationRetrieve>>
>;
export type V1ListsRandomRegistrationRetrieveQueryError = AxiosError<void>;

export const useV1ListsRandomRegistrationRetrieve = <TError = AxiosError<void>>(
listId: number,
params?: V1ListsRandomRegistrationRetrieveParams,
options?: {
swr?: SWRConfiguration<
Awaited<ReturnType<typeof v1ListsRandomRegistrationRetrieve>>,
TError
> & { swrKey?: Key; enabled?: boolean };
axios?: AxiosRequestConfig;
},
) => {
const { swr: swrOptions, axios: axiosOptions } = options ?? {};

const isEnabled = swrOptions?.enabled !== false && !!listId;
const swrKey =
swrOptions?.swrKey ??
(() =>
isEnabled
? getV1ListsRandomRegistrationRetrieveKey(listId, params)
: null);
const swrFn = () =>
v1ListsRandomRegistrationRetrieve(listId, params, axiosOptions);

const query = useSwr<Awaited<ReturnType<typeof swrFn>>, TError>(
swrKey,
swrFn,
swrOptions,
);

return {
swrKey,
...query,
};
};

export const v1ListsRegistrationsRetrieve = (
listId: number,
options?: AxiosRequestConfig,
Expand Down
45 changes: 43 additions & 2 deletions src/common/api/potlock/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { POTLOCK_REQUEST_CONFIG } from "@/common/constants";
import { ByAccountId, ConditionalExecution } from "@/common/types";
import { ByAccountId, ByListId, ConditionalExecution } from "@/common/types";

import { swrHooks } from "./generated";
import { ByPotId } from "./types";
import { ByPotId, V1ListsRandomRegistrationRetrieveParams } from "./types";

/**
* https://dev.potlock.io/api/schema/swagger-ui/#/v1/v1_donate_contract_config_retrieve
*/
export const useDonationConfig = () => {
const queryResult = swrHooks.useV1DonateContractConfigRetrieve(
POTLOCK_REQUEST_CONFIG,
Expand All @@ -24,6 +27,9 @@ export const useAccounts = (params?: ConditionalExecution) => {
return { ...queryResult, data: queryResult.data?.data };
};

/**
* https://dev.potlock.io/api/schema/swagger-ui/#/v1/v1_accounts_retrieve_2
*/
export const useAccount = ({ accountId }: Partial<ByAccountId>) => {
const queryResult = swrHooks.useV1AccountsRetrieve2(accountId ?? "unknown", {
...POTLOCK_REQUEST_CONFIG,
Expand All @@ -33,6 +39,9 @@ export const useAccount = ({ accountId }: Partial<ByAccountId>) => {
return { ...queryResult, data: queryResult.data?.data };
};

/**
* https://dev.potlock.io/api/schema/swagger-ui/#/v1/v1_accounts_active_pots_retrieve
*/
export const useAccountActivePots = ({ accountId }: ByAccountId) => {
const queryResult = swrHooks.useV1AccountsActivePotsRetrieve(
accountId,
Expand All @@ -43,12 +52,18 @@ export const useAccountActivePots = ({ accountId }: ByAccountId) => {
return { ...queryResult, data: queryResult.data?.data };
};

/**
* https://dev.potlock.io/api/schema/swagger-ui/#/v1/v1_pots_retrieve
*/
export const usePots = () => {
const queryResult = swrHooks.useV1PotsRetrieve(POTLOCK_REQUEST_CONFIG);

return { ...queryResult, data: queryResult.data?.data };
};

/**
* https://dev.potlock.io/api/schema/swagger-ui/#/v1/v1_accounts_donations_received_retrieve
*/
export const useAccountDonationsReceived = ({ accountId }: ByAccountId) => {
const queryResult = swrHooks.useV1AccountsDonationsReceivedRetrieve(
accountId,
Expand All @@ -58,6 +73,9 @@ export const useAccountDonationsReceived = ({ accountId }: ByAccountId) => {
return { ...queryResult, data: queryResult.data?.data };
};

/**
* https://dev.potlock.io/api/schema/swagger-ui/#/v1/v1_pots_retrieve_2
*/
export const usePot = ({ potId }: Partial<ByPotId>) => {
const queryResult = swrHooks.useV1PotsRetrieve2(potId ?? "unknown", {
...POTLOCK_REQUEST_CONFIG,
Expand All @@ -66,3 +84,26 @@ export const usePot = ({ potId }: Partial<ByPotId>) => {

return { ...queryResult, data: queryResult.data?.data };
};

/**
* https://dev.potlock.io/api/schema/swagger-ui/#/v1/v1_lists_random_registration_retrieve
*
* Note: automatic refresh is disabled for optimization.
* Call `mutate()` for manual refresh.
*/
export const useRandomListRegistration = ({
listId,
status,
}: ByListId & V1ListsRandomRegistrationRetrieveParams) => {
const queryResult = swrHooks.useV1ListsRandomRegistrationRetrieve(
listId,
{ status },

{
...POTLOCK_REQUEST_CONFIG,
swr: { revalidateIfStale: false, revalidateOnFocus: false },
},
);

return { ...queryResult, data: queryResult.data?.data };
};
8 changes: 7 additions & 1 deletion src/common/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Account } from "near-api-js";

export interface ConditionalExecution {
enabled: boolean;
enabled?: boolean;
}

export type AccountId = Account["accountId"];
Expand All @@ -18,3 +18,9 @@ export type TokenId = "near" | AccountId;
export interface ByTokenId {
tokenId: TokenId;
}

export type ListId = number;

export interface ByListId {
listId: ListId;
}
37 changes: 37 additions & 0 deletions src/modules/donation/components/buttons.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { potlock } from "@/common/api/potlock";
import { POTLOCK_REGISTRY_LIST_ID } from "@/common/constants";
import { Button, Skeleton } from "@/common/ui/components";

import { useDonation } from "../hooks/feature";

export const DonationRandomButton = () => {
const {
isLoading: isRandomPGRegistryEntryLoading,
data: isRandomPGRegistryEntry,
mutate: refetchRandomPGRegistryEntry,
} = potlock.useRandomListRegistration({
listId: POTLOCK_REGISTRY_LIST_ID,
status: "Approved",
});

const randomProjectAccountId = isRandomPGRegistryEntry?.registrant.id;

const { openDonationModal: openRandomDonationModal } = useDonation({
accountId: randomProjectAccountId ?? "unknown",
});

const onDonateRandomlyClick = (event: React.MouseEvent) => {
openRandomDonationModal(event);
refetchRandomPGRegistryEntry();
};

return isRandomPGRegistryEntryLoading ? (
<Skeleton className="h-10 w-full bg-[rgba(246,118,122,0.3)] md:w-[180px]" />
) : (
randomProjectAccountId && (
<Button className="w-full md:w-[180px]" onClick={onDonateRandomlyClick}>
Donate Randomly
</Button>
)
);
};
25 changes: 25 additions & 0 deletions src/modules/donation/hooks/feature.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useCallback } from "react";

import { useModal } from "@ebay/nice-modal-react";

import { dispatch } from "@/app/_store";

import { DonationModal } from "../components/DonationModal";
import { DonationParameters } from "../models";

export const useDonation = (props: DonationParameters) => {
const modal = useModal(DonationModal);

return {
openDonationModal: useCallback(
(event: React.MouseEvent) => {
event.preventDefault();
event.stopPropagation();
dispatch.donation.reset();
modal.show(props);
},

[modal, props],
),
};
};
28 changes: 2 additions & 26 deletions src/modules/donation/index.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,3 @@
import { useCallback } from "react";

import { useModal } from "@ebay/nice-modal-react";

import { dispatch } from "@/app/_store";

import { DonationModal } from "./components/DonationModal";
import { DonationParameters } from "./models";

export { DonationRandomButton } from "./components/buttons";
export { donationModel } from "./models";

export const useDonation = (props: DonationParameters) => {
const modal = useModal(DonationModal);

return {
openDonationModal: useCallback(
(event: React.MouseEvent) => {
event.preventDefault();
event.stopPropagation();
dispatch.donation.reset();
modal.show(props);
},

[modal, props],
),
};
};
export * from "./hooks/feature";
Loading

0 comments on commit 855c415

Please sign in to comment.