diff --git a/package-lock.json b/package-lock.json
index 825913bcf9..6c093c08c4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,7 +10,7 @@
"@apollo/client": "^3.7.10",
"@chakra-ui/next-js": "^2.2.0",
"@chakra-ui/react": "^2.8.2",
- "@decent-org/fractal-ui": "^0.1.23",
+ "@decent-org/fractal-ui": "^0.1.25",
"@emotion/react": "^11.10.6",
"@emotion/styled": "^11.10.6",
"@ethersproject/abstract-signer": "^5.7.0",
@@ -34,6 +34,7 @@
"axios": "^0.27.2",
"classnames": "^2.3.1",
"date-fns": "^2.29.3",
+ "date-fns-tz": "^2.0.1",
"ethers": "^5.7.2",
"evm-proxy-detection": "^1.1.0",
"formik": "^2.2.9",
@@ -3448,9 +3449,9 @@
}
},
"node_modules/@decent-org/fractal-ui": {
- "version": "0.1.23",
- "resolved": "https://registry.npmjs.org/@decent-org/fractal-ui/-/fractal-ui-0.1.23.tgz",
- "integrity": "sha512-2ML5Yzj60k4faIdWQ0LRV9X4704JcOq3cRKUmqDNjFmTWRktSuQ9yeCTk6OOqBOktLVD1Ca8FcE4HUm/P/8sMg==",
+ "version": "0.1.25",
+ "resolved": "https://registry.npmjs.org/@decent-org/fractal-ui/-/fractal-ui-0.1.25.tgz",
+ "integrity": "sha512-mWIpaQ+HlXAskE5tSUaWcETyDHz/skq68FFF5O7jK4vJQAk7Ko7bIf+iujhY5DnAwg44v9+Nrad/zu3j6uNbgA==",
"peerDependencies": {
"@chakra-ui/react": "^2.3.4",
"react": "^16 || ^17 || ^18",
@@ -14712,6 +14713,14 @@
"url": "https://opencollective.com/date-fns"
}
},
+ "node_modules/date-fns-tz": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-2.0.1.tgz",
+ "integrity": "sha512-fJCG3Pwx8HUoLhkepdsP7Z5RsucUi+ZBOxyM5d0ZZ6c4SdYustq0VMmOu6Wf7bli+yS/Jwp91TOCqn9jMcVrUA==",
+ "peerDependencies": {
+ "date-fns": "2.x"
+ }
+ },
"node_modules/dayjs": {
"version": "1.11.7",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz",
@@ -30976,9 +30985,9 @@
}
},
"@decent-org/fractal-ui": {
- "version": "0.1.23",
- "resolved": "https://registry.npmjs.org/@decent-org/fractal-ui/-/fractal-ui-0.1.23.tgz",
- "integrity": "sha512-2ML5Yzj60k4faIdWQ0LRV9X4704JcOq3cRKUmqDNjFmTWRktSuQ9yeCTk6OOqBOktLVD1Ca8FcE4HUm/P/8sMg==",
+ "version": "0.1.25",
+ "resolved": "https://registry.npmjs.org/@decent-org/fractal-ui/-/fractal-ui-0.1.25.tgz",
+ "integrity": "sha512-mWIpaQ+HlXAskE5tSUaWcETyDHz/skq68FFF5O7jK4vJQAk7Ko7bIf+iujhY5DnAwg44v9+Nrad/zu3j6uNbgA==",
"requires": {}
},
"@emotion/babel-plugin": {
@@ -39526,6 +39535,12 @@
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz",
"integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA=="
},
+ "date-fns-tz": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-2.0.1.tgz",
+ "integrity": "sha512-fJCG3Pwx8HUoLhkepdsP7Z5RsucUi+ZBOxyM5d0ZZ6c4SdYustq0VMmOu6Wf7bli+yS/Jwp91TOCqn9jMcVrUA==",
+ "requires": {}
+ },
"dayjs": {
"version": "1.11.7",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz",
diff --git a/package.json b/package.json
index dcff7f09e4..18281e5629 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,7 @@
"@apollo/client": "^3.7.10",
"@chakra-ui/next-js": "^2.2.0",
"@chakra-ui/react": "^2.8.2",
- "@decent-org/fractal-ui": "^0.1.23",
+ "@decent-org/fractal-ui": "^0.1.25",
"@emotion/react": "^11.10.6",
"@emotion/styled": "^11.10.6",
"@ethersproject/abstract-signer": "^5.7.0",
@@ -29,6 +29,7 @@
"axios": "^0.27.2",
"classnames": "^2.3.1",
"date-fns": "^2.29.3",
+ "date-fns-tz": "^2.0.1",
"ethers": "^5.7.2",
"evm-proxy-detection": "^1.1.0",
"formik": "^2.2.9",
diff --git a/src/components/DaoCreator/hooks/usePrepareFormData.ts b/src/components/DaoCreator/hooks/usePrepareFormData.ts
index 4bdde0509f..33ae1832c5 100644
--- a/src/components/DaoCreator/hooks/usePrepareFormData.ts
+++ b/src/components/DaoCreator/hooks/usePrepareFormData.ts
@@ -85,13 +85,11 @@ export function usePrepareFormData() {
if (freezeGuard) {
freezeGuardData = await prepareFreezeGuardData(freezeGuard);
}
- if (freezeGuardData) {
- return {
- trustedAddresses: resolvedAddresses,
- ...freezeGuardData,
- ...rest,
- };
- }
+ return {
+ trustedAddresses: resolvedAddresses,
+ ...freezeGuardData,
+ ...rest,
+ };
},
[signer, prepareFreezeGuardData],
);
diff --git a/src/components/Proposals/MultisigProposalDetails/TxDetails.tsx b/src/components/Proposals/MultisigProposalDetails/TxDetails.tsx
index 32d4d2a3f2..45e72c0edd 100644
--- a/src/components/Proposals/MultisigProposalDetails/TxDetails.tsx
+++ b/src/components/Proposals/MultisigProposalDetails/TxDetails.tsx
@@ -1,37 +1,13 @@
-import { Box, Divider, Flex, Text } from '@chakra-ui/react';
+import { Box, Divider, Text } from '@chakra-ui/react';
import { format } from 'date-fns';
+import { formatInTimeZone } from 'date-fns-tz';
import { useTranslation } from 'react-i18next';
import { BACKGROUND_SEMI_TRANSPARENT } from '../../../constants/common';
import { createAccountSubstring } from '../../../hooks/utils/useDisplayName';
import { MultisigProposal } from '../../../types';
import { DEFAULT_DATE_TIME_FORMAT } from '../../../utils/numberFormats';
import ContentBox from '../../ui/containers/ContentBox';
-import DisplayTransaction from '../../ui/links/DisplayTransaction';
-
-export function InfoRow({
- property,
- value,
- txHash,
-}: {
- property: string;
- value?: string;
- txHash?: string | null;
-}) {
- return (
-
-
- {property}
-
- {txHash ? : {value}}
-
- );
-}
+import InfoRow from '../../ui/proposal/InfoRow';
export function TxDetails({ proposal }: { proposal: MultisigProposal }) {
const { t } = useTranslation('proposal');
@@ -54,7 +30,8 @@ export function TxDetails({ proposal }: { proposal: MultisigProposal }) {
/>
- {totalFiatValue}
+ {formatUSD(totalFiatValue)}
);
diff --git a/src/components/ui/proposal/InfoRow.tsx b/src/components/ui/proposal/InfoRow.tsx
new file mode 100644
index 0000000000..1e58dfd0b7
--- /dev/null
+++ b/src/components/ui/proposal/InfoRow.tsx
@@ -0,0 +1,39 @@
+import { Flex, Text, Tooltip } from '@chakra-ui/react';
+import DisplayTransaction from '../../ui/links/DisplayTransaction';
+
+export default function InfoRow({
+ property,
+ value,
+ txHash,
+ tooltip,
+}: {
+ property: string;
+ value?: string;
+ txHash?: string | null;
+ tooltip?: string;
+}) {
+ return (
+
+
+ {property}
+
+ {tooltip === undefined ? (
+ txHash ? (
+
+ ) : (
+ {value}
+ )
+ ) : (
+
+ {txHash ? : {value}}
+
+ )}
+
+ );
+}
diff --git a/src/components/ui/proposal/ProposalCountdown.tsx b/src/components/ui/proposal/ProposalCountdown.tsx
index f73e7456eb..c7d0ac17c3 100644
--- a/src/components/ui/proposal/ProposalCountdown.tsx
+++ b/src/components/ui/proposal/ProposalCountdown.tsx
@@ -25,22 +25,19 @@ export function ProposalCountdown({
proposal: FractalProposal;
showIcon?: boolean;
}) {
- const secondsLeft = useProposalCountdown(proposal);
+ const totalSecondsLeft = useProposalCountdown(proposal);
const { t } = useTranslation('proposal');
const state: FractalProposalState | null = useMemo(() => proposal.state, [proposal]);
const { isSnapshotProposal } = useSnapshotProposal(proposal);
- const showCountdown = useMemo(
- () =>
- !!secondsLeft &&
- secondsLeft > 0 &&
- (state === FractalProposalState.ACTIVE ||
- state === FractalProposalState.TIMELOCKED ||
- state === FractalProposalState.EXECUTABLE ||
- isSnapshotProposal),
- [state, secondsLeft, isSnapshotProposal],
- );
+ const showCountdown =
+ !!totalSecondsLeft &&
+ totalSecondsLeft > 0 &&
+ (state === FractalProposalState.ACTIVE ||
+ state === FractalProposalState.TIMELOCKED ||
+ state === FractalProposalState.EXECUTABLE ||
+ isSnapshotProposal);
if (!showCountdown) return null;
@@ -63,9 +60,15 @@ export function ProposalCountdown({
? Execute
: null;
- const daysLeft = Math.floor(secondsLeft! / (60 * 60 * 24));
- const hoursLeft = Math.floor((secondsLeft! / (60 * 60)) % 24);
- const minutesLeft = Math.floor((secondsLeft! / 60) % 60);
+ const daysLeft = Math.floor(totalSecondsLeft / (60 * 60 * 24));
+ const hoursLeft = Math.floor((totalSecondsLeft / (60 * 60)) % 24);
+ const minutesLeft = Math.floor((totalSecondsLeft / 60) % 60);
+ const secondsLeft = Math.floor(totalSecondsLeft % 60);
+
+ const showDays = daysLeft > 0;
+ const showHours = showDays || hoursLeft > 0;
+ const showMinutes = showHours || minutesLeft > 0;
+ const showSeconds = secondsLeft >= 0;
return (
- {daysLeft > 0 && `${zeroPad(daysLeft)}:`}
- {hoursLeft > 0 && `${zeroPad(hoursLeft)}:`}
- {minutesLeft > 0 && `${zeroPad(minutesLeft)}:`}
- {secondsLeft! >= 0 && `${zeroPad(secondsLeft! % 60)}`}
+ {showDays && `${zeroPad(daysLeft)}:`}
+ {showHours && `${zeroPad(hoursLeft)}:`}
+ {showMinutes && `${zeroPad(minutesLeft)}:`}
+ {showSeconds && `${zeroPad(secondsLeft)}`}
diff --git a/src/providers/App/hooks/usePriceAPI.ts b/src/providers/App/hooks/usePriceAPI.ts
index 28fc0f8494..1ee58adbaf 100644
--- a/src/providers/App/hooks/usePriceAPI.ts
+++ b/src/providers/App/hooks/usePriceAPI.ts
@@ -41,6 +41,9 @@ export default function usePriceAPI() {
}
}
} catch (e) {
+ // When doing local development, it's unlikely that the Pricing Service is going to be running locally,
+ // so don't worry about logging or showing the error toast.
+ if (process.env.NODE_ENV === 'development') return;
logError('Error while getting tokens prices', e);
toast.warning(t('tokenPriceFetchingError'));
return;
diff --git a/src/providers/Providers.tsx b/src/providers/Providers.tsx
index def0190b26..c41f087bd7 100644
--- a/src/providers/Providers.tsx
+++ b/src/providers/Providers.tsx
@@ -1,11 +1,11 @@
'use client';
import { ApolloProvider } from '@apollo/client';
import { ChakraProvider } from '@chakra-ui/react';
-import { theme } from '@decent-org/fractal-ui';
import { RainbowKitProvider, midnightTheme } from '@rainbow-me/rainbowkit';
import { ReactNode, useEffect } from 'react';
import { ToastContainer } from 'react-toastify';
import { WagmiConfig } from 'wagmi';
+import { theme } from '../assets/theme';
import { ModalProvider } from '../components/ui/modals/ModalProvider';
import Layout from '../components/ui/page/Layout';
import { ErrorFallback } from '../components/ui/utils/ErrorFallback';
diff --git a/src/utils/numberFormats.ts b/src/utils/numberFormats.ts
index 07194f0ba0..14987105bc 100644
--- a/src/utils/numberFormats.ts
+++ b/src/utils/numberFormats.ts
@@ -2,7 +2,7 @@ import { SafeBalanceUsdResponse } from '@safe-global/safe-service-client';
import { BigNumber, ethers } from 'ethers';
import bigDecimal from 'js-big-decimal';
-export const DEFAULT_DATE_TIME_FORMAT = 'MMM dd, yyyy, h:mm aa';
+export const DEFAULT_DATE_TIME_FORMAT = 'MMM dd, yyyy, h:mm aa O';
export const DEFAULT_DATE_FORMAT = 'yyyy-MM-dd';
export const formatPercentage = (