@@ -21,35 +21,69 @@ const completedPercentage = computed(() => {
2121 return (completedTodos / totalOfTodos ) * 100
2222})
2323
24+ const isEmpty = computed (() => todoList .todos .length < 1 )
25+
2426const toast = useToast ()
2527
26- function addNewTodo() {
28+ function isTodoCreated(name : string ) {
29+ const repeatedList = todoList .todos .filter (todo => slugger (todo .name ) === slugger (name ))
30+
31+ if (repeatedList .length > 0 ) return true
32+ else return false
33+ }
34+
35+ function addNewTodo(name : string ) {
2736 // Prevent todo names less than 2 characters
28- if (todoInput . value .length < 2 ) {
37+ if (name .length < 2 ) {
2938 error .value = true
3039 toast .warning (" The to-do name has to be more than 2 characters" )
3140 return
3241 }
3342
3443 // Prevent repeated todos
35- const repeatedList = todoList .todos .filter (todo => slugger (todo .name ) === slugger (todoInput .value ))
36- if (repeatedList .length > 0 ) {
44+ if (isTodoCreated (name )) {
3745 error .value = true
3846 toast .warning (" There is already a to-do with that name" )
3947 return
4048 }
4149
4250
4351 todoList .todos .push ({
44- name: todoInput . value ,
52+ name: name ,
4553 complete: false ,
46- id: slugger (todoInput . value ) + ' _' + Date .now ()
54+ id: slugger (name ) + ' _' + Date .now ()
4755 })
4856 window .scrollTo ({ top: document .body .scrollHeight , behavior: ' smooth' })
4957 todoInput .value = ' '
5058
5159}
5260
61+ const randomTodos = [
62+ ' Read "Foundation", Isaac Asimov.' ,
63+ ' Watch "The Matrix"' ,
64+ ' Watch "Inglourious Basterds"' ,
65+ ' Watch "Mr. Robot" serie' ,
66+ ' Play Skyrim game' ,
67+ ' Listen "Da Ponte pra Cá", Racionais MC.' ,
68+ ]
69+ const randomTodoTryTime = ref (1 )
70+
71+ function addRandomTodo() {
72+ if (randomTodoTryTime .value > randomTodos .length ) return
73+
74+ const randomIndex = Math .floor (Math .random () * randomTodos .length )
75+ const randomTodo = randomTodos [randomIndex ]
76+
77+
78+ if (isTodoCreated (randomTodo )) {
79+ randomTodoTryTime .value += 1
80+ addRandomTodo ()
81+ }
82+ else {
83+ addNewTodo (randomTodo )
84+ }
85+ }
86+
5387function removeTodo(todoId : string ) {
5488 todoList .todos = todoList .todos .filter ((todo ) => todo .id !== todoId )
5589}
@@ -73,6 +107,8 @@ onMounted(() => {
73107 todoList .todos .push (... parsedTodoList )
74108 }
75109
110+ addRandomTodo ()
111+
76112 todoInputComponent ?.value ?.addEventListener (" animationend" , () => {
77113 error .value = false
78114 })
@@ -83,24 +119,26 @@ onMounted(() => {
83119
84120<template >
85121 <div class =" space-y-5" >
86- <div class =" fixed left-0 right-0 top-0 h-2 w-full " :class =" todoList.todos.length > 0 && 'bg-neutral-100'" >
122+ <div class =" fixed top-0 left-0 right-0 w-full h-2" :class =" todoList.todos.length > 0 && 'bg-neutral-100'" >
87123 <div :data-percentage =" completedPercentage"
88124 class =' h-full bg-vue-light transition-all rounded-r-full data-[percentage="100"]:rounded-none'
89125 :style =" { width: completedPercentage + '%' }" />
90126 </div >
91127 <div :data-error =" error" ref =" todoInputComponent"
92128 class =' content-container fixed bottom-20 space-y-1 data-[error="true"]:animate-shake' >
93129 <div class =" flex items-stretch justify-between gap-3" >
94- <input type =" text" v-model =" todoInput" @keypress.enter =" addNewTodo" placeholder =" Some task"
130+ <input type =" text" v-model =" todoInput" @keypress.enter =" () => addNewTodo(todoInput) " placeholder =" Some task"
95131 class =" h-12 w-full rounded-lg border-none bg-neutral-200/95 p-3 text-xl backdrop-blur-[80px] focus:bg-neutral-100/95 focus:ring-2 focus:ring-vue-light transition-colors" />
96- <button @click =" addNewTodo"
132+ <button @click =" () => addNewTodo(todoInput) "
97133 class =" flex aspect-square h-12 items-center justify-center rounded-lg bg-vue-dark/70 text-xl text-white backdrop-blur-[80px] transition-colors hover:bg-vue-dark" >
98134 <PhPlus weight =" bold" />
99135 </button >
100136 </div >
101137 </div >
102138
103- <div class =" content-container space-y-1" >
139+ <div class =" space-y-1 content-container" >
140+ <img src =" /to-do-list.svg" :data-is-empty =" isEmpty"
141+ class =" fixed opacity-50 -translate-x-1/2 data-[is-empty='false']:opacity-10 transition-opacity duration-500 -translate-y-1/3 w-96 -z-10 top-1/3 left-1/2" />
104142 <Todo v-for =" todo in todoList.todos" :key =" todo.id" :todo =" todo" :remove-fn =" removeTodo"
105143 :toggle-fn =" toggleTodoCheck" />
106144 </div >
0 commit comments