Skip to content

Commit

Permalink
feat: donation
Browse files Browse the repository at this point in the history
  • Loading branch information
Davide Carpini committed Nov 18, 2023
1 parent a444612 commit f8e902c
Show file tree
Hide file tree
Showing 6 changed files with 195 additions and 50 deletions.
33 changes: 33 additions & 0 deletions src/api/getExchangeRate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import axios from "axios";

const symbolToCoinGeckoId: { [key: string]: string } = {
ETH: "ethereum",
};

export const getExchangeRate = async (
currencySymbol: string
): Promise<number | void> => {
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;
}
};
82 changes: 82 additions & 0 deletions src/components/DonationModal.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<Modal isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent>
<ModalHeader>Make a Donation</ModalHeader>
<ModalCloseButton />
<ModalBody>
<FormControl>
<FormLabel>Donation Amount ({coinSymbol})</FormLabel>
<Input
type="number"
placeholder="Enter donation amount"
value={donationAmount}
onChange={(e) => setDonationAmount(e.target.value)}
/>
<Text pt={2}>
equivalent to: {Number(donationAmount) * (exchangeRate || 0)}$
</Text>
</FormControl>
</ModalBody>
<ModalFooter>
<Button colorScheme="blue" mr={3} onClick={handleDonate}>
Donate
</Button>
<Button variant="ghost" onClick={onClose}>
Cancel
</Button>
</ModalFooter>
</ModalContent>
</Modal>
);
};

export default DonationModal;
1 change: 1 addition & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ export * from "./Navbar";
export * from "./NetworkSelector";
export * from "./SafeInfo";
export * from "./MapComponent";
export * from "./DonationModal";
34 changes: 18 additions & 16 deletions src/hooks/useReportById.ts
Original file line number Diff line number Diff line change
@@ -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<BaseReport>();

const [baseReport, setBaseReport] = useState<BaseReport>()
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,
}

}
};
};
2 changes: 1 addition & 1 deletion src/models/report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export type ReportMetadata = {
analysis: AnalyzeImageResponse;
};

enum ReportState {
export enum ReportState {
InReview,
Available,
PendingVerification,
Expand Down
93 changes: 60 additions & 33 deletions src/screens/Report.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<HStack w={"full"} h={"full"}>
<Box h={"full"} w={"50%"} overflow={"auto"} pr={4}>
<Image src={report.metadata.images[0]} w={"full"} />
<Box py={4}>
<Box pb={2}>
<Text fontSize="lg" fontWeight={"bold"}>
{report.metadata.name}
</Text>
</Box>
<Box pb={6}>
<Text fontSize="md" textAlign={"justify"}>
{report.metadata.analysis.description}
</Text>
<>
<HStack w={"full"} h={"full"}>
<Box h={"full"} w={"50%"} overflow={"auto"} pr={4}>
<Image src={report.metadata.images[0]} w={"full"} />
<Box py={4}>
<Box pb={2}>
<Text fontSize="lg" fontWeight={"bold"}>
{report.metadata.name}
</Text>
</Box>
<Box pb={6}>
<Text fontSize="md" textAlign={"justify"}>
{report.metadata.analysis.description}
</Text>
</Box>
<Box pb={4} justifyContent={"center"} display={"flex"}>
<Button
colorScheme="blue"
mr={3}
onClick={onOpenDonationModal}
isDisabled={report.state !== ReportState.Available}
>
Donate
</Button>
<Button colorScheme="green">Clean</Button>
</Box>
</Box>
<Box pb={4} justifyContent={"center"} display={"flex"}>
<Button colorScheme="blue" mr={3}>
Fund the project
</Button>
<Button colorScheme="green">Clean</Button>
<Box h={"full"} w={"50%"}>
<MapComponent
defaultActiveReport={report.id}
defaultMapCenter={report.metadata.location}
route={Routes.Report}
/>
</Box>
</Box>
</Box>
<Box h={"full"} w={"50%"}>
<MapComponent
defaultActiveReport={report.id}
defaultMapCenter={report.metadata.location}
route={Routes.Report}
/>
</Box>
</HStack>
</HStack>
<DonationModal
isOpen={isOpenDonationModal}
onClose={onCloseDonationModal}
reportId={report.id}
/>
</>
);
};

0 comments on commit f8e902c

Please sign in to comment.