Skip to content

Commit a939b5a

Browse files
committed
Dia 3
1 parent 856b832 commit a939b5a

File tree

9 files changed

+150
-23
lines changed

9 files changed

+150
-23
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { mount } from '@vue/test-utils'
3+
import HelloWorld from './HelloWorld.vue'
4+
5+
describe('HelloWorld', () => {
6+
it('should render', () => {
7+
const wrapper = mount(HelloWorld, {
8+
props: {
9+
msg: 'Hello World',
10+
},
11+
})
12+
13+
expect(wrapper.html()).toContain('<h1>Hello World</h1>')
14+
})
15+
16+
it('emits the salute event', () => {
17+
const wrapper = mount(HelloWorld, {
18+
props: {
19+
msg: 'Hello World',
20+
},
21+
})
22+
23+
const button = wrapper.find('button')
24+
button.trigger('click')
25+
26+
const emittedEvents = wrapper.emitted()
27+
28+
expect(emittedEvents.salute[0]).toEqual(['hiiiiii'])
29+
})
30+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<template>
2+
<div>
3+
<h1>{{ msg }}</h1>
4+
<h2 v-if="subtitle">{{ subtitle }}</h2>
5+
<button @click="emit('salute', 'hiiiiii')">Click me</button>
6+
</div>
7+
</template>
8+
9+
<script setup lang="ts">
10+
defineProps<{
11+
msg: string
12+
subtitle?: string
13+
}>()
14+
15+
const emit = defineEmits<{
16+
salute: [salutation: string]
17+
}>()
18+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { beforeEach, describe, expect, it } from 'vitest'
2+
import { mount } from '@vue/test-utils'
3+
4+
import ToDoList from './ToDoList.vue'
5+
import { createPinia, setActivePinia } from 'pinia'
6+
7+
describe('ToDoList', () => {
8+
beforeEach(() => {
9+
setActivePinia(createPinia())
10+
})
11+
12+
it('should render', () => {
13+
const wrapper = mount(ToDoList)
14+
15+
const label = wrapper.find('label')
16+
17+
console.log(label)
18+
19+
expect(label.text()).toMatchInlineSnapshot(`"Show only pending"`)
20+
})
21+
})

04-frameworks/03-vue/Dia_3/src/components/ToDoList.vue renamed to 04-frameworks/03-vue/Dia_3/src/components/ToDoList/ToDoList.vue

+26-7
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,44 @@
11
<script setup lang="ts">
2-
import { onMounted } from 'vue'
3-
import { useTodosStore } from '../stores/todos'
2+
import { ref, onMounted } from 'vue'
3+
import { useTodosStore } from '../../stores/todos'
44
55
const todosStore = useTodosStore()
66
7-
onMounted(() => {
8-
todosStore.loadTodos()
9-
})
10-
117
const onChange = (timestamp: number) => {
128
todosStore.toggleCompleted(timestamp)
139
}
1410
1511
const onClick = (timestamp: number) => {
1612
todosStore.removeTodo(timestamp)
1713
}
14+
15+
const toDosToShow = ref(todosStore.todos)
16+
17+
const showOnlyPendingToDos = (event: Event) => {
18+
if ((event.target as HTMLInputElement)?.checked) {
19+
toDosToShow.value = todosStore.pendingToDos
20+
} else {
21+
toDosToShow.value = todosStore.todos
22+
}
23+
}
24+
25+
onMounted(() => {
26+
todosStore.loadTodos()
27+
toDosToShow.value = todosStore.todos
28+
})
1829
</script>
1930

2031
<template>
32+
<div v-if="todosStore.total">
33+
<p>Completed: {{ todosStore.completed }} / {{ todosStore.total }}</p>
34+
</div>
35+
<div>
36+
<input type="checkbox" id="toggle" @change="showOnlyPendingToDos" />
37+
<label for="toggle">Show only pending</label>
38+
</div>
39+
<hr />
2140
<ul class="max-w-[500px]">
22-
<li v-for="todo in todosStore.todos" :key="todo.timestamp">
41+
<li v-for="todo in toDosToShow" :key="todo.timestamp">
2342
<form @submit.prevent class="flex items-center justify-between">
2443
<input
2544
type="checkbox"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
export const useStorage = <T>(storageKey: string) => {
2+
const get = () => {
3+
const value = localStorage.getItem(storageKey)
4+
return value ? (JSON.parse(value) as T) : []
5+
}
6+
7+
const set = (value: T) => {
8+
localStorage.setItem(storageKey, JSON.stringify(value))
9+
}
10+
11+
return {
12+
get,
13+
set,
14+
}
15+
}

04-frameworks/03-vue/Dia_3/src/stores/todos.ts

+17-14
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,57 @@
1-
import { ref } from 'vue'
1+
import { computed, ref } from 'vue'
22
import { defineStore } from 'pinia'
33

44
import type { ToDo } from '../types'
5+
import { useStorage } from '../composables/storage'
56

67
const toDoFactory = (text: string): ToDo => ({
78
timestamp: Date.now(),
89
text,
910
completed: false,
1011
})
1112

12-
const getTodosFromLocalStorage = (): ToDo[] => {
13-
const todos = localStorage.getItem('todos') ? JSON.parse(localStorage.getItem('todos')!) : []
14-
return todos
15-
}
16-
17-
const setTodosToLocalStorage = (todo: ToDo) => {
18-
const storedValue = getTodosFromLocalStorage()
19-
storedValue.push(todo)
20-
localStorage.setItem('todos', JSON.stringify(storedValue))
21-
}
22-
2313
export const useTodosStore = defineStore('todosStore', () => {
2414
const todos = ref<ToDo[]>([])
15+
const completedToDos = computed(() => todos.value.filter((todo) => todo.completed))
16+
const pendingToDos = computed(() => todos.value.filter((todo) => !todo.completed))
17+
18+
const total = computed(() => todos.value.length)
19+
const completed = computed(() => completedToDos.value.length)
20+
21+
const storage = useStorage<ToDo[]>('todos')
2522

2623
const loadTodos = () => {
27-
todos.value = getTodosFromLocalStorage()
24+
todos.value = storage.get()
2825
}
2926

3027
const addTodo = (todo: string) => {
3128
const newTodo = toDoFactory(todo)
3229
todos.value.push(newTodo)
33-
setTodosToLocalStorage(newTodo)
30+
storage.set(todos.value)
3431
}
3532

3633
const toggleCompleted = (timestamp: number) => {
3734
const todo = todos.value.find((todo) => todo.timestamp === timestamp)
3835
if (todo) {
3936
todo.completed = !todo.completed
4037
}
38+
storage.set(todos.value)
4139
}
4240

4341
const removeTodo = (timestamp: number) => {
4442
const index = todos.value.findIndex((todo) => todo.timestamp === timestamp)
4543
if (index !== -1) {
4644
todos.value.splice(index, 1)
4745
}
46+
storage.set(todos.value)
4847
}
4948

5049
return {
5150
todos,
51+
total,
52+
completed,
53+
completedToDos,
54+
pendingToDos,
5255
loadTodos,
5356
addTodo,
5457
toggleCompleted,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { describe, it, expect } from 'vitest'
2+
import { sum } from './sum'
3+
4+
describe('sum', () => {
5+
it('should add two numbers', () => {
6+
expect(sum(1, 2)).toBe(3)
7+
})
8+
9+
it('should add three numbers', () => {
10+
const result = sum(1, 2, 3)
11+
12+
const expected = 6
13+
14+
expect(result).toBe(expected)
15+
})
16+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export const sum = (...operands: number[]) =>
2+
operands.reduce((accumulator, current) => accumulator + current, 0)
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
<script setup lang="ts">
2-
import { ref } from 'vue'
2+
import HelloWorld from '../components/HelloWorld/HelloWorld.vue'
33
import ToDoForm from '../components/ToDoForm.vue'
4-
import TodoList from '../components/TodoList.vue'
4+
import TodoList from '../components/ToDoList/ToDoList.vue'
55
</script>
66

77
<template>
88
<main class="py-4">
99
<ToDoForm />
1010
<TodoList />
1111
</main>
12+
<footer>
13+
<HelloWorld msg="holaaaa" />
14+
</footer>
1215
</template>

0 commit comments

Comments
 (0)