-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from ConstanceBeguier/seb
Seb
- Loading branch information
Showing
34 changed files
with
24,527 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"extends": "next/core-web-vitals" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.js | ||
|
||
# testing | ||
/coverage | ||
|
||
# next.js | ||
/.next/ | ||
/out/ | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
*.pem | ||
|
||
# debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
.pnpm-debug.log* | ||
|
||
# local env files | ||
.env*.local | ||
|
||
# vercel | ||
.vercel | ||
|
||
# typescript | ||
*.tsbuildinfo | ||
next-env.d.ts | ||
|
||
# rust | ||
target |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
nodeLinker: node-modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import React from 'react'; | ||
import { useRouter } from 'next/router'; | ||
import style from '../styles/BackButton.module.css'; | ||
|
||
const BackButton = () => { | ||
const router = useRouter(); | ||
|
||
const goBack = () => { | ||
router.goBack(); // Utilise la pile d'historique de React Router pour revenir en arrière | ||
}; | ||
|
||
return ( | ||
<button onClick={goBack} className={style.button}> | ||
Retour | ||
</button> | ||
); | ||
}; | ||
|
||
export default BackButton; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { WalletModalButton ,WalletDisconnectButton} from "@solana/wallet-adapter-react-ui"; | ||
import { useAppContext } from "../context/context"; | ||
import style from "../styles/Header.module.css"; | ||
import Link from 'next/link'; | ||
const Header = () => { | ||
const {isCo} = useAppContext(); | ||
|
||
return ( | ||
<div className={style.wrapper}> | ||
<Link href="/"> | ||
<div className={style.title}>PolliSol</div> | ||
</Link> | ||
<nav className={style.nav}> | ||
<Link href="/"> | ||
<a>Accueil</a> | ||
</Link> | ||
{ | ||
isCo &&<Link href="/proposal/create"> | ||
<a>Create a Proposal</a> | ||
</Link> | ||
} | ||
</nav> | ||
{isCo ? <WalletDisconnectButton /> : <WalletModalButton/> } | ||
</div> | ||
); | ||
}; | ||
|
||
export default Header; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { useEffect, useState } from "react"; | ||
|
||
import style from '../styles/ResumeProposal.module.css'; | ||
import { toCamelCase } from "../utils/helper"; | ||
const ResumeProposal = ({publicKey, account, setActiveClass}) => { | ||
const [period, setPeriod] = useState(''); | ||
|
||
useEffect(()=>{ | ||
setPeriod(Object.values(account.period)); | ||
setActiveClass(toCamelCase(Object.values(account.period)[0].toString())); | ||
},[account]); | ||
|
||
return ( | ||
<div className={style.card}> | ||
<div className={style.cardHeader}> | ||
<span className={style.cardTitle}>{account.title}</span> | ||
</div> | ||
<div className={style.cardBody}> | ||
<span className={style.cardPeriod}>Period : {period}</span> | ||
</div> | ||
<div className={style.cardFooter}> | ||
<span className={style.cardPubkey}>pubkey: {publicKey}</span> | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
export default ResumeProposal; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { useState } from "react"; | ||
import { useAppContext } from "../context/context"; | ||
import style from '../styles/ViewProposals.module.css'; | ||
import ResumeProposal from "./ResumeProposal"; | ||
import Link from 'next/link'; | ||
const ViewProposals = () => { | ||
const {proposals} = useAppContext(); | ||
const [activeClass, setActiveClass] = useState({}); // Un objet pour garder les états actifs des différents ResumeProposal | ||
|
||
const handleSetActiveClass = (key, className) => { | ||
setActiveClass(prev => ({ ...prev, [key]: style[className] })); | ||
}; | ||
|
||
return ( | ||
<div className={style.gridContainer}> | ||
{proposals?.map((proposal) => ( | ||
<div key={proposal.publicKey} className={`${style.proposalContainer} ${activeClass[proposal.publicKey] || ''}`}> | ||
<Link href={`/proposal/${proposal.publicKey}`}> | ||
<a> | ||
<ResumeProposal | ||
key={proposal.publicKey} | ||
{...proposal} | ||
setActiveClass={className => handleSetActiveClass(proposal.publicKey, className)} | ||
/> | ||
</a> | ||
</Link> | ||
</div> | ||
))} | ||
</div> | ||
); | ||
}; | ||
|
||
export default ViewProposals; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
import { createContext, useState, useEffect, useContext, useMemo } from "react"; | ||
import { SystemProgram, Keypair, PublicKey } from "@solana/web3.js"; | ||
import { useAnchorWallet, useConnection } from "@solana/wallet-adapter-react"; | ||
import { BN } from "bn.js"; | ||
|
||
import { | ||
getProgram, | ||
getBallotAddress | ||
} from "../utils/program"; | ||
import { confirmTx, mockWallet, stringToU8Array16, stringToU8Array32, u8ArrayToString } from "../utils/helper"; | ||
|
||
export const AppContext = createContext(); | ||
|
||
export const AppProvider = ({ children }) => { | ||
const [error, setError] = useState(""); | ||
const [success, setSuccess] = useState(""); | ||
const [isCo, setIsCo] = useState(false); | ||
const { connection } = useConnection(); | ||
const wallet = useAnchorWallet(); | ||
const program = useMemo(() => { | ||
if (connection) { | ||
return getProgram(connection, wallet ?? mockWallet()); | ||
} | ||
}, [connection, wallet]); | ||
useEffect(() => { | ||
connection && wallet ? setIsCo(true) : setIsCo(false); | ||
}, [connection, wallet]); | ||
useEffect(() => { | ||
if(proposals.length == 0){ | ||
fetch_proposals(); | ||
} | ||
}, [program]); | ||
|
||
const [proposals, setProposals] = useState([]); | ||
|
||
const fetch_proposals = async () => { | ||
const proposals = await program.account.proposal.all(); | ||
// const sortedVotes = proposals.sort((a, b) => a.account.deadline - b.account.deadline); | ||
const now = new Date().getTime(); | ||
const readableProposals = proposals.map(proposal => { | ||
const tmpProposal = { | ||
publicKey: '', | ||
account: { | ||
admin: '', | ||
title: '', | ||
description: '', | ||
choices: [], | ||
choicesRegistrationInterval: {start:'', end:''}, | ||
votersRegistrationInterval: {start:'', end:''}, | ||
votingSessionInterval: {start:'', end:''}, | ||
period: {}, | ||
}, | ||
}; | ||
|
||
tmpProposal.publicKey = proposal.publicKey.toString(); | ||
tmpProposal.account.admin = proposal.account.admin.toString(); | ||
tmpProposal.account.title = u8ArrayToString(proposal.account.title); | ||
tmpProposal.account.description = u8ArrayToString(proposal.account.description); | ||
tmpProposal.account.choices = (proposal.account.choices.length > 0 ) | ||
? proposal.account.choices.map(ch=> { return { count: ch.count, label: u8ArrayToString(ch.label)}}) | ||
: []; | ||
const choicesRegistrationIntervalStart = Number(proposal.account.choicesRegistrationInterval.start) * 1000; | ||
const choicesRegistrationIntervalEnd = Number(proposal.account.choicesRegistrationInterval.end) * 1000; | ||
const votersRegistrationIntervalStart = Number(proposal.account.votersRegistrationInterval.start) * 1000; | ||
const votersRegistrationIntervalEnd = Number(proposal.account.votersRegistrationInterval.end) * 1000; | ||
const votingSessionIntervalStart = Number(proposal.account.votingSessionInterval.start) * 1000; | ||
const votingSessionIntervalEnd = Number(proposal.account.votingSessionInterval.end) * 1000; | ||
|
||
if(choicesRegistrationIntervalStart <= now && choicesRegistrationIntervalEnd >= now) { | ||
tmpProposal.account.period = {0: "Choices Registration"}; | ||
} else if(votersRegistrationIntervalStart <= now && votersRegistrationIntervalEnd >= now) { | ||
tmpProposal.account.period = {1: "Voters Registration"}; | ||
} else if(votingSessionIntervalStart <= now && votingSessionIntervalEnd >= now) { | ||
tmpProposal.account.period = {2: "Voting Session"}; | ||
} else { | ||
tmpProposal.account.period = {3: "Terminate"}; | ||
} | ||
tmpProposal.account.choicesRegistrationInterval.start = new Date(choicesRegistrationIntervalStart); | ||
tmpProposal.account.choicesRegistrationInterval.end = new Date(choicesRegistrationIntervalEnd); | ||
tmpProposal.account.votersRegistrationInterval.start = new Date(votersRegistrationIntervalStart); | ||
tmpProposal.account.votersRegistrationInterval.end = new Date(votersRegistrationIntervalEnd); | ||
tmpProposal.account.votingSessionInterval.start = new Date(votingSessionIntervalStart); | ||
tmpProposal.account.votingSessionInterval.end = new Date(votingSessionIntervalEnd); | ||
return tmpProposal; | ||
}) | ||
setProposals(readableProposals); | ||
|
||
} | ||
|
||
const fetch_ballot = async (proposalPK) => { | ||
const ballotAddress = await getBallotAddress(new PublicKey(proposalPK), wallet.publicKey); | ||
const ballot = await program.account.ballot.fetch(ballotAddress); | ||
return ballot; | ||
} | ||
const create_proposal = async ( | ||
title, | ||
description, | ||
cr_start, | ||
cr_end, | ||
vr_start, | ||
vr_end, | ||
vs_start, | ||
vs_end, | ||
) => { | ||
setError(""); | ||
setSuccess(""); | ||
try { | ||
const proposal = Keypair.generate(); | ||
|
||
const txHash = await program.methods | ||
.createProposal( | ||
stringToU8Array16(title), | ||
stringToU8Array32(description), | ||
new BN(cr_start), | ||
new BN(cr_end), | ||
new BN(vr_start), | ||
new BN(vr_end), | ||
new BN(vs_start), | ||
new BN(vs_end), | ||
) | ||
.accounts({ | ||
proposal: proposal.publicKey, | ||
admin: wallet.publicKey, | ||
systemProgram: SystemProgram.programId, | ||
}) | ||
.signers([proposal]) | ||
.rpc(); | ||
|
||
const confirm = await confirmTx(txHash, connection); | ||
|
||
await fetch_proposals(); | ||
if(confirm) { | ||
setSuccess('Proposal Create'); | ||
const newProposal = proposals.find(pp=>pp.account.title == title && pp.account.description == description); | ||
return newProposal; | ||
} | ||
} catch (err) { | ||
setError(err.message.split('Error Message:')[1]); | ||
} | ||
}; | ||
|
||
const add_choice_for_one_proposal = async (choice, proposalPK) => { | ||
setError(""); | ||
setSuccess(""); | ||
try { | ||
|
||
const txHash = await program.methods | ||
.addChoiceForOneProposal( | ||
stringToU8Array16(choice), | ||
) | ||
.accounts({ | ||
proposal: proposalPK, | ||
admin: wallet.publicKey, | ||
}) | ||
.signers([]) | ||
.rpc(); | ||
await confirmTx(txHash, connection); | ||
|
||
fetch_proposals(); | ||
} catch (err) { | ||
setError(err.message.split('Error Message:')[1]); | ||
} | ||
}; | ||
const register_voter = async (voter, proposalPK) => { | ||
setError(""); | ||
setSuccess(""); | ||
try { | ||
const ballotAddress = await getBallotAddress(new PublicKey(proposalPK), new PublicKey(voter)); | ||
|
||
const txHash = await program.methods | ||
.registerVoter(new PublicKey(voter)) | ||
.accounts({ | ||
proposal: proposalPK, | ||
ballot: ballotAddress, | ||
admin: wallet.publicKey, | ||
systemProgram: SystemProgram.programId, | ||
}) | ||
.signers([]) | ||
.rpc(); | ||
await confirmTx(txHash, connection); | ||
|
||
fetch_proposals(); | ||
} catch (err) { | ||
setError(err.message.split('Error Message:')[1]); | ||
} | ||
}; | ||
const cast_vote = async (index, proposalPK) => { | ||
try { | ||
const ballotAddress = await getBallotAddress(new PublicKey(proposalPK), wallet.publicKey); | ||
|
||
const txHash = await program.methods | ||
.castVote(index) | ||
.accounts({ | ||
proposal: proposalPK, | ||
ballot: ballotAddress, | ||
voter: wallet.publicKey, | ||
}) | ||
.signers([]) | ||
.rpc(); | ||
await confirmTx(txHash, connection); | ||
|
||
fetch_proposals(); | ||
} catch (err) { | ||
console.log("err", err); | ||
setError(err.message); | ||
} | ||
} | ||
return ( | ||
<AppContext.Provider | ||
value={{ | ||
create_proposal, | ||
fetch_proposals, | ||
fetch_ballot, | ||
cast_vote, | ||
register_voter, | ||
add_choice_for_one_proposal, | ||
proposals, | ||
error, | ||
success, | ||
isCo | ||
}} | ||
> | ||
{children} | ||
</AppContext.Provider> | ||
); | ||
}; | ||
|
||
export const useAppContext = () => { | ||
return useContext(AppContext); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
/** @type {import('next').NextConfig} */ | ||
const nextConfig = { | ||
reactStrictMode: true, | ||
swcMinify: true, | ||
} | ||
|
||
module.exports = nextConfig |
Oops, something went wrong.