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()...