Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ NEXT_PUBLIC_AUTH_BASE_ROUTE=
NEXT_PUBLIC_NOTIFICATION_BASE_ROUTE=
NEXT_PUBLIC_BACKEND_LINK=
NEXT_PUBLIC_FRONTEND_LINK=
NEXT_PUBLIC_V6_FRONTEND_LINK=
NEXT_PUBLIC_V6_GRAPHQL_ENDPOINT=

# backup donation service
MONGO_DONATION_URL=
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ yarn-error.log*
.env.development.local
.env.test.local
.env.production.local
.env*

# vercel
.vercel
Expand Down
3 changes: 3 additions & 0 deletions lang/ct.json
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,9 @@
"label.campaign": "Campanya",
"label.cancel": "Cancel·lar",
"label.cancel_upload": "Cancel·la la pujada",
"label.v6_qf_redirect.body": "Per assegurar-te que la teva donació compti per al matching, dona a través de la pàgina de la ronda de QF.",
"label.v6_qf_redirect.go_to_qf_project_page": "Anar a la pàgina del projecte a QF",
"label.v6_qf_redirect.title": "Aquest projecte és en una ronda de Finançament quadràtic",
"label.cant_donate": "No podeu fer una donació? Compartiu aquesta pàgina en lloc.",
"label.categories_for_your_project": "categories per al teu projecte.",
"label.category": "per categoria",
Expand Down
3 changes: 3 additions & 0 deletions lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,9 @@
"label.campaign": "Campaign",
"label.cancel": "Cancel",
"label.cancel_upload": "Cancel upload",
"label.v6_qf_redirect.body": "To make sure your donation counts toward matching, please donate through the QF round page.",
"label.v6_qf_redirect.go_to_qf_project_page": "Go to QF project page",
"label.v6_qf_redirect.title": "This project is in a Quadratic Funding round",
"label.cant_donate": "Can't donate? Share this page instead.",
"label.categories_for_your_project": "categories for your project.",
"label.category": "by category",
Expand Down
3 changes: 3 additions & 0 deletions lang/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,9 @@
"label.campaign": "Campaña",
"label.cancel": "Cancelar",
"label.cancel_upload": "Cancelar subida",
"label.v6_qf_redirect.body": "Para asegurarte de que tu donación cuente para el matching, dona a través de la página de la ronda de QF.",
"label.v6_qf_redirect.go_to_qf_project_page": "Ir a la página del proyecto en QF",
"label.v6_qf_redirect.title": "Este proyecto está en una ronda de Financiamiento Cuadrático",
"label.cant_donate": "¿No puedes donar? Comparte esta pagina.",
"label.categories_for_your_project": "categorias para tu proyecto.",
"label.category": "por categoria",
Expand Down
90 changes: 90 additions & 0 deletions src/components/V6ProjectDonateLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import Link, { LinkProps } from 'next/link';
import { CSSProperties, MouseEvent, ReactNode, useState } from 'react';
import { useRouter } from 'next/router';
import { useQueryClient } from '@tanstack/react-query';
import V6ProjectQFRedirectModal from '@/components/modals/V6ProjectQFRedirectModal';
import { v6QfRedirectQueryOptions } from '@/services/v6QF';

interface IV6ProjectDonateLinkProps extends LinkProps {
children: ReactNode;
projectId?: number | string;
className?: string;
id?: string;
style?: CSSProperties;
onClick?: (event: MouseEvent<HTMLAnchorElement>) => void;
}

const shouldInterceptDonateClick = (event: MouseEvent<HTMLAnchorElement>) => {
return (
event.button === 0 &&
!event.defaultPrevented &&
!event.metaKey &&
!event.ctrlKey &&
!event.shiftKey &&
!event.altKey
);
};

