[FE] Fetch custom labels from BE.
This commit is contained in:
parent
1cb2885454
commit
b24f969cec
@ -56,7 +56,7 @@ ALTER TABLE register MODIFY COLUMN register_custom_label INTEGER NOT NULL DEFAUL
|
|||||||
UPDATE register SET register_custom_label = 1;
|
UPDATE register SET register_custom_label = 1;
|
||||||
|
|
||||||
-- Add constraint after all values are set to empty label
|
-- Add constraint after all values are set to empty label
|
||||||
ALTER TABLE register CONSTRAINT fk_register_custom_label
|
ALTER TABLE register ADD CONSTRAINT fk_register_custom_label
|
||||||
FOREIGN KEY (register_custom_label)
|
FOREIGN KEY (register_custom_label)
|
||||||
REFERENCES custom_label(custom_label_id);
|
REFERENCES custom_label(custom_label_id);
|
||||||
|
|
||||||
|
110
frontend/src/certs/NewRegister/CustomLabelSelect.tsx
Normal file
110
frontend/src/certs/NewRegister/CustomLabelSelect.tsx
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
import { createEffect, createSignal, For, onMount } from "solid-js";
|
||||||
|
import { allCourses } from "../../utils/allCourses";
|
||||||
|
|
||||||
|
export function CustomLabelSelect(props: {
|
||||||
|
onChange: (id: number | null) => void,
|
||||||
|
count: number
|
||||||
|
}) {
|
||||||
|
const [filter, setFilter] = createSignal("");
|
||||||
|
const [selected, setSelected] = createSignal<number | null>(null);
|
||||||
|
const [inputValue, setInputValue] = createSignal("");
|
||||||
|
|
||||||
|
const iHandler = (ev: KeyboardEvent & {currentTarget: HTMLInputElement, target: Element}) => {
|
||||||
|
const inputEl = ev.target as HTMLInputElement;
|
||||||
|
// Clear current selection
|
||||||
|
setSelected(null);
|
||||||
|
|
||||||
|
let filter: string = inputEl.value.toLowerCase();
|
||||||
|
filter = filter.replace("á", "a");
|
||||||
|
filter = filter.replace("é", "e");
|
||||||
|
filter = filter.replace("í", "i");
|
||||||
|
filter = filter.replace("ó", "o");
|
||||||
|
filter = filter.replace("ú", "u");
|
||||||
|
setFilter(filter);
|
||||||
|
};
|
||||||
|
|
||||||
|
createEffect(() => {
|
||||||
|
props.onChange(selected());
|
||||||
|
});
|
||||||
|
|
||||||
|
createEffect(() => {
|
||||||
|
// Makes reactivity happen, don't remove
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
const _count = props.count;
|
||||||
|
|
||||||
|
setFilter("");
|
||||||
|
setSelected(null);
|
||||||
|
setInputValue("");
|
||||||
|
});
|
||||||
|
|
||||||
|
let inputElement: HTMLInputElement | undefined;
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
inputElement?.addEventListener("keydown", (ev) => {
|
||||||
|
if (ev.code === "Enter") {
|
||||||
|
ev.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const filteredOptions = () => {
|
||||||
|
const filterText = filter();
|
||||||
|
|
||||||
|
return allCourses().filter((course) => {
|
||||||
|
let courseText = course.course_name.toLowerCase();
|
||||||
|
courseText = courseText.replace("á", "a");
|
||||||
|
courseText = courseText.replace("é", "e");
|
||||||
|
courseText = courseText.replace("í", "i");
|
||||||
|
courseText = courseText.replace("ó", "o");
|
||||||
|
courseText = courseText.replace("ú", "u");
|
||||||
|
|
||||||
|
return selected() === null && courseText.indexOf(filterText) !== -1;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<input
|
||||||
|
id="create-subject"
|
||||||
|
ref={inputElement}
|
||||||
|
class={`bg-c-background text-c-on-background
|
||||||
|
${selected() !== null ? "border-c-green" : "border-c-outline"}
|
||||||
|
border-2 rounded-tl rounded-tr px-2 py-1
|
||||||
|
w-full
|
||||||
|
invalid:border-c-error invalid:text-c-error
|
||||||
|
focus:border-c-primary outline-none
|
||||||
|
disabled:opacity-50 disabled:cursor-not-allowed`}
|
||||||
|
type="text"
|
||||||
|
placeholder="Curso"
|
||||||
|
onkeyup={iHandler}
|
||||||
|
value={inputValue()}
|
||||||
|
onchange={(ev) => setInputValue(ev.target.value)}
|
||||||
|
autocomplete="off"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<div
|
||||||
|
class="border-c-outline border-l-2 border-b-2 border-r-2
|
||||||
|
rounded-bl rounded-br overflow-y-scroll h-[10rem]"
|
||||||
|
>
|
||||||
|
<For each={filteredOptions()}>
|
||||||
|
{(s) => (
|
||||||
|
<button
|
||||||
|
class="w-full text-left py-1 px-2
|
||||||
|
hover:bg-c-primary-container hover:text-c-on-primary-container"
|
||||||
|
onclick={(ev) => {
|
||||||
|
ev.preventDefault();
|
||||||
|
|
||||||
|
setSelected(s.course_id);
|
||||||
|
setInputValue(s.course_name);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{s.course_name}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</For>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
4
frontend/src/types/CustomLabel.ts
Normal file
4
frontend/src/types/CustomLabel.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export type CustomLabel = {
|
||||||
|
custom_label_id: number,
|
||||||
|
custom_label_value: string,
|
||||||
|
}
|
19
frontend/src/utils/allCustomLabels.ts
Normal file
19
frontend/src/utils/allCustomLabels.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { createSignal } from "solid-js";
|
||||||
|
import { CustomLabel } from "../types/CustomLabel";
|
||||||
|
|
||||||
|
type CustomLabelsMap = {[k: number]: CustomLabel};
|
||||||
|
|
||||||
|
export const [customLabelsMap, setCustomLabelsMap] = createSignal<{[k: number]: CustomLabel}>({});
|
||||||
|
|
||||||
|
(() => {
|
||||||
|
// Get all labels from the API
|
||||||
|
fetch(`${import.meta.env.VITE_BACKEND_URL}/api/labels`)
|
||||||
|
.then((res) => res.json())
|
||||||
|
.then((data: Array<CustomLabel>) => {
|
||||||
|
const map: CustomLabelsMap = {};
|
||||||
|
for (const label of data) {
|
||||||
|
map[label.custom_label_id] = label;
|
||||||
|
}
|
||||||
|
setCustomLabelsMap(map);
|
||||||
|
});
|
||||||
|
})();
|
Loading…
Reference in New Issue
Block a user