### Description This pull request migrates to Nuxt 4.0.0, adds docker, and uses Orval and OpenAPI 3.0 specification to interact with backend Reviewed-on: #1 Co-authored-by: bivashy <botyrbojey@gmail.com> Co-committed-by: bivashy <botyrbojey@gmail.com>
74 lines
2.6 KiB
Vue
74 lines
2.6 KiB
Vue
<script setup lang="ts">
|
|
import { Button } from '~/components/ui/button';
|
|
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '~/components/ui/dialog';
|
|
import { kodik, type KodikTranslation } from '~/openapi/extractor';
|
|
|
|
const route = useRoute();
|
|
const animeId = ref(route.params.slug as string)
|
|
|
|
const results = ref<KodikTranslation[]>([])
|
|
const isLoading = ref(false)
|
|
const error = ref<unknown>(null)
|
|
|
|
const isSelectingEpisode = ref(false)
|
|
const currentSelectionItem = ref<KodikTranslation | null>(null)
|
|
|
|
watchEffect(async () => {
|
|
if (!animeId.value) return
|
|
try {
|
|
isLoading.value = true
|
|
error.value = null
|
|
const response = await kodik({ id: animeId.value })
|
|
results.value = response?.data?.translations || []
|
|
} catch (err) {
|
|
error.value = err
|
|
console.error('Failed to fetch anime details:', err)
|
|
} finally {
|
|
isLoading.value = false
|
|
}
|
|
})
|
|
|
|
function episodesSelect(item: KodikTranslation) {
|
|
currentSelectionItem.value = item
|
|
isSelectingEpisode.value = true
|
|
}
|
|
|
|
function closeDialog() {
|
|
console.log('Dialog closed')
|
|
isSelectingEpisode.value = false
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div v-for="item in results" :key="item.id" class="flex w-[32rem]">
|
|
<div @click="episodesSelect(item)">
|
|
<span>{{ item.title }}</span>
|
|
<span>{{ item.episodeCount }}</span>
|
|
</div>
|
|
</div>
|
|
<p>{{ route.params.slug }}</p>
|
|
<Dialog v-bind:open="isSelectingEpisode">
|
|
<DialogTrigger as-child>
|
|
<Button variant="outline">
|
|
Select episode
|
|
</Button>
|
|
</DialogTrigger>
|
|
<DialogContent class="sm:max-w-[425px] max-h-[90dvh] overflow-y-auto" :close="closeDialog">
|
|
<DialogHeader>
|
|
<DialogTitle>Select episode</DialogTitle>
|
|
</DialogHeader>
|
|
<div class="grid gap-4 py-4">
|
|
<div v-for="n in currentSelectionItem?.episodeCount || 0" :key="n"
|
|
class="flex items-center justify-between">
|
|
<NuxtLink
|
|
:to="{ path: '/watch', query: { mediaType: currentSelectionItem?.mediaType, mediaId: currentSelectionItem?.mediaId, mediaHash: currentSelectionItem?.mediaHash, episode: n } }"
|
|
class="flex items-center justify-between gap-2 w-full">
|
|
<span>Episode {{ n }}</span>
|
|
<Button variant="outline" @click="closeDialog">Watch</Button>
|
|
</NuxtLink>
|
|
</div>
|
|
</div>
|
|
</DialogContent>
|
|
</Dialog>
|
|
</template>
|