@@ -5,7 +5,9 @@ import { useToast } from 'vue-toastification'
55import Todo from ' ./components/TodoItem.vue'
66import { slugger } from ' ./lib/slugger'
77
8+ const error = ref (false )
89const todoInput = ref (' ' )
10+ const todoInputComponent = ref <HTMLDivElement >()
911const todoList: { todos: TodoData [] } = reactive ({
1012 todos: []
1113})
@@ -24,14 +26,15 @@ const toast = useToast()
2426function addNewTodo() {
2527 // Prevent todo names less than 2 characters
2628 if (todoInput .value .length < 2 ) {
29+ error .value = true
2730 toast .warning (" The to-do name has to be more than 2 characters" )
2831 return
2932 }
3033
3134 // Prevent repeated todos
3235 const repeatedList = todoList .todos .filter (todo => slugger (todo .name ) === slugger (todoInput .value ))
33- console .log (repeatedList )
3436 if (repeatedList .length > 0 ) {
37+ error .value = true
3538 toast .warning (" There is already a to-do with that name" )
3639 return
3740 }
@@ -69,6 +72,12 @@ onMounted(() => {
6972 const parsedTodoList: TodoData [] = JSON .parse (savedTodoList )
7073 todoList .todos .push (... parsedTodoList )
7174 }
75+
76+ todoInputComponent ?.value ?.addEventListener (" animationend" , () => {
77+ error .value = false
78+ })
79+
80+
7281})
7382 </script >
7483
@@ -79,7 +88,8 @@ onMounted(() => {
7988 class =' h-full bg-vue-light transition-all rounded-r-full data-[percentage="100"]:rounded-none'
8089 :style =" { width: completedPercentage + '%' }" />
8190 </div >
82- <div class =" content-container fixed bottom-20 space-y-1" >
91+ <div :data-error =" error" ref =" todoInputComponent"
92+ class =' content-container fixed bottom-20 space-y-1 data-[error="true"]:animate-shake' >
8393 <div class =" flex items-stretch justify-between gap-3" >
8494 <input type =" text" v-model =" todoInput" @keypress.enter =" addNewTodo" placeholder =" Some task"
8595 class =" h-12 w-full rounded-lg border-none bg-neutral-200/80 p-3 text-xl backdrop-blur-[80px] focus:bg-neutral-200/10 focus:ring-2 focus:ring-vue-light" />
0 commit comments