|
|
@ -78,18 +78,24 @@
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="toast-container position-fixed bottom-0 end-0 p-3">
|
|
|
|
|
|
|
|
<ErrorToast v-for="item in errors" :key="item" :messages="item.messages" @closed="removeToast(item)" />
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
<script setup>
|
|
|
|
import { ref, onMounted, computed } from 'vue'
|
|
|
|
import { ref, onMounted, computed, reactive } from 'vue'
|
|
|
|
import { onBeforeRouteUpdate, useRoute, RouterLink } from 'vue-router'
|
|
|
|
import { onBeforeRouteUpdate, useRoute, RouterLink } from 'vue-router'
|
|
|
|
import svc from '../services/todoService'
|
|
|
|
import svc from '../services/todoService'
|
|
|
|
import { useDebouncedRef } from '../services/composables'
|
|
|
|
import { useDebouncedRef } from '../services/composables'
|
|
|
|
import TodoItem from './TodoItem.vue';
|
|
|
|
import TodoItem from './TodoItem.vue';
|
|
|
|
|
|
|
|
import ErrorToast from './ErrorToast.vue';
|
|
|
|
|
|
|
|
|
|
|
|
const route = useRoute()
|
|
|
|
const route = useRoute()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const errors = reactive([])
|
|
|
|
|
|
|
|
|
|
|
|
const totalCount = ref(0)
|
|
|
|
const totalCount = ref(0)
|
|
|
|
const left = ref(0)
|
|
|
|
const left = ref(0)
|
|
|
|
const search = ref()
|
|
|
|
const search = ref()
|
|
|
@ -111,6 +117,41 @@ const completedFilter = computed(() => {
|
|
|
|
})
|
|
|
|
})
|
|
|
|
const isEmpty = computed(() => !totalCount.value)
|
|
|
|
const isEmpty = computed(() => !totalCount.value)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function handleError(e) {
|
|
|
|
|
|
|
|
const messages = []
|
|
|
|
|
|
|
|
console.log(e)
|
|
|
|
|
|
|
|
const response = e.response
|
|
|
|
|
|
|
|
if (response) {
|
|
|
|
|
|
|
|
const status = response.status
|
|
|
|
|
|
|
|
if(status) {
|
|
|
|
|
|
|
|
if(status == 400) {
|
|
|
|
|
|
|
|
messages.push('API Error. HTTP 400: Bad request')
|
|
|
|
|
|
|
|
} else if (status == 401) {
|
|
|
|
|
|
|
|
messages.push('API Error. HTTP 401: Unauthorized')
|
|
|
|
|
|
|
|
} else if (status == 403) {
|
|
|
|
|
|
|
|
messages.push('API Error. HTTP 403: Forbidden')
|
|
|
|
|
|
|
|
} else if (status == 404) {
|
|
|
|
|
|
|
|
messages.push('API Error. HTTP 404: Not found')
|
|
|
|
|
|
|
|
} else if (status == 500) {
|
|
|
|
|
|
|
|
messages.push('API Error. HTTP 500: Internal server error')
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
messages.push(`API Error. HTTP ${status}`)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
messages.push('API Error. Network error')
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (e.code == 'ERR_NETWORK') {
|
|
|
|
|
|
|
|
messages.push('API Error: Connection refused')
|
|
|
|
|
|
|
|
} else if (e.code == 'ECONNABORTED' || e.code == 'ETIMEDOUT') {
|
|
|
|
|
|
|
|
messages.push('API Error: Timeout')
|
|
|
|
|
|
|
|
} else if (e.code == 'ERR_BAD_RESPONSE') {
|
|
|
|
|
|
|
|
messages.push('API Error: Bad response')
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
messages.push(`Unidentified error: ${e}`)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
errors.push({ messages })
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function updateStatus() {
|
|
|
|
async function updateStatus() {
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
const status = await svc.status()
|
|
|
|
const status = await svc.status()
|
|
|
@ -122,7 +163,7 @@ async function updateStatus() {
|
|
|
|
isCompleted.value = false
|
|
|
|
isCompleted.value = false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
} catch (e) {
|
|
|
|
console.log(e)
|
|
|
|
handleError(e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -137,7 +178,7 @@ async function refresh() {
|
|
|
|
totalCount.value = rv.totalCount
|
|
|
|
totalCount.value = rv.totalCount
|
|
|
|
await updateStatus()
|
|
|
|
await updateStatus()
|
|
|
|
} catch (e) {
|
|
|
|
} catch (e) {
|
|
|
|
console.log(e)
|
|
|
|
handleError(e)
|
|
|
|
} finally {
|
|
|
|
} finally {
|
|
|
|
isLoading.value = false
|
|
|
|
isLoading.value = false
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -152,7 +193,7 @@ async function deleteItem(id) {
|
|
|
|
})
|
|
|
|
})
|
|
|
|
await updateStatus()
|
|
|
|
await updateStatus()
|
|
|
|
} catch (e) {
|
|
|
|
} catch (e) {
|
|
|
|
console.log(e)
|
|
|
|
handleError(e)
|
|
|
|
} finally {
|
|
|
|
} finally {
|
|
|
|
isLoading.value = false
|
|
|
|
isLoading.value = false
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -173,7 +214,7 @@ async function onSubmit() {
|
|
|
|
await updateStatus()
|
|
|
|
await updateStatus()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
catch (e) {
|
|
|
|
console.log(e)
|
|
|
|
handleError(e)
|
|
|
|
} finally {
|
|
|
|
} finally {
|
|
|
|
isLoading.value = false
|
|
|
|
isLoading.value = false
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -197,7 +238,7 @@ async function onToggle(todo) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
await updateStatus()
|
|
|
|
await updateStatus()
|
|
|
|
} catch (e) {
|
|
|
|
} catch (e) {
|
|
|
|
console.log(e)
|
|
|
|
handleError(e)
|
|
|
|
} finally {
|
|
|
|
} finally {
|
|
|
|
isLoading.value = false
|
|
|
|
isLoading.value = false
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -223,7 +264,7 @@ async function onToggleAll() {
|
|
|
|
await updateStatus()
|
|
|
|
await updateStatus()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
catch (e) {
|
|
|
|
console.log(e)
|
|
|
|
handleError(e)
|
|
|
|
} finally {
|
|
|
|
} finally {
|
|
|
|
isLoading.value = false
|
|
|
|
isLoading.value = false
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -234,13 +275,20 @@ async function deleteCompleted() {
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
await svc.deleteCompleted();
|
|
|
|
await svc.deleteCompleted();
|
|
|
|
} catch (e) {
|
|
|
|
} catch (e) {
|
|
|
|
console.log(e)
|
|
|
|
handleError(e)
|
|
|
|
} finally {
|
|
|
|
} finally {
|
|
|
|
isLoading.value = false
|
|
|
|
isLoading.value = false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
await refresh()
|
|
|
|
await refresh()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function removeToast(item) {
|
|
|
|
|
|
|
|
const idx = errors.findIndex(x => x == item)
|
|
|
|
|
|
|
|
if (idx >= 0) {
|
|
|
|
|
|
|
|
errors.splice(idx, 1)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(refresh)
|
|
|
|
onMounted(refresh)
|
|
|
|
|
|
|
|
|
|
|
|
onBeforeRouteUpdate(async to => {
|
|
|
|
onBeforeRouteUpdate(async to => {
|
|
|
|