diff --git a/anonymousVoting/clientAnonymousVoting/public/assets/explorer.png b/anonymousVoting/clientAnonymousVoting/public/assets/explorer.png new file mode 100644 index 00000000..e69de29b diff --git a/anonymousVoting/clientAnonymousVoting/public/assets/image.png b/anonymousVoting/clientAnonymousVoting/public/assets/image.png new file mode 100644 index 00000000..418d600e Binary files /dev/null and b/anonymousVoting/clientAnonymousVoting/public/assets/image.png differ diff --git a/anonymousVoting/clientAnonymousVoting/src/App.js b/anonymousVoting/clientAnonymousVoting/src/App.js index 392a179e..952ecd75 100644 --- a/anonymousVoting/clientAnonymousVoting/src/App.js +++ b/anonymousVoting/clientAnonymousVoting/src/App.js @@ -1,4 +1,5 @@ import Navbar from './components/Navbar'; +import Explorer from "./components/Explorer"; import { BrowserRouter as Router, Route, Routes,Navigate } from 'react-router-dom' import 'bootstrap/dist/css/bootstrap.css'; @@ -31,6 +32,7 @@ function App() { // }else{ ret = + } /> } /> } /> } /> diff --git a/anonymousVoting/clientAnonymousVoting/src/components/ConnectWallet.js b/anonymousVoting/clientAnonymousVoting/src/components/ConnectWallet.js index 0cbecd89..8a6d5065 100644 --- a/anonymousVoting/clientAnonymousVoting/src/components/ConnectWallet.js +++ b/anonymousVoting/clientAnonymousVoting/src/components/ConnectWallet.js @@ -124,4 +124,4 @@ const ConnectWallet = () => { ); } -export default ConnectWallet; \ No newline at end of file +export default ConnectWallet; diff --git a/anonymousVoting/clientAnonymousVoting/src/components/CreateProcessPage.js b/anonymousVoting/clientAnonymousVoting/src/components/CreateProcessPage.js index f5e4ed38..8987dd07 100644 --- a/anonymousVoting/clientAnonymousVoting/src/components/CreateProcessPage.js +++ b/anonymousVoting/clientAnonymousVoting/src/components/CreateProcessPage.js @@ -5,8 +5,8 @@ import styles from './CreateProcessPage.module.css'; import {ethers} from 'ethers'; //web3 imports -import { deployVotingProcess, deployTestContract, getTestContract } from '../web3/contracts' -import { useState, useEffect, useRef } from 'react'; +import { deployVotingProcess} from '../web3/contracts' +import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; @@ -27,35 +27,51 @@ const CreateProcess = () => { const [open, setOpen] = useState(false); const [transactionResult, setTransactionResult] = useState(null); - const refValue = useRef(false); + // const refValue = useRef(false); - const createProcess = async (e) => { - e.preventDefault(); - console.log("name: ", name); - //format proposals - let proposalArray = formatProposals(proposals); - //check form inputs - if(!isFormValid()){ - window.alert("Form is not valid"); - return; - } + const createProcess = async (e) => { + e.preventDefault(); + + if (!isFormValid()) { + window.alert("Form is not valid"); + return; + } + + try { setPending(true); - refValue.current = true; - //deploy new process contract - const result = await deployVotingProcess(name, description, proposalArray,1000000,1000000); + + const proposalArray = formatProposals(proposals); + const result = await deployVotingProcess( + name, + description, + proposalArray, + 1000000, + 1000000 + ); + setTransactionResult(result); + setShow(true); - refValue.current = false; + } catch (err) { + console.error(err); + window.alert("Transaction failed"); + } finally { setPending(false); - - setShow(true); } +}; + +const isFormValid = () => { + // Split proposals by comma, trim each item, and filter out empty strings + const validProposals = proposals + .split(',') + .map(p => p.trim()) + .filter(p => p.length > 0); + + // Must have at least 2 valid proposals + return validProposals.length >= 2; +}; + - const isFormValid = () => { - if(proposals < 2) - return false; - return true; - } const formatProposals = (input) => { let proposals = input.split(','); @@ -67,9 +83,6 @@ const CreateProcess = () => { } - useEffect(() => { - // setPending(!pending); - }, [pending]) return (
@@ -105,11 +118,27 @@ const CreateProcess = () => { />
- + +
- {refValue.current == true &&
- -
} + @@ -148,4 +177,4 @@ const CreateProcess = () => { ); } -export default CreateProcess; \ No newline at end of file +export default CreateProcess; diff --git a/anonymousVoting/clientAnonymousVoting/src/components/Explorer.js b/anonymousVoting/clientAnonymousVoting/src/components/Explorer.js new file mode 100644 index 00000000..4226f348 --- /dev/null +++ b/anonymousVoting/clientAnonymousVoting/src/components/Explorer.js @@ -0,0 +1,12 @@ +import React from 'react'; + +function Explorer() { + return ( +
+

Explorer

+

Blockchain explorer coming soon.

+
+ ); +} + +export default Explorer; diff --git a/anonymousVoting/clientAnonymousVoting/src/components/Navbar.js b/anonymousVoting/clientAnonymousVoting/src/components/Navbar.js index 1f9f1d7a..dd76e257 100644 --- a/anonymousVoting/clientAnonymousVoting/src/components/Navbar.js +++ b/anonymousVoting/clientAnonymousVoting/src/components/Navbar.js @@ -13,9 +13,30 @@ function Navbar({header, infoText, pictureUrl}) {
- settings - logout -
+ settings + + + explorer + + + +logout + + ) } diff --git a/anonymousVoting/clientAnonymousVoting/src/components/modals/AddCandidateModal.js b/anonymousVoting/clientAnonymousVoting/src/components/modals/AddCandidateModal.js index bd2f8af4..ec060020 100644 --- a/anonymousVoting/clientAnonymousVoting/src/components/modals/AddCandidateModal.js +++ b/anonymousVoting/clientAnonymousVoting/src/components/modals/AddCandidateModal.js @@ -2,17 +2,20 @@ import { useState } from 'react'; import { Flex, Modal, Button, Card } from "rimble-ui"; import { ethers } from "ethers"; import ElectionOrganiser from "../../build/ElectionOrganizer.json"; -import {successtoast, dangertoast } from '../utilities/Toasts'; +import { successtoast, dangertoast } from '../utilities/Toasts'; import { toast } from "react-toastify"; -import {addProposal} from '../../web3/contracts'; +import { addProposal } from '../../web3/contracts'; export function AddCandidateModal({ electionId }) { const [isOpen, setIsOpen] = useState(false); + const [candidateDetail, setCandidateDetail] = useState({ name: '', description: '' }); + // ADDED: terms acceptance state + const [acceptedTerms, setAcceptedTerms] = useState(false); const handleCandidateDetailChange = (e) => { const { name, value } = e.target; @@ -20,34 +23,40 @@ export function AddCandidateModal({ electionId }) { ...candidateDetail, [name]: value }); - } - + }; const handleSubmitCandidate = async (e) => { - let id ; + let id; e.preventDefault(); + + // ✅ ADDED: enforce terms acceptance + if (!acceptedTerms) { + toast.error("You must accept the Terms & Conditions"); + return; + } + try { - - - let tx = await addProposal(electionId,ethers.utils.toUtf8Bytes(candidateDetail.name.trim())); - - await tx.wait(); - console.log(tx); - - // successtoast(id, "Candidate Added Successfully") - - - - } catch(err) { - dangertoast(id ,"Candidate Addition Failed") + let tx = await addProposal( + electionId, + ethers.utils.toUtf8Bytes(candidateDetail.name.trim()) + ); + + await tx.wait(); + console.log(tx); + + // successtoast(id, "Candidate Added Successfully") + setIsOpen(false); + setAcceptedTerms(false); + } catch (err) { + dangertoast(id, "Candidate Addition Failed"); console.log(err); - } - - } + } + }; const closeModal = e => { e.preventDefault(); setIsOpen(false); + setAcceptedTerms(false); // ✅ reset }; const openModal = e => { @@ -57,14 +66,14 @@ export function AddCandidateModal({ electionId }) { return (
-
- Add Candidate +
+ Add Candidate
- + - + -
+
Add candidates
- -
+
Canidate Name -
- - + +

Canidate Description -
- +
+