diff --git a/src/components/ProposalBuilder/index.tsx b/src/components/ProposalBuilder/index.tsx
index 206405d77..c8893b956 100644
--- a/src/components/ProposalBuilder/index.tsx
+++ b/src/components/ProposalBuilder/index.tsx
@@ -1,5 +1,5 @@
-import { Box, Flex, Grid, GridItem, Icon, Text } from '@chakra-ui/react';
-import { ArrowLeft, SquaresFour } from '@phosphor-icons/react';
+import { Box, Flex, Grid, GridItem, Text } from '@chakra-ui/react';
+import { ArrowLeft } from '@phosphor-icons/react';
import { Formik, FormikProps } from 'formik';
import { useEffect } from 'react';
import { useTranslation } from 'react-i18next';
@@ -265,21 +265,11 @@ export function ProposalBuilder({
gap="0.5rem"
>
-
-
- {t('actions', { ns: 'actions' })}
-
+ {t('actions', { ns: 'actions' })}
{actions.map((action, index) => {
return (
diff --git a/src/components/Roles/RoleDetailsTabs.tsx b/src/components/Roles/RoleDetailsTabs.tsx
index f03e4af3a..1dbacea73 100644
--- a/src/components/Roles/RoleDetailsTabs.tsx
+++ b/src/components/Roles/RoleDetailsTabs.tsx
@@ -63,17 +63,20 @@ function RolesDetailsPayments({
variant="darker"
my={4}
/>
- {sortedPayments.map((payment, index) => (
-
- ))}
+ {sortedPayments.map(payment => {
+ const thisPaymentIndex = payments?.findIndex(p => p.streamId === payment.streamId);
+ return (
+
+ );
+ })}
>
);
}
diff --git a/src/components/Roles/RolePaymentDetails.tsx b/src/components/Roles/RolePaymentDetails.tsx
index 27af8401a..a503352b1 100644
--- a/src/components/Roles/RolePaymentDetails.tsx
+++ b/src/components/Roles/RolePaymentDetails.tsx
@@ -8,12 +8,11 @@ import { Address, getAddress, Hex } from 'viem';
import { useAccount, usePublicClient } from 'wagmi';
import { DETAILS_BOX_SHADOW, isDemoMode } from '../../constants/common';
import { DAO_ROUTES } from '../../constants/routes';
-import { useFractal } from '../../providers/App/AppProvider';
import { useNetworkConfig } from '../../providers/NetworkConfig/NetworkConfigProvider';
import { useDaoInfoStore } from '../../store/daoInfo/useDaoInfoStore';
import { useRolesStore } from '../../store/roles/useRolesStore';
import { BigIntValuePair } from '../../types';
-import { DEFAULT_DATE_FORMAT, formatCoin, formatUSD } from '../../utils';
+import { DEFAULT_DATE_FORMAT, formatCoin } from '../../utils';
import { ModalType } from '../ui/modals/ModalProvider';
import { useDecentModal } from '../ui/modals/useDecentModal';
@@ -140,9 +139,6 @@ export function RolePaymentDetails({
roleTerms,
}: RolePaymentDetailsProps) {
const { t } = useTranslation(['roles']);
- const {
- treasury: { assetsFungible },
- } = useFractal();
const { safe } = useDaoInfoStore();
const { address: connectedAccount } = useAccount();
const { addressPrefix } = useNetworkConfig();
@@ -216,40 +212,23 @@ export function RolePaymentDetails({
}
}, [addressPrefix, navigate, safe?.address, withdraw]);
- const amountPerWeek = useMemo(() => {
- if (!payment.amount?.bigintValue) {
- return;
- }
-
- const endTime = payment.endDate.getTime() / 1000;
- const startTime = payment.startDate.getTime() / 1000;
- const totalSeconds = Math.round(endTime - startTime); // @dev due to milliseconds we need to round it to avoid problems with BigInt
- const amountPerSecond = payment.amount.bigintValue / BigInt(totalSeconds);
- const secondsInWeek = BigInt(60 * 60 * 24 * 7);
- return amountPerSecond * secondsInWeek;
- }, [payment]);
-
- const streamAmountUSD = useMemo(() => {
- // @todo add price support for tokens not found in assetsFungible
- const foundAsset = assetsFungible.find(
- asset => getAddress(asset.tokenAddress) === payment.asset.address,
- );
- if (!foundAsset || foundAsset.usdPrice === undefined) {
- return;
- }
- return Number(payment.amount.value) * foundAsset.usdPrice;
- }, [payment, assetsFungible]);
-
const isActiveStream =
!payment.isCancelled && Date.now() < payment.endDate.getTime() && !payment.isCancelling;
const activeStreamProps = useCallback(
- (isTop: boolean) =>
- isActiveStream
+ (section: 'top' | 'bottom') => {
+ const borderTopRadius = section === 'top' ? '0.75rem' : '0';
+ const borderBottomRadius = section === 'bottom' ? '0.75rem' : '0';
+ const borderBottom = section === 'bottom' ? '1px solid' : 'none';
+
+ return isActiveStream
? {
bg: 'neutral-2',
sx: undefined,
boxShadow: DETAILS_BOX_SHADOW,
+ borderTopRadius,
+ borderBottomRadius,
+ py: '1rem',
}
: {
sx: {
@@ -260,9 +239,13 @@ export function RolePaymentDetails({
bg: 'none',
boxShadow: 'none',
border: '1px solid',
- borderBottom: isTop ? 'none' : '1px solid',
+ borderBottom,
+ borderTopRadius,
+ borderBottomRadius,
+ py: '1rem',
borderColor: 'neutral-4',
- },
+ };
+ },
[isActiveStream],
);
@@ -327,35 +310,37 @@ export function RolePaymentDetails({
transitionTimingFunction="ease-out"
>
-
- {payment.amount?.bigintValue
- ? formatCoin(
- payment.amount.bigintValue,
- false,
- payment.asset.decimals,
- payment.asset.symbol,
- )
- : undefined}
-
+
+
+
+ {payment.amount?.bigintValue
+ ? formatCoin(
+ payment.amount.bigintValue,
+ false,
+ payment.asset.decimals,
+ payment.asset.symbol,
+ )
+ : undefined}
+
+
{(payment.isCancelled || payment.isCancelling) && (
)}
-
-
-
- {payment.asset.symbol ?? t('selectLabel', { ns: 'modals' })}
-
-
+
-
-
- {streamAmountUSD !== undefined ? formatUSD(streamAmountUSD.toString()) : '$ ---'}
-
- {amountPerWeek !== undefined && (
-
-
-
- {`${formatCoin(amountPerWeek, true, payment.asset.decimals, payment.asset.symbol)} / ${t('week')}`}
-
-
- )}
-
-
+
void }) {
+export function RoleFormCreateProposal({ close }: { close: () => void }) {
const [drawerViewingRole, setDrawerViewingRole] = useState();
const { t } = useTranslation(['modals', 'common', 'proposal']);
@@ -71,8 +69,8 @@ export default function RoleFormCreateProposal({ close }: { close: () => void })
const wearer =
roleHat.isTermed && !!termedNominee
? termedNominee
- : !!roleHat?.wearer
- ? getAddress(roleHat.wearer)
+ : !!roleHat?.resolvedWearer
+ ? roleHat.resolvedWearer
: zeroAddress;
return {
@@ -153,21 +151,20 @@ export default function RoleFormCreateProposal({ close }: { close: () => void })
field: FieldInputProps;
form: FormikProps;
}) => (
-
- {
- setFieldValue('proposalMetadata.title', e.target.value);
- setFieldTouched('proposalMetadata.title', true);
- }}
- testId={field.name}
- placeholder="Proposal Title"
- isRequired={false}
- gridContainerProps={{
- gridTemplateColumns: { base: '1fr', md: '1fr' },
- }}
- />
-
+ {
+ setFieldValue('proposalMetadata.title', e.target.value);
+ setFieldTouched('proposalMetadata.title', true);
+ }}
+ testId={field.name}
+ placeholder="Proposal Title"
+ isRequired
+ gridContainerProps={{
+ gridTemplateColumns: { base: '1fr', md: '1fr' },
+ }}
+ />
)}
@@ -180,20 +177,19 @@ export default function RoleFormCreateProposal({ close }: { close: () => void })
field: FieldInputProps;
form: FormikProps;
}) => (
-
- {
- setFieldValue('proposalMetadata.description', e.target.value);
- setFieldTouched('proposalMetadata.description', true);
- }}
- isRequired={false}
- placeholder={t('proposalDescriptionPlaceholder', { ns: 'proposal' })}
- gridContainerProps={{
- gridTemplateColumns: { base: '1fr', md: '1fr' },
- }}
- />
-
+ {
+ setFieldValue('proposalMetadata.description', e.target.value);
+ setFieldTouched('proposalMetadata.description', true);
+ }}
+ isRequired
+ placeholder={t('proposalDescriptionPlaceholder', { ns: 'proposal' })}
+ gridContainerProps={{
+ gridTemplateColumns: { base: '1fr', md: '1fr' },
+ }}
+ />
)}
@@ -219,17 +215,12 @@ export default function RoleFormCreateProposal({ close }: { close: () => void })
-
{t('actions', { ns: 'actions' })}
@@ -276,7 +267,11 @@ export default function RoleFormCreateProposal({ close }: { close: () => void })
diff --git a/src/components/Roles/forms/RoleFormPaymentStream.tsx b/src/components/Roles/forms/RoleFormPaymentStream.tsx
index 3b62fd39e..7c345c656 100644
--- a/src/components/Roles/forms/RoleFormPaymentStream.tsx
+++ b/src/components/Roles/forms/RoleFormPaymentStream.tsx
@@ -108,7 +108,7 @@ function FixedDate({ formIndex, disabled }: { formIndex: number; disabled: boole
);
}
-export default function RoleFormPaymentStream({ formIndex }: { formIndex: number }) {
+export function RoleFormPaymentStream({ formIndex }: { formIndex: number }) {
const { t } = useTranslation(['roles']);
const { values, errors, setFieldValue } = useFormikContext();
const { getPayment } = useRolesStore();
@@ -145,6 +145,29 @@ export default function RoleFormPaymentStream({ formIndex }: { formIndex: number
onSubmit: handleConfirmCancelPayment,
});
+ function PaymentCancelHint() {
+ return (
+
+
+
+
+
+ {t(payment?.isCancelling ? 'cancellingPaymentInfoMessage' : 'cancelPaymentInfoMessage')}
+
+
+ );
+ }
+
return (
<>
{canBeCancelled && (
-
-
-
-
- {t('cancelPaymentInfoMessage')}
-
+
)}
{(canBeCancelled || !streamId) && (
@@ -199,12 +209,13 @@ export default function RoleFormPaymentStream({ formIndex }: { formIndex: number
isDisabled={!!roleEditingPaymentsErrors}
onClick={() => {
setFieldValue('roleEditing.roleEditingPaymentIndex', undefined);
+ setFieldValue(`roleEditing.payments.${formIndex}.isValidatedAndSaved`, true);
}}
>
{t('save')}
)}
- {isDevMode() && (
+ {isDevMode() && !canBeCancelled && (
)}
+
-
-
-
-
-
- {t(payment?.isCancelling ? 'cancellingPaymentInfoMessage' : 'cancelPaymentInfoMessage')}
-
-
+
{canBeCancelled && (