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.
mvfront-react/services/api.js

225 lines
5.7 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 { title, mails, tokens, locale } = res;
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) => new URL(`/vote/${pid}`, origin);
const urlResult = (pid) => new URL(`/result/${pid}`, origin);
const recipientVariables = {};
tokens.forEach((token, index) => {
recipientVariables[mails[index]] = {
urlVote: urlVote(token),
urlResult: urlResult(token),
};
});
const req = fetch("/.netlify/functions/send-invite-email/", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
recipientVariables,
title,
locale,
}),
});
return Promise.all([
new Promise((resolve, reject) => {
resolve(res);
}),
req,
]);
};
const createElection = (
title,
candidates,
{
/**
* Create an election from its title, its candidates and a bunch of options
*/
emails,
numGrades,
start,
finish,
restrictResult,
locale,
},
successCallback,
failureCallback
) => {
const endpoint = new URL(api.routesServer.setElection, api.urlServer);
console.log(endpoint.href);
fetch(endpoint.href, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title,
candidates,
on_invitation_only: emails.length > 0,
num_grades: numGrades,
elector_emails: emails || [],
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) => sendInviteMail({ locale, mails: emails || [], ...res }))
.then((res) => res[0]) // remove response from mail invitations
.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((err) => err)
.then(failureCallback || console.log);
};
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 || console.log);
};
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("Oops... The election is unknown.");
}
if (error.includes(ONGOING_ELECTION_ERROR)) {
return t(
"The election is still going on. You can't access now to the results."
);
}
if (error.includes(NO_VOTE_ERROR)) {
return t("No votes have been recorded yet. Come back later.");
}
if (error.includes(ELECTION_NOT_STARTED_ERROR)) {
return t("The election has not started yet.");
}
if (error.includes(ELECTION_FINISHED_ERROR)) {
return t("The election is over. You can't vote anymore");
}
if (error.includes(INVITATION_ONLY_ERROR)) {
return t("You need a token to vote in this election");
}
if (error.includes(USED_TOKEN_ERROR)) {
return t("You seem to have already voted.");
}
if (error.includes(WRONG_ELECTION_ERROR)) {
return t("The parameters of the election are incorrect.");
}
};
export {
api,
getDetails,
getResults,
createElection,
sendInviteMail,
castBallot,
};