Home / Blog / Building a “Procrastination Timer” with Vue 3 Composition API
Building a “Procrastination Timer” with Vue 3 Composition API

Building a “Procrastination Timer” with Vue 3 Composition API

Daniel Kelly
Daniel Kelly
Updated: September 4th 2024

NOTE: This article was written entirely by Claude.ai for fun and to test out the abilities of the AI model. We hope you enjoy this humorous Vue component. Plus it does actually work!

Intro

Are you tired of productivity apps shaming you into work? Fear not! Today, we're going to build the world's first (probably) Procrastination Timer using Vue 3's Composition API. This revolutionary component will help users track and celebrate their procrastination efforts. Remember, time you enjoy wasting is not wasted time!

The "Problem"

In a world obsessed with productivity, we're missing out on the joys of procrastination. Our users need a tool to track their leisure time and remind them to take more breaks. It's not procrastination; it's "pre-productivity"!

The Solution: A Vue 3 Procrastination Timer

We'll create a timer that counts up instead of down, rewarding users for their dedication to doing absolutely nothing productive. Let's dive into the code:

<template>
  <div class="procrastination-timer">
    <h2>{{ title }}</h2>
    <div class="timer">{{ formattedTime }}</div>
    <div class="controls">
      <button @click="startTimer" :disabled="isRunning">Start Slacking</button>
      <button @click="pauseTimer" :disabled="!isRunning">Pause (As If You Need It)</button>
      <button @click="resetTimer">Back to "Work"</button>
    </div>
    <div class="achievement" v-if="currentAchievement">
      <p>Achievement Unlocked: {{ currentAchievement }}</p>
    </div>
  </div>
</template>

<script>
import { ref, computed, watch } from 'vue'

export default {
  name: 'ProcrastinationTimer',
  setup() {
    const title = ref('Procrastination Timer: Because Productivity is Overrated')
    const time = ref(0)
    const isRunning = ref(false)
    const interval = ref(null)
    const currentAchievement = ref('')

    const achievements = [
      { time: 300, message: "Coffee Break Master" },
      { time: 900, message: "Social Media Guru" },
      { time: 1800, message: "Netflix Episode Completionist" },
      { time: 3600, message: "Professional Time Waster" }
    ]

    const formattedTime = computed(() => {
      const hours = Math.floor(time.value / 3600)
      const minutes = Math.floor((time.value % 3600) / 60)
      const seconds = time.value % 60
      return `${hours.toString().padStart(2, '0')}:${minutes
        .toString()
        .padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`
    })

    const startTimer = () => {
      if (!isRunning.value) {
        isRunning.value = true
        interval.value = setInterval(() => {
          time.value++
        }, 1000)
      }
    }

    const pauseTimer = () => {
      clearInterval(interval.value)
      isRunning.value = false
    }

    const resetTimer = () => {
      pauseTimer()
      time.value = 0
      currentAchievement.value = ''
    }

    watch(time, (newValue) => {
      const achievement = achievements.find(a => a.time === newValue)
      if (achievement) {
        currentAchievement.value = achievement.message
      }
    })

    return {
      title,
      formattedTime,
      isRunning,
      currentAchievement,
      startTimer,
      pauseTimer,
      resetTimer
    }
  }
}
</script>

<style scoped>
.procrastination-timer {
  text-align: center;
  font-family: 'Comic Sans MS', cursive; /* Because we're serious about not being serious */
}

.timer {
  font-size: 2em;
  margin: 20px 0;
}

.controls button {
  margin: 0 10px;
  padding: 10px 20px;
  font-size: 1em;
  background-color: #f0f0f0;
  border: none;
  border-radius: 5px;
  cursor: pointer;
}

.controls button:hover {
  background-color: #e0e0e0;
}

.achievement {
  margin-top: 20px;
  font-style: italic;
  color: #4a4a4a;
}
</style>

NOTE: The code generated by clause doesn’t use script setup. We could have probably refined it further in the chat but left the original intact for the sake of transparency. If you’d like to learn more about using script setup with the composition API and why you should, checkout our course Vue 3 Composition API.

How It Works (or Doesn't, We Don't Judge)

  1. We use ref to create reactive references for our state variables.
  2. The computed function creates a formatted time string.
  3. We have three methods: startTimer, pauseTimer, and resetTimer.
  4. A watch function observes the time ref and unlocks achievements.
  5. We return the necessary refs and methods from our setup function.

Using the Procrastination Timer

Here's how you can integrate this life-changing component into your app:

<template>
  <div>
    <h1>Welcome to the Procrastination Zone</h1>
    <ProcrastinationTimer />
  </div>
</template>

<script>
import { defineComponent } from 'vue'
import ProcrastinationTimer from './ProcrastinationTimer.vue'

export default defineComponent({
  name: 'App',
  components: {
    ProcrastinationTimer
  }
})
</script>

NOTE: Once again, we probably would have opted for script seutp.

Benefits of This Approach (Besides Avoiding Real Work)

  1. Reusability: Procrastinate across multiple components!
  2. Composition API: Embrace the future of Vue while avoiding the future of work.
  3. Achievements: Gamify your laziness for maximum satisfaction.
  4. Humor: Inject some fun into your app and your workday.

Conclusion

By creating this Procrastination Timer, we've solved the age-old problem of productivity apps making us feel guilty. This component celebrates the art of doing nothing while showcasing Vue 3's Composition API. Remember, it's not about the destination, it's about the journey... especially if that journey involves your couch and a bag of chips.

Next time your boss asks what you've been working on, just show them this timer. They'll either be impressed by your Vue 3 skills or concerned about your work ethic. Either way, that's a problem for future you!

Start learning Vue.js for free

Daniel Kelly
Daniel Kelly
Daniel is the lead instructor at Vue School and enjoys helping other developers reach their full potential. He has 10+ years of developer experience using technologies including Vue.js, Nuxt.js, and Laravel.

Comments

Latest Vue School Articles

From Vue.js Options API to Composition API: Is it Worth it?

From Vue.js Options API to Composition API: Is it Worth it?

Explore the technicalities of transitioning from Options API to Composition API in Vue.js. Discover if migrating your app is worth the effort in our detailed guide
Mostafa Said
Mostafa Said
What’s New in Nuxt 4

What’s New in Nuxt 4

Have anxiety about a new major version of Nuxt coming out? Worried about a big migration project? Don’t worry about it, a peaceful and easy upgrade is literally one of the features of Nuxt version 4.
Daniel Kelly
Daniel Kelly

Our goal is to be the number one source of Vue.js knowledge for all skill levels. We offer the knowledge of our industry leaders through awesome video courses for a ridiculously low price.

More than 200.000 users have already joined us. You are welcome too!

Follow us on Social

© All rights reserved. Made with ❤️ by BitterBrains, Inc.