You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
229 lines
5.5 KiB
229 lines
5.5 KiB
const api = {
|
|
urlServer:
|
|
process.env.NEXT_PUBLIC_SERVER_URL || "https://demo.mieuxvoter.fr/api/",
|
|
feedbackForm:
|
|
process.env.NEXT_PUBLIC_FEEDBACK_FORM ||
|
|
"https://docs.google.com/forms/d/e/1FAIpQLScuTsYeBXOSJAGSE_AFraFV7T2arEYua7UCM4NRBSCQQfRB6A/viewform",
|
|
routesServer: {
|
|
setElection: "election/",
|
|
getElection: "election/get/:slug/",
|
|
getResults: "election/results/:slug",
|
|
voteElection: "election/vote/",
|
|
},
|
|
};
|
|
|
|
const sendInviteMail = (res) => {
|
|
/**
|
|
* Send an invitation mail using a micro-service with Netlify
|
|
*/
|
|
const { id, title, mails, tokens, locale } = res;
|
|
|
|
if (!mails || !mails.length) {
|
|
throw new Error("No emails are provided.");
|
|
}
|
|
|
|
if (mails.length !== tokens.length) {
|
|
throw new Error("The number of emails differ from the number of tokens");
|
|
}
|
|
|
|
const origin =
|
|
typeof window !== "undefined" && window.location.origin
|
|
? window.location.origin
|
|
: "http://localhost";
|
|
const urlVote = (pid, token) => new URL(`/vote/${pid}/${token}`, origin);
|
|
const urlResult = (pid) => new URL(`/result/${pid}`, origin);
|
|
|
|
const recipientVariables = {};
|
|
tokens.forEach((token, index) => {
|
|
recipientVariables[mails[index]] = {
|
|
urlVote: urlVote(id, token),
|
|
urlResult: urlResult(id),
|
|
};
|
|
});
|
|
|
|
const req = fetch("/.netlify/functions/send-invite-email/", {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify({
|
|
recipientVariables,
|
|
title,
|
|
locale,
|
|
}),
|
|
});
|
|
|
|
return req.then((any) => res);
|
|
};
|
|
|
|
const createElection = (
|
|
title,
|
|
candidates,
|
|
{
|
|
/**
|
|
* Create an election from its title, its candidates and a bunch of options
|
|
*/
|
|
mails,
|
|
numGrades,
|
|
start,
|
|
finish,
|
|
restrictResult,
|
|
locale,
|
|
},
|
|
successCallback,
|
|
failureCallback
|
|
) => {
|
|
const endpoint = new URL(api.routesServer.setElection, api.urlServer);
|
|
|
|
console.log(endpoint.href);
|
|
const onInvitationOnly = mails && mails.length > 0;
|
|
|
|
fetch(endpoint.href, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify({
|
|
title,
|
|
candidates,
|
|
on_invitation_only: onInvitationOnly,
|
|
num_grades: numGrades,
|
|
elector_emails: mails || [],
|
|
start_at: start,
|
|
finish_at: finish,
|
|
select_language: locale || "en",
|
|
front_url: window.location.origin,
|
|
restrict_results: restrictResult,
|
|
send_mail: false,
|
|
}),
|
|
})
|
|
.then((response) => {
|
|
if (!response.ok) {
|
|
throw Error(response.statusText);
|
|
}
|
|
return response.json();
|
|
})
|
|
.then((res) => {
|
|
if (onInvitationOnly) {
|
|
return sendInviteMail({ locale, mails: mails, ...res });
|
|
}
|
|
return res;
|
|
})
|
|
.then(successCallback)
|
|
.catch(failureCallback || console.log);
|
|
};
|
|
|
|
const getResults = (pid, successCallback, failureCallback) => {
|
|
/**
|
|
* Fetch results from external API
|
|
*/
|
|
|
|
const endpoint = new URL(
|
|
api.routesServer.getResults.replace(new RegExp(":slug", "g"), pid),
|
|
api.urlServer
|
|
);
|
|
|
|
return fetch(endpoint.href)
|
|
.then((response) => {
|
|
if (!response.ok) {
|
|
return Promise.reject(response.text());
|
|
}
|
|
return response.json();
|
|
})
|
|
.then(successCallback || ((res) => res))
|
|
.catch(failureCallback || ((err) => err));
|
|
};
|
|
|
|
const getDetails = (pid, successCallback, failureCallback) => {
|
|
/**
|
|
* Fetch data from external API
|
|
*/
|
|
|
|
const detailsEndpoint = new URL(
|
|
api.routesServer.getElection.replace(new RegExp(":slug", "g"), pid),
|
|
api.urlServer
|
|
);
|
|
return fetch(detailsEndpoint.href)
|
|
.then((response) => {
|
|
if (!response.ok) {
|
|
return Promise.reject(response.text());
|
|
}
|
|
return response.json();
|
|
})
|
|
.then(successCallback || ((res) => res))
|
|
.catch(failureCallback || ((err) => err))
|
|
.then((res) => res);
|
|
};
|
|
|
|
const castBallot = (judgments, pid, token, callbackSuccess, callbackError) => {
|
|
/**
|
|
* Save a ballot on the remote database
|
|
*/
|
|
|
|
const endpoint = new URL(api.routesServer.voteElection, api.urlServer);
|
|
|
|
const payload = {
|
|
election: pid,
|
|
grades_by_candidate: judgments,
|
|
};
|
|
if (token && token !== "") {
|
|
payload["token"] = token;
|
|
}
|
|
|
|
fetch(endpoint.href, {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify(payload),
|
|
})
|
|
.then(callbackSuccess || ((res) => res))
|
|
.catch(callbackError || console.log);
|
|
};
|
|
|
|
export const UNKNOWN_ELECTION_ERROR = "E1:";
|
|
export const ONGOING_ELECTION_ERROR = "E2:";
|
|
export const NO_VOTE_ERROR = "E3:";
|
|
export const ELECTION_NOT_STARTED_ERROR = "E4:";
|
|
export const ELECTION_FINISHED_ERROR = "E5:";
|
|
export const INVITATION_ONLY_ERROR = "E6:";
|
|
export const UNKNOWN_TOKEN_ERROR = "E7:";
|
|
export const USED_TOKEN_ERROR = "E8:";
|
|
export const WRONG_ELECTION_ERROR = "E9:";
|
|
|
|
export const apiErrors = (error, t) => {
|
|
if (error.includes(UNKNOWN_ELECTION_ERROR)) {
|
|
return t("error.e1");
|
|
}
|
|
if (error.includes(ONGOING_ELECTION_ERROR)) {
|
|
return t("error.e2");
|
|
}
|
|
if (error.includes(NO_VOTE_ERROR)) {
|
|
return t("error.e3");
|
|
}
|
|
if (error.includes(ELECTION_NOT_STARTED_ERROR)) {
|
|
return t("error.e4");
|
|
}
|
|
if (error.includes(ELECTION_FINISHED_ERROR)) {
|
|
return t("error.e5");
|
|
}
|
|
if (error.includes(INVITATION_ONLY_ERROR)) {
|
|
return t("error.e6");
|
|
}
|
|
if (error.includes(USED_TOKEN_ERROR)) {
|
|
return t("error.e7");
|
|
}
|
|
if (error.includes(WRONG_ELECTION_ERROR)) {
|
|
return t("error.e8");
|
|
} else {
|
|
return t("error.catch22");
|
|
}
|
|
};
|
|
|
|
export {
|
|
api,
|
|
getDetails,
|
|
getResults,
|
|
createElection,
|
|
sendInviteMail,
|
|
castBallot,
|
|
};
|