Compare commits
1 Commits
training-r
...
1.0.4
| Author | SHA1 | Date | |
|---|---|---|---|
| 3848eb939a |
@@ -26,7 +26,7 @@ router.post("/", async (req: Request, res: Response) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
//admin posts LOA
|
//admin posts LOA
|
||||||
router.post("/admin", [requireRole("17th Administrator")], async (req: Request, res: Response) => {
|
router.post("/admin", [requireRole(['17th Administrator', '17th HQ', '17th Command'])], async (req: Request, res: Response) => {
|
||||||
let LOARequest = req.body as LOARequest;
|
let LOARequest = req.body as LOARequest;
|
||||||
LOARequest.created_by = req.user.id;
|
LOARequest.created_by = req.user.id;
|
||||||
LOARequest.filed_date = new Date();
|
LOARequest.filed_date = new Date();
|
||||||
@@ -67,7 +67,7 @@ router.get("/history", async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
router.get('/all', [requireRole("17th Administrator")], async (req: Request, res: Response) => {
|
router.get('/all', [requireRole(['17th Administrator', '17th HQ', '17th Command'])], async (req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
const page = Number(req.query.page) || undefined;
|
const page = Number(req.query.page) || undefined;
|
||||||
const pageSize = Number(req.query.pageSize) || undefined;
|
const pageSize = Number(req.query.pageSize) || undefined;
|
||||||
@@ -107,7 +107,7 @@ router.post('/cancel/:id', async (req: Request, res: Response) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
//TODO: enforce admin only
|
//TODO: enforce admin only
|
||||||
router.post('/adminCancel/:id', [requireRole("17th Administrator")], async (req: Request, res: Response) => {
|
router.post('/adminCancel/:id', [requireRole(['17th Administrator', '17th HQ', '17th Command'])], async (req: Request, res: Response) => {
|
||||||
let closer = req.user.id;
|
let closer = req.user.id;
|
||||||
try {
|
try {
|
||||||
await closeLOA(Number(req.params.id), closer);
|
await closeLOA(Number(req.params.id), closer);
|
||||||
@@ -119,7 +119,7 @@ router.post('/adminCancel/:id', [requireRole("17th Administrator")], async (req:
|
|||||||
})
|
})
|
||||||
|
|
||||||
// TODO: Enforce admin only
|
// TODO: Enforce admin only
|
||||||
router.post('/extend/:id', [requireRole("17th Administrator")], async (req: Request, res: Response) => {
|
router.post('/extend/:id', [requireRole(['17th Administrator', '17th HQ', '17th Command'])], async (req: Request, res: Response) => {
|
||||||
const to: Date = req.body.to;
|
const to: Date = req.body.to;
|
||||||
|
|
||||||
if (!to) {
|
if (!to) {
|
||||||
|
|||||||
@@ -80,19 +80,6 @@ function onSubmit(vals) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function matchesSearch(text: string, search: string) {
|
|
||||||
if (!search) return true
|
|
||||||
|
|
||||||
const tokens = search
|
|
||||||
.toLowerCase()
|
|
||||||
.trim()
|
|
||||||
.split(/\s+/)
|
|
||||||
|
|
||||||
const target = text.toLowerCase()
|
|
||||||
|
|
||||||
return tokens.every(token => target.includes(token))
|
|
||||||
}
|
|
||||||
|
|
||||||
const { remove, push, fields } = useFieldArray('attendees');
|
const { remove, push, fields } = useFieldArray('attendees');
|
||||||
|
|
||||||
const selectedCourse = computed<Course | undefined>(() => { return trainings.value?.find(c => c.id == values.course_id) })
|
const selectedCourse = computed<Course | undefined>(() => { return trainings.value?.find(c => c.id == values.course_id) })
|
||||||
@@ -123,24 +110,11 @@ const memberSearch = ref('')
|
|||||||
const MAX_RESULTS = 50
|
const MAX_RESULTS = 50
|
||||||
|
|
||||||
const filteredMembers = computed(() => {
|
const filteredMembers = computed(() => {
|
||||||
const q = memberSearch.value?.toLowerCase().trim() ?? ""
|
const q = memberSearch?.value?.toLowerCase() ?? ""
|
||||||
|
|
||||||
if (!q) {
|
|
||||||
return (members.value ?? []).slice(0, MAX_RESULTS)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Split search into words (handles multiple spaces)
|
|
||||||
const tokens = q.split(/\s+/)
|
|
||||||
|
|
||||||
const results: MemberLight[] = []
|
const results: MemberLight[] = []
|
||||||
|
|
||||||
for (const m of members.value ?? []) {
|
for (const m of members.value ?? []) {
|
||||||
const name = (m.displayName || m.username).toLowerCase()
|
if (!q || (m.displayName || m.username).toLowerCase().includes(q)) {
|
||||||
|
|
||||||
// ALL tokens must be present (order does not matter)
|
|
||||||
const matches = tokens.every(token => name.includes(token))
|
|
||||||
|
|
||||||
if (matches) {
|
|
||||||
results.push(m)
|
results.push(m)
|
||||||
if (results.length >= MAX_RESULTS) break
|
if (results.length >= MAX_RESULTS) break
|
||||||
}
|
}
|
||||||
@@ -149,17 +123,6 @@ const filteredMembers = computed(() => {
|
|||||||
return results
|
return results
|
||||||
})
|
})
|
||||||
|
|
||||||
const courseSearch = ref('')
|
|
||||||
|
|
||||||
const filteredCourses = computed(() => {
|
|
||||||
if (!trainings.value) return []
|
|
||||||
|
|
||||||
return trainings.value.filter(course =>
|
|
||||||
matchesSearch(course.name, courseSearch.value)
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<form id="trainingForm" @submit.prevent="submitForm" class="flex flex-col gap-5">
|
<form id="trainingForm" @submit.prevent="submitForm" class="flex flex-col gap-5">
|
||||||
@@ -176,22 +139,18 @@ const filteredCourses = computed(() => {
|
|||||||
selectCourse = false
|
selectCourse = false
|
||||||
}" class="w-full">
|
}" class="w-full">
|
||||||
<ComboboxAnchor class="w-full">
|
<ComboboxAnchor class="w-full">
|
||||||
<ComboboxInput @focus="selectCourse = true"
|
<ComboboxInput @focus="selectCourse = true" placeholder="Search courses..."
|
||||||
@input="courseSearch = $event.target.value"
|
class="w-full pl-3" :display-value="(id) => {
|
||||||
placeholder="Search courses..."
|
|
||||||
class="w-full pl-3"
|
|
||||||
:display-value="(id) => {
|
|
||||||
const c = trainings?.find(t => t.id === id)
|
const c = trainings?.find(t => t.id === id)
|
||||||
return c ? c.name : '';
|
return c ? c.name : '';
|
||||||
}"
|
}" />
|
||||||
/>
|
|
||||||
</ComboboxAnchor>
|
</ComboboxAnchor>
|
||||||
|
|
||||||
<ComboboxList class="w-full">
|
<ComboboxList class="w-full">
|
||||||
<ComboboxEmpty class="text-muted-foreground w-full">No results</ComboboxEmpty>
|
<ComboboxEmpty class="text-muted-foreground w-full">No results</ComboboxEmpty>
|
||||||
<ComboboxGroup>
|
<ComboboxGroup>
|
||||||
<div class="max-h-80 overflow-y-scroll scrollbar-themed min-w-md">
|
<div class="max-h-80 overflow-y-scroll scrollbar-themed min-w-md">
|
||||||
<template v-for="course in filteredCourses" :key="course.id">
|
<template v-for="course in trainings" :key="course.id">
|
||||||
<ComboboxItem :value="course.id"
|
<ComboboxItem :value="course.id"
|
||||||
class="data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground relative cursor-pointer select-none px-2 py-1.5 w-full">
|
class="data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground relative cursor-pointer select-none px-2 py-1.5 w-full">
|
||||||
{{ course.name }}
|
{{ course.name }}
|
||||||
|
|||||||
Reference in New Issue
Block a user