@@ -0,0 +1,15 @@
|
|||||||
|
const choo = require('../../')
|
||||||
|
|
||||||
|
const stopwatch = require('./models/stopwatch')
|
||||||
|
const mainView = require('./views/main')
|
||||||
|
|
||||||
|
const app = choo()
|
||||||
|
|
||||||
|
app.model(stopwatch)
|
||||||
|
|
||||||
|
app.router((route) => [
|
||||||
|
route('/', mainView)
|
||||||
|
])
|
||||||
|
|
||||||
|
const tree = app.start()
|
||||||
|
document.body.appendChild(tree)
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
const raf = require('raf')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
state: {
|
||||||
|
elapsed: 0,
|
||||||
|
startTime: 0,
|
||||||
|
start: false,
|
||||||
|
laps: []
|
||||||
|
},
|
||||||
|
reducers: {
|
||||||
|
start: (data, state) => ({ start: true, startTime: Date.now() - state.elapsed }),
|
||||||
|
stop: (data, state) => ({ start: false }),
|
||||||
|
update: (data, state) => ({ elapsed: data }),
|
||||||
|
reset: (data, state) => ({ startTime: Date.now(), elapsed: 0, laps: [] }),
|
||||||
|
add: (data, state) => ({ laps: state.laps.concat(data) })
|
||||||
|
},
|
||||||
|
effects: {
|
||||||
|
now: (data, state, send, done) => {
|
||||||
|
if (state.start) {
|
||||||
|
let elapsed = data - state.startTime
|
||||||
|
send('update', elapsed, done)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
subscriptions: [
|
||||||
|
(send, done) => {
|
||||||
|
raf(function loop () {
|
||||||
|
send('now', Date.now(), done)
|
||||||
|
raf(loop)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "stopwatch",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "client.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "budo client.js -p 8080 -- -t es2020"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "traducer <traducer21@gmail.com>",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"budo": "^8.3.0",
|
||||||
|
"raf": "^3.2.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"es2020": "^1.1.7"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
function formatMinutes (minutes) {
|
||||||
|
return `${minutes >= 10 ? minutes : (minutes < 10) ? '0' + minutes : '00'}`
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatSeconds (seconds) {
|
||||||
|
return `${seconds < 10 ? '0' + seconds : seconds}`
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = function format (elapsed) {
|
||||||
|
const minutes = formatMinutes(Math.floor((elapsed / 1000) / 60))
|
||||||
|
const seconds = formatSeconds(Math.floor((elapsed / 1000) % 60))
|
||||||
|
const ms = formatSeconds(Math.floor((elapsed % 1000) / 10))
|
||||||
|
|
||||||
|
return `${minutes}:${seconds}.${ms}`
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
const html = require('../../../html')
|
||||||
|
const format = require('../utilities/format')
|
||||||
|
|
||||||
|
function toggle (state, send) {
|
||||||
|
if (state.start) {
|
||||||
|
send('stop')
|
||||||
|
} else {
|
||||||
|
send('start')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = (state, prev, send) => {
|
||||||
|
const start = state.start
|
||||||
|
const elapsed = state.elapsed
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<main class="app">
|
||||||
|
<h1>stopwatch</h1>
|
||||||
|
<p>${format(elapsed)}</p>
|
||||||
|
<button
|
||||||
|
onclick=${e => toggle(state, send)}
|
||||||
|
>${start ? 'stop' : 'start'}</button>
|
||||||
|
<button
|
||||||
|
style="display:${start ? 'none' : 'inline'};"
|
||||||
|
onclick=${e => send('reset')}
|
||||||
|
>reset</button>
|
||||||
|
<button
|
||||||
|
style="display:${start ? 'inline' : 'none'};"
|
||||||
|
onclick=${e => send('add', format(elapsed))}
|
||||||
|
>lap</button>
|
||||||
|
<ol>
|
||||||
|
${state.laps.map(lap => html`<li>${lap}</li>`)}
|
||||||
|
</ol>
|
||||||
|
</main>
|
||||||
|
`
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user