export const V6ProjectDonateLink = ({
children,
projectId,
href,
onClick,
...linkProps
}: IV6ProjectDonateLinkProps) => {
const router = useRouter();
const queryClient = useQueryClient();
const [redirectUrl, setRedirectUrl] = useState<string>();
const [showRedirectModal, setShowRedirectModal] = useState(false);
const [isChecking, setIsChecking] = useState(false);

return (
<>
<Link
href={href}
{...linkProps}
onClick={async event => {
onClick?.(event);
if (
!shouldInterceptDonateClick(event) ||
!projectId ||
typeof href !== 'string'
) {
return;
}

event.preventDefault();
setIsChecking(true);

try {
const redirectInfo = await queryClient.fetchQuery(
v6QfRedirectQueryOptions(Number(projectId)),
);
if (redirectInfo?.redirectUrl) {
setRedirectUrl(redirectInfo.redirectUrl);
setShowRedirectModal(true);
return;
}
} catch {
// Fall through to normal navigation on error
} finally {
setIsChecking(false);
}

router.push(href);
}}
aria-busy={isChecking || undefined}
>
{children}
</Link>
{showRedirectModal && redirectUrl && (
<V6ProjectQFRedirectModal
setShowModal={setShowRedirectModal}
redirectUrl={redirectUrl}
/>
)}
</>
);
};

export default V6ProjectDonateLink;
85 changes: 85 additions & 0 deletions src/components/modals/V6ProjectQFRedirectModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { FC } from 'react';
import styled from 'styled-components';
import { Button, P } from '@giveth/ui-design-system';
import { useIntl } from 'react-intl';
import { mediaQueries } from '@/lib/constants/constants';
import { Modal } from '@/components/modals/Modal';
import { useModalAnimation } from '@/hooks/useModalAnimation';
import { IModal } from '@/types/common';

interface IV6ProjectQFRedirectModalProps extends IModal {
redirectUrl: string;
}

export const V6ProjectQFRedirectModal: FC<IV6ProjectQFRedirectModalProps> = ({
setShowModal,
redirectUrl,
}) => {
const { isAnimating, closeModal } = useModalAnimation(setShowModal);
const { formatMessage } = useIntl();

return (
<Modal
closeModal={closeModal}
isAnimating={isAnimating}
headerTitle={formatMessage({
id: 'label.v6_qf_redirect.title',
})}
headerTitlePosition='left'
hiddenClose
doNotCloseOnClickOutside
>
<ModalContainer>
<Description>
{formatMessage({
id: 'label.v6_qf_redirect.body',
})}
</Description>
<Buttons>
<PrimaryButton
buttonType='primary'
label={formatMessage({
id: 'label.v6_qf_redirect.go_to_qf_project_page',
})}
onClick={() => {
window.location.assign(redirectUrl);
}}
/>
<SecondaryButton
buttonType='secondary'
label={formatMessage({
id: 'label.cancel',
})}
onClick={closeModal}
/>
</Buttons>
</ModalContainer>
</Modal>
);
};

const ModalContainer = styled.div`
padding: 24px;
width: 100%;

${mediaQueries.tablet} {
width: 494px;
}
`;

const Description = styled(P)`
margin: 0 0 24px;
text-align: left;
`;

const Buttons = styled.div`
display: flex;
flex-direction: column;
gap: 12px;
`;

const PrimaryButton = styled(Button)``;

const SecondaryButton = styled(Button)``;

export default V6ProjectQFRedirectModal;
6 changes: 4 additions & 2 deletions src/components/project-card/ProjectCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import {
getSumDonationValueUsdForActiveQfRound,
haveProjectRound,
} from '@/lib/helpers/projectHelpers';
import V6ProjectDonateLink from '@/components/V6ProjectDonateLink';

const cardRadius = '12px';
const imgHeight = '226px';
Expand Down Expand Up @@ -424,8 +425,9 @@ const ProjectCard = (props: IProjectCard) => {
</CardBody>
{!isListingInsideCauseProjectTabs && (
<ActionButtons className='action-buttons'>
<Link
<V6ProjectDonateLink
id='Donate_Card'
projectId={id}
href={donateLink}
onClick={e => {
setDestination(donateLink);
Expand All @@ -438,7 +440,7 @@ const ProjectCard = (props: IProjectCard) => {
label={formatMessage({ id: 'label.donate' })}
$isHover={isHover}
/>
</Link>
</V6ProjectDonateLink>
</ActionButtons>
)}
{showHintModal && activeQFRound && (
Expand Down
56 changes: 38 additions & 18 deletions src/components/views/donate/DonateIndex.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import { isWalletSanctioned } from '@/services/donation';
import SanctionModal from '@/components/modals/SanctionedModal';
import { GIVBACKS_DONATION_QUALIFICATION_VALUE_USD } from '@/lib/constants/constants';
import QRDonationDetails from './OneTime/SelectTokenModal/QRCodeDonation/QRDonationDetails';
import V6ProjectQFRedirectModal from '@/components/modals/V6ProjectQFRedirectModal';

const DonateIndex: FC = () => {
const { formatMessage } = useIntl();
Expand All @@ -61,6 +62,10 @@ const DonateIndex: FC = () => {
startTimer,
setDonateModalByPriority,
setIsModalPriorityChecked,
isV6ProjectInActiveQFRound,
v6ProjectRedirectUrl,
showV6ProjectRedirectModal,
setShowV6ProjectRedirectModal,
} = useDonateData();
const { renewExpirationDate, retrieveDraftDonation } =
useQRCodeDonation(project);
Expand Down Expand Up @@ -118,6 +123,12 @@ const DonateIndex: FC = () => {
validateSanctions();
}, [project, address]);

useEffect(() => {
if (isV6ProjectInActiveQFRound) {
setShowV6ProjectRedirectModal(true);
}
}, [isV6ProjectInActiveQFRound, setShowV6ProjectRedirectModal]);

useEffect(() => {
if (
userData?.id !== undefined &&
Expand Down Expand Up @@ -272,29 +283,38 @@ const DonateIndex: FC = () => {
<DonateHeader />
<Wrapper>
<DonateContainer>
{shouldRenderModal(
DonateModalPriorityValues.DonationByProjectOwner,
) && (
<DonationByProjectOwner
closeModal={() => {
setDonateModalByPriority(
DonateModalPriorityValues.None,
);
}}
{showV6ProjectRedirectModal && v6ProjectRedirectUrl && (
<V6ProjectQFRedirectModal
setShowModal={setShowV6ProjectRedirectModal}
redirectUrl={v6ProjectRedirectUrl}
/>
)}

{shouldRenderModal(
DonateModalPriorityValues.DonationByProjectOwner,
) &&
!isV6ProjectInActiveQFRound && (
<DonationByProjectOwner
closeModal={() => {
setDonateModalByPriority(
DonateModalPriorityValues.None,
);
}}
/>
)}

{shouldRenderModal(
DonateModalPriorityValues.OFACSanctionListModal,
) && (
<SanctionModal
closeModal={() => {
setDonateModalByPriority(
DonateModalPriorityValues.None,
);
}}
/>
)}
) &&
!isV6ProjectInActiveQFRound && (
<SanctionModal
closeModal={() => {
setDonateModalByPriority(
DonateModalPriorityValues.None,
);
}}
/>
)}

{showAlreadyDonatedWrapper && (
<AlreadyDonatedWrapper>
Expand Down
14 changes: 13 additions & 1 deletion src/components/views/donate/OneTime/OneTimeDonationCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ const CryptoDonation: FC<{
shouldRenderModal,
setDonateModalByPriority,
setIsModalPriorityChecked,
isV6ProjectInActiveQFRound,
setShowV6ProjectRedirectModal,
ensureV6ProjectRedirect,
} = useDonateData();
const dispatch = useAppDispatch();

Expand Down Expand Up @@ -586,7 +589,16 @@ const CryptoDonation: FC<{
id='Donate_Final'
label={formatMessage({ id: 'label.donate' })}
size='medium'
onClick={handleDonate}
onClick={async () => {
if (isV6ProjectInActiveQFRound) {
setShowV6ProjectRedirectModal(true);
return;
}
if (await ensureV6ProjectRedirect()) {
return;
}
handleDonate();
}}
/>
))}
{!isConnected && (
Expand Down
Loading
Loading