|
<template> |
|
<div id="app"> |
|
<nav> |
|
<ul> |
|
<li><a href="#" @click="showPage('pomodoro')">Pomodoro Timer</a></li> |
|
<li><a href="#" @click="showPage('login')">Login</a></li> |
|
<li><a href="#" @click="showPage('register')">Register</a></li> |
|
</ul> |
|
</nav> |
|
|
|
<div v-if="page === 'pomodoro'"> |
|
<h1>Pomodoro Timer</h1> |
|
<div class="timer"> |
|
<div>{{ formattedTime }}</div> |
|
<button @click="startTimer">{{ isRunning ? "Pause" : "Start" }}</button> |
|
<button @click="resetTimer">Reset</button> |
|
</div> |
|
<div class="tasks"> |
|
<h2>Tasks</h2> |
|
<ul> |
|
<li v-for="(task, index) in tasks" :key="index"> |
|
<input |
|
type="checkbox" |
|
v-model="task.completed" |
|
@change="completeTask(index)" |
|
/> |
|
{{ task.name }} |
|
<button @click="deleteTask(index)">Delete</button> |
|
</li> |
|
</ul> |
|
<input |
|
v-model="newTask" |
|
placeholder="New task" |
|
@keyup.enter="addTask" |
|
/> |
|
<button @click="addTask">Add Task</button> |
|
</div> |
|
<footer> |
|
<p> |
|
Check out my |
|
<a href="https://linkedin.com/in/kevin-marville" target="_blank"> |
|
LinkedIn |
|
</a> |
|
</p> |
|
</footer> |
|
</div> |
|
|
|
<div v-if="page === 'login'"> |
|
<h1>Login</h1> |
|
<input v-model="username" placeholder="Username" /> |
|
<input type="password" v-model="password" placeholder="Password" /> |
|
<button @click="login">Login</button> |
|
<p v-if="loginMessage">{{ loginMessage }}</p> |
|
</div> |
|
|
|
<div v-if="page === 'register'"> |
|
<h1>Register</h1> |
|
<input v-model="newUsername" placeholder="Username" /> |
|
<input type="password" v-model="newPassword" placeholder="Password" /> |
|
<button @click="register">Register</button> |
|
<p v-if="registerMessage">{{ registerMessage }}</p> |
|
</div> |
|
|
|
<div class="floating-bubble"> |
|
<a href="https://kvnbbg-creations.io" target="_blank"> |
|
<span role="img" aria-label="panda">🐼</span> |
|
Je cherche de nouvelles opportunités sur le marché du travail |
|
aujourd'hui |
|
</a> |
|
</div> |
|
|
|
<audio ref="audio" :src="alarmSound"></audio> |
|
</div> |
|
</template> |
|
|
|
<script> |
|
export default { |
|
data() { |
|
return { |
|
page: "pomodoro", |
|
time: 25 * 60, |
|
timer: null, |
|
isRunning: false, |
|
tasks: [], |
|
newTask: "", |
|
username: "", |
|
password: "", |
|
loginMessage: "", |
|
newUsername: "", |
|
newPassword: "", |
|
registerMessage: "", |
|
alarmSound: "https://www.soundjay.com/button/beep-07.wav" |
|
}; |
|
}, |
|
computed: { |
|
formattedTime() { |
|
const minutes = Math.floor(this.time / 60); |
|
const seconds = this.time % 60; |
|
return `${minutes |
|
.toString() |
|
.padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`; |
|
} |
|
}, |
|
methods: { |
|
showPage(page) { |
|
this.page = page; |
|
}, |
|
startTimer() { |
|
if (this.isRunning) { |
|
this.pauseTimer(); |
|
} else { |
|
this.isRunning = true; |
|
this.timer = setInterval(() => { |
|
if (this.time > 0) { |
|
this.time--; |
|
} else { |
|
this.stopTimer(); |
|
this.playAlarm(); |
|
} |
|
}, 1000); |
|
} |
|
}, |
|
pauseTimer() { |
|
clearInterval(this.timer); |
|
this.isRunning = false; |
|
}, |
|
stopTimer() { |
|
clearInterval(this.timer); |
|
this.isRunning = false; |
|
}, |
|
resetTimer() { |
|
this.stopTimer(); |
|
this.time = 25 * 60; |
|
}, |
|
addTask() { |
|
if (this.newTask.trim()) { |
|
this.tasks.push({ name: this.newTask, completed: false }); |
|
this.newTask = ""; |
|
} |
|
}, |
|
deleteTask(index) { |
|
this.tasks.splice(index, 1); |
|
}, |
|
completeTask(index) { |
|
if (this.tasks[index].completed) { |
|
this.deleteTask(index); |
|
} |
|
}, |
|
playAlarm() { |
|
this.$refs.audio.play(); |
|
}, |
|
login() { |
|
if (this.username && this.password) { |
|
this.loginMessage = `Bravo! ${this.username}, félicitations, vous avez réussi à vous connecter.`; |
|
} else { |
|
this.loginMessage = "Veuillez remplir tous les champs."; |
|
} |
|
}, |
|
register() { |
|
if (this.newUsername && this.newPassword) { |
|
this.registerMessage = `Bravo! ${this.newUsername}, félicitations, vous vous êtes inscrit avec succès.`; |
|
} else { |
|
this.registerMessage = "Veuillez remplir tous les champs."; |
|
} |
|
} |
|
}, |
|
beforeDestroy() { |
|
this.stopTimer(); |
|
} |
|
}; |
|
</script> |
|
|
|
<style> |
|
#app { |
|
font-family: Avenir, Helvetica, Arial, sans-serif; |
|
text-align: center; |
|
color: #2c3e50; |
|
margin-top: 60px; |
|
background: #fff; |
|
border-radius: 10px; |
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); |
|
padding: 20px; |
|
width: 90%; |
|
max-width: 600px; |
|
margin: 20px auto; |
|
transition: all 0.3s ease; |
|
} |
|
|
|
nav ul { |
|
list-style: none; |
|
padding: 0; |
|
display: flex; |
|
justify-content: center; |
|
margin-bottom: 20px; |
|
} |
|
|
|
nav li { |
|
margin: 0 10px; |
|
} |
|
|
|
nav a { |
|
text-decoration: none; |
|
color: #4fc08d; |
|
font-weight: bold; |
|
} |
|
|
|
h1 { |
|
font-size: 2em; |
|
margin-bottom: 20px; |
|
} |
|
|
|
.timer { |
|
font-size: 2em; |
|
margin-bottom: 20px; |
|
} |
|
|
|
button { |
|
background: #4fc08d; |
|
color: #fff; |
|
border: none; |
|
padding: 10px 20px; |
|
border-radius: 5px; |
|
cursor: pointer; |
|
margin: 5px; |
|
transition: background 0.3s; |
|
} |
|
|
|
button:hover { |
|
background: #3da76f; |
|
} |
|
|
|
.tasks { |
|
text-align: left; |
|
margin-top: 20px; |
|
} |
|
|
|
.tasks h2 { |
|
font-size: 1.5em; |
|
margin-bottom: 10px; |
|
} |
|
|
|
.tasks ul { |
|
list-style: none; |
|
padding: 0; |
|
} |
|
|
|
.tasks li { |
|
background: #ececec; |
|
border: 1px solid #ddd; |
|
margin: 10px 0; |
|
padding: 10px; |
|
border-radius: 5px; |
|
display: flex; |
|
justify-content: space-between; |
|
align-items: center; |
|
} |
|
|
|
.tasks input[type="text"] { |
|
padding: 10px; |
|
border: 1px solid #ddd; |
|
border-radius: 5px; |
|
width: calc(100% - 40px); |
|
} |
|
|
|
.tasks input[type="checkbox"] { |
|
margin-right: 10px; |
|
} |
|
|
|
footer { |
|
margin-top: 20px; |
|
} |
|
|
|
footer a { |
|
color: #4fc08d; |
|
text-decoration: none; |
|
} |
|
|
|
.floating-bubble { |
|
position: fixed; |
|
bottom: 20px; |
|
right: 20px; |
|
background: #4fc08d; |
|
color: #fff; |
|
padding: 10px; |
|
border-radius: 5px; |
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); |
|
animation: float 5s ease-in-out infinite; |
|
} |
|
|
|
.floating-bubble a { |
|
color: #fff; |
|
text-decoration: none; |
|
} |
|
|
|
@keyframes float { |
|
0% { |
|
transform: translateY(0); |
|
} |
|
50% { |
|
transform: translateY(-10px); |
|
} |
|
100% { |
|
transform: translateY(0); |
|
} |
|
} |
|
</style> |