diff --git a/plugins/maciVoting/components/proposal/index.tsx b/plugins/maciVoting/components/proposal/index.tsx
index 15a381c..a5880e9 100644
--- a/plugins/maciVoting/components/proposal/index.tsx
+++ b/plugins/maciVoting/components/proposal/index.tsx
@@ -51,15 +51,7 @@ export default function ProposalCard(props: ProposalInputs) {
const winningOption = getWinningOption(proposal?.tally as Tally);
if (!proposal && showLoading) {
- return (
-
- );
+ return
;
} else if (!proposalMetadata?.title && !proposalMetadata?.summary) {
// We have the proposal but no metadata yet
return (
diff --git a/plugins/maciVoting/pages/new.tsx b/plugins/maciVoting/pages/new.tsx
index f6d1efe..92eb77a 100644
--- a/plugins/maciVoting/pages/new.tsx
+++ b/plugins/maciVoting/pages/new.tsx
@@ -15,6 +15,7 @@ import { NEXT_MINIMUM_START_DELAY_IN_SECONDS, PUBLIC_CHAIN, PUBLIC_MACI_VOTING_P
import { ActionCard } from "@/components/actions/action";
import { useMutation } from "@tanstack/react-query";
import classNames from "classnames";
+import Link from "next/link";
enum ActionType {
Signaling,
@@ -38,6 +39,15 @@ export default function Create() {
const { writeContract: createProposalWrite, data: createTxHash, status, error } = useWriteContract();
const { isLoading: isConfirming, isSuccess: isConfirmed } = useWaitForTransactionReceipt({ hash: createTxHash });
const [actionType, setActionType] = useState
(ActionType.Signaling);
+ const [errors, setErrors] = useState<{
+ title?: string;
+ summary?: string;
+ description?: string;
+ startDate?: string;
+ endDate?: string;
+ withdrawal?: string;
+ custom?: string;
+ }>({});
const changeActionType = (actionType: ActionType) => {
setActions([]);
@@ -82,20 +92,21 @@ export default function Create() {
}, [status, createTxHash, isConfirming, isConfirmed, error, push]);
const submitProposal = async () => {
+ let formErrors = {};
try {
// Check metadata
if (!title.trim()) {
- return addAlert("Invalid proposal details", {
- description: "Please, enter a title",
- type: "error",
- });
+ formErrors = {
+ ...formErrors,
+ title: "Please, enter a title",
+ };
}
if (!summary.trim()) {
- return addAlert("Invalid proposal details", {
- description: "Please, enter a summary of what the proposal is about",
- type: "error",
- });
+ formErrors = {
+ ...formErrors,
+ summary: "Please, enter a summary of what the proposal is about",
+ };
}
// Check the action
@@ -104,18 +115,18 @@ export default function Create() {
break;
case ActionType.Withdrawal:
if (!actions.length) {
- return addAlert("Invalid proposal details", {
- description: "Please ensure that the withdrawal address and the amount to transfer are valid",
- type: "error",
- });
+ formErrors = {
+ ...formErrors,
+ withdrawal: "Please ensure that the withdrawal address and the amount to transfer are valid",
+ };
}
break;
default:
if (!actions.length || !actions[0].data || actions[0].data === "0x") {
- return addAlert("Invalid proposal details", {
- description: "Please ensure that the values of the action to execute are complete and correct",
- type: "error",
- });
+ formErrors = {
+ ...formErrors,
+ custom: "Please ensure that the values of the action to execute are complete and correct",
+ };
}
}
@@ -132,21 +143,20 @@ export default function Create() {
const ipfsPin = await uploadToPinata(blob);
if (!startDate || !endDate) {
- addAlert("You need to specify the start date and end date of the voting period", {
- timeout: 4 * 1000,
- });
- return null;
+ formErrors = {
+ ...formErrors,
+ startDate: "You need to specify the start date and end date of the voting period",
+ };
}
const currentTime = Math.floor(Date.now() / 1000);
const startDateTime = Math.floor(new Date(`${startDate}T${startTime ? startTime : "00:00:00"}`).getTime() / 1000);
if (startDateTime - currentTime < NEXT_MINIMUM_START_DELAY_IN_SECONDS) {
- addAlert(`The start date must be at least ${NEXT_MINIMUM_START_DELAY_IN_SECONDS} seconds in the future`, {
- timeout: 4 * 1000,
- type: "error",
- });
- return null;
+ formErrors = {
+ ...formErrors,
+ startDate: `The start date must be at least ${NEXT_MINIMUM_START_DELAY_IN_SECONDS} seconds in the future`,
+ };
}
const endDateTime = Math.floor(new Date(`${endDate}T${endTime ? endTime : "00:00:00"}`).getTime() / 1000);
@@ -160,6 +170,11 @@ export default function Create() {
tryEarlyExecution,
]);
+ if (Object.keys(formErrors).length > 0) {
+ setErrors(formErrors);
+ return;
+ }
+
if (chainId !== PUBLIC_CHAIN.id) await switchChainAsync({ chainId: PUBLIC_CHAIN.id });
createProposalWrite({
chainId: PUBLIC_CHAIN.id,
@@ -199,11 +214,20 @@ export default function Create() {
const isDisabled = submitProposalMutation.isPending || isConfirming;
return (
+
+
+ Back
+
Create Proposal
setStartDate(e.target.value)}
@@ -260,7 +284,7 @@ export default function Create() {
setEndDate(e.target.value)}
@@ -341,6 +365,14 @@ export default function Create() {
+
+ {Object.entries(errors).map(([key, value]) => (
+
+ {value}
+
+ ))}
+
+
diff --git a/plugins/maciVoting/pages/proposal.tsx b/plugins/maciVoting/pages/proposal.tsx
index 0c0f50c..18cbf2a 100644
--- a/plugins/maciVoting/pages/proposal.tsx
+++ b/plugins/maciVoting/pages/proposal.tsx
@@ -23,9 +23,20 @@ export default function ProposalDetail({ id: proposalId }: { id: string }) {
if (!proposal || !proposalMetadata || !creator || showProposalLoading) {
return (
-
+
);
}
@@ -41,7 +52,7 @@ export default function ProposalDetail({ id: proposalId }: { id: string }) {
/>
-
+
diff --git a/tailwind.config.ts b/tailwind.config.ts
index e76f491..87a316e 100644
--- a/tailwind.config.ts
+++ b/tailwind.config.ts
@@ -11,6 +11,8 @@ const config: Config = {
theme: {
extend: {
colors: {
+ slate: "#CBD5E1",
+ danger: "#e7000b",
voting: {
yes: "#10b981",
no: "#dc2626",