Add proper error handling and loading screen

This commit is contained in:
dragongoose 2023-04-10 00:12:52 -04:00
parent 9104e62779
commit d27ef3560c
Signed by: dragongoose
GPG key ID: 50DB99B921579009
5 changed files with 100 additions and 86 deletions

View file

@ -1,22 +1,5 @@
<script lang="ts">
export default {
props: {
errMessage: {
type: Object,
default() {
{
;('Error')
}
}
}
},
setup(props) {
return {
errorMessage: props.errMessage
}
}
}
export default {}
</script>
<template>
@ -31,10 +14,5 @@ export default {
<p class="text-xl">
the server was encountered an error while retriving the data, and now we're here :3
</p>
<div class="mt-5">
<p class="text-xl">please contact the administrator with this code</p>
<p class="text-xl">error identifier: {{ errorMessage.code }}</p>
</div>
</div>
</template>

View file

@ -0,0 +1,8 @@
<template>
<div class="flex mx-auto justify-center bg-ctp-crust rounded-lg w-2/3 p-2 text-white">
<div class="flex space-x-3">
<h1 class="text-4xl font-bold">Searching...</h1>
<v-icon name="fa-circle-notch" class="animate-spin w-10 h-10"></v-icon>
</div>
</div>
</template>

View file

@ -1,22 +1,35 @@
<script lang="ts">
import { useRoute } from 'vue-router'
import { ref, type Ref } from 'vue'
import StreamPreviewVue from '@/components/StreamPreview.vue'
import ErrorMessage from '@/components/ErrorMessage.vue'
import LoadingScreen from '@/components/LoadingScreen.vue'
export default {
async setup() {
const protocol = import.meta.env.VITE_HTTPS === 'true' ? 'https://' : 'http://'
const data: Ref<any | undefined> = ref()
const frontend_url = protocol + import.meta.env.VITE_INSTANCE_DOMAIN
const route = useRoute()
const game = route.params.game
const res = await fetch(`${protocol}${import.meta.env.VITE_BACKEND_DOMAIN}/api/discover/${game}`)
const data = await res.json()
let frontend_url = protocol + import.meta.env.VITE_INSTANCE_DOMAIN
return {
data,
frontend_url
}
},
async mounted() {
const protocol = import.meta.env.VITE_HTTPS === 'true' ? 'https://' : 'http://'
const game: string = this.$route.params.game.toString()
try {
const res = await fetch(`${protocol}${import.meta.env.VITE_BACKEND_DOMAIN}/api/discover/${game}`)
if (!res.ok) {
return this.data = { status: 'error' }
}
this.data = await res.json()
} catch (err) {
this.data = { status: 'error' }
console.error(err)
}
},
methods: {
abbreviate(text: number) {
return Intl.NumberFormat('en-US', {
@ -27,13 +40,18 @@ export default {
}
},
components: {
StreamPreviewVue
StreamPreviewVue,
ErrorMessage,
LoadingScreen
}
}
</script>
<template>
<div class="flex flex-col max-w-5xl mx-auto">
<loading-screen v-if="!data"></loading-screen>
<error-message v-else-if="data.status === 'error' || !data"></error-message>
<div v-else class="flex flex-col max-w-5xl mx-auto">
<div class="flex space-x-4 p-3">
<img :src="data.cover" class="self-start rounded-md" />

View file

@ -1,15 +1,16 @@
<script lang="ts">
import { ref, type Ref } from 'vue'
import StreamPreviewVue from '@/components/StreamPreview.vue'
import ErrorMessage from '@/components/ErrorMessage.vue'
import LoadingScreen from '@/components/LoadingScreen.vue'
export default {
async setup() {
const protocol = import.meta.env.VITE_HTTPS === 'true' ? 'https://' : 'http://'
const res = await fetch(`${protocol}${import.meta.env.VITE_BACKEND_DOMAIN}/api/discover`)
let data: Ref<any[] | undefined> = ref()
let data: Ref<any | undefined> = ref()
let frontend_url = protocol + import.meta.env.VITE_INSTANCE_DOMAIN
data.value = await res.json()
return {
data,
@ -29,8 +30,8 @@ export default {
},
filterSearches(toFilter: string) {
const categories = this.$refs.categoryItem
const wantedTags = toFilter.split(',').filter((v) => v.toLowerCase())
const categories: HTMLCollectionOf<Element> = this.$refs.categoryItem as HTMLCollectionOf<Element>
const wantedTags: string[] = toFilter.split(',').filter((v) => v.toLowerCase())
for (let category of categories as any) {
let tagElements = category.getElementsByTagName('span')
@ -67,6 +68,9 @@ export default {
const res = await fetch(
`${this.protocol}${import.meta.env.VITE_BACKEND_DOMAIN}/api/discover/?cursor=${cursor}`
)
if (!res.ok) {
throw new Error('Failed to fetch data')
}
const data = await res.json()
for (let category of data) {
@ -76,7 +80,7 @@ export default {
}
}
},
mounted() {
async mounted() {
this.getNextCategory()
let following = localStorage.getItem('following')
@ -85,15 +89,33 @@ export default {
} else {
this.following = []
}
try {
const res = await fetch(`${this.protocol}${import.meta.env.VITE_BACKEND_DOMAIN}/api/discover`)
if (!res.ok) {
throw new Error('Failed to fetch data')
}
this.data = await res.json()
} catch (error) {
console.error(error)
this.data = { status: 'error' }
}
},
components: {
StreamPreviewVue
StreamPreviewVue,
ErrorMessage,
LoadingScreen
}
}
</script>
<template>
<div class="max-w-5xl mx-auto">
<loading-screen v-if="!data"></loading-screen>
<error-message v-else-if="data.status === 'error'"></error-message>
<div v-else class="max-w-5xl mx-auto">
<div v-if="following.length > 0" class="p-2 text-white">
<h1 class="font-bold text-5xl">Following</h1>
<p class="text-xl">Streamers you follow</p>

View file

@ -5,61 +5,56 @@ import VideoPlayer from '@/components/VideoPlayer.vue'
import TwitchChat from '@/components/TwitchChat.vue'
import ErrorMessage from '@/components/ErrorMessage.vue'
import FollowButton from '@/components/FollowButton.vue'
import LoadingScreen from '@/components/LoadingScreen.vue'
export default {
async setup() {
const route = useRoute()
const username = route.params.username
const protocol = import.meta.env.VITE_HTTPS === 'true' ? 'https://' : 'http://'
const getUser = async () => {
const res = await fetch(`${protocol}${import.meta.env.VITE_BACKEND_DOMAIN}/api/users/${username}`)
if (res.status !== 200) {
try {
const res = await fetch(`${protocol}${import.meta.env.VITE_BACKEND_DOMAIN}/api/users/${username}`)
const data = await res.json()
if (!data.code) {
return {
status: 'error',
code: 'error'
}
}
return data
} catch (error) {
console.error(error)
return {
...data
status: 'error',
}
}
const data = await res.json()
return data
}
const data = ref()
onMounted(async () => {
const fetchedUser = await getUser()
data.value = fetchedUser
})
const videoOptions = {
autoplay: true,
controls: true,
sources: [
{
src: `${protocol}${import.meta.env.VITE_BACKEND_DOMAIN}/proxy/stream/${username}/hls.m3u8`,
type: 'application/vnd.apple.mpegurl'
}
],
fluid: true
}
return {
data,
videoOptions: {
autoplay: true,
controls: true,
sources: [
{
src: `${protocol}${import.meta.env.VITE_BACKEND_DOMAIN}/proxy/stream/${username}/hls.m3u8`,
type: 'application/vnd.apple.mpegurl'
}
],
fluid: true
}
videoOptions,
getUser
}
},
components: {
VideoPlayer,
TwitchChat,
ErrorMessage,
FollowButton
VideoPlayer,
TwitchChat,
ErrorMessage,
FollowButton,
LoadingScreen
},
async mounted() {
const fetchedUser = await this.getUser()
this.data = fetchedUser
},
methods: {
truncate(value: string, length: number) {
@ -73,19 +68,12 @@ export default {
}
</script>
<template>
<div
v-if="!data"
id="loadingDiv"
class="flex mx-auto justify-center bg-ctp-crust rounded-lg w-2/3 p-2 text-white"
>
<div class="flex space-x-3">
<h1 class="text-4xl font-bold">Searching...</h1>
<v-icon name="fa-circle-notch" class="animate-spin w-10 h-10"></v-icon>
</div>
</div>
<error-message v-else-if="data.status === 'error'" :errMessage="data"></error-message>
<template>
<loading-screen v-if="!data"></loading-screen>
<error-message v-else-if="data.status === 'error'"></error-message>
<div v-else class="w-full justify-center inline-flex space-x-4 p-4">
<div class="flex bg-ctp-crust flex-col p-6 rounded-lg max-w-prose min-w-[65ch] text-white">