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 = (