let isEditing = false; const RESERVATION_API_ENDPOINT = '/reservations'; const TIME_API_ENDPOINT = '/times'; const THEME_API_ENDPOINT = '/themes'; const MEMBER_API_ENDPOINT = '/members'; const timesOptions = []; const themesOptions = []; const membersOptions = []; document.addEventListener('DOMContentLoaded', () => { document.getElementById('add-button').addEventListener('click', addInputRow); document.getElementById('filter-form').addEventListener('submit', applyFilter); requestRead(RESERVATION_API_ENDPOINT) .then(render) .catch(error => console.error('Error fetching reservations:', error)); fetchTimes(); fetchThemes(); fetchMembers(); }); function render(data) { const tableBody = document.getElementById('table-body'); tableBody.innerHTML = ''; data.data.reservations.forEach(item => { const row = tableBody.insertRow(); const isPaid = item.status === 'CONFIRMED' ? '결제 완료' : '결제 대기'; row.insertCell(0).textContent = item.id; // 예약 id row.insertCell(1).textContent = item.member.name; // 사용자 name row.insertCell(2).textContent = item.theme.name; // 테마 name row.insertCell(3).textContent = item.date; // date row.insertCell(4).textContent = item.time.startAt; // 예약 시간 startAt row.insertCell(5).textContent = isPaid; // 결제 const actionCell = row.insertCell(row.cells.length); actionCell.appendChild(createActionButton('삭제', 'btn-danger', deleteRow)); }); } function fetchTimes() { requestRead(TIME_API_ENDPOINT) .then(data => { timesOptions.push(...data.data.times); }) .catch(error => console.error('Error fetching time:', error)); } function fetchThemes() { requestRead(THEME_API_ENDPOINT) .then(data => { themesOptions.push(...data.data.themes); populateSelect('theme', themesOptions, 'name'); }) .catch(error => console.error('Error fetching theme:', error)); } function fetchMembers() { requestRead(MEMBER_API_ENDPOINT) .then(data => { membersOptions.push(...data.data.members); populateSelect('member', membersOptions, 'name'); }) .catch(error => console.error('Error fetching member:', error)); } function populateSelect(selectId, options, textProperty) { const select = document.getElementById(selectId); options.forEach(optionData => { const option = document.createElement('option'); option.value = optionData.id; option.textContent = optionData[textProperty]; select.appendChild(option); }); } function createSelect(options, defaultText, selectId, textProperty) { const select = document.createElement('select'); select.className = 'form-control'; select.id = selectId; // 기본 옵션 추가 const defaultOption = document.createElement('option'); defaultOption.textContent = defaultText; select.appendChild(defaultOption); // 넘겨받은 옵션을 바탕으로 드롭다운 메뉴 아이템 생성 options.forEach(optionData => { const option = document.createElement('option'); option.value = optionData.id; option.textContent = optionData[textProperty]; // 동적 속성 접근 select.appendChild(option); }); return select; } function createActionButton(label, className, eventListener) { const button = document.createElement('button'); button.textContent = label; button.classList.add('btn', className, 'mr-2'); button.addEventListener('click', eventListener); return button; } function addInputRow() { if (isEditing) return; // 이미 편집 중인 경우 추가하지 않음 const tableBody = document.getElementById('table-body'); const row = tableBody.insertRow(); isEditing = true; const dateInput = createInput('date'); const timeDropdown = createSelect(timesOptions, "시간 선택", 'time-select', 'startAt'); const themeDropdown = createSelect(themesOptions, "테마 선택", 'theme-select', 'name'); const memberDropdown = createSelect(membersOptions, "멤버 선택", 'member-select', 'name'); const cellFieldsToCreate = ['', memberDropdown, themeDropdown, dateInput, timeDropdown]; cellFieldsToCreate.forEach((field, index) => { const cell = row.insertCell(index); if (typeof field === 'string') { cell.textContent = field; } else { cell.appendChild(field); } }); const actionCell = row.insertCell(row.cells.length); actionCell.appendChild(createActionButton('확인', 'btn-custom', saveRow)); actionCell.appendChild(createActionButton('취소', 'btn-secondary', () => { row.remove(); isEditing = false; })); } function createInput(type) { const input = document.createElement('input'); input.type = type; input.className = 'form-control'; return input; } function createActionButton(label, className, eventListener) { const button = document.createElement('button'); button.textContent = label; button.classList.add('btn', className, 'mr-2'); button.addEventListener('click', eventListener); return button; } function saveRow(event) { // 이벤트 전파를 막는다 event.stopPropagation(); const row = event.target.parentNode.parentNode; const dateInput = row.querySelector('input[type="date"]'); const memberSelect = row.querySelector('#member-select'); const themeSelect = row.querySelector('#theme-select'); const timeSelect = row.querySelector('#time-select'); const reservation = { date: dateInput.value, themeId: themeSelect.value, timeId: timeSelect.value, memberId: memberSelect.value, }; requestCreate(reservation) .then(() => { location.reload(); }) .catch(error => console.error('Error:', error)); isEditing = false; // isEditing 값을 false로 설정 } function deleteRow(event) { const row = event.target.closest('tr'); const reservationId = row.cells[0].textContent; requestDelete(reservationId) .then(() => row.remove()) .catch(error => console.error('Error:', error)); } function applyFilter(event) { event.preventDefault(); const themeId = document.getElementById('theme').value; const memberId = document.getElementById('member').value; const dateFrom = document.getElementById('date-from').value; const dateTo = document.getElementById('date-to').value; const queryParams = { themeId: themeId, memberId: memberId, dateFrom: dateFrom, dateTo: dateTo } const searchParams = new URLSearchParams(queryParams); const endpoint = '/reservations/search'; const url = `${endpoint}?${searchParams.toString()}`; fetch(url, { // 예약 검색 API 호출 method: 'GET', headers: { 'Content-Type': 'application/json' }, }).then(response => { if (response.status === 200) return response.json(); throw new Error('Read failed'); }).then(render) .catch(error => console.error("Error fetching available times:", error)); } function requestCreate(reservation) { const requestOptions = { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(reservation) }; return fetch('/reservations/admin', requestOptions) .then(response => { if (response.status === 201) return response.json(); throw new Error('Create failed'); }); } function requestDelete(id) { const requestOptions = { method: 'DELETE', }; return fetch(`${RESERVATION_API_ENDPOINT}/${id}`, requestOptions) .then(response => { if (response.status !== 204) throw new Error('Delete failed'); }); } function requestRead(endpoint) { return fetch(endpoint) .then(response => { if (response.status === 200) return response.json(); throw new Error('Read failed'); }); }