Skip to content

Commit

Permalink
reorganize, add realtime validation
Browse files Browse the repository at this point in the history
  • Loading branch information
acao committed Jan 11, 2023
1 parent b0afbd7 commit d4821bd
Show file tree
Hide file tree
Showing 4 changed files with 307 additions and 268 deletions.
289 changes: 289 additions & 0 deletions _includes/list-nomination.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@

// Constants - configure here if the Betriebsrat law changes!
const employeeThreshholds = {
5: 0,
21: 1,
51: 3,
101: 5,
201: 7,
401: 9,
701: 11,
1001: 13,
1501: 15,
2001: 17,
2501: 19,
3001: 21,
3501: 23,
4001: 25,
4501: 27,
5001: 29,
6001: 31,
7001: 33,
9001: 35
}

// Seed data for the example generator

const lastNames = ["Schmidt", "Miller", "Xi", "Patel", "Ortez", "Goldman", "Shevchenko", "Melnyk", "Popova"]
const firstNames = ["Chris", "Sam", "Hannah", "Raj", "Aditi", "Thomas", "Marie", "Mahmoud"];
const jobTitles = ["Vulture capitalist", "Customer support", "Working student", "Warehouse picker", "IT support", "QA engineer", "Delivery rider", "Marketing manager", "Software engineer"]


let exampleEmployeeCount = 0;

function onLoad() {
let employee_count = localStorage.getItem('election.employee_count')
document.getElementById('employee_count').value = employee_count;
document.getElementById('candidate_count').value = localStorage.getItem('election.candidate_count');
document.getElementById('list_name').value = localStorage.getItem('election.list_name');
document.getElementById('list_owners').value = localStorage.getItem('election.list_owners');

if (employee_count) {
handleTemplateGeneratorFormSubmit();
handleEmployeeCount();
}
}

function handleTemplateGeneratorFormSubmit() {
persistForm()
signaturesTable()
candidateTable()
}

function handleTemplateGeneratorExampleFormSubmit() {
exampleEmployeeCount = Math.floor(Math.random() * (1000 - 25 + 1)) + 25;
signaturesTable(true)
candidateTable(true)
}

function handleEmployeeCount() {
persistValue('employee_count')

const countField = document.getElementById('candidate_count')
const minCandidates = worksCouncil();
if(minCandidates) {
countField.setAttribute('min', `${minCandidates}`)
document.getElementById('minimum-candidates').innerText = `Note: you must include at least ${minCandidates} candidates`
}

}

function persistValue(id) {
const value = document.getElementById(id).value;
window.localStorage.setItem("election." + id, value || '')
}

function persistForm() {
persistValue('employee_count')
persistValue('candidate_count')
persistValue('list_owners')
persistValue('list_name')
}

function listOwners() {
// currently no option to directly enter candidate names, but when that happens this can be generated from that
return localStorage.getItem('election.list_owners') || ''
}

function listName() {
// if a list name is not provided, the first two names on list suffice
return (localStorage.getItem('election.list_name') || listOwners()) || ''
}

function employeeCount(isExample) {
return isExample ? exampleEmployeeCount : parseInt(localStorage.getItem('election.employee_count'))
}

function candidateTable(isExample) {
const tableBody = document.querySelector("#candidates_id");
const caption = document.querySelector("#candidate_table > caption");

let caption_text = `${worksCouncil(isExample)} coworkers will represent you and your ${employeeCount(isExample) - 1} co-workers in your future Works Council.
Candidate list proposal: ${listName()} ideally has ${candidates(isExample)} candidates.
${supporters(isExample)} supporting signature(s) are also necessary, once all the candidates for ${listName()} list are finalized.
`

let tableData = ""
if (!isExample) {
for (let i = 0; i < candidates(); i++) {
tableData +=
`<tr>
<td>${i == 0 ? candidate1() : ''}</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>`
}
} else {
for (let i = 0; i < candidates(isExample); i++) {
genders = ["male", "female", "diverse", "non-binary"];
tableData +=
`<tr>
<td>${randomItem(firstNames)}</td>
<td>${randomItem(lastNames)}</td>
<td>${randomDate()}</td>
<td>${randomItem(genders)}</td>
<td>${randomItem(jobTitles)}</td>
<td>${randomItem(["😅", "🙈", "✊", "👾"])}</td>
</tr>`
}
}

tableBody.innerHTML = tableData;
caption.innerHTML = caption_text
}

function candidate1() {
if (listOwners()) {
return listOwners().split(",")[0]
} else {
return ''
}
}

function randomItem(items) {
return items[Math.floor(Math.random() * items.length)]
}

function getRandomInt(max) {
return Math.floor(Math.random() * max);
}

function randomDate() {
let start = new Date('1970-01-01')
let end = new Date('2004-12-31')

return new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime())).toLocaleDateString();
}

function getTableData(isExample) {
let tableData = ""
if (!isExample) {
for (let i = 0; i < supporters(); i++) {
let bgColor = i + 1 < supporters() ? "#FFCCCB" : "#66FF99"
let text = "#FFCCCB" == bgColor ? "Almost" : "Congrats!"
tableData +=
`<tr>
<td></td>
<td></td>
<td></td>
<td style="background-color:${bgColor}">${text}</td>
</tr>`
}
tableData += extraSupporterRows()
} else {
for (let i = 0; i < supporters(isExample); i++) {
let bgColor = i + 1 < supporters(isExample) ? "#FFCCCB" : "#66FF99"
let text = "#FFCCCB" == bgColor ? "Almost" : "Congrats!"
tableData +=
`<tr>
<td>${randomItem(firstNames)}</td>
<td>${randomItem(lastNames)}</td>
<td>${randomItem(["😅", "🙈", "✊", "👾"])}</td>
<td style="background-color:${bgColor}">${text}</td>
</tr>`
}
}
return tableData
}

function getCandidateData(isExample) {
let candidateData = ""

const numCandidates = candidates()

if (!isExample) {
for (let i = 0; i < numCandidates; i++) {
candidateData +=
`<tr>
<td>#${i + 1}</td>
<td>${i == 0 ? candidate1() : ''}</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>`
}
} else {
for (let i = 0; i < numCandidates; i++) {
genders = ["male", "female", "diverse", "non-binary"];
candidateData +=
`<tr>
<td>#${i + 1}</td>
<td>${randomItem(firstNames)}</td>
<td>${randomItem(lastNames)}</td>
<td>${randomDate()}</td>
<td>${randomItem(genders)}</td>
<td>${randomItem(jobTitles)}</td>
</tr>`
}
}

return candidateData
}

function signaturesTable(isExample) {
const tableSignatureBody = document.querySelector("#signatures_id");
const tableCandidateSignatureBody = document.querySelector("#signatures_candidate_id");
const caption = document.querySelector("#signature_candidate_table > caption");
let caption_text = `
List proposal Solidarity needs at least ${supporters(isExample)} supporting signatures
for the following candidates of the Solidarity list nomination.`

if (!isExample) {
caption_text = `List proposal ${listName()} needs at least ${supporters()} supporting signatures
for the following candidates of the ${listName()} list nomination.`
}

tableSignatureBody.innerHTML = getTableData(isExample);
tableCandidateSignatureBody.innerHTML = getCandidateData(isExample);
caption.innerHTML = caption_text
}

function extraSupporterRows() {
// when no signatures are required, extras are not either
if (supporters() < 2) {
return ''
} else {
return `<tr>
<td></td>
<td></td>
<td></td>
<td style="background-color:#FFD2669">Optional extra signatures</td>
</tr>`.repeat(Math.min(supporters(), 5))
}
}


function worksCouncil(isExample) {
let employees = employeeCount(isExample)
for (const limit in employeeThreshholds) {
if (employees < limit) {
return employeeThreshholds[limit];
}
}
// if the lookup table doesn't furnish a provided limit
return Math.ceil((employees - 9000) / 3000) * 2 + 35
}

function candidates(isExample) {
if (isExample) {
return 2 * worksCouncil(isExample)
}
// if unknown, double works council size is recommended
return parseInt(localStorage.getItem('election.candidate_count')) || 2 * worksCouncil()
}

function supporters(isExample) {
let employees = employeeCount(isExample)
if (employees < 21) {
return 0
} else if (employees < 101) {
return 2
} else
return Math.min(Math.ceil(employees * 1.0 / 20), 50)
}

onLoad();
Loading

0 comments on commit d4821bd

Please sign in to comment.