diff --git a/src/api/getExchangeRate.ts b/src/api/getExchangeRate.ts new file mode 100644 index 0000000..89e0467 --- /dev/null +++ b/src/api/getExchangeRate.ts @@ -0,0 +1,33 @@ +import axios from "axios"; + +const symbolToCoinGeckoId: { [key: string]: string } = { + ETH: "ethereum", +}; + +export const getExchangeRate = async ( + currencySymbol: string +): Promise => { + try { + const response = await axios.get( + `https://api.coingecko.com/coins/${symbolToCoinGeckoId[currencySymbol]}`, + { + headers: { + "x-cg-pro-api-key": import.meta.env.VITE_COINGECKO_API_KEY, + }, + } + ); + console.log(response.data); + return response.data; + } catch (ex) { + console.error(ex); + const hardcodedRates = { + ETH: 1940.79, + DAI: 1, + CELO: 0.535419, + MATIC: 0.800984, + }; + return hardcodedRates[ + currencySymbol as keyof typeof hardcodedRates + ] as number; + } +}; diff --git a/src/components/DonationModal.tsx b/src/components/DonationModal.tsx new file mode 100644 index 0000000..69a7255 --- /dev/null +++ b/src/components/DonationModal.tsx @@ -0,0 +1,82 @@ +import { useState } from "react"; +import { + Button, + FormControl, + FormLabel, + Input, + Modal, + ModalBody, + ModalCloseButton, + ModalContent, + ModalFooter, + ModalHeader, + ModalOverlay, + Text, +} from "@chakra-ui/react"; +import { useAccountAbstraction } from "@/store"; +import { useQuery } from "@tanstack/react-query"; +import { getExchangeRate } from "@/api/getExchangeRate"; +import { parseEther } from "viem"; +import { useCleanifyContract } from "@/hooks"; + +type Props = { + isOpen: boolean; + onClose: () => void; + reportId: number; +}; + +export const DonationModal = ({ isOpen, onClose, reportId }: Props) => { + const [donationAmount, setDonationAmount] = useState(""); + + const { chain } = useAccountAbstraction(); + const coinSymbol = chain.nativeCurrency.symbol; + + const { data: exchangeRate } = useQuery({ + queryKey: ["exchangeRate", coinSymbol], + queryFn: () => getExchangeRate(coinSymbol), + }); + + const { contract } = useCleanifyContract(); + + const handleDonate = async () => { + const options = { + value: String(parseEther(donationAmount)), + }; + await contract.addRewards(reportId, options); + onClose(); + }; + + return ( + + + + Make a Donation + + + + Donation Amount ({coinSymbol}) + setDonationAmount(e.target.value)} + /> + + equivalent to: {Number(donationAmount) * (exchangeRate || 0)}$ + + + + + + + + + + ); +}; + +export default DonationModal; diff --git a/src/components/index.ts b/src/components/index.ts index ceab0de..50fc1cf 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -7,3 +7,4 @@ export * from "./Navbar"; export * from "./NetworkSelector"; export * from "./SafeInfo"; export * from "./MapComponent"; +export * from "./DonationModal"; diff --git a/src/hooks/useReportById.ts b/src/hooks/useReportById.ts index e099f7b..f22ad2f 100644 --- a/src/hooks/useReportById.ts +++ b/src/hooks/useReportById.ts @@ -1,32 +1,34 @@ -import { useReportMetadata } from "@hooks/useReportMetadata.ts" -import { BaseReport } from "@models/report.ts" -import { useEffect, useState } from "react" -import { useCleanifyContract } from "@hooks/useCleanifyContract.ts" +import { useReportMetadata } from "@hooks/useReportMetadata.ts"; +import { BaseReport } from "@models/report.ts"; +import { useEffect, useState } from "react"; +import { useCleanifyContract } from "@hooks/useCleanifyContract.ts"; export const useReportById = (id: number) => { + const { contract } = useCleanifyContract(); - const { contract } = useCleanifyContract() + const [baseReport, setBaseReport] = useState(); - const [baseReport, setBaseReport] = useState() + const { report } = useReportMetadata(baseReport); - const { report } = useReportMetadata(baseReport) - - useEffect(() => { + const getReport = async () => { if (contract) { - contract.reports(id).then((baseReport) => { + contract.getReportById(id).then((baseReport) => { setBaseReport({ id: baseReport.id.toNumber(), creator: baseReport.creator, metadata: baseReport.metadata, totalRewards: baseReport.totalRewards.toNumber(), state: baseReport.state, - }) - }) + }); + }); } - }, [id]) + }; + + useEffect(() => { + getReport(); + }, []); return { report, - } - -} + }; +}; diff --git a/src/models/report.ts b/src/models/report.ts index 64584b2..2100445 100644 --- a/src/models/report.ts +++ b/src/models/report.ts @@ -23,7 +23,7 @@ export type ReportMetadata = { analysis: AnalyzeImageResponse; }; -enum ReportState { +export enum ReportState { InReview, Available, PendingVerification, diff --git a/src/screens/Report.tsx b/src/screens/Report.tsx index fe86760..0063f50 100644 --- a/src/screens/Report.tsx +++ b/src/screens/Report.tsx @@ -1,49 +1,76 @@ -import { MapComponent } from "@/components"; +import { DonationModal, MapComponent } from "@/components"; import { Routes } from "@/router"; -import { Box, Button, HStack, Image, Text } from "@chakra-ui/react"; +import { + Box, + Button, + HStack, + Image, + Text, + useDisclosure, +} from "@chakra-ui/react"; import { useParams } from "react-router-dom"; -import {useReportById} from "@hooks/useReportById.ts" +import { useReportById } from "@hooks/useReportById.ts"; +import { ReportState } from "@/models/report"; export const Report = () => { const params = useParams(); + console.log("params.id", params.id); - const { report }= useReportById(Number(params.id)) - - console.log(params) + const { report } = useReportById(Number(params.id)); + console.log("report", report); + console.log(params); + const { + onOpen: onOpenDonationModal, + onClose: onCloseDonationModal, + isOpen: isOpenDonationModal, + } = useDisclosure(); if (!report) return null; + console.log("report.state", report.state); return ( - - - - - - - {report.metadata.name} - - - - - {report.metadata.analysis.description} - + <> + + + + + + + {report.metadata.name} + + + + + {report.metadata.analysis.description} + + + + + + - - - + + - - - - - + + + ); };