b05e074456
Co-authored-by: ISMAIL MASSERAN <topaz@ISMAILs-Macbook.local> Co-authored-by: ISMAIL MASSERAN <topaz@Mac.dlinkrouter.local> Reviewed-on: #11
112 lines
4.3 KiB
Vue
112 lines
4.3 KiB
Vue
<script lang="ts" setup>
|
|
import { useRouter } from 'vue-router'
|
|
import { AlertRoot, AlertTitle, AlertDescription } from '@/components/ui/alert'
|
|
import { Badge } from '@/components/ui/badge'
|
|
import { Box } from '@/components/ui/box'
|
|
import { Button } from '@/components/ui/button'
|
|
import { Input } from '@/components/ui/input'
|
|
import { Lucide } from '@/components/ui/lucide'
|
|
import { useExternalSystemList } from '../composables/useExternalSystemList'
|
|
import { useExternalSystemLaunch } from '../composables/useExternalSystemLaunch'
|
|
import {
|
|
externalSystemStatusLabel,
|
|
externalSystemStatusVariant,
|
|
formatExternalSystemDateTime,
|
|
getExternalSystemStatus,
|
|
} from '../utils/external-system.utils'
|
|
import type { ExternalSystem } from '../types/external-system.types'
|
|
|
|
const router = useRouter()
|
|
const { systems, search, loading, error, availableCount } = useExternalSystemList()
|
|
const { launching, launchExternalSystem } = useExternalSystemLaunch()
|
|
|
|
function goToDetail(system: ExternalSystem) {
|
|
router.push({ name: 'view-external-system', params: { id: system.id } })
|
|
}
|
|
|
|
function handleOpen(system: ExternalSystem) {
|
|
launchExternalSystem(system)
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div>
|
|
<div class="flex flex-wrap items-start justify-between gap-4">
|
|
<div>
|
|
<h2 class="text-lg font-medium">Sistem Luaran</h2>
|
|
</div>
|
|
<Badge look="outline" variant="primary">
|
|
{{ availableCount }} tersedia
|
|
</Badge>
|
|
</div>
|
|
|
|
<AlertRoot v-if="error" class="mb-6" variant="danger">
|
|
<AlertTitle>Ralat</AlertTitle>
|
|
<AlertDescription>{{ error }}</AlertDescription>
|
|
</AlertRoot>
|
|
|
|
<div class="mt-5 grid grid-cols-12 gap-x-6 gap-y-8">
|
|
<div class="col-span-12 mt-2 flex flex-wrap items-center sm:flex-nowrap">
|
|
<div class="w-full sm:w-auto">
|
|
<div class="relative w-56">
|
|
<Input v-model="search" class="w-56 pr-10" type="search" placeholder="Cari sistem..." :disabled="loading" />
|
|
<Lucide class="absolute inset-y-0 right-0 my-auto mr-3 h-4 w-4" icon="Search" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<template v-if="systems.length">
|
|
<Box v-for="system in systems" :key="system.id"
|
|
class="col-span-12 flex h-full flex-col p-5 md:col-span-6 xl:col-span-4">
|
|
<div class="mb-4 flex items-start justify-between gap-3">
|
|
<div class="flex size-10 shrink-0 items-center justify-center rounded-xl bg-primary/10 text-primary">
|
|
<Lucide :icon="system.icon" class="size-5" />
|
|
</div>
|
|
<Badge look="outline" :variant="externalSystemStatusVariant(getExternalSystemStatus(system))">
|
|
{{ externalSystemStatusLabel(getExternalSystemStatus(system)) }}
|
|
</Badge>
|
|
</div>
|
|
|
|
<div class="text-base font-medium">{{ system.name }}</div>
|
|
<div class="mt-1 text-xs font-medium uppercase tracking-wide text-primary/80">
|
|
{{ system.code }}
|
|
</div>
|
|
<p class="mt-2 flex-1 text-sm leading-relaxed opacity-70">
|
|
{{ system.description }}
|
|
</p>
|
|
|
|
<div class="mt-4 space-y-1 text-xs opacity-70">
|
|
<div>
|
|
<span class="font-medium">Mula:</span>
|
|
{{ formatExternalSystemDateTime(system.starts_at) }}
|
|
</div>
|
|
<div>
|
|
<span class="font-medium">Tamat:</span>
|
|
{{ formatExternalSystemDateTime(system.ends_at) }}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-5 flex flex-col gap-2 sm:flex-row">
|
|
<Button class="w-full sm:flex-1" look="outline" variant="primary"
|
|
:disabled="getExternalSystemStatus(system) !== 'available' || launching"
|
|
@click="handleOpen(system)">
|
|
Buka Sistem
|
|
<Lucide icon="ExternalLink" class="size-4" />
|
|
</Button>
|
|
<Button class="w-full sm:flex-1" variant="ghost" @click="goToDetail(system)">
|
|
Butiran
|
|
<Lucide icon="ArrowRight" class="size-4" />
|
|
</Button>
|
|
</div>
|
|
</Box>
|
|
</template>
|
|
|
|
<Box v-else-if="!loading" class="col-span-12 p-8 text-center">
|
|
<Lucide icon="SearchX" class="mx-auto size-8 opacity-40" />
|
|
<div class="mt-3 text-base font-medium">Tiada sistem dijumpai</div>
|
|
<p class="mt-1 text-sm opacity-70">Cuba istilah carian yang berbeza.</p>
|
|
</Box>
|
|
</div>
|
|
</div>
|
|
</template>
|