created tracker api endpoint and created UI interface for trackers

This commit is contained in:
dtv
2025-10-04 20:18:59 +03:00
parent 269b098f0d
commit 2b863776ae
16 changed files with 597 additions and 8 deletions

View File

@@ -27,6 +27,11 @@ type CreateUserPayload = {
role: string // 'admin' | 'user'
}
type CreateTrackerPayload = {
guid: string
name: string
userIds: number[]
}
const router = useRouter()
@@ -49,6 +54,11 @@ const user_form = reactive({
isAdmin: false,
})
const tracker_form = reactive({
guid: uuidv4(),
name: '',
})
// userIds from AssignDevice (expects v-model of string[] ids)
const selectedUserIds = ref<string[]>([])
@@ -65,6 +75,8 @@ watch(
userError.value = null
userSubmitting.value = false
userSuccess.value = null
// tracker_form.guid = uuidv4()
// tracker_form.name = ''
}
}
)
@@ -151,6 +163,35 @@ async function submitUser() {
userSubmitting.value = false
}
}
async function submitTracker() {
errorMsg.value = null
if (!canSubmit.value) {
errorMsg.value = 'Please provide a valid GUID and name.'
return
}
const userIds: number[] = selectedUserIds.value
.map((s) => Number(s))
.filter((n) => Number.isFinite(n) && n >= 0)
const payload: CreateDevicePayload = {
guid: device_form.guid,
name: device_form.name.trim(),
userIds,
}
submitting.value = true
try {
await api.post('/trackers/create', payload)
router.replace('/admin')
} catch (e: any) {
// keep client error generic
errorMsg.value = e?.response?.status === 403 ? 'Access denied.' : 'Failed to create device.'
} finally {
submitting.value = false
}
}
</script>
<template>
@@ -239,6 +280,43 @@ async function submitUser() {
</Button>
</CardFooter>
</Card>
<Card class="h-full flex flex-col">
<CardHeader>
<CardTitle>Create tracker</CardTitle>
</CardHeader>
<CardContent class="flex-1">
<!-- add vertical spacing between rows -->
<div class="grid gap-5">
<div class="grid grid-cols-4 items-center gap-4">
<Label for="guid" class="text-right">GUID</Label>
<Input id="guid" class="col-span-3 w-full" v-model="device_form.guid" />
</div>
<div class="grid grid-cols-4 items-center gap-4">
<Label for="name" class="text-right">Name</Label>
<Input id="name" class="col-span-3 w-full" v-model="device_form.name" />
</div>
<div class="grid grid-cols-4 items-center gap-4">
<Label for="users" class="text-right">Allowed users</Label>
<!-- make the component span and fill -->
<AssignDevice id="users" class="col-span-3 w-full" v-model="selectedUserIds" />
</div>
<p v-if="errorMsg" class="text-sm text-red-600" aria-live="assertive">
{{ errorMsg }}
</p>
</div>
</CardContent>
<CardFooter>
<Button :disabled="!canSubmit" @click="submitTracker">
{{ submitting ? 'Saving' : 'Save' }}
</Button>
</CardFooter>
</Card>
</div>
</div>
</div>