Create components for modal dialog and table

This commit is contained in:
Aleksey Filippov 2024-12-17 12:06:26 +04:00
parent 295a7853a2
commit afc53ce5c3
4 changed files with 192 additions and 125 deletions

54
js/api.js Normal file
View File

@ -0,0 +1,54 @@
const API = "http://localhost:3001";
const STUDENTS = `${API}/students`;
const GROUPS = `${API}/groups`;
const addStudent = async (data) => {
const response = await fetch(STUDENTS, {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
});
if (!response.ok) {
throw new Error(`Response status: ${response.status}`);
}
};
const editStudent = async (id, data) => {
const response = await fetch(`${STUDENTS}/${id}`, {
method: "put",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
});
if (!response.ok) {
throw new Error(`Response status: ${response.status}`);
}
};
const deleteStudent = async (id) => {
const response = await fetch(`${STUDENTS}/${id}`, { method: "delete" });
if (!response.ok) {
throw new Error(`Response status: ${response.status}`);
}
};
const getGroups = async () => {
const response = await fetch(GROUPS);
if (!response.ok) {
throw new Error(`Response status: ${response.status}`);
}
return response.json();
};
const getStudents = async () => {
const response = await fetch(`${STUDENTS}?_expand=group`);
if (!response.ok) {
throw new Error(`Response status: ${response.status}`);
}
return response.json();
};
export { addStudent, deleteStudent, editStudent, getGroups, getStudents };

48
js/uimodal.js Normal file
View File

@ -0,0 +1,48 @@
const studentModal = (idModal, callback) => {
const modalEl = document.getElementById(idModal);
// eslint-disable-next-line no-undef
const myModal = bootstrap.Modal.getOrCreateInstance(modalEl);
const studentForm = document.querySelector(`#${idModal} form`);
const setModalData = (element) => {
const inputs = studentForm.querySelectorAll("input[required]");
inputs.forEach((input) => {
const control = input;
control.value = element ? element[input.getAttribute("id")] : "";
});
const idInput = studentForm.querySelector("#id");
idInput.value = element ? element.id : "";
const groupSelector = studentForm.querySelector("select");
groupSelector.value = element ? element.group.id : "";
myModal.show();
};
modalEl.addEventListener("shown.bs.modal", (event) => {
if (!event.relatedTarget) {
return;
}
setModalData();
});
studentForm.addEventListener("submit", async (event) => {
event.preventDefault();
const data = {};
const inputs = studentForm.querySelectorAll("input[required]");
inputs.forEach((input) => {
data[input.getAttribute("id")] = input.value;
});
const idInput = studentForm.querySelector("#id");
const studentId = idInput.value;
const groupSelector = studentForm.querySelector("select");
data.groupId = groupSelector.value;
console.log(data);
myModal.hide();
if (callback) {
callback(studentId, data);
}
});
return { setData: (element) => setModalData(element) };
};
export default studentModal;

59
js/uitable.js Normal file
View File

@ -0,0 +1,59 @@
const createTh = (value) => {
const th = document.createElement("th");
th.setAttribute("scope", "row");
th.innerText = value;
return th;
};
const createTd = (value) => {
const td = document.createElement("td");
td.innerText = value;
return td;
};
const createButton = (text, type, action) => {
const btn = document.createElement("button");
btn.setAttribute("type", "button");
btn.classList.add("btn", type);
btn.innerHTML = text;
btn.addEventListener("click", action);
const td = document.createElement("td");
td.appendChild(btn);
return td;
};
const studentTable = (tableId, editCallback, deleteCallback) => {
const draw = async (data) => {
const students = document.getElementById(tableId);
students.innerHTML = "";
data.forEach((element) => {
const container = document.createElement("tr");
container.classList.add("align-middle");
container.appendChild(createTh(element.id));
container.appendChild(createTd(element.last_name));
container.appendChild(createTd(element.first_name));
container.appendChild(createTd(element.bdate));
container.appendChild(createTd(element.email));
container.appendChild(createTd(element.phone));
container.appendChild(createTd(element.group.name));
container.appendChild(
createButton("Edit", "btn-warning", async () => {
if (editCallback) {
editCallback(element);
}
})
);
container.appendChild(
createButton("Delete", "btn-danger", async () => {
if (deleteCallback) {
deleteCallback(element.id);
}
})
);
students.appendChild(container);
});
};
return { draw };
};
export default studentTable;

View File

@ -120,147 +120,53 @@
Автор, 2022
</footer>
<script type="module">
// eslint-disable-next-line no-undef
const myModal = bootstrap.Modal.getOrCreateInstance(document.getElementById("studentModal"));
const studentForm = document.querySelector("#studentModal form");
import { addStudent, editStudent, getStudents, deleteStudent, getGroups } from "./js/api";
import studentModal from "./js/uimodal";
import studentTable from "./js/uitable";
const setModalData = (element) => {
const inputs = studentForm.querySelectorAll("input[required]");
inputs.forEach((input) => {
const control = input;
control.value = element ? element[input.getAttribute("id")] : "";
});
const idInput = studentForm.querySelector("#id");
idInput.value = element ? element.id : "";
const groupSelector = studentForm.querySelector("select");
groupSelector.value = element ? element.group.id : "";
myModal.show();
};
const modalEl = document.getElementById("studentModal");
modalEl.addEventListener("shown.bs.modal", (event) => {
if (!event.relatedTarget) {
return;
}
setModalData();
});
const addStudent = async (data) => {
const response = await fetch("http://localhost:3001/students", {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
});
if (!response.ok) {
throw new Error(`Response status: ${response.status}`);
}
};
const editStudent = async (id, data) => {
const response = await fetch(`http://localhost:3001/students/${id}`, {
method: "put",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
});
if (!response.ok) {
throw new Error(`Response status: ${response.status}`);
}
};
const deleteStudent = async (id) => {
// eslint-disable-next-line no-restricted-globals, no-alert
const answer = confirm(`Do you want to delete student with id = ${id}?`);
if (!answer) {
return;
}
const response = await fetch(`http://localhost:3001/students/${id}`, { method: "delete" });
if (!response.ok) {
throw new Error(`Response status: ${response.status}`);
}
};
const getStudents = async () => {
const students = document.getElementById("students");
students.innerHTML = "";
const response = await fetch("http://localhost:3001/students?_expand=group");
if (!response.ok) {
throw new Error(`Response status: ${response.status}`);
}
const data = await response.json();
data.forEach((element) => {
const createTh = (value) => {
const th = document.createElement("th");
th.setAttribute("scope", "row");
th.innerText = value;
return th;
};
const createTd = (value) => {
const td = document.createElement("td");
td.innerText = value;
return td;
};
const createButton = (text, type, action) => {
const btn = document.createElement("button");
btn.setAttribute("type", "button");
btn.classList.add("btn", type);
btn.innerHTML = text;
btn.addEventListener("click", action);
const td = document.createElement("td");
td.appendChild(btn);
return td;
};
const container = document.createElement("tr");
container.classList.add("align-middle");
container.appendChild(createTh(element.id));
container.appendChild(createTd(element.last_name));
container.appendChild(createTd(element.first_name));
container.appendChild(createTd(element.bdate));
container.appendChild(createTd(element.email));
container.appendChild(createTd(element.phone));
container.appendChild(createTd(element.group.name));
container.appendChild(
createButton("Edit", "btn-warning", async () => {
setModalData(element);
})
);
container.appendChild(
createButton("Delete", "btn-danger", async () => {
await deleteStudent(element.id);
getStudents();
})
);
students.appendChild(container);
});
console.log(data);
};
document.addEventListener("DOMContentLoaded", () => {
studentForm.addEventListener("submit", async (event) => {
event.preventDefault();
const data = {};
const inputs = studentForm.querySelectorAll("input[required]");
inputs.forEach((input) => {
data[input.getAttribute("id")] = input.value;
});
const idInput = studentForm.querySelector("#id");
const studentId = idInput.value;
const groupSelector = studentForm.querySelector("select");
data.groupId = groupSelector.value;
console.log(data);
const studentModalDialog = studentModal("studentModal", async (studentId, data) => {
if (!studentId) {
await addStudent(data);
} else {
await editStudent(studentId, data);
}
myModal.hide();
getStudents();
// eslint-disable-next-line no-use-before-define
getStudentsLogic();
});
getStudents();
const deleteStudentLogic = async (id) => {
// eslint-disable-next-line no-restricted-globals, no-alert
const answer = confirm(`Do you want to delete student with id = ${id}?`);
if (!answer) {
return;
}
deleteStudent(id);
};
const studentTableUI = studentTable(
"students",
async (element) => studentModalDialog.setData(element),
async (id) => deleteStudentLogic(id)
);
const getGroupsLogic = async () => {
const groups = document.querySelector("#studentModal form select");
groups.innerHTML = `<option value="">Select group</option>`;
const data = await getGroups();
data.forEach((element) => {
groups.innerHTML += `<option value="${element.id}">${element.name}</option>`;
});
console.log("groups", data);
};
const getStudentsLogic = async () => {
getGroupsLogic();
const data = await getStudents();
studentTableUI.draw(data);
};
document.addEventListener("DOMContentLoaded", () => {
getStudentsLogic();
});
</script>
</body>