created tracker api endpoint and created UI interface for trackers
This commit is contained in:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user