From e8abcd587f535fa8fb9a575354adc8c072102d66 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lu=C3=ADs=20Torres?=
<26875009+luistorres@users.noreply.github.com>
Date: Thu, 23 May 2024 18:13:55 +0100
Subject: [PATCH] Update refund to match design (#262)
---
.../dialogs/refund-dialog/index.tsx | 44 +++-
.../web-app/app/_ui/my-projects/header.tsx | 76 ++++++
.../app/_ui/my-projects/loading-field.tsx | 3 +
.../app/_ui/my-projects/my-contribution.tsx | 25 ++
.../app/_ui/my-projects/my-project.tsx | 242 +-----------------
.../web-app/app/_ui/my-projects/my-tokens.tsx | 84 ++++++
.../web-app/app/_ui/my-projects/refund.tsx | 23 ++
.../app/_ui/project/project-content.tsx | 4 +-
packages/web-app/app/_ui/projects/index.tsx | 2 +-
9 files changed, 254 insertions(+), 249 deletions(-)
create mode 100644 packages/web-app/app/_ui/my-projects/header.tsx
create mode 100644 packages/web-app/app/_ui/my-projects/loading-field.tsx
create mode 100644 packages/web-app/app/_ui/my-projects/my-contribution.tsx
create mode 100644 packages/web-app/app/_ui/my-projects/my-tokens.tsx
create mode 100644 packages/web-app/app/_ui/my-projects/refund.tsx
diff --git a/packages/web-app/app/_ui/components/dialogs/refund-dialog/index.tsx b/packages/web-app/app/_ui/components/dialogs/refund-dialog/index.tsx
index f12210cb..0ea4a5bf 100644
--- a/packages/web-app/app/_ui/components/dialogs/refund-dialog/index.tsx
+++ b/packages/web-app/app/_ui/components/dialogs/refund-dialog/index.tsx
@@ -3,7 +3,14 @@ import { Spinner } from '../../svg/spinner';
import { Error } from '../../svg/error';
import { Done } from '../done';
import { Check } from '../../svg/check';
-import { WriteContractErrorType } from 'viem';
+import { WriteContractErrorType, formatEther } from 'viem';
+import {
+ useReadCtzndSaleRefundAmount,
+ useWriteCtzndSaleRefund,
+} from '@/wagmi.generated';
+import { use } from 'react';
+import { useAccount } from 'wagmi';
+import { useEffectSafe } from '@/app/_lib/hooks';
type TTitleProps = {
txHash?: `0x${string}`;
@@ -40,24 +47,35 @@ const Title = ({ txHash, error }: TTitleProps) => {
);
};
-type TRefundDialogProps = {
- refundValue: string;
- txHash?: `0x${string}`;
- error: string | null;
-};
+export const RefundDialog = () => {
+ const { address } = useAccount();
+ const { data: refundValue } = useReadCtzndSaleRefundAmount({
+ args: [address!],
+ });
+ const formattedValue =
+ refundValue !== undefined ? formatEther(refundValue) : '0';
+
+ const { writeContract, data: txHash, error } = useWriteCtzndSaleRefund();
+
+ useEffectSafe(() => {
+ if (!address) return;
+ writeContract({ args: [address] });
+ }, [address]);
+
+ if (error) {
+ console.log('error', error);
+ }
-export const RefundDialog = ({
- refundValue,
- txHash,
- error,
-}: TRefundDialogProps) => {
return (
<>
-
+
@@ -65,7 +83,7 @@ export const RefundDialog = ({
Refund After cap calculations
-
{refundValue} USDC
+
{formattedValue} USDC
diff --git a/packages/web-app/app/_ui/my-projects/header.tsx b/packages/web-app/app/_ui/my-projects/header.tsx
new file mode 100644
index 00000000..d501fbfe
--- /dev/null
+++ b/packages/web-app/app/_ui/my-projects/header.tsx
@@ -0,0 +1,76 @@
+import { useCtzndSaleCapStatus, useCtzndSaleStatus } from '@/app/_lib/hooks';
+import { useTotalInvestedUsdcCtznd } from '@/app/_lib/queries';
+import { useReadCtzndSaleInvestorCount } from '@/wagmi.generated';
+import { useCountdown } from '../hooks/useCountdown';
+import Image from 'next/image';
+import { usdValue } from '../utils/intl-formaters/usd-value';
+import { number } from '../utils/intl-formaters/number';
+import { TProjectSaleDetails } from '@/app/_types';
+import { getRelativePath } from '../utils/getRelativePath';
+
+export const Header = ({ project, logo, end }: TProjectSaleDetails) => {
+ const { data: numberOfParticipants } = useReadCtzndSaleInvestorCount({
+ query: {
+ staleTime: 0,
+ },
+ });
+ const totalCommittedUsdc = useTotalInvestedUsdcCtznd();
+ const status = useCtzndSaleStatus();
+ const formattedNumberOfParticipants = number(numberOfParticipants || 0);
+ const saleCapStatus = useCtzndSaleCapStatus();
+ const projectTitle =
+ project === 'citizend' ? 'Citizend Community Sale' : project;
+ const { days, hours, minutes, seconds } = useCountdown(end);
+
+ return (
+
+
+
+
+ {projectTitle}
+ {status === 'completed' ? (
+
+ Closed
+
+ ) : null}
+ {status === 'live' ? (
+ <>
+
+
+ Sale ends in {days}d {hours}h {minutes}m {seconds}s
+
+ >
+ ) : null}
+
+
+
+
+
Number of participants
+
{formattedNumberOfParticipants}
+
+
+
Total amount committed
+
{usdValue(totalCommittedUsdc)}
+
+
+
Rising Tide Mechanism
+
+ {saleCapStatus === 'above'
+ ? 'ON (max. target reached)'
+ : 'OFF (total contributed below max.)'}
+
+
+
+
+ );
+};
diff --git a/packages/web-app/app/_ui/my-projects/loading-field.tsx b/packages/web-app/app/_ui/my-projects/loading-field.tsx
new file mode 100644
index 00000000..0cfc2b3b
--- /dev/null
+++ b/packages/web-app/app/_ui/my-projects/loading-field.tsx
@@ -0,0 +1,3 @@
+export const LoadingField = () => (
+
+);
diff --git a/packages/web-app/app/_ui/my-projects/my-contribution.tsx b/packages/web-app/app/_ui/my-projects/my-contribution.tsx
new file mode 100644
index 00000000..762b6f45
--- /dev/null
+++ b/packages/web-app/app/_ui/my-projects/my-contribution.tsx
@@ -0,0 +1,25 @@
+import { useAccount } from 'wagmi';
+import { number } from '../utils/intl-formaters/number';
+import { EdgeLink } from '../components/edge';
+import { useProject } from '@/app/_providers/project/context';
+import { useUserTotalInvestedUsdcCtznd } from '@/app/_lib/queries';
+import { useCtzndSaleStatus } from '@/app/_lib/hooks';
+
+export const MyContribution = () => {
+ const { address } = useAccount();
+ const { projectId } = useProject();
+ const usdcValue = useUserTotalInvestedUsdcCtznd(address!);
+ const status = useCtzndSaleStatus();
+
+ return (
+
+
My Contribution
+
{`${number(Number(usdcValue))} USDC`}
+ {status === 'live' ? (
+
+ New Contribution
+
+ ) : null}
+
+ );
+};
diff --git a/packages/web-app/app/_ui/my-projects/my-project.tsx b/packages/web-app/app/_ui/my-projects/my-project.tsx
index cba7d1ac..5083f098 100644
--- a/packages/web-app/app/_ui/my-projects/my-project.tsx
+++ b/packages/web-app/app/_ui/my-projects/my-project.tsx
@@ -1,241 +1,14 @@
import { useProject } from '@/app/_providers/project/context';
-import {
- useFetchProjectsSaleDetails,
- useTotalInvestedUsdcCtznd,
- useUserTotalInvestedUsdcCtznd,
-} from '@/app/_lib/queries';
+import { useFetchProjectsSaleDetails } from '@/app/_lib/queries';
import { NavLink } from '../components/nav-link';
import { Right } from '../components/svg/right';
-import Image from 'next/image';
-import { TProjectSaleDetails } from '@/app/_types';
-import { getRelativePath } from '../utils/getRelativePath';
-import { EdgeButton, EdgeLink } from '../components/edge';
import { CardSkeleton } from '../components/skeletons/card-skeleton';
-import {
- useReadCtzndSaleAllocation,
- useReadCtzndSaleInvestorCount,
- useReadCtzndSaleRefundAmount,
- useReadCtzndSaleTokenToPaymentToken,
- useReadCtzndSaleUncappedAllocation,
- useWriteCtzndSaleRefund,
-} from '@/wagmi.generated';
+import { Header } from './header';
+import { MyTokens } from './my-tokens';
+import { MyContribution } from './my-contribution';
+import { Refund } from './refund';
import { useAccount } from 'wagmi';
-import { formatEther, parseEther } from 'viem';
-import {
- useCtzndRisingTideCap,
- useCtzndSaleCapStatus,
- useCtzndSaleStatus,
-} from '@/app/_lib/hooks';
-import { useDialog } from '@/app/_providers/dialog/context';
-import { number } from '../utils/intl-formaters/number';
-import { usdValue } from '../utils/intl-formaters/usd-value';
-import { useCountdown } from '../hooks/useCountdown';
-import { calculateTokenPrice } from '../utils/calculateTokenPrice';
-
-const Header = ({ project, logo, end }: TProjectSaleDetails) => {
- const { data: numberOfParticipants } = useReadCtzndSaleInvestorCount({
- query: {
- staleTime: 0,
- },
- });
- const totalCommittedUsdc = useTotalInvestedUsdcCtznd();
- const status = useCtzndSaleStatus();
- const formattedNumberOfParticipants = number(numberOfParticipants || 0);
- const saleCapStatus = useCtzndSaleCapStatus();
- const projectTitle =
- project === 'citizend' ? 'Citizend Community Sale' : project;
- const { days, hours, minutes, seconds } = useCountdown(end);
-
- return (
-
-
-
-
- {projectTitle}
- {status === 'completed' ? (
-
- Closed
-
- ) : null}
- {status === 'live' ? (
- <>
-
-
- Sale ends in {days}d {hours}h {minutes}m {seconds}s
-
- >
- ) : null}
-
-
-
-
-
Number of participants
-
{formattedNumberOfParticipants}
-
-
-
Total amount committed
-
{usdValue(totalCommittedUsdc)}
-
-
-
Rising Tide Mechanism
-
- {saleCapStatus === 'above'
- ? 'ON (max. target reached)'
- : 'OFF (total contributed below max.)'}
-
-
-
-
- );
-};
-
-const LoadingField = () => (
-
-);
-
-const Refund = ({ address }: { address: `0x${string}` }) => {
- const { data: refundValue } = useReadCtzndSaleRefundAmount({
- args: [address],
- });
- const {
- writeContract,
- data: refundTxHash,
- error,
- } = useWriteCtzndSaleRefund();
- const { open } = useDialog();
- const formattedValue =
- refundValue !== undefined ? formatEther(refundValue) : '0';
- if (error) {
- console.log(error);
- }
-
- return (
-
-
Refund After Cap Calculations
-
- {refundValue !== undefined ? (
- <>{formattedValue} USDC>
- ) : (
-
- )}
- {refundValue && refundValue > 0n ? (
-
- {
- writeContract({ args: [address] });
- open('refundDialog', {
- refundValue: formattedValue,
- txHash: refundTxHash,
- error: (error as unknown as any)?.shortMessage || null,
- });
- }}
- >
- Claim
-
-
- ) : null}
-
-
- );
-};
-
-const MyContribution = () => {
- const { address } = useAccount();
- const { projectId } = useProject();
- const usdcValue = useUserTotalInvestedUsdcCtznd(address!);
- const status = useCtzndSaleStatus();
-
- return (
-
-
My Contribution
-
{`${number(Number(usdcValue))} USDC`}
- {status === 'live' ? (
-
- New Contribution
-
- ) : null}
- {status === 'completed' && address ?
: null}
-
- );
-};
-
-const useAvailableToClaim = () => {
- const { address } = useAccount();
- const capStatus = useCtzndSaleCapStatus();
- const { data: availableToClaim } = useReadCtzndSaleAllocation({
- args: [address!],
- query: {
- enabled: !!address,
- staleTime: 0,
- },
- });
-
- if (capStatus == 'above') {
- return 'TBD once sale ends';
- }
-
- return `${number(Number(formatEther(availableToClaim || 0n)))} CTND`;
-};
-
-const MyTokens = () => {
- const { address } = useAccount();
- const investedUsdc = useUserTotalInvestedUsdcCtznd(address!);
- const { data: refund } = useReadCtzndSaleRefundAmount({
- args: [address!],
- query: {
- enabled: !!address,
- staleTime: 0,
- },
- });
- const refundValue = refund ? formatEther(refund!) : 0;
- const confirmedAllocation = Number(investedUsdc) - Number(refundValue);
- const status = useCtzndSaleStatus();
- const totalContributions = useTotalInvestedUsdcCtznd();
- const currentTokenPrice = calculateTokenPrice(Number(totalContributions));
- const availableToClaim = useAvailableToClaim();
-
- return (
-
-
-
- Confirmed Allocation
- {status === 'live' ? (
-
- Ongoing cap calculations
-
- ) : null}
-
-
-
{confirmedAllocation} USDC
-
-
-
Current CTND PRICE (FDV)
-
- {usdValue(currentTokenPrice)} {`($${currentTokenPrice * 100}m)`}
-
-
-
-
CTND Available to Claim
-
{availableToClaim}
-
-
-
Available for refund
-
{refundValue} USDC
-
-
-
- );
-};
+import { useCtzndSaleStatus } from '@/app/_lib/hooks';
export const MyProjectSkeleton = () => (
@@ -252,6 +25,7 @@ export const MyProjectSkeleton = () => (
export const MyProject = () => {
const { projectId } = useProject();
+ const { address } = useAccount();
const {
data: saleDetails,
isLoading: isDetailsLoading,
@@ -260,6 +34,7 @@ export const MyProject = () => {
const project = saleDetails?.find(
(project) => project.project.toLowerCase() === projectId,
);
+ const status = useCtzndSaleStatus();
const isLoading = isDetailsLoading;
const error = detailsError;
@@ -295,6 +70,7 @@ export const MyProject = () => {
+ {status === 'completed' && address ? : null}
);
};
diff --git a/packages/web-app/app/_ui/my-projects/my-tokens.tsx b/packages/web-app/app/_ui/my-projects/my-tokens.tsx
new file mode 100644
index 00000000..6fc2ae7d
--- /dev/null
+++ b/packages/web-app/app/_ui/my-projects/my-tokens.tsx
@@ -0,0 +1,84 @@
+import { useCtzndSaleCapStatus, useCtzndSaleStatus } from '@/app/_lib/hooks';
+import {
+ useTotalInvestedUsdcCtznd,
+ useUserTotalInvestedUsdcCtznd,
+} from '@/app/_lib/queries';
+import {
+ useReadCtzndSaleAllocation,
+ useReadCtzndSaleRefundAmount,
+} from '@/wagmi.generated';
+import { formatEther } from 'viem';
+import { useAccount } from 'wagmi';
+import { calculateTokenPrice } from '../utils/calculateTokenPrice';
+import { number } from '../utils/intl-formaters/number';
+import { usdValue } from '../utils/intl-formaters/usd-value';
+
+const useAvailableToClaim = () => {
+ const { address } = useAccount();
+ const capStatus = useCtzndSaleCapStatus();
+ const { data: availableToClaim } = useReadCtzndSaleAllocation({
+ args: [address!],
+ query: {
+ enabled: !!address,
+ staleTime: 0,
+ },
+ });
+
+ if (capStatus == 'above') {
+ return 'TBD once sale ends';
+ }
+
+ return `${number(Number(formatEther(availableToClaim || 0n)))} CTND`;
+};
+
+export const MyTokens = () => {
+ const { address } = useAccount();
+ const investedUsdc = useUserTotalInvestedUsdcCtznd(address!);
+ const { data: refund } = useReadCtzndSaleRefundAmount({
+ args: [address!],
+ query: {
+ enabled: !!address,
+ staleTime: 0,
+ },
+ });
+ const refundValue = refund ? formatEther(refund!) : 0;
+ const confirmedAllocation = Number(investedUsdc) - Number(refundValue);
+ const status = useCtzndSaleStatus();
+ const totalContributions = useTotalInvestedUsdcCtznd();
+ const currentTokenPrice = calculateTokenPrice(Number(totalContributions));
+ const availableToClaim = useAvailableToClaim();
+
+ return (
+ <>
+
+
+
+ Confirmed Allocation
+ {status === 'live' ? (
+
+ Ongoing cap calculations
+
+ ) : null}
+
+
+
{confirmedAllocation} USDC
+
+
+
Current CTND PRICE (FDV)
+
+ {usdValue(currentTokenPrice)} {`($${currentTokenPrice * 100}m)`}
+
+
+
+
CTND Available to Claim
+
{availableToClaim}
+
+
+
Available for refund
+
{refundValue} USDC
+
+
+
+ >
+ );
+};
diff --git a/packages/web-app/app/_ui/my-projects/refund.tsx b/packages/web-app/app/_ui/my-projects/refund.tsx
new file mode 100644
index 00000000..71508679
--- /dev/null
+++ b/packages/web-app/app/_ui/my-projects/refund.tsx
@@ -0,0 +1,23 @@
+import { useDialog } from '@/app/_providers/dialog/context';
+import { useReadCtzndSaleRefundAmount } from '@/wagmi.generated';
+import { EdgeButton } from '../components/edge';
+
+export const Refund = ({ address }: { address: `0x${string}` }) => {
+ const { data: refundValue } = useReadCtzndSaleRefundAmount({
+ args: [address],
+ });
+
+ const { open } = useDialog();
+
+ if (!refundValue || refundValue === 0n) {
+ return null;
+ }
+
+ return (
+
+
open('refundDialog')}>
+ Refund
+
+
+ );
+};
diff --git a/packages/web-app/app/_ui/project/project-content.tsx b/packages/web-app/app/_ui/project/project-content.tsx
index 062565e9..5b3805c6 100644
--- a/packages/web-app/app/_ui/project/project-content.tsx
+++ b/packages/web-app/app/_ui/project/project-content.tsx
@@ -5,7 +5,6 @@ import clsx from 'clsx';
import { CitizendProjectDescription } from './citizend-project-description';
import { HowToParticipate } from './how-to-participate';
import { SaleStatus } from './sale-status';
-import { ApplyButton } from './apply-button';
import {
useCanContribute,
useFetchProjectsSaleDetails,
@@ -58,13 +57,14 @@ export const ProjectContent = () => {
);
}
- if (isError)
+ if (isError && !project)
return (
Something went wrong...
{error.message}
);
+
if (!project) return Project not found
;
const { start, startRegistration, endRegistration } = project;
diff --git a/packages/web-app/app/_ui/projects/index.tsx b/packages/web-app/app/_ui/projects/index.tsx
index 78afccdc..5348af40 100644
--- a/packages/web-app/app/_ui/projects/index.tsx
+++ b/packages/web-app/app/_ui/projects/index.tsx
@@ -11,7 +11,7 @@ export const Projects = () => {
return ;
}
- if (isError) return Something went wrong...
;
+ if (isError && !data) return Something went wrong...
;
return (