React
by Abdul Ahmad
HTML
<div id="app"></div>
SCSS
$app-background-color: #20262E;
* {
box-sizing: border-box;
}
html, body {
background: #20262E;
font-family: Helvetica;
margin: 0;
color: white;
}
#app {
transition: all 0.2s;
// border: 1px dashed black;
}
.app {
// display: flex;
position: relative;
}
.sprint-timer {
position: sticky;
top: 0;
padding: 20px;
background: $app-background-color;
border-bottom: 1px solid darken($app-background-color, 2%);
}
.tickets {
display: flex;
margin-top: 20px;
}
.col {
margin-left: 10px;
}
.ticket {
$background-color: darken(#20262E, 5%);
padding: 20px;
display: flex;
justify-content: center;
align-items: center;
border-radius: 5px;
background: white;
margin-top: 5px;
color: black;
background: $background-color;
color: lighten($background-color, 30%);
.info {
margin-top: 5px;
}
.info:first-of-type {
margin-top: 0px;
}
.points {
text-align: center;
font-size: 32px;
color: darken(desaturate(tomato, 40%), 10%);
}
}
React
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
const availablePoints = [1, 3, 5, 8];
const timeInSprint = 80;
const pointsToTimeMap = {
'1': [1, 4],
'3': [2, 16],
'5': [16, 50],
'8': [40, 80],
};
const pointsToStringMap = {
'1': 'one',
'3': 'three',
'5': 'five',
'8': 'eight',
};
let ticketNum = 0;
const registeredCallbacks = {};
const state = {};
let time = 0;
const ticketTimer = setInterval(() => {
time += 1;
registeredCallbacks.setSprintTimer(time);
const remainingTickets = [];
registeredCallbacks.getTickets().forEach((t, i) => {
if (time - t.startTime < t.calculatedDuration) {
remainingTickets.push(t);
}
});
registeredCallbacks.setTickets(remainingTickets);
}, 1000);
function registerCallback(name, cb) {
registeredCallbacks[name] = cb;
}
function createTicket({ calculatedDuration } = {}) {
ticketNum += 1;
const points = availablePoints[getRandomInt(0, availablePoints.length - 1)];
const duration = pointsToTimeMap[points];
const _calculatedDuration = getRandomInt(duration[0], duration[1]);
const newTicket = {
points,
ticketNum,
startTime: time,
calculatedDuration: calculatedDuration || _calculatedDuration,
};
return newTicket;
}
function App() {
const [sprintTimer, setSprintTimer] = React.useState(0);
const [tickets, setTickets] = React.useState([
createTicket(),
createTicket(),
createTicket(),
createTicket(),
createTicket(),
createTicket(),
createTicket(),
createTicket(),
]);
React.useEffect(() => {
registerCallback('addTicket', addTicket);
registerCallback('getTickets', getTickets);
registerCallback('removeTicket', removeTicket);
registerCallback('setSprintTimer', setSprintTimer);
registerCallback('setTickets', setTickets);
});
function addTicket() {
setTickets([ ...tickets, createTicket() ]);
};
function getTickets()...