JSFiddle - React, Tailwind, and code Playground
by Michael Prosser
February 13, 2025
HTML
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<h1>DOT Drug Testing</h1>
<div class="drug-test-controls">
<label
>Select
<input name="userCount" type="number" min="0" step="1" value="3" /> random
users</label
>
<label
>who have not had a test in the past
<input name="daysCount" type="number" min="0" step="1" value="30"
/></label>
<button class="get-user-selection">Generate</button>
</div>
<div class="drugtest-holder"></div>
CSS
.drug-test-controls {
padding: 15px;
font-family: helvetica, serif;
font-size: 13px;
text-align: center;
}
h1 {
font-family: helvetica, serif;
position: relative !important;
padding: 9px !important;
border: solid 1px #666 !important;
box-shadow: 1px 5px 4px rgb(0 0 0 / 41%) !important;
line-height: 24px !important;
font-size: 24px !important;
min-height: 20px !important;
font-weight: 300 !important;
margin-right: auto !important;
margin-left: 65px !important;
margin-top: 10px !important;
margin-bottom: 20px !important;
text-transform: uppercase !important;
}
h1:before {
content: "";
background-image: url(https://agrisphere-portal.com/dot.preview/assets/drug.testing.svg);
display: block;
position: absolute;
width: 48px;
height: 48px;
background-size: 100% auto;
left: -55px;
top: 0px;
}
.drug-test-controls > label {
}
.drug-test-controls > label > input[type="number"] {
width: 36px;
padding: 4px;
border-radius: 4px;
border: solid 1px #999;
}
.drug-test-controls > button {
padding: 5px;
border-radius: 4px;
border: none;
background-color: #389845;
color: #fff;
width: 100px;
cursor: pointer;
}
.drug-test {
list-style: none;
font-family: helvetica;
font-size: 13px;
background-color: #ccc;
padding: 20px;
max-width: 1200px;
margin: auto;
}
.drug-test > button.confirm-user-selection {
padding: 6px;
padding-left: 18px;
padding-right: 18px;
background-color: #4caf50;
color: #fff;
border: none;
border-radius: 5px;
display: block;
margin: auto;
cursor: pointer;
}
.drug-test > li {
margin: 5px;
background-color: #fff;
padding: 5px;
display: inline-block;
vertical-align: top;
width: calc(25% - 20px);
position: relative;
overflow: hidden;
}
.drug-test > li.selected-for-randomization {
background-color: darkorange;
}
.drug-test > li.recently-tested:before {
content: "";
display: block;
position: absolute;
width: 0px;
height: 0px;
...
JavaScript
class DrugTest {
constructor(parent, users, count, requiredDaysSinceLastTest) {
/*
users = array of users
(with timestamp of last test - 0000-00-00 if not test exists)
count = how many users
(should be selected for testing)
requiredDaysSinceLastTest
(configuration setting of days since last test)
*/
this.c = 0
this.users = [...users]
this.count = count
this.element = $('<div class="drug-test"><ul></ul></div>')
parent.append(this.element)
for (let i = 0; i < this.users.length; i++) {
let lastTest
let lastTested
if (this.users[i].timestampOfLastTest == "0000-00-00") {
lastTest = 0
lastTested = "NEVER"
} else {
lastTest = Date.parse(this.users[i].timestampOfLastTest)
lastTested = this.users[i].timestampOfLastTest
}
let user = $(
'<li data-user-id="' +
this.users[i].id +
'"><img src="' +
this.users[i].profile +
'"><label>' +
this.users[i].name +
"<br /><span>Last Tested: " +
lastTested +
"</span></label></li>",
)
if (Date.now() - requiredDaysSinceLastTest * 86400 * 1000 > lastTest) {
} else {
user.addClass("recently-tested")
}
this.users[i].element = user
this.element.append(user)
}
}
randomize(upward, callback) {
let t = this
let rand = t.randomNumberBetween(0, t.users.length - 1)
if (
t.users[rand].element.hasClass("selected-for-testing") ||
t.users[rand].element.hasClass("recently-tested")
) {
t.randomize(upward, callback)
return
}
let timers = []
for (let i = 0; i < t.users.length; i++) {
let timer = setTimeout(function () {
t.element.find("li").removeClass("selected-for-randomization")
t.users[i].element.addClass("selected-for-randomization")
if (upward) {
if (rand == i) {
...