diff --git a/lang/ca.json b/lang/ca.json index 5dfdaf138f..51adaf1269 100644 --- a/lang/ca.json +++ b/lang/ca.json @@ -604,6 +604,7 @@ "label.look_for_the_share_and_get_rewarded": "Busca el botó 'Comparteix i guanya recompenses' per generar enllaços a pàgines específiques a tot el lloc de Giveth.", "label.make_a_recurring_donation_with": "Fes una donació recurrent amb ", "label.make_it_anonymous": "Fes-ho anònim", + "label.transaction_detail": "Detall de la transacció", "label.qr_code_error": "S'ha produït un error en generar el codi QR. Torneu-ho a provar.", "label.make_it_easier_for_donors_to_find_your_project": "Fes més fàcil que els donants trobin el teu projecte proporcionant una ubicació.", "label.make_it_unique_and_memorable_to_stand_out_from_other_projects": "Fes-ho únic i memorable per destacar entre altres projectes.", @@ -632,6 +633,7 @@ "label.modify_stream_balance": "Modificar el Saldo de la Transmissió", "label.month": "{count, plural, one { Mes} other { Mesos} }", "label.monthly": "Mensualment", + "label.sign_in_with_your_eth_wallet_for_givebacks": "Inicieu la sessió amb la vostra adreça d'ETH per ser elegible per a GIVbacks.", "label.monthly_across_all_projects": "mensualment a tots els projectes", "label.months": "{count, plural, one { Mes} other { Mesos} }", "label.more_about_us": "Més sobre nosaltres", @@ -767,8 +769,8 @@ "label.project_status": "Estat del projecte", "label.project_story": "Història del projecte", "label.project_verification": "Verificació del projecte", - "label.project_verify": "Verifica el projecte", - "label.project_verify_resume": "Reprendre la verificació", + "label.project_verify": "Sol·licitar l'Elegibilitat per a GIVbacks", + "label.project_verify_resume": "Reprendre la Sol·licitud de GIVbacks", "label.proud_of_our_partners": "Orgullosos dels nostres socis", "label.provide_liquidity": "Proporciona liquiditat", "label.providing_location_details_makes_a_personal_connection_with": "Proporcionar detalls de ubicació crea una connexió personal amb persones de la teva àrea.", @@ -822,7 +824,7 @@ "label.resend_email": "Reenviar correu electrònic", "label.resend_email_in": "Reenviar correu electrònic en", "label.resolved_as": "Resolt com a ", - "label.resume_verification": "REPRENDRE VERIFICACIÓ", + "label.resume_verification": "REPRENDRE FORMULARI DE GIVBACKS", "label.review_your_staked_giv_lockup_period": "Revisa el teu GIV en stake, períodes de bloqueig, multiplicadors i guanys.", "label.rewards": "Recompenses", "label.rewards_breakdown": "Desglossament de recompenses", @@ -1011,6 +1013,7 @@ "label.the_service_is_a_kycfree_authorized_financial_intermediary": "El servei és un intermediari financer autoritzat lliure de KYC, amb seu a Suïssa", "label.think_about_where_your_potential_donors_might_look_for_a_project_like_yours": "Pensa on els teus possibles donants podrien buscar un projecte com el teu.", "label.this_address_is_already_used": "Aquesta adreça ja s'utilitza per a un altre projecte. Si us plau, introduïu una adreça que no estigui associada actualment a cap altre projecte.", + "label.this_address_and_memo_is_already_used": "Aquesta adreça ja s'utilitza per a un altre projecte amb el mateix MEMO. Introduïu una adreça diferent o un MEMO diferent.", "label.this_documentation": "aquest article de documentació", "label.this_farm_has_ended": "Aquesta farm ha finalitzat", "label.this_feature_will_be_available_soon": "Aquesta funció estarà disponible aviat.", @@ -1106,9 +1109,9 @@ "label.verification_status": "Estat de verificació", "label.verified": "Verificat", "label.verified_projects": "Projectes verificats", - "label.verified_status_for": "Estat de verificació per", + "label.verified_status_for": "Elegibilitat per a GIVbacks per a", "label.verify_email_address": "Verificar correu electrònic", - "label.verify_your_project": "Verifica el teu projecte", + "label.verify_your_project": "Formulari d'Elegibilitat per a GIVbacks", "label.verify_your_project.modal.four": "requereix alguna informació addicional sobre el teu projecte i l'impacte previst de la teva organització.", "label.verify_your_project.modal.one": "El programa GIVbacks és un concepte revolucionari que recompensa els donants de projectes verificats amb tokens GIV. Al sol·licitar l'estat de projecte 'Verificat', podràs fer que el teu projecte destacar i fomentar més donacions. Aconseguir que el teu projecte sigui verificat també construeix una relació de confiança amb els teus donants en demostrar la legitimetat del teu projecte i mostrar que els fons s'estan utilitzant per crear un canvi positiu.", "label.verify_your_project.modal.three": "procés de verificació ", @@ -1228,12 +1231,14 @@ "label.new_qr_code_needed": "Si no ho has aconseguit a temps, has de generar un nou codi QR.", "label.please_wait_for_you_donation_to_come_through": "Espera que la teva donació es processi!", "label.please_wait": "Espera", + "label.the_time_is_up": "S'ha acabat el temps.", "label.the_community_of_makers": "La comunitat de creadors", "page.project.we_are_supporting_stellar": "Aquest projecte admet donacions en Stellar", "page.project.you_can_try_donating": "Prova de fer donacions utilitzant la Xarxa Stellar.", "page.project.donate_with_stellar": "Dona amb Stellar", "label.try_donating_wuth_stellar": "Prova de donar amb Stellar.", "label.check_donations": "Comprova les donacions", + "label.check_donation": "Comprova la donació", "error.enter_amount": "La quantitat ha de ser superior a 0", "label.enter_the_memo": "Introdueix el memo", "label.be_carefull_some_exchanges": "Ves amb compte! Alguns intercanvis i carteres requereixen Memo per finançar el teu compte. Assegura't d'introduir-ho al formulari si la teva cartera admet un memo.", @@ -1296,6 +1301,8 @@ "label.we_need_a_bit_more_info": "Necessitem una mica més d'informació!", "label.passport_connected": "Passaport connectat", "label.increase_passport_score": "Augmenta la puntuació del passaport", + "label.project_owner_address_detected": "Adreça del propietari del projecte detectada", + "label.project_owner_cant_donate_to_own_project": "No pots donar a un projecte del qual ets propietari. Hi ha milers de projectes a Giveth que busquen el teu suport! Si us plau, tria un altre projecte per donar.", "label.qf_donor_eligibility.banner.check_eligibility": "Fes que les teves donacions es igualin! Verifica la teva unicitat amb un clic.", "label.qf_donor_eligibility.banner.recheck_eligibility": "Fes que les teves donacions es igualin! Augmenta la teva puntuació de Gitcoin Passport abans de", "label.qf_donor_eligibility.banner.more_info_needed": "Necessitem una mica més d'informació per verificar la teva elegibilitat per QF!", @@ -1609,19 +1616,18 @@ "partnerships": "Asociacions", "peace-and-justice": "Pau i Justícia", "poverity": "Pobresa", - "project.givback_toast.description.non_verified_owner": "El teu projecte pot ser elegible per ser 'verificat' com a projecte de bé públic a Giveth! Els projectes verificats proporcionen recompenses als donants, tenen més visibilitat i oportunitats addicionals per recaptar fons.", - "project.givback_toast.description.non_verified_owner_cancelled": "Ens sap greu sentir que el teu projecte està cancel·lat. Actualment no està llistat a Giveth, i la recaptació de fons està aturada. Si alguna vegada vols reviure'l o començar de nou, estem aquí per recolzar la teva visió!", - "project.givback_toast.description.non_verified_owner_deactive": "Ui! El teu projecte actualment està en mode desactivat. No apareixerà a Giveth, i la recaptació de fons està pausada. Reactivem-lo junts i torna a posar la teva causa en l'escenari!", - "project.givback_toast.description.non_verified_owner_draft": "No deixis que la teva visió es quedi en mode esborrany! Publica el teu projecte ara per iniciar el teu viatge i desbloquejar el potencial de recaptar fons més ràpid. Com més aviat comparteixis, més aviat faràs un impacte!", - "project.givback_toast.description.non_verified_owner_incomplete": "No has presentat la teva sol·licitud de verificació! Continua omplint la teva sol·licitud i presenta-la perquè l'equip de Giveth pugui revisar la teva elegibilitat.", - "project.givback_toast.description.non_verified_owner_rejected_1": "El teu projecte no va complir amb els criteris per a la verificació. No et preocupis, encara pots recaptar fons a Giveth i participar en certes rondes de finançament quadràtic. Si vols millorar la teva sol·licitud i tornar a aplicar, si us plau contacta", - "project.givback_toast.description.non_verified_owner_rejected_2": "o suport de Discord per a més instruccions.", - "project.givback_toast.description.non_verified_owner_submitted": "Bones notícies! La teva sol·licitud ha estat enviada i està en cua per ser revisada pel nostre equip de verificació de béns públics. Et respondrem dins de 1-2 setmanes.", - "project.givback_toast.description.non_verified_public": "En l'actualitat, els GIVbacks només s'atorguen per les donacions fetes a projectes verificats a Ethereum. La teva contribució encara és important, encara que no generi GIVbacks!", - "project.givback_toast.description.verified_owner": "Impulsa el teu projecte per augmentar la quantitat de GIVbacks que reben els teus donants a Ethereum i augmenta la seva visibilitat entre altres projectes!", - "project.givback_toast.description.verified_owner.note": "Com a propietari d'aquest projecte, no obtindràs GIVbacks per donar-hi.", - "project.givback_toast.description.verified_public": "Les donacions a Ethereum a projectes verificats es recompensen amb GIV. Augmenta aquest projecte per incrementar el seu percentatge de recompenses i fer-lo més visible a la pàgina de projectes!", - "project.givback_toast.title.non_verified_owner": "El teu projecte està creant o donant suport a béns públics?", + "project.givback_toast.description.non_verified_owner": "El teu projecte pot ser elegible per convertir-se en Elegible per a GIVbacks per ser un projecte de bé públic a Giveth! Els projectes elegibles per a GIVbacks proporcionen recompenses als donants, tenen més visibilitat i oportunitats addicionals per recaptar fons.", + "project.givback_toast.description.non_verified_owner_cancelled": "Aquest projecte ha violat un o més dels Termes de Servei o polítiques d'assegurament de qualitat de Giveth. Si creus que això ha estat un error, contacta'ns a través de Discord.", + "project.givback_toast.description.non_verified_owner_deactive": "El teu projecte està actualment desactivat. No apareixerà a la llista de projectes i no pot rebre donacions. Pots reactivar el teu projecte en qualsevol moment.", + "project.givback_toast.description.non_verified_owner_draft": "El teu projecte encara és un esborrany. Publica el teu projecte ara perquè els donants descobreixin el teu projecte i facin donacions. Com més aviat el comparteixis, més aviat podràs començar a recaptar fons!", + "project.givback_toast.description.non_verified_owner_incomplete": "La teva sol·licitud d'elegibilitat per a GIVbacks està incompleta i requereix més informació! Omple la informació que falta i envia-la perquè l'equip de Giveth pugui revisar la teva elegibilitat.", + "project.givback_toast.description.non_verified_owner_rejected_1": "El teu projecte no va complir amb els criteris per a l'elegibilitat de GIVbacks. No et preocupis, encara pots recaptar fons a Giveth i participar en certes rondes de finançament quadràtic. Si vols millorar la teva sol·licitud i tornar a aplicar, si us plau contacta a ", + "project.givback_toast.description.non_verified_owner_rejected_2": " o al suport de Discord per a més instruccions.", + "project.givback_toast.description.non_verified_owner_submitted": "Notícies emocionants! La teva sol·licitud ha estat enviada i està a la cua per ser revisada pel nostre equip de revisió d'elegibilitat per a GIVbacks. Et respondrem en un termini d'1-2 setmanes.", + "project.givback_toast.description.non_verified_public": "Actualment, els GIVbacks només s'atorguen per donacions fetes a projectes elegibles per a GIVbacks a Ethereum. La teva contribució segueix sent important, fins i tot si no genera GIVbacks!", + "project.givback_toast.description.verified_owner": "Impulsa el teu projecte per augmentar la quantitat de GIVbacks que reben els teus donants a Ethereum i augmentar la seva visibilitat entre altres projectes.", + "project.givback_toast.description.verified_owner.note": "Com a propietari d'aquest projecte, no rebràs GIVbacks per donar-hi.", + "project.givback_toast.description.verified_public": "Les donacions a Ethereum a projectes elegibles per a GIVbacks són recompensades amb GIV. Impulsa aquest projecte per augmentar el seu percentatge de recompenses i fer-lo més visible a la pàgina de projectes!", "project.givback_toast.title.non_verified_owner": "El teu projecte està creant o donant suport a béns públics?", "project.givback_toast.title.non_verified_owner_cancelled": "Estat Cancel·lat", "project.givback_toast.title.non_verified_owner_deactive": "Mode Desactivat", "project.givback_toast.title.non_verified_owner_draft": "Publica el teu projecte avui!", diff --git a/lang/en.json b/lang/en.json index bd74cf382b..1c73cb3262 100644 --- a/lang/en.json +++ b/lang/en.json @@ -635,6 +635,7 @@ "label.modify_stream_balance": "Modify Stream Balance", "label.month": "{count, plural, one { Month} other { Months} }", "label.monthly": "Monthly", + "label.sign_in_with_your_eth_wallet_for_givebacks": "Sign in with your ETH address to be eligible for GIVbacks.", "label.monthly_across_all_projects": "monthly, across all projects", "label.months": "{count, plural, one { Month} other { Months} }", "label.more_about_us": "More about us", @@ -770,8 +771,8 @@ "label.project_status": "Project status", "label.project_story": "Project story", "label.project_verification": "Project Verification", - "label.project_verify": "Verify Project", - "label.project_verify_resume": "Resume Verification", + "label.project_verify": "Apply for GIVbacks Eligibility", + "label.project_verify_resume": "Resume GIVbacks Application", "label.proud_of_our_partners": "Proud of our partners", "label.provide_liquidity": "Provide Liquidity", "label.providing_location_details_makes_a_personal_connection_with": "Providing location details makes a personal connection with people in your area.", @@ -825,7 +826,7 @@ "label.resend_email": "Re-send email", "label.resend_email_in": "Re-send email in", "label.resolved_as": "Resolves as ", - "label.resume_verification": "RESUME VERIFICATION", + "label.resume_verification": "RESUME GIVBACKS FORM", "label.review_your_staked_giv_lockup_period": "Review your staked GIV, lockup periods, multipliers & earnings.", "label.rewards": "Rewards", "label.rewards_breakdown": "Rewards breakdown", @@ -1014,6 +1015,7 @@ "label.the_service_is_a_kycfree_authorized_financial_intermediary": "The service is a KYC-free authorized financial intermediary based in Switzerland", "label.think_about_where_your_potential_donors_might_look_for_a_project_like_yours": "Think about where your potential donors might look for a project like yours.", "label.this_address_is_already_used": "This address is already used for another project. Please enter an address which is not currently associated with any other project.", + "label.this_address_and_memo_is_already_used": "This address is already used for another project with the same MEMO. Please enter a different address or a different MEMO.", "label.this_documentation": "this documentation article", "label.this_farm_has_ended": "This farm has ended", "label.this_feature_will_be_available_soon": "This feature will be available soon.", @@ -1106,12 +1108,12 @@ "label.use_your_giv_to_influence": "Use your GIV to influence which projects are most visible on the platform and the most rewarding to future donors! It makes giving fun, and empowers you to “boost” high-quality projects to the next level of funding support.", "label.verification_process": "verification process", "label.verification_rejected": "Verification Rejected", - "label.verification_status": "Verification status", + "label.verification_status": "GIVbacks Eligibility status", "label.verified": "Verified", "label.verified_projects": "Verified projects", - "label.verified_status_for": "Verified status for", + "label.verified_status_for": "GIVbacks Eligibility for", "label.verify_email_address": "Verify email address", - "label.verify_your_project": "Verify your project", + "label.verify_your_project": "GIVbacks Eligibility Form", "label.verify_your_project.modal.four": "requires some additional information about your project and the intended impact of your organization.", "label.verify_your_project.modal.one": "The GIVbacks program is a revolutionary concept that rewards donors to verified projects with GIV tokens. By applying for a 'Verified' project status, you will be able to make your project stand out and encourage more donations. Getting your project verified also builds a relationship of trust with your donors by demonstrating your project's legitimacy and showing that the funds are being used to create positive change.", "label.verify_your_project.modal.three": "verification process ", @@ -1231,13 +1233,16 @@ "label.valid_for": "Valid for", "label.new_qr_code_needed": "If you didn’t make it in time, you need to generate a new QR code.", "label.please_wait_for_you_donation_to_come_through": "Do not close this page until your donation is successful.", + "label.transaction_detail": "Transaction detail", "label.please_wait": "Please wait", + "label.the_time_is_up": "The time is up.", "label.the_community_of_makers": "The community of makers", "page.project.we_are_supporting_stellar": "This Project supports Donations on Stellar", "page.project.you_can_try_donating": "Try out making donations using the Stellar Network.", "page.project.donate_with_stellar": "Donate with Stellar", "label.try_donating_wuth_stellar": "Try donating with Stellar.", "label.check_donations": "View Donation Receipt", + "label.check_donation": "View Donation", "error.enter_amount": "Amount must be greater than 0", "label.enter_the_memo": "Enter the Memo", "label.be_carefull_some_exchanges": "Be careful! Some exchanges and wallets requires Memo to fund your account. Make sure to put it in the form if your wallet supports a memo.", @@ -1300,6 +1305,8 @@ "label.we_need_a_bit_more_info": "We need a bit more info!", "label.passport_connected": "Passport connected", "label.increase_passport_score": "Increase Passport score", + "label.project_owner_address_detected": "Project Owner Address Detected", + "label.project_owner_cant_donate_to_own_project": "You cannot donate to a project you are the owner of. There are thousands of projects on Giveth looking for your support! Please choose another project to donate to.", "label.qf_donor_eligibility.banner.check_eligibility": "Get your donations matched! Verify your uniqueness with one click.", "label.qf_donor_eligibility.banner.recheck_eligibility": "Get your donations matched! Increase your Gitcoin Passport score before", "label.qf_donor_eligibility.banner.more_info_needed": "We need a bit more information to verify your QF Eligibility!", @@ -1614,18 +1621,18 @@ "partnerships": "Partnerships", "peace-and-justice": "Peace & Justice", "poverity": "Poverty", - "project.givback_toast.description.non_verified_owner": "You project may be eligible to be 'verified' as a public good project on Giveth! Verified projects provide donor rewards, have increased visibility and extra opportunities to raise funds.", + "project.givback_toast.description.non_verified_owner": "You project may be eligible to become GIVbacks Eligible for being a public good project on Giveth! GIVbacks Eligible projects provide donor rewards, have increased visibility and extra opportunities to raise funds.", "project.givback_toast.description.non_verified_owner_cancelled": "This Project has violated one or more of Giveth’s Terms of Service or quality assurance policies. If you think this was a mistake, reach out to us via Discord.", "project.givback_toast.description.non_verified_owner_deactive": "Your Project is currently Deactivated. It won’t appear in the list of projects and cannot receive donations. You can reactivate your project any time you wish.", "project.givback_toast.description.non_verified_owner_draft": "Your Project is still a draft. Publish your project now to let donors discover your project & make donations. The sooner you share, the sooner you can start raising funds!", - "project.givback_toast.description.non_verified_owner_incomplete": "Your verification application is incomplete and requires more information! Fill out the missing info and submit it so the Giveth team can review your eligibility.", - "project.givback_toast.description.non_verified_owner_rejected_1": "Your project didn't meet the criteria for verification. Don't worry, you can still raise funds on Giveth & participate in certain quadratic funding rounds. If you would like to improve your application and reapply, please contact ", + "project.givback_toast.description.non_verified_owner_incomplete": "Your GIVbacks Eligibility application is incomplete and requires more information! Fill out the missing info and submit it so the Giveth team can review your eligibility.", + "project.givback_toast.description.non_verified_owner_rejected_1": "Your project didn't meet the criteria for GIVbacks Eligibility. Don't worry, you can still raise funds on Giveth & participate in certain quadratic funding rounds. If you would like to improve your application and reapply, please contact ", "project.givback_toast.description.non_verified_owner_rejected_2": " or Discord support for more instructions.", - "project.givback_toast.description.non_verified_owner_submitted": "Exciting news! Your application has been submitted and is in the queue for review by our public goods verification team. We will get back to you with a response within 1-2 weeks.", - "project.givback_toast.description.non_verified_public": "GIVbacks are currently only awarded for donations made to verified projects on Ethereum. Your contribution still matters, even if it doesn't generate GIVbacks!", + "project.givback_toast.description.non_verified_owner_submitted": "Exciting news! Your application has been submitted and is in the queue for review by our GIVbacks Eligibility review team. We will get back to you with a response within 1-2 weeks.", + "project.givback_toast.description.non_verified_public": "GIVbacks are currently only awarded for donations made to GIVbacks Eligible projects on Ethereum. Your contribution still matters, even if it doesn't generate GIVbacks!", "project.givback_toast.description.verified_owner": "Boost your project to increase the amount of GIVbacks your donors on Ethereum receive and increase its visibility among other projects!", "project.givback_toast.description.verified_owner.note": "As the owner of this project, you won’t get GIVbacks for donating to it.", - "project.givback_toast.description.verified_public": "Ethereum donations to verified projects are rewarded with GIV. Boost this project to increase its rewards percentage and make it more visible on the projects page!", + "project.givback_toast.description.verified_public": "Ethereum donations to GIVbacks Eligible projects are rewarded with GIV. Boost this project to increase its rewards percentage and make it more visible on the projects page!", "project.givback_toast.title.non_verified_owner": "Is your project creating or supporting public goods?", "project.givback_toast.title.non_verified_owner_cancelled": "Project Cancelled", "project.givback_toast.title.non_verified_owner_deactive": "Project Deactivated", diff --git a/lang/es.json b/lang/es.json index c9e9a59f8a..47de99c310 100644 --- a/lang/es.json +++ b/lang/es.json @@ -632,6 +632,7 @@ "label.modify_stream_balance": "Modificar el Saldo de Transmisión", "label.month": "{count, plural, one { Mes} other { Meses} }", "label.monthly": "Mensualmente", + "label.sign_in_with_your_eth_wallet_for_givebacks": "Inicia sesión con tu dirección ETH para poder optar a los GIVbacks.", "label.monthly_across_all_projects": "mensualmente en todos los proyectos", "label.months": "{count, plural, one { Mes} other { Meses} }", "label.more_about_us": "Más acerca de nosotros", @@ -767,8 +768,8 @@ "label.project_status": "Estado del Proyecto", "label.project_story": "Historia del proyecto", "label.project_verification": "Verificación del proyecto", - "label.project_verify": "Verificar proyecto", - "label.project_verify_resume": "Reanudar la verificación", + "label.project_verify": "Solicitar Elegibilidad para GIVbacks", + "label.project_verify_resume": "Reanudar Solicitud de GIVbacks", "label.proud_of_our_partners": "Orgullosos de nuestros socios", "label.provide_liquidity": "Proveer Liquidez", "label.providing_location_details_makes_a_personal_connection_with": "Proporcionar detalles de ubicación crea una conexión personal con personas de tu área.", @@ -822,7 +823,7 @@ "label.resend_email": "Reenviar email", "label.resend_email_in": "Reenviar email en", "label.resolved_as": "Resuelto como ", - "label.resume_verification": "REANUDAR VERIFICAIÓN", + "label.resume_verification": "REANUDAR FORMULARIO DE GIVBACKS", "label.review_your_staked_giv_lockup_period": "Revisa tu GIV en stake, períodos de bloqueo, multiplicadores y ganancias.", "label.rewards": "Recompensas", "label.rewards_breakdown": "Desglose de recompensas", @@ -1011,6 +1012,7 @@ "label.the_service_is_a_kycfree_authorized_financial_intermediary": "Son una entidad financiera autorizada localizada en Suiza, libre de KYC", "label.think_about_where_your_potential_donors_might_look_for_a_project_like_yours": "Piensa dónde tus posibles donantes podrían buscar un proyecto como el tuyo.", "label.this_address_is_already_used": "Esta dirección ya esta en uso para otro proyecto. Por favor ingrese una dirección que no este actualmente asociada a ningún otro proyecto.", + "label.this_address_and_memo_is_already_used": "Esta dirección ya se utiliza para otro proyecto con el mismo MEMO. Por favor, introduzca una dirección diferente o un MEMO diferente.", "label.this_documentation": "este artículo de documentación", "label.this_farm_has_ended": "Esta Farm ha terminado", "label.this_feature_will_be_available_soon": "Esta función estará disponible pronto.", @@ -1106,9 +1108,9 @@ "label.verification_status": "Estado de verificación", "label.verified": "Verificado", "label.verified_projects": "Proyectos verificados", - "label.verified_status_for": "Estado de verificación para", + "label.verified_status_for": "Elegibilidad para GIVbacks para", "label.verify_email_address": "Verificar email", - "label.verify_your_project": "Verifica tu proyecto", + "label.verify_your_project": "Formulario de Elegibilidad para GIVbacks", "label.verify_your_project.modal.four": "requiere un poco de información adicional sobre tu proyecto y el impacto previsto de tu organización.", "label.verify_your_project.modal.one": "El programa GIVbacks es un concepto revolucionario que recompensa a los donantes de proyectos verificados con tokens GIV. Al solicitar el estatus de proyecto \"Verificado\", podrás hacer que tu proyecto destaque y fomente más donaciones. Conseguir que su proyecto sea verificado también construye una relación de confianza con sus donantes al demostrar la legitimidad de su proyecto y mostrar que los fondos se están utilizando para crear un cambio positivo.", "label.verify_your_project.modal.three": "proceso de verificación ", @@ -1228,18 +1230,21 @@ "label.new_qr_code_needed": "Si no lo lograste a tiempo, necesitas generar un nuevo código QR.", "label.please_wait_for_you_donation_to_come_through": "¡Por favor espera a que tu donación se procese!", "label.please_wait": "Por favor espera", + "label.the_time_is_up": "Se acabó el tiempo.", "label.the_community_of_makers": "La comunidad de creadores", "page.project.we_are_supporting_stellar": "Este proyecto admite donaciones en Stellar", "page.project.you_can_try_donating": "Prueba a hacer donaciones usando la Red Stellar.", "page.project.donate_with_stellar": "Dona con Stellar", "label.try_donating_wuth_stellar": "Intenta donar con Stellar.", "label.check_donations": "Verificar donaciones", + "label.check_donation": "Verificar donación", "error.enter_amount": "La cantidad debe ser mayor que 0", "label.enter_the_memo": "Introduce el memo", "label.be_carefull_some_exchanges": "¡Ten cuidado! Algunos intercambios y billeteras requieren Memo para financiar tu cuenta. Asegúrate de ingresarlo en el formulario si tu billetera admite un memo.", "label.the_donation_was_successful": "La donación fue exitosa. Guarda esta URL si deseas mantener un registro de tu donación.", "label.view_details": "Ver detalles", "label.transaction_link": "Enlace de la transacción", + "label.transaction_detail": "Detalles de la transacción", "label.your_transactions_have_been_submitted": "Tus transacciones han sido enviadas", "label.your_withdrawal_from_this_stream_balance_is_being_processed": "Tu retiro de este saldo de transmisión se está procesando.", "label.your_withdrawal_from_this_stream_balance_was_successful": "Tu retiro de este saldo de transmisión ha sido exitoso.", @@ -1296,6 +1301,8 @@ "label.we_need_a_bit_more_info": "¡Necesitamos un poco más de información!", "label.passport_connected": "Pasaporte conectado", "label.increase_passport_score": "Aumentar la puntuación del pasaporte", + "label.project_owner_address_detected": "Dirección del propietario del proyecto detectada", + "label.project_owner_cant_donate_to_own_project": "No puedes donar a un proyecto del que eres propietario. ¡Hay miles de proyectos en Giveth que buscan tu apoyo! Por favor, elige otro proyecto para donar.", "label.qf_donor_eligibility.banner.check_eligibility": "¡Haz que tus donaciones sean igualadas! Verifica tu unicidad con un clic.", "label.qf_donor_eligibility.banner.recheck_eligibility": "¡Haz que tus donaciones sean igualadas! Aumenta tu puntuación de Gitcoin Passport antes de", "label.qf_donor_eligibility.banner.more_info_needed": "¡Necesitamos un poco más de información para verificar tu elegibilidad para QF!", @@ -1609,18 +1616,18 @@ "partnerships": "Asociaciones", "peace-and-justice": "Paz & Justicia", "poverity": "Pobreza", - "project.givback_toast.description.non_verified_owner": "¡Tu proyecto puede ser elegible para ser 'verificado' como un proyecto de bien público en Giveth! Los proyectos verificados proporcionan recompensas a los donantes, tienen mayor visibilidad y oportunidades adicionales para recaudar fondos.", - "project.givback_toast.description.non_verified_owner_cancelled": "Sentimos escuchar que tu proyecto está cancelado. Actualmente no está listado en Giveth y la recaudación de fondos está detenida. Si alguna vez deseas revivirlo o empezar de nuevo, ¡estamos aquí para apoyar tu visión!", - "project.givback_toast.description.non_verified_owner_deactive": "¡Ups! Tu proyecto está actualmente en modo desactivado. No aparecerá en Giveth y la recaudación de fondos está pausada. ¡Reactivémoslo juntos y devolvamos tu causa al centro de atención!", - "project.givback_toast.description.non_verified_owner_draft": "¡No dejes que tu visión permanezca en modo borrador! Publica tu proyecto ahora para iniciar tu viaje y desbloquear el potencial de recaudar fondos más rápido. Cuanto antes compartas, antes tendrás un impacto.", - "project.givback_toast.description.non_verified_owner_incomplete": "¡No has enviado tu solicitud de verificación! Continúa completando tu solicitud y envíala para que el equipo de Giveth pueda revisar tu elegibilidad.", - "project.givback_toast.description.non_verified_owner_rejected_1": "Tu proyecto no cumplió con los criterios para la verificación. No te preocupes, aún puedes recaudar fondos en Giveth y participar en ciertas rondas de financiación cuadrática. Si deseas mejorar tu solicitud y volver a aplicar, por favor contacta", - "project.givback_toast.description.non_verified_owner_rejected_2": "o soporte de Discord para más instrucciones.", - "project.givback_toast.description.non_verified_owner_submitted": "¡Buenas noticias! Tu solicitud ha sido enviada y está en cola para ser revisada por nuestro equipo de verificación de bienes públicos. Te responderemos dentro de 1-2 semanas.", - "project.givback_toast.description.non_verified_public": "Actualmente, los GIVbacks solo se otorgan por donaciones realizadas a proyectos verificados en Ethereum. ¡Tu contribución sigue siendo importante, incluso si no genera GIVbacks!", - "project.givback_toast.description.verified_owner": "¡Impulsa tu proyecto para aumentar la cantidad de GIVbacks que reciben tus donantes por Ethereum y aumenta su visibilidad entre otros proyectos!", + "project.givback_toast.description.non_verified_owner": "¡Tu proyecto puede ser elegible para convertirse en Elegible para GIVbacks por ser un proyecto de bien público en Giveth! Los proyectos elegibles para GIVbacks proporcionan recompensas a los donantes, tienen mayor visibilidad y oportunidades adicionales para recaudar fondos.", + "project.givback_toast.description.non_verified_owner_cancelled": "Este proyecto ha violado uno o más de los Términos de Servicio o políticas de aseguramiento de calidad de Giveth. Si crees que esto fue un error, contáctanos a través de Discord.", + "project.givback_toast.description.non_verified_owner_deactive": "Tu proyecto está actualmente desactivado. No aparecerá en la lista de proyectos y no puede recibir donaciones. Puedes reactivar tu proyecto en cualquier momento.", + "project.givback_toast.description.non_verified_owner_draft": "Tu proyecto aún es un borrador. Publica tu proyecto ahora para que los donantes descubran tu proyecto y hagan donaciones. ¡Cuanto antes lo compartas, antes podrás empezar a recaudar fondos!", + "project.givback_toast.description.non_verified_owner_incomplete": "¡Tu solicitud de elegibilidad para GIVbacks está incompleta y requiere más información! Rellena la información faltante y envíala para que el equipo de Giveth pueda revisar tu elegibilidad.", + "project.givback_toast.description.non_verified_owner_rejected_1": "Tu proyecto no cumplió con los criterios para la elegibilidad de GIVbacks. No te preocupes, aún puedes recaudar fondos en Giveth y participar en ciertas rondas de financiación cuadrática. Si deseas mejorar tu solicitud y volver a aplicar, por favor contacta a ", + "project.givback_toast.description.non_verified_owner_rejected_2": " o al soporte de Discord para más instrucciones.", + "project.givback_toast.description.non_verified_owner_submitted": "¡Noticias emocionantes! Tu solicitud ha sido enviada y está en la cola para ser revisada por nuestro equipo de revisión de elegibilidad para GIVbacks. Te responderemos en un plazo de 1-2 semanas.", + "project.givback_toast.description.non_verified_public": "Actualmente, los GIVbacks solo se otorgan por donaciones hechas a proyectos elegibles para GIVbacks en Ethereum. ¡Tu contribución sigue siendo importante, incluso si no genera GIVbacks!", + "project.givback_toast.description.verified_owner": "Impulsa tu proyecto para aumentar la cantidad de GIVbacks que reciben tus donantes en Ethereum y aumentar su visibilidad entre otros proyectos.", "project.givback_toast.description.verified_owner.note": "Como propietario de este proyecto, no recibirás GIVbacks por donar a él.", - "project.givback_toast.description.verified_public": "Los donaciones en Ethereum a proyectos verificados son recompensados con GIV! Impulsa este proyecto para aumentar su porcentaje de recompensas y hacerlo más visible en la página de proyectos.", + "project.givback_toast.description.verified_public": "Las donaciones en Ethereum a proyectos elegibles para GIVbacks son recompensadas con GIV. ¡Impulsa este proyecto para aumentar su porcentaje de recompensas y hacerlo más visible en la página de proyectos!", "project.givback_toast.title.non_verified_owner": "¿Tu proyecto está creando o apoyando bienes públicos?", "project.givback_toast.title.non_verified_owner_cancelled": "Estado Cancelado", "project.givback_toast.title.non_verified_owner_deactive": "Modo Desactivado", diff --git a/package.json b/package.json index c51b98d34c..2c14a02ee4 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "cypress": "cypress open" }, "resolutions": { - "styled-components": "^6", + "styled-components": "^6.1.12", "@types/react": "^18.0.15", "@types/react-dom": "^18.0.6" }, @@ -68,7 +68,7 @@ "react-share": "^5.0.3", "sharp": "^0.33.3", "siwe": "^2.3.2", - "styled-components": "^6.1.11", + "styled-components": "^6.1.12", "swiper": "^11.1.3", "unsplash-js": "^7.0.19", "viem": "^2.16.1", diff --git a/pages/transaction/[id]/index.tsx b/pages/transaction/[id]/index.tsx new file mode 100644 index 0000000000..5de8d1c5a5 --- /dev/null +++ b/pages/transaction/[id]/index.tsx @@ -0,0 +1,8 @@ +import React from 'react'; +import TransactionView from '@/components/views/transaction/Transaction.view'; + +const TransactionRoute = () => { + return ; +}; + +export default TransactionRoute; diff --git a/src/apollo/gql/gqlProjects.ts b/src/apollo/gql/gqlProjects.ts index e3559d5429..2b59212024 100644 --- a/src/apollo/gql/gqlProjects.ts +++ b/src/apollo/gql/gqlProjects.ts @@ -491,8 +491,16 @@ export const UPLOAD_IMAGE = gql` `; export const WALLET_ADDRESS_IS_VALID = gql` - query WalletAddressIsValid($address: String!) { - walletAddressIsValid(address: $address) + query WalletAddressIsValid( + $address: String! + $chainType: String + $memo: String + ) { + walletAddressIsValid( + address: $address + chainType: $chainType + memo: $memo + ) } `; diff --git a/src/components/VerificationBadge.tsx b/src/components/VerificationBadge.tsx index f95eddf7f9..265e9cc5f8 100644 --- a/src/components/VerificationBadge.tsx +++ b/src/components/VerificationBadge.tsx @@ -22,7 +22,7 @@ const VerificationBadge: FC = ({ isVerified, verificationStatus }) => { badgeStatus = EBadgeStatus.GIVETH; break; case EVerificationStatus.VERIFIED: - label = 'Verified'; + label = 'Eligible'; badgeStatus = EBadgeStatus.SUCCESS; break; case EVerificationStatus.DRAFT: @@ -30,7 +30,7 @@ const VerificationBadge: FC = ({ isVerified, verificationStatus }) => { badgeStatus = EBadgeStatus.WARNING; break; default: - label = 'Not Verified'; + label = 'Ineligible'; badgeStatus = EBadgeStatus.ERROR; } return ; diff --git a/src/components/menu/FilterMenu.tsx b/src/components/menu/FilterMenu.tsx index a5c0740287..a7baeb5d9a 100644 --- a/src/components/menu/FilterMenu.tsx +++ b/src/components/menu/FilterMenu.tsx @@ -65,10 +65,10 @@ const fundsFilter = [ label: 'Polygon ZKEVM', value: EProjectsFilter.ACCEPT_FUND_ON_ZKEVM, }, - // { - // label: 'Stellar', - // value: EProjectsFilter.ACCEPT_FUND_ON_STELLAR, - // }, + { + label: 'Stellar', + value: EProjectsFilter.ACCEPT_FUND_ON_STELLAR, + }, ]; fundsFilter.push({ diff --git a/src/components/modals/Boost/BoostedInnerModal.tsx b/src/components/modals/Boost/BoostedInnerModal.tsx index 8ef1e12d67..5749ee5570 100644 --- a/src/components/modals/Boost/BoostedInnerModal.tsx +++ b/src/components/modals/Boost/BoostedInnerModal.tsx @@ -89,7 +89,7 @@ const Desc = styled(Lead)` const SeeGivPowerAllocationsButton = styled(CustomButtonLink)` &:hover { - color: ${brandColors.pinky[600]}; + color: ${brandColors.pinky[600]} !important; } `; diff --git a/src/components/modals/DonateWrongNetwork.tsx b/src/components/modals/DonateWrongNetwork.tsx index 2d88a6dd99..d06945db60 100644 --- a/src/components/modals/DonateWrongNetwork.tsx +++ b/src/components/modals/DonateWrongNetwork.tsx @@ -46,7 +46,7 @@ const networks = [ config.SOLANA_CONFIG, config.BASE_CONFIG, config.ZKEVM_CONFIG, - // config.STELLAR_CONFIG, + config.STELLAR_CONFIG, ]; export const DonateWrongNetwork: FC = props => { diff --git a/src/components/modals/DonationByProjectOwner.tsx b/src/components/modals/DonationByProjectOwner.tsx new file mode 100644 index 0000000000..62978d202b --- /dev/null +++ b/src/components/modals/DonationByProjectOwner.tsx @@ -0,0 +1,138 @@ +import React from 'react'; +import { + brandColors, + Button, + IconAlertTriangleFilled32, + Lead, + neutralColors, +} from '@giveth/ui-design-system'; +import styled from 'styled-components'; +import { useIntl } from 'react-intl'; +import { useRouter } from 'next/router'; +import { Modal } from '@/components/modals/Modal'; +import Routes from '@/lib/constants/Routes'; +import { mediaQueries } from '@/lib/constants/constants'; +import { useModalAnimation } from '@/hooks/useModalAnimation'; + +// Define the props interface +interface DonationByProjectOwnerProps { + setShowDonationByProjectOwner: ( + showDonationByProjectOwner: boolean, + ) => void; +} + +export const DonationByProjectOwner: React.FC = ({ + setShowDonationByProjectOwner, +}) => { + const { formatMessage } = useIntl(); + const router = useRouter(); + const { closeModal } = useModalAnimation(setShowDonationByProjectOwner); + + const navigateToAllProjects = () => { + router.push(Routes.AllProjects); + closeModal(); + }; + + return ( + } + doNotCloseOnClickOutside + > + + + + {formatMessage({ + id: 'label.project_owner_cant_donate_to_own_project', + })} + + + + + + + + ); +}; + +const ModalContainer = styled.div` + background: white; + color: black; + padding: 24px 24px 38px; + margin: 0; + width: 100%; + + ${mediaQueries.tablet} { + width: 494px; + } +`; + +const ModalBox = styled.div` + color: ${brandColors.deep[900]}; + + > :first-child { + margin-bottom: 8px; + } + + h3 { + margin-top: -5px; + } + + h6 { + color: ${neutralColors.gray[700]}; + margin-top: -5px; + } + + > :last-child { + margin: 12px 0 32px 0; + + > span { + font-weight: 500; + } + } +`; + +const ModalButton = styled(Button)` + background: ${props => + props.disabled ? brandColors.giv[200] : brandColors.giv[500]}; + + &:hover:enabled { + background: ${brandColors.giv[700]}; + } + + :disabled { + cursor: not-allowed; + } + + > :first-child > div { + border-top: 3px solid ${brandColors.giv[200]}; + animation-timing-function: linear; + } + + text-transform: uppercase; +`; + +const Buttons = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + + > :first-child { + margin: 15px 0; + } +`; + +export default DonationByProjectOwner; diff --git a/src/components/modals/ManageProjectAddresses/AddNewAddress.tsx b/src/components/modals/ManageProjectAddresses/AddNewAddress.tsx index 11886b3325..841b9f0640 100644 --- a/src/components/modals/ManageProjectAddresses/AddNewAddress.tsx +++ b/src/components/modals/ManageProjectAddresses/AddNewAddress.tsx @@ -152,6 +152,7 @@ export const AddNewAddress: FC = ({ placeholder={formatMessage({ id: 'label.enter_the_memo', })} + maxLength={28} /> )} {errors.address && ( diff --git a/src/components/views/create/CreateProject.tsx b/src/components/views/create/CreateProject.tsx index 98cf89dc7e..e1507dcaf8 100644 --- a/src/components/views/create/CreateProject.tsx +++ b/src/components/views/create/CreateProject.tsx @@ -349,6 +349,17 @@ const CreateProject: FC = ({ project }) => { return; } + // replace memo with undefined if it is not a stellar chain or if it is a stellar chain but memo is empty + addresses.forEach(address => { + if ( + address.chainType !== ChainType.STELLAR || + !address.memo || + address.memo === '' + ) { + address.memo = undefined; + } + }); + const projectData: IProjectCreation = { title: name, description: description!, diff --git a/src/components/views/create/WalletAddressInput.tsx b/src/components/views/create/WalletAddressInput.tsx index ef1325a187..a2e33e62d6 100644 --- a/src/components/views/create/WalletAddressInput.tsx +++ b/src/components/views/create/WalletAddressInput.tsx @@ -95,6 +95,14 @@ const WalletAddressInput: FC = ({ const isProjectPrevAddress = (newAddress: string) => { // Do not validate if the input address is the same as project prev wallet address if (userAddresses.length === 0) return false; + if (isStellarChain) { + const isAddressMatch = userAddresses.some( + address => + address === newAddress && + (!memoValue || memoValue === prevMemo), + ); + return isAddressMatch; + } return userAddresses .map(prevAddress => prevAddress.toLowerCase()) .includes(newAddress.toLowerCase()); @@ -111,7 +119,7 @@ const WalletAddressInput: FC = ({ else throw formatMessage({ id: 'label.invalid_ens_address' }); }; - const addressValidation = async (address?: string) => { + const addressValidation = async (address?: string, memo?: string) => { try { setError({ ...error, message: '' }); setResolvedENS(undefined); @@ -151,7 +159,11 @@ const WalletAddressInput: FC = ({ { type: 'ETH' }, ); } - const res = await gqlAddressValidation(_address); + const res = await gqlAddressValidation({ + address: _address, + chainType, + memo: isStellarChain ? memo : undefined, + }); setIsValidating(false); return res; } catch (e: any) { @@ -180,16 +192,16 @@ const WalletAddressInput: FC = ({ useEffect(() => { //We had an issue with onBlur so when the user clicks on submit exactly after filling the address, then process of address validation began, so i changed it to this. - if (walletAddressValue === prevAddress) + if (walletAddressValue === prevAddress && memoValue === prevMemo) setError({ ...error, message: '' }); - addressValidation(walletAddressValue).then(res => { + addressValidation(walletAddressValue, memoValue).then(res => { if (res === true) { setError({ ...error, message: '' }); return; } setError({ ...error, message: res }); }); - }, [walletAddressValue]); + }, [walletAddressValue, memoValue]); const [inputRef] = useFocus(); @@ -234,15 +246,6 @@ const WalletAddressInput: FC = ({ !error.message || !walletAddressValue ? undefined : error } /> - {delayedIsAddressUsed && ( - - )} {isStellarChain && ( <>
@@ -255,9 +258,22 @@ const WalletAddressInput: FC = ({ size={InputSize.LARGE} value={memoValue} onChange={e => setMemoValue(e.target.value)} + maxLength={28} /> )} + {delayedIsAddressUsed && ( + + )} {delayedResolvedENS && ( { try { @@ -19,11 +20,19 @@ export const gqlTitleValidation = async (title: string, locale: string) => { } }; -export const gqlAddressValidation = async (address: string) => { +export const gqlAddressValidation = async ({ + address, + chainType, + memo, +}: { + address: string; + chainType?: ChainType; + memo?: string; +}) => { try { const { data } = await client.query({ query: WALLET_ADDRESS_IS_VALID, - variables: { address }, + variables: { address, chainType, memo }, }); return data.walletAddressIsValid; } catch (error: any) { diff --git a/src/components/views/donate/DonateIndex.tsx b/src/components/views/donate/DonateIndex.tsx index a8de6ce984..9758a8e374 100644 --- a/src/components/views/donate/DonateIndex.tsx +++ b/src/components/views/donate/DonateIndex.tsx @@ -1,4 +1,4 @@ -import React, { FC, useEffect } from 'react'; +import React, { FC, useEffect, useState } from 'react'; import styled from 'styled-components'; import { Col, @@ -24,7 +24,7 @@ import { EContentType } from '@/lib/constants/shareContent'; import { PassportBanner } from '@/components/PassportBanner'; import { useAlreadyDonatedToProject } from '@/hooks/useAlreadyDonatedToProject'; import { Shadow } from '@/components/styled-components/Shadow'; -import { useAppDispatch } from '@/features/hooks'; +import { useAppDispatch, useAppSelector } from '@/features/hooks'; import { setShowHeader } from '@/features/general/general.slice'; import { DonateHeader } from './DonateHeader'; import { DonationCard, ETabs } from './DonationCard'; @@ -34,10 +34,18 @@ import ProjectCardImage from '@/components/project-card/ProjectCardImage'; import { useGeneralWallet } from '@/providers/generalWalletProvider'; import { DonatePageProjectDescription } from './DonatePageProjectDescription'; import { getActiveRound } from '@/helpers/qf'; +import QRDonationDetails from './OnTime/SelectTokenModal/QRCodeDonation/QRDonationDetails'; import InlineToast, { EToastType } from '@/components/toasts/InlineToast'; +import { client } from '@/apollo/apolloClient'; +import { FETCH_DONATION_BY_ID } from '@/apollo/gql/gqlDonations'; +import { IDonation, IWalletAddress } from '@/apollo/types/types'; +import config from '@/configuration'; +import { ChainType } from '@/types/config'; import { useQRCodeDonation } from '@/hooks/useQRCodeDonation'; import EndaomentProjectsInfo from '@/components/views/project/EndaomentProjectsInfo'; import { IDraftDonation } from '@/apollo/types/gqlTypes'; +import StorageLabel from '@/lib/localStorage'; +import DonationByProjectOwner from '@/components/modals/DonationByProjectOwner'; const DonateIndex: FC = () => { const { formatMessage } = useIntl(); @@ -48,20 +56,25 @@ const DonateIndex: FC = () => { qrDonationStatus, draftDonationData, hasActiveQFRound, - // setSuccessDonation, + setSuccessDonation, setQRDonationStatus, setDraftDonationData, + setPendingDonationExists, startTimer, } = useDonateData(); - const { renewExpirationDate } = useQRCodeDonation(); + const { renewExpirationDate, retrieveDraftDonation } = + useQRCodeDonation(project); + const { isSignedIn, isEnabled } = useAppSelector(state => state.user); const alreadyDonated = useAlreadyDonatedToProject(project); + const { userData } = useAppSelector(state => state.user); + const [showDonationByProjectOwner, setShowDonationByProjectOwner] = + useState(false); const dispatch = useAppDispatch(); const isSafeEnv = useIsSafeEnvironment(); const { isOnSolana } = useGeneralWallet(); const router = useRouter(); const { chainId } = useAccount(); - const [showQRCode, setShowQRCode] = React.useState( !!router.query.draft_donation, ); @@ -74,6 +87,51 @@ const DonateIndex: FC = () => { }; }, [dispatch]); + useEffect(() => { + setShowDonationByProjectOwner( + userData?.id !== undefined && userData?.id === project.adminUser.id, + ); + }, [userData?.id, project.adminUser]); + + useEffect(() => { + const fetchDonation = async () => { + if (qrDonationStatus === 'success') { + const { + data: { getDonationById }, + } = (await client.query({ + query: FETCH_DONATION_BY_ID, + variables: { + id: Number(draftDonationData?.matchedDonationId), + }, + fetchPolicy: 'no-cache', + })) as { data: { getDonationById: IDonation } }; + + if (!getDonationById) return; + + const { transactionId, isTokenEligibleForGivback } = + getDonationById; + + if (!transactionId) return; + + setSuccessDonation({ + txHash: [ + { + txHash: transactionId, + chainType: ChainType.STELLAR, + }, + ], + givBackEligible: + isTokenEligibleForGivback && + project.verified && + isSignedIn && + isEnabled, + chainId: config.STELLAR_NETWORK_NUMBER, + }); + } + }; + fetchDonation(); + }, [qrDonationStatus]); + const isRecurringTab = router.query.tab?.toString() === ETabs.RECURRING; const { activeStartedRound } = getActiveRound(project.qfRounds); const isOnEligibleNetworks = @@ -83,18 +141,62 @@ const DonateIndex: FC = () => { const updateQRCode = async () => { if (!draftDonationData?.id) return; - const expiresAt = await renewExpirationDate(draftDonationData?.id); - setDraftDonationData((prev: IDraftDonation | null) => { - if (!prev) return null; - return { - ...prev, - status: 'pending', - expiresAt: expiresAt?.toString() ?? undefined, - }; - }); - setQRDonationStatus('waiting'); - const stopTimerFun = startTimer?.(new Date(expiresAt!)); - setStopTimer(() => stopTimerFun); + const draftDonations = localStorage.getItem( + StorageLabel.DRAFT_DONATIONS, + ); + + const parsedLocalStorageItem = JSON.parse(draftDonations!); + + const projectAddress: IWalletAddress | undefined = + project.addresses?.find( + address => address.chainType === ChainType.STELLAR, + ); + let draftDonationId = parsedLocalStorageItem + ? parsedLocalStorageItem[projectAddress?.address!] + : null; + + const retDraftDonation = !!draftDonationId + ? await retrieveDraftDonation(Number(draftDonationId)) + : null; + + if (retDraftDonation && retDraftDonation.status === 'pending') { + setPendingDonationExists?.(true); + parsedLocalStorageItem[projectAddress?.address!] = + retDraftDonation.id; + localStorage.setItem( + StorageLabel.DRAFT_DONATIONS, + JSON.stringify(parsedLocalStorageItem), + ); + router.push( + { + query: { + ...router.query, + draft_donation: retDraftDonation.id, + }, + }, + undefined, + { shallow: true }, + ); + } else { + const expiresAt = await renewExpirationDate(draftDonationData?.id); + setDraftDonationData((prev: IDraftDonation | null) => { + if (!prev) return null; + return { + ...prev, + status: 'pending', + expiresAt: expiresAt?.toString() ?? undefined, + }; + }); + parsedLocalStorageItem[projectAddress?.address!] = + draftDonationData.id; + localStorage.setItem( + StorageLabel.DRAFT_DONATIONS, + JSON.stringify(parsedLocalStorageItem), + ); + setQRDonationStatus('waiting'); + const stopTimerFun = startTimer?.(new Date(expiresAt!)); + setStopTimer(() => stopTimerFun); + } }; useEffect(() => { @@ -102,6 +204,12 @@ const DonateIndex: FC = () => { else setStopTimer(() => undefined); }, [showQRCode]); + useEffect(() => { + if (qrDonationStatus === 'failed') { + stopTimer?.(); + } + }, [qrDonationStatus]); + return successDonation ? ( <> @@ -113,6 +221,13 @@ const DonateIndex: FC = () => { <> + {showDonationByProjectOwner && ( + + )} {alreadyDonated && ( @@ -135,29 +250,34 @@ const DonateIndex: FC = () => { /> - - {/* {showQRCode ? ( + + {showQRCode ? ( - ) : ( */} - <> - - - - - {!isMobile ? ( - (!isRecurringTab && hasActiveQFRound) || - (isRecurringTab && isOnEligibleNetworks) ? ( - - ) : ( - + + + - ) - ) : null} - - {/* )} */} + + {!isMobile ? ( + (!isRecurringTab && hasActiveQFRound) || + (isRecurringTab && + isOnEligibleNetworks) ? ( + + ) : ( + + ) + ) : null} + + )} {isFailedOperation && ( diff --git a/src/components/views/donate/DonationCard.tsx b/src/components/views/donate/DonationCard.tsx index e4826bb464..7495dc964f 100644 --- a/src/components/views/donate/DonationCard.tsx +++ b/src/components/views/donate/DonationCard.tsx @@ -12,7 +12,7 @@ import config from '@/configuration'; import { useDonateData } from '@/context/donate.context'; import { ChainType } from '@/types/config'; import { IconWithTooltip } from '@/components/IconWithToolTip'; -// import { QRDonationCard } from './OnTime/SelectTokenModal/QRCodeDonation/QRDonationCard'; +import { QRDonationCard } from './OnTime/SelectTokenModal/QRCodeDonation/QRDonationCard'; import { client } from '@/apollo/apolloClient'; import { PROJECT_ACCEPTED_TOKENS } from '@/apollo/gql/gqlProjects'; import { showToastError } from '@/lib/helpers'; @@ -90,48 +90,34 @@ export const DonationCard: FC = ({ }); }, []); + // Check if the 'tab' query parameter is not present in the URL and project 'hasOpAddress' is true. + // If both conditions are met, set the active tab to 'RECURRING' using the setTab function. + // This ensures that the 'RECURRING' tab is active by default if project has Op Address. + useEffect(() => { + if (!router.query.tab && hasOpAddress) { + setTab(ETabs.RECURRING); + } + }, [router.query, hasOpAddress]); + return ( - {/* {!isQRDonation ? ( */} - <> - - {formatMessage({ - id: 'label.how_do_you_want_to_donate', - })} - - - { - setTab(ETabs.ONE_TIME); - router.push( - { - query: { - ...router.query, - tab: ETabs.ONE_TIME, - }, - }, - undefined, - { shallow: true }, - ); - }} - > + {!isQRDonation ? ( + <> + {formatMessage({ - id: 'label.one_time_donation', + id: 'label.how_do_you_want_to_donate', })} - </Tab> - {!disableRecurringDonations && - hasOpAddress && - isOwnerOnEVM ? ( + + { - setTab(ETabs.RECURRING); + setTab(ETabs.ONE_TIME); router.push( { query: { ...router.query, - tab: ETabs.RECURRING, + tab: ETabs.ONE_TIME, }, }, undefined, @@ -140,49 +126,72 @@ export const DonationCard: FC = ({ }} > {formatMessage({ - id: 'label.recurring_donation', + id: 'label.one_time_donation', })} - ) : ( - !disableRecurringDonations && ( - + {!disableRecurringDonations && + hasOpAddress && + isOwnerOnEVM ? ( + { + setTab(ETabs.RECURRING); + router.push( + { + query: { + ...router.query, + tab: ETabs.RECURRING, + }, + }, + undefined, + { shallow: true }, + ); + }} + > + {formatMessage({ + id: 'label.recurring_donation', + })} + + ) : ( + !disableRecurringDonations && ( + + {formatMessage({ + id: 'label.recurring_donation', + })} + + } + direction='bottom' + > + <> {formatMessage({ - id: 'label.recurring_donation', + id: 'label.this_project_is_not_eligible_for_recurring_donations', })} - - } - direction='bottom' - > - <> - {formatMessage({ - id: 'label.this_project_is_not_eligible_for_recurring_donations', - })} - - - ) - )} - - - - {tab === ETabs.ONE_TIME && ( - - )} - {tab === ETabs.RECURRING && } - - - {/* // ) : ( - // - // )} */} + + + ) + )} + + + + {tab === ETabs.ONE_TIME && ( + + )} + {tab === ETabs.RECURRING && } + + + ) : ( + + )} ); }; diff --git a/src/components/views/donate/DonationInfo.tsx b/src/components/views/donate/DonationInfo.tsx index eeb6a9cc34..a66c986fda 100644 --- a/src/components/views/donate/DonationInfo.tsx +++ b/src/components/views/donate/DonationInfo.tsx @@ -54,9 +54,10 @@ const TxRow = ({ export const DonationInfo = () => { const { formatMessage } = useIntl(); - const { successDonation, project } = useDonateData(); + const { successDonation, project, draftDonationData } = useDonateData(); const { txHash = [] } = successDonation || {}; const hasMultipleTxs = txHash.length > 1; + const isStellar = txHash[0]?.chainType === ChainType.STELLAR; return ( @@ -64,6 +65,24 @@ export const DonationInfo = () => { {formatMessage({ id: 'label.your_transactions_have_been_submitted', })} + {isStellar && ( + + {' '} + + window.open( + Routes.Invoice + + '/' + + draftDonationData?.id, + '_blank', + ) + } + > + {formatMessage({ id: 'label.check_donation' })}{' '} + + + + )}
{formatMessage({ id: 'label.you_can_view_them_on_a_blockchain_explorer_here', @@ -110,3 +129,12 @@ const TxLink = styled(Lead)` color: ${neutralColors.gray[700]}; } `; + +const CheckDonation = styled.span` + display: inline-flex; + gap: 8px; + align-items: center; + cursor: pointer; + text-transform: capitalize; + color: ${brandColors.pinky[500]} !important; +`; diff --git a/src/components/views/donate/OnTime/DonateModal.tsx b/src/components/views/donate/OnTime/DonateModal.tsx index 2335b9ec6a..fd9b8b3654 100644 --- a/src/components/views/donate/OnTime/DonateModal.tsx +++ b/src/components/views/donate/OnTime/DonateModal.tsx @@ -40,9 +40,7 @@ import { calcDonationShare } from '@/components/views/donate/helpers'; import { Spinner } from '@/components/Spinner'; import { FETCH_GIVETH_PROJECT_BY_ID } from '@/apollo/gql/gqlProjects'; import createGoogleTagEventPurchase from '@/helpers/googleAnalytics'; -import { isWalletSanctioned } from '@/services/donation'; import SanctionModal from '@/components/modals/SanctionedModal'; -import { ORGANIZATION } from '@/lib/constants/organizations'; interface IDonateModalProps extends IModal { token: IProjectAcceptedToken; @@ -152,38 +150,20 @@ const DonateModal: FC = props => { // this function is used to validate the token and check if the wallet is sanctioned const validateTokenThenDonate = async () => { setDonating(true); - try { - if ( - project?.organization?.label === ORGANIZATION.endaoment && - address - ) { - // We just need to check if the wallet is sanctioned for endaoment projects - const sanctioned = await isWalletSanctioned(address); - if (sanctioned) { - setIsSanctioned(true); - setDonating(false); - return; + client + .query({ + query: VALIDATE_TOKEN, + fetchPolicy: 'no-cache', + }) + .then((res: IMeGQL) => { + const _address = res.data?.me?.walletAddress; + if (compareAddresses(_address, address)) { + handleDonate(); + } else { + handleFailedValidation(); } - } - - client - .query({ - query: VALIDATE_TOKEN, - fetchPolicy: 'no-cache', - }) - .then((res: IMeGQL) => { - const _address = res.data?.me?.walletAddress; - if (compareAddresses(_address, address)) { - handleDonate(); - } else { - handleFailedValidation(); - } - }) - .catch(handleFailedValidation); - } catch (error) { - setDonating(false); - showToastError('Error validating wallet address'); - } + }) + .catch(handleFailedValidation); }; const handleFailedValidation = () => { diff --git a/src/components/views/donate/OnTime/OneTimeDonationCard.tsx b/src/components/views/donate/OnTime/OneTimeDonationCard.tsx index 6336035696..f977521755 100644 --- a/src/components/views/donate/OnTime/OneTimeDonationCard.tsx +++ b/src/components/views/donate/OnTime/OneTimeDonationCard.tsx @@ -23,12 +23,12 @@ import config from '@/configuration'; import InlineToast, { EToastType } from '@/components/toasts/InlineToast'; import { EProjectStatus } from '@/apollo/types/gqlEnums'; +import { truncateToDecimalPlaces } from '@/lib/helpers'; +import { IProjectAcceptedToken } from '@/apollo/types/gqlTypes'; import { calcDonationShare, prepareTokenList, } from '@/components/views/donate/helpers'; -import { truncateToDecimalPlaces } from '@/lib/helpers'; -import { IProjectAcceptedToken } from '@/apollo/types/gqlTypes'; import GIVBackToast from '@/components/views/donate/GIVBackToast'; import { DonateWrongNetwork } from '@/components/modals/DonateWrongNetwork'; import { useAppDispatch, useAppSelector } from '@/features/hooks'; @@ -58,6 +58,8 @@ import { TokenIcon } from '../TokenIcon/TokenIcon'; import { SelectTokenModal } from './SelectTokenModal/SelectTokenModal'; import { Spinner } from '@/components/Spinner'; import { useSolanaBalance } from '@/hooks/useSolanaBalance'; +import { isWalletSanctioned } from '@/services/donation'; +import SanctionModal from '@/components/modals/SanctionedModal'; const CryptoDonation: FC<{ setIsQRDonation: (isQRDonation: boolean) => void; @@ -95,6 +97,7 @@ const CryptoDonation: FC<{ const [showDonateModal, setShowDonateModal] = useState(false); const [showInsufficientModal, setShowInsufficientModal] = useState(false); const [showChangeNetworkModal, setShowChangeNetworkModal] = useState(false); + const [isSanctioned, setIsSanctioned] = useState(false); const [acceptedChains, setAcceptedChains] = useState( [], ); @@ -146,6 +149,10 @@ const CryptoDonation: FC<{ address => address.chainType === ChainType.STELLAR, ); + useEffect(() => { + validateSanctions(); + }, [project, address]); + useEffect(() => { if ( (networkId || @@ -320,6 +327,17 @@ const CryptoDonation: FC<{ } }, [selectedTokenBalance, amount, selectedOneTimeToken?.address, gasfee]); + const validateSanctions = async () => { + if (project?.organization?.label === 'endaoment' && address) { + // We just need to check if the wallet is sanctioned for endaoment projects + const sanctioned = await isWalletSanctioned(address); + if (sanctioned) { + setIsSanctioned(true); + return; + } + } + }; + const amountErrorText = useMemo(() => { const totalAmount = Number(formatUnits(gasfee, tokenDecimals)).toFixed( 10, @@ -345,13 +363,20 @@ const CryptoDonation: FC<{ return ( + {isSanctioned && ( + { + setIsSanctioned(false); + }} + /> + )} {showQFModal && ( )} - {showChangeNetworkModal && acceptedChains && ( + {!isSanctioned && showChangeNetworkModal && acceptedChains && ( )} - {/* {hasStellarAddress && ( + {hasStellarAddress && ( {config.NETWORKS_CONFIG[ChainType.STELLAR]?.chainLogo(32)} {formatMessage({ id: 'label.try_donating_wuth_stellar', })} - )} */} + )} = ({ text }) => { + const [isAnimating, setIsAnimating] = useState(false); + + const copyToClipboard = () => { + navigator.clipboard.writeText(text); + setIsAnimating(true); + + setTimeout(() => { + setIsAnimating(false); + }, 300); + }; + + return ( + +

{text}

+ } + onClick={copyToClipboard} + isAnimating={isAnimating} + /> +
+ ); +}; + +const StyledCopyContainer = styled.div` + display: flex; + border: 1px solid ${neutralColors.gray[300]}; + flex-direction: column; + justify-content: space-between; + align-items: center; + border-radius: 8px; + gap: 16px; + padding: 16px; + width: 100%; + word-break: break-word; + overflow-wrap: break-word; + + ${mediaQueries.mobileL} { + flex-direction: row; + } +`; + +const animateButton = keyframes` + 0% { + transform: scale(1); + } + 50% { + transform: scale(1.1); + } + 100% { + transform: scale(1); + } +`; + +const StyledCopyButton = styled(Button)<{ isAnimating: boolean }>` + box-shadow: ${Shadow.Neutral[400]}; + ${props => + props.isAnimating && + css` + animation: ${animateButton} 0.3s; + `} +`; + +export default CopyContainer; diff --git a/src/components/views/donate/OnTime/SelectTokenModal/QRCodeDonation/QRDonationCard.tsx b/src/components/views/donate/OnTime/SelectTokenModal/QRCodeDonation/QRDonationCard.tsx new file mode 100644 index 0000000000..745cf1a89d --- /dev/null +++ b/src/components/views/donate/OnTime/SelectTokenModal/QRCodeDonation/QRDonationCard.tsx @@ -0,0 +1,451 @@ +import React, { FC, useEffect, useState } from 'react'; +import { useRouter } from 'next/router'; +import Image from 'next/image'; +import styled from 'styled-components'; +import { + B, + P, + Button, + Flex, + neutralColors, + IconArrowLeft, + mediaQueries, +} from '@giveth/ui-design-system'; +import { useIntl } from 'react-intl'; +import { formatUnits } from 'viem'; + +import { + InputWrapper, + SelectTokenWrapper, +} from '../../../Recurring/RecurringDonationCard'; +import { TokenIconWithGIVBack } from '../../../TokenIcon/TokenIconWithGIVBack'; +import { IProjectAcceptedToken } from '@/apollo/types/gqlTypes'; +import { fetchPriceWithCoingeckoId } from '@/services/token'; +import { ChainType } from '@/types/config'; +import config from '@/configuration'; +import { + truncateToDecimalPlaces, + capitalizeAllWords, + formatBalance, + showToastError, +} from '@/lib/helpers'; +import { IDonationCardProps } from '../../../DonationCard'; +import QRDonationCardContent from './QRDonationCardContent'; +import { useQRCodeDonation } from '@/hooks/useQRCodeDonation'; +import { useDonateData } from '@/context/donate.context'; +import { AmountInput } from '@/components/AmountInput/AmountInput'; +import StorageLabel from '@/lib/localStorage'; +import InlineToast, { EToastType } from '@/components/toasts/InlineToast'; +import { useAppSelector } from '@/features/hooks'; +import { useModalCallback } from '@/hooks/useModalCallback'; +import links from '@/lib/constants/links'; + +interface QRDonationCardProps extends IDonationCardProps { + qrAcceptedTokens: IProjectAcceptedToken[]; + setIsQRDonation: (isQRDonation: boolean) => void; +} + +const formatAmountToDisplay = (amount: bigint) => { + const decimals = 18; + return truncateToDecimalPlaces( + formatUnits(amount, decimals), + decimals / 3, + ).toString(); +}; + +export const QRDonationCard: FC = ({ + showQRCode, + qrAcceptedTokens, + setIsQRDonation, + setShowQRCode, +}) => { + const { formatMessage } = useIntl(); + const router = useRouter(); + const { isSignedIn, isEnabled } = useAppSelector(state => state.user); + const [showDonateModal, setShowDonateModal] = useState(false); + const { modalCallback: signInThenDonate } = useModalCallback(() => + setShowDonateModal(true), + ); + + const { + project, + setQRDonationStatus, + setDraftDonationData, + setPendingDonationExists, + fetchDraftDonation, + pendingDonationExists, + qrDonationStatus, + draftDonationData, + draftDonationLoading, + } = useDonateData(); + const { + createDraftDonation, + markDraftDonationAsFailed, + checkDraftDonationStatus, + retrieveDraftDonation, + } = useQRCodeDonation(project); + + const { addresses, id } = project; + const draftDonationId = Number(router.query.draft_donation!); + const [amount, setAmount] = useState(0n); + const [usdAmount, setUsdAmount] = useState('0.00'); + const [tokenPrice, setTokenPrice] = useState(0); + + const stellarToken = qrAcceptedTokens.find( + token => token.chainType === ChainType.STELLAR, + ); + const projectAddress = addresses?.find( + address => address.chainType === ChainType.STELLAR, + ); + + useEffect(() => { + const eventSource = new EventSource( + `${process.env.NEXT_PUBLIC_BASE_ROUTE}/events`, + ); + + const handleFetchDraftDonation = async (draftDonationId: number) => { + const draftDonation = await fetchDraftDonation?.(draftDonationId); + if (draftDonation?.status === 'matched') { + setQRDonationStatus('success'); + setDraftDonationData(draftDonation); + } + }; + + eventSource.onmessage = (event: MessageEvent) => { + const { data, type } = JSON.parse(event.data); + if ( + type === 'new-donation' && + data.draftDonationId === draftDonationId + ) { + handleFetchDraftDonation(draftDonationId); + } else if ( + type === 'draft-donation-failed' && + data.draftDonationId === draftDonationId + ) { + setQRDonationStatus('failed'); + } + }; + + eventSource.onerror = (error: Event) => { + console.error('EventSource failed:', error); + }; + + return () => { + eventSource.close(); + }; + }, [draftDonationId]); + + const goBack = async () => { + if (showQRCode) { + const draftDonation = + await checkDraftDonationStatus(draftDonationId); + if (draftDonation?.status === 'matched') { + setQRDonationStatus('success'); + setDraftDonationData(draftDonation); + return; + } + await markDraftDonationAsFailed(draftDonationId); + setPendingDonationExists?.(false); + setShowQRCode(false); + } else { + setIsQRDonation(false); + } + setQRDonationStatus('waiting'); + }; + + const handleNext = async () => { + if (isEnabled && !isSignedIn) { + signInThenDonate(); + } else { + const draftDonations = localStorage.getItem( + StorageLabel.DRAFT_DONATIONS, + ); + const parsedLocalStorageItem = JSON.parse(draftDonations!); + const projectAddress = project.addresses?.find( + address => address.chainType === ChainType.STELLAR, + ); + let draftDonationId = parsedLocalStorageItem + ? parsedLocalStorageItem[projectAddress?.address!] + : null; + + const retDraftDonation = draftDonationId + ? await retrieveDraftDonation(Number(draftDonationId)) + : null; + + if (retDraftDonation && retDraftDonation.status === 'pending') { + setPendingDonationExists?.(true); + } else { + if (!stellarToken?.symbol || !projectAddress?.address) return; + + try { + const payload = { + walletAddress: projectAddress.address, + projectId: Number(id), + amount: Number(formatAmountToDisplay(amount)), + token: stellarToken, + anonymous: isSignedIn && isEnabled ? false : true, + symbol: stellarToken.symbol, + setFailedModalType: () => {}, + useDonationBox: false, + chainId: stellarToken?.networkId, + memo: projectAddress.memo, + }; + + draftDonationId = await createDraftDonation(payload); + } catch (error) { + showToastError(error); + return; + } + setPendingDonationExists?.(false); + } + + if (draftDonationId) { + await router.push( + { + query: { + ...router.query, + draft_donation: draftDonationId, + }, + }, + undefined, + { shallow: true }, + ); + } + setShowQRCode(true); + } + }; + + const convertAmountToUSD = (amount: bigint) => { + if (!stellarToken || !tokenPrice) return '0.00'; + + const priceBigInt = BigInt(Math.floor(tokenPrice * 100)); + const amountInUsd = (amount * priceBigInt) / 100n; + return formatBalance(formatAmountToDisplay(amountInUsd)); + }; + + const calculateUsdAmount = (amount?: number) => { + if (!tokenPrice || !amount) return '0.00'; + + return formatBalance(amount * tokenPrice); + }; + + useEffect(() => { + setUsdAmount(convertAmountToUSD(amount)); + }, [amount, tokenPrice]); + + useEffect(() => { + const fetchTokenPrice = async () => { + const coingeckoChainId = + config.NETWORKS_CONFIG[ChainType.STELLAR].coingeckoChainName; + const price = await fetchPriceWithCoingeckoId(coingeckoChainId); + if (price) setTokenPrice(price); + }; + + fetchTokenPrice(); + }, []); + + return ( + <> + + + + + + {formatMessage({ + id: showQRCode + ? 'label.go_back_to_modify_your_donation' + : 'page.project.donate_with_stellar', + })} + + + {pendingDonationExists && ( + + )} + {!showQRCode && !isSignedIn && stellarToken?.isGivbackEligible && ( + + )} + {!showQRCode ? ( + <> + + + + + + { + config.NETWORKS_CONFIG[ + ChainType.STELLAR + ].name + }{' '} + ({stellarToken?.symbol}) + + + + + + $ {usdAmount} + + + + +

+ {formatMessage({ id: 'label.donating_to' })}{' '} + + {project.title || '--'} + +

+ {formatAmountToDisplay(amount)} +
+ + + {formatMessage({ + id: 'label.your_total_donation', + })} + + {formatAmountToDisplay(amount)} + +