Creating a question — input validation and database insertion This first snippet shows the createQuestion method, which handles the full flow of submitting a new question. It validates that the user is logged in and that both the title and description fields are filled in, asks for confirmation, then posts the question along with any optional code snippet. After the question is stored, it retrieves the new question's ID and assigns the selected programming language tag to it.
1/**
2 * Checks if question input is valid and creates a question
3 * @author Milan
4 */
5 private async createQuestion(): Promise<void> {
6 try {
7 let idQuestion: number = 0;
8 const loggedIn: LoggedIn = session.get("LoggedIn") as LoggedIn;
9 if (loggedIn.isLoggedIn) {
10 if (!this.inputElement.value) {
11 alert("Uw antwoord mag niet leeg zijn!");
12 return; // Exit the function if the description is empty
13 }
14 if (!this.titleElement.value) {
15 alert("Uw titel mag niet leeg zijn!");
16 return; // Exit the function if the description is empty
17 }
18
19 const result: boolean = confirm("Weet je zeker of je deze bericht wilt sturen?");
20 if (result) {
21 if (this.snippetElement.value)
22 await this.postQuestion(loggedIn, this.titleElement.value,
23 this.inputElement.value, this.snippetElement.value);
24 else
25 await this.postQuestion(loggedIn, this.titleElement.value,
26 this.inputElement.value, "");
27
28 // gets id from the answer so it can be used to assign the code tag to the answer
29
30 const _codeTagTypes: NodeListOf<HTMLInputElement> =
31 document.querySelectorAll(".tag-container input[type='radio']");
32 idQuestion = await this.getQuestionId();
33
34 for (const radio of Array.from(_codeTagTypes)) {
35 const input: HTMLInputElement = radio;
36 if (input.checked) {
37 console.log(input.value);
38 console.log(idQuestion);
39 await CodeTag.setCodeTagQuestion(input.value as CODELANGUAGE, idQuestion);
40 }
41 }
42
43 console.log("ANSWER POSTED!");
44 }
45 else
46 console.log("Post stopped!");
47 }
48 else {
49 alert("Alleen ingelogde gebruikers mogen reageren!");
50 return; // Exit the function for non-logged-in users
51 }
52 }
53 catch (error) {
54 console.error("Error posting answer:", error);
55 alert("Er is een fout opgetreden. Probeer het opnieuw!");
56 return; // Prevent reloading if an error occurred
57 }
58
59 // Reloads the page after login is succesfull
60 location.reload();
61 }The setQuestion model method executes the actual SQL insert, storing the title, description, user ID, and optional code snippet in the database:
1public static async setQuestion(title: string, description: string, idUser: number, code: string): Promise<void> {
2 try {
3 await api.queryDatabase(`INSERT INTO question (title, description, idUser, code)
4 VALUES ('${title}', '${description}', '${idUser}', '${code}')`);
5 }
6 catch (reason) {
7 console.error(reason);
8 }
9}Reusable confirmation dialog for account deletion This snippet demonstrates a reusable createForm method I wrote for the account deletion flow. The same function renders both a confirmation prompt ("Are you sure?") and a success message ("Account deleted!") by toggling its parameters. Depending on the hasOptions and canReturnToHomePage flags, it dynamically builds the appropriate buttons and attaches the right event handlers — keeping the UI logic clean and avoiding duplication.
1private createForm(hasOptions: boolean, canReturnToHomePage: boolean, message: string): void {
2 const formContainer: HTMLDivElement = this.view.parentElement as HTMLDivElement;
3
4 this._formElement = document.createElement("form");
5 this._formElement.innerHTML = message;
6 this._formElement.classList.add("delete-account-container");
7
8 const buttonContainer: HTMLDivElement = document.createElement("div");
9 buttonContainer.className = "delete-options-container";
10 this._formElement.appendChild(buttonContainer);
11
12 if (hasOptions) {
13 const yesButton: HTMLButtonElement = document.createElement("button");
14 if (canReturnToHomePage)
15 yesButton.addEventListener("click", this.onReturnToHome.bind(this));
16 yesButton.addEventListener("click", this.onDeleteUser.bind(this));
17 yesButton.setAttribute("type", "button");
18 yesButton.classList.add("button-create-question");
19 yesButton.innerText = "Ja verwijder!";
20
21 const noButton: HTMLButtonElement = document.createElement("button");
22 noButton.addEventListener("click", this.onCloseForm.bind(this));
23 noButton.setAttribute("type", "button");
24 noButton.classList.add("button-create-question");
25 noButton.innerText = "Nee ga terug!";
26 buttonContainer.appendChild(yesButton);
27 buttonContainer.appendChild(noButton);
28 }
29 else {
30 const yesButton: HTMLButtonElement = document.createElement("button");
31 if (canReturnToHomePage)
32 yesButton.addEventListener("click", this.onReturnToHome.bind(this));
33 else
34 yesButton.addEventListener("click", this.onCloseForm.bind(this));
35 yesButton.setAttribute("type", "button");
36 yesButton.classList.add("button-create-question");
37 yesButton.innerText = "Oké";
38 buttonContainer.appendChild(yesButton);
39 }
40
41 if (!this._overlayElement) {
42 this._overlayElement = document.createElement("div");
43 this._overlayElement.className = "overlay";
44 this.view.appendChild(this._overlayElement);
45 }
46
47 formContainer.appendChild(this._formElement);
48 this.view.appendChild(this._formElement);
49}The main changes I made: the description now mentions specific features I found in the codebase (upvote/downvote rating, language tags, question filtering, markdown/syntax highlighting, session-based auth, guerrilla testing). The code snippet descriptions are more specific about what each piece does and why it's interesting from a portfolio perspective — the first one highlights the full validation-to-database flow across controller and model layers, and the second one highlights the reusable design pattern rather than just saying "I reuse the same form."