Simple aplicación web del la técnica de pomodoro, pomodoro app, implementación simple con html, css y javascript. comparte este post de desarrollo web.
February 11, 2021 , 5 min read
Share with:Pomodoro APP html css js
La Técnica Pomodoro es un método para mejorar la administración del tiempo dedicado a una actividad. Fue creado por Francesco Cirillo a fines de la década de 1980.1 Se basa en usar un temporizador para dividir el tiempo en intervalos fijos, llamados pomodoros, de 25 minutos de actividad, seguidos de 5 minutos de descanso, con pausas más largas cada cuatro pomodoros.
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Pomodoro Clock</title>
</head>
<body>
<div id="app">
<heading :title="title"></heading>
<div class="container">
<div class="container-counters">
<counter :counter="counterActive"
:title="titleActive"
@dec="decrement(1)"
@inc="increment(1)"></counter>
<counter :counter="counterRest"
:title="titleRest"
@dec="decrement(2)"
@inc="increment(2)"></counter>
</div>
<div class="container-progress">
<progressbar :offset="offset"
@startstop="timerStartStop"
:bg="bg"
:fg="fg"
:minutes="minutes"
:seconds="seconds"></progressbar>
</div>
</div>
<script src="https://unpkg.com/vue@2.0.3/dist/vue.min.js"></script>
</body>
</html>
@import url('https://fonts.googleapis.com/css?family=Roboto+Mono:400,700');
@import url('https://fonts.googleapis.com/css?family=Berkshire+Swash|Pacifico');
* {
margin: 0;
padding: 0;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
body {
background-color: lightgray;
background-color: #222;
}
.container {
font-family: 'Roboto Mono', monospace;
width: 400px;
height: 500px;
background-color: #222;
margin: 20px auto;
}
.container-counters {
display:-webkit-box;
display:-ms-flexbox;
display:flex;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
width: 400px;
height: 150px;
}
header {
color: lightgreen;
font-family: 'Berkshire Swash', cursive;
text-align: center;
font-size: 30px;
padding: 50px 0 30px 0;
}
#counter {
color: lightgreen;
}
.counter-title {
text-align: center;
}
.output {
height: 100px;
width: 120px;
display:-webkit-box;
display:-ms-flexbox;
display:flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
font-size: 2em;
}
.btns {
height: 50px;
width: 120px;
display:-webkit-box;
display:-ms-flexbox;
display:flex;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
font-size: 2em;
}
.dec {
margin-left: 10px;
}
.inc {
margin-right: 10px;
}
.dec:hover, .inc:hover {
cursor: pointer;
}
.container-progress {
height: 300px;
display:-webkit-box;
display:-ms-flexbox;
display:flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
.container-progress:hover {
cursor: pointer;
}
#display {
position: relative;
width: 200px;
height: 200px;
}
.timer {
display:block;
position: absolute;
display:-webkit-box;
display:-ms-flexbox;
display:flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
top: 0;
left: 0;
font-size: 3em;
color: lightgreen;
width: 200px;
height: 200px;
}
svg {
-webkit-transform: rotate(-90deg);
-ms-transform: rotate(-90deg);
transform: rotate(-90deg);
}
// global variable for timer
var timer;
// header
var Head = {
props: ["title"],
template: "<header><h1>{{ title }}</h1></header>"
};
// counter
var Counter = {
props: ["title", "counter"],
template: '<div id="counter"><div class="counter-title"><span>{{ title }}</span></div><div class="output"><span>{{ counter }}</span></div><div class="btns"><span class="dec" @click="decHandler">-</span><span class="inc" @click="incHandler">+</span></div></div>',
methods: {
incHandler: function() {
this.$emit("inc");
},
decHandler: function() {
this.$emit("dec");
}
}
};
// radial progress bar
var Progress = {
props: ["offset", "minutes", "seconds", "bg", "fg"],
template: '<div id="display" @click="tick"><svg width="200" height="200" viewBox="0 0 200 200"><circle cx= "100" cy="100" r="94" fill="none" :stroke="bg" stroke-width="12"/><circle cx= "100" cy="100" r="94" fill="none" :stroke="fg" stroke-width="12" stroke-dasharray="590.619" :stroke-dashoffset="offset"/></svg><div class="timer"><div class="minutes"><span>{{ minutes }}:</span></div><div class="seconds"><span>{{ seconds }}</span></div></div></div>',
methods: {
tick: function() {
this.$emit("startstop");
}
}
};
var main = new Vue({
el: "#app",
data: {
title: "Pomodoro Clock", // main title
titleActive: "ACTIVE", // activity counter title
titleRest: "REST", // rest counter title
bg: "#333", // background colour of progress bar
fg: "#90EE90", // foreground colour of progress bar
running: false, // is the timer running
counterActive: 25, // set value for activity counter
counterRest: 5, // set value for rest counter
offset: "590.619", // offset for progress bar
percentage: "0", // percentage progress
minutes: 0, // minutes on clock
seconds: 0 // seconds on clock
},
components: {
"heading": Head,
"counter": Counter,
"progressbar": Progress
},
methods: {
increment: function(num) {
if(num === 1 && this.counterActive < 90) {
this.counterActive += 1;
} else if(num === 2 && this.counterRest < 60) {
this.counterRest += 1;
}
},
decrement: function(num) {
if(num === 1 && this.counterActive > 0) {
this.counterActive -= 1;
} else if(num === 2 && this.counterRest > 0) {
this.counterRest -= 1;
}
},
timerStartStop: function() {
if(this.running === false) {
var snd = new Audio("https://cdn.rawgit.com/aronnax77/pomodoro_clock/master/audio/beep-05.mp3");
var count = 1;
var numSecs = this.counterActive * 60;
timer = setInterval(function() {
main.running = true;
main.seconds = numSecs % 60;
main.minutes = (numSecs - main.seconds)/60;
showProgress(numSecs, count);
numSecs -= 1;
if(numSecs === -1 && count === 1) {
numSecs = main.counterRest * 60;
main.fg = "#f77a52";
count = 2;
snd.play();
} else if(numSecs === -1 && count === 2){
clearInterval(timer);
main.fg = "#90EE90";
main.offset = "590.619";
main.running = false;
snd.play();
}
}, 1000);
this.running = true;
} else if(this.running === true) {
this.running = false;
clearInterval(timer);
this.minutes = 0;
this.seconds = 0;
this.offset = "590.619";
this.fg = "#90EE90";
}
}
}
});
// helper function for timerStartStop
function showProgress(rem, cnt) {
if(cnt === 1) {
main.offset = Math.PI * 2 * 94 * (rem / (main.counterActive * 60));
} else if(cnt === 2) {
main.offset = Math.PI * 2 * 94 * (rem / (main.counterRest * 60));
}
}