<template>
<section class="page">
<GnPageHeader title="Scanning" kicker="Devices">
<template #actions>
<div class="devices-actions">
<GnButton
:variant="scanningStore.mode === 'setup' ? 'primary' : 'secondary'"
@click="setMode('setup')"
>
Setup
</GnButton>
<GnButton
:variant="scanningStore.mode === 'all' ? 'primary' : 'secondary'"
@click="setMode('all')"
>
All
</GnButton>
<GnButton
:loading="scanningStore.isLoading"
icon="ph-magnifying-glass"
@click="scan"
>
Scan
</GnButton>
</div>
</template>
</GnPageHeader>
<AppLoadingState v-if="scanningStore.isLoading" text="Scanning network" />
<AppErrorState
v-else-if="scanningStore.error"
title="Scan failed"
:message="scanningStore.error.message"
:retry="scan"
/>
<AppEmptyState
v-else-if="scanningStore.devices.length === 0"
title="No devices found"
message="Choose scan mode and click Scan to discover devices."
/>
<div v-else class="devices-panel">
<div class="devices-summary">
<GnBadge variant="primary">{{ scanningStore.total }} found</GnBadge>
<GnBadge variant="secondary">Mode: {{ scanningStore.mode }}</GnBadge>
</div>
<GnTable
:columns="tableColumns"
:rows="tableRows"
caption="Discovered devices"
>
<template #cell-device_name="{ row }">
<strong>{{ row.device_name }}</strong>
<small>{{ row.device_type }}</small>
</template>
<template #cell-status="{ row }">
<GnBadge :variant="row.status === 'setup' ? 'warning' : 'success'">{{ row.status }}</GnBadge>
</template>
<template #cell-actions="{ row }">
<GnButton
v-if="row.status === 'setup'"
variant="primary"
icon="ph-plus"
@click="openSetup(row)"
>
Add
</GnButton>
</template>
</GnTable>
</div>
<GnModal
:open="showSetupModal"
title="Setup new device"
@update:open="showSetupModal = $event"
>
<div class="form-group">
<GnInput v-model="setupForm.alias" label="Alias" placeholder="kitchen_relay" />
</div>
<div class="form-group">
<GnInput v-model="setupForm.name" label="Name" placeholder="Kitchen Relay" />
</div>
<div class="form-group">
<GnInput v-model="setupForm.description" label="Description" />
</div>
<div v-if="setupError" class="form-group">
<GnAlert variant="danger">{{ setupError }}</GnAlert>
</div>
<template #footer>
<GnButton variant="secondary" @click="showSetupModal = false">Cancel</GnButton>
<GnButton variant="primary" icon="ph-plus" :loading="setupLoading" @click="submitSetup">
Add device
</GnButton>
</template>
</GnModal>
</section>
</template>
<script setup>
import { ref, reactive, computed } from "vue";
import { useScanningStore } from "../../../stores/scanning";
import {
GnPageHeader,
GnButton,
GnBadge,
GnTable,
GnModal,
GnInput,
GnAlert,
} from "gnexus-ui-kit/vue";
import AppEmptyState from "../../../components/feedback/AppEmptyState.vue";
import AppErrorState from "../../../components/feedback/AppErrorState.vue";
import AppLoadingState from "../../../components/feedback/AppLoadingState.vue";
const scanningStore = useScanningStore();
const showSetupModal = ref(false);
const setupLoading = ref(false);
const setupError = ref("");
const setupForm = reactive({
device_ip: "",
alias: "",
name: "",
description: "",
});
const tableColumns = [
{ key: "device_name", label: "Device" },
{ key: "ip_address", label: "IP" },
{ key: "mac_address", label: "MAC" },
{ key: "firmware_version", label: "Firmware" },
{ key: "status", label: "Status" },
{ key: "actions", label: "Actions" },
];
const tableRows = computed(() =>
scanningStore.devices.map((device) => ({
id: device.device_id || device.ip_address,
device_name: device.device_name || "Unknown",
device_type: device.device_type || "unknown",
ip_address: device.ip_address || "unknown",
mac_address: device.mac_address || "unknown",
firmware_version: device.firmware_version || "unknown",
status: device.status || "unknown",
}))
);
function setMode(mode) {
scanningStore.setMode(mode);
}
function scan() {
scanningStore.scan();
}
function openSetup(row) {
setupForm.device_ip = row.ip_address;
setupForm.alias = "";
setupForm.name = "";
setupForm.description = "";
setupError.value = "";
showSetupModal.value = true;
}
async function submitSetup() {
setupLoading.value = true;
setupError.value = "";
const result = await scanningStore.setupDevice({ ...setupForm });
setupLoading.value = false;
if (!result.ok) {
setupError.value = result.error?.message || "Failed to setup device";
return;
}
showSetupModal.value = false;
}
</script>
<style scoped>
.form-group {
margin-bottom: 16px;
}
</style>