이 애플리케이션의 주요 기능은 다음과 같습니다:
이 프로젝트에서는 다음과 같은 기술과 라이브러리를 사용했습니다:
<template>
<div class="page-container">
<!-- 사이드바 -->
<div class="sidebar">
<button class="btn btn-primary" @click="isOpenClose = !isOpenClose">{{ isOpenClose ? '입력 창 닫기' : '데이터 입력' }}</button>
<button class="btn btn-info" @click="showlist">데이터 가져오기</button>
</div>
<!-- 메인 콘텐츠 -->
<div class="main-content">
<!-- 입력 폼 -->
<div v-show="isOpenClose" class="form-container">
<form autocomplete="off">
<div class="form-group">
<label class="form-label">날짜</label>
<input type="date" class="form-control" v-model="date">
</div>
<div class="form-group">
<label class="form-label">할 일</label>
<input type="text" class="form-control" v-model="work">
</div>
<div class="form-group">
<label class="form-label">중요도</label>
<select class="form-control" v-model="force">
<option value="상">상</option>
<option value="중">중</option>
<option value="하">하</option>
</select>
</div>
<div class="form-group">
<label class="form-label">결과</label>
<select class="form-control" v-model="result">
<option value="미완료">미완료</option>
<option value="진행중">진행중</option>
<option value="완료">완료</option>
</select>
</div>
<div class="form-actions">
<button type="button" class="btn btn-success" v-if="!isEditing" @click="input">저장</button>
<button type="button" class="btn btn-warning" v-if="isEditing" @click="update(currentId)">업데이트</button>
<button type="button" class="btn btn-secondary" @click="cancelEdit">취소</button>
</div>
</form>
</div>
<!-- 할 일 목록 테이블 -->
<div class="table-container">
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>날짜</th>
<th>할 일</th>
<th>중요도</th>
<th>처리 결과</th>
<th>삭제/업데이트</th>
</tr>
</thead>
<tbody>
<tr v-for="daily in dailys" :key="daily.id">
<td>{{ daily.id }}</td>
<td>{{ daily.date }}</td>
<td>{{ daily.work }}</td>
<td>{{ daily.force }}</td>
<td>{{ daily.result }}</td>
<td>
<button type="button" @click="deleteData(daily.id)" class="btn btn-danger">삭제</button>
<button type="button" @click="editData(daily)" class="btn btn-info">업데이트</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</template>
<script setup>
import axios from "axios";
import { ref } from "vue";
// 반응형 데이터 선언
const isOpenClose = ref(false); // 폼 열림/닫힘 상태
const date = ref(''); // 입력할 날짜
const work = ref(''); // 입력할 할 일
const force = ref('상'); // 중요도
const result = ref('미완료'); // 결과 상태
const dailys = ref([]); // 할 일 목록
const isEditing = ref(false); // 수정 모드 상태
const currentId = ref(null); // 현재 수정 중인 할 일 ID
// 할 일 추가
const input = async () => {
try {
await axios.post("http://localhost:3000/daily", {
date: date.value,
work: work.value,
force: force.value,
result: result.value
});
resetForm(); // 폼 초기화
showlist(); // 목록 갱신
} catch (error) {
console.log('전송 실패');
}
}
// 할 일 삭제
const deleteData = async (id) => {
const isconfirm = confirm("삭제 하시겠습니까?");
if (!isconfirm) {
return;
}
try {
await axios.delete(`http://localhost:3000/daily/${id}`);
showlist(); // 목록 갱신
} catch (error) {
console.log('삭제 실패');
}
}
// 할 일 업데이트
const update = async (id) => {
try {
await axios.put(`http://localhost:3000/daily/${id}`, {
date: date.value,
work: work.value,
force: force.value,
result: result.value,
});
resetForm(); // 폼 초기화
showlist(); // 목록 갱신
} catch (error) {
console.log('업데이트 실패');
}
}
// 할 일 수정 폼에 데이터 로드
const editData = (daily) => {
date.value = daily.date;
work.value = daily.work;
force.value = daily.force;
result.value = daily.result;
currentId.value = daily.id;
isEditing.value = true;
isOpenClose.value = true;
}
// 폼 초기화
const resetForm = () => {
date.value = '';
work.value = '';
force.value = '상';
result.value = '미완료';
isOpenClose.value = false;
isEditing.value = false;
currentId.value = null;
}
// 수정 취소
const cancelEdit = () => {
resetForm();
}
// 할 일 목록 가져오기
const showlist = async () => {
const res = await axios.get("http://localhost:3000/daily");
dailys.value = res.data; // 목록 업데이트
console.log(dailys.value);
isOpenClose.value = false; // 폼 닫기
}
</script>
.page-container {
display: flex;
min-height: 100vh;
background-color: #f0f2f5;
}
.sidebar {
width: 250px;
background-color: #2c3e50;
padding: 20px;
display: flex;
flex-direction: column;
gap: 20px;
align-items: center;
justify-content: center;
}
.main-content {
flex-grow: 1;
padding: 40px;
background-color: #ecf0f1;
}
/* Form styles */
.form-container {
background-color: white;
padding: 30px;
border-radius: 12px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
margin-bottom: 40px;
}
.form-group {
margin-bottom: 20px;
}
.form-label {
font-size: 1rem;
margin-bottom: 8px;
display: block;
color: #34495e;
}
.form-control {
width: 100%;
padding: 12px;
border-radius: 8px;
border: 1px solid #bdc3c7;
font-size: 1rem;
}
.form-actions {
display: flex;
justify-content: flex-end;
gap: 10px;
}
/* Button styles */
button {
padding: 12px 18px;
font-size: 1rem;
border-radius: 8px;
cursor: pointer;
transition: background-color 0.3s ease;
}
button.btn-primary {
background-color: #2980b9;
color: white;
}
button.btn-info {
background-color: #27ae60;
color: white;
}
button.btn-danger {
background-color: #c0392b;
color: white;
}
button.btn-secondary {
background-color: #7f8c8d;
color: white;
}
button.btn-success {
background-color: #2ecc71;
color: white;
}
button.btn-warning {
background-color: #f39c12;
color: white;
}
/* Table styles */
.table-container {
background-color: white;
border-radius: 12px;
padding: 20px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
}
.table {
width: 100%;
border-collapse: collapse;
background-color: #fff;
}
.table th, .table td {
text-align: left;
padding: 12px;
border-bottom: 1px solid #ddd;
}
.table th {
background-color: #34495e;
color: white;
}
.table td button {
margin-right: 10px;
}
.table tr:hover {
background-color: #f9f9f9;
}
.table-container {
margin-top: 30px;
}

