-
vue.js 프로젝트: 일정 관리가 포함된 홈페이지 만들기정보교육/프런트엔드 2024. 6. 23. 22:05
vue.js를 공부한 다음 인공지능 chatGPT 4o를 사용해서 만들어보았다. 역시 공부하기 전에는 기본 구조부터 프로그램의 돌아가는 원리를 잘 이해하지 못해 gpt를 사용해도 만들지 못했을 것이다. 공부한 후에는 구조와 원리를 파악한 후 수정할 부분을 파악할 수 있었고 익스플로어나 크롬에 있는 개발자 도구를 사용해 버그도 찾아낼 수 있었다.
우선 재사용 가능한 컴포넌트를 만드는데 집중하였고, 그 컴포넌트를 여기저기 쓸 수 있게 되었다. 스케쥴 등록, 수정, 삭제가능한 컴포넌트를 만들었고 그 다음 캘린더 컴포넌트를 붙이고 emit 명령어를 사용하여 연결하였다. 이 과정에서 개발자 도구를 사용하여 에러를 찾아서 수정하였다. 특별히 데이터베이스를 사용하지 않고 로컬 저장소를 사용하여 아주 간단한 로직을 구현하였다.
Calendar.vue
<template> <div class="calendar"> <div class="header"> <button @click="prevMonth">Prev</button> <h2>{{ monthNames[currentMonth] }} {{ currentYear }}</h2> <button @click="nextMonth">Next</button> </div> <div class="weekdays"> <div v-for="day in weekDays" :key="day">{{ day }}</div> </div> <div class="days"> <div v-for="day in daysInMonth" :key="day.date ? day.date.toDateString() : day.index" :class="{'today': isToday(day.date), 'has-event': hasEvent(day.date)}" > <span v-if="day.date">{{ day.date.getDate() }}</span> </div> </div> </div> </template> <script> export default { props: { events: Array }, data() { return { currentDate: new Date(), currentMonth: new Date().getMonth(), currentYear: new Date().getFullYear(), weekDays: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], monthNames: [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ] }; }, computed: { daysInMonth() { const days = []; const firstDay = new Date(this.currentYear, this.currentMonth, 1).getDay(); const lastDate = new Date(this.currentYear, this.currentMonth + 1, 0).getDate(); for (let i = 0; i < firstDay; i++) { days.push({ date: null, index: `empty-${i}` }); } for (let date = 1; date <= lastDate; date++) { days.push({ date: new Date(this.currentYear, this.currentMonth, date) }); } return days; } }, methods: { prevMonth() { if (this.currentMonth === 0) { this.currentMonth = 11; this.currentYear--; } else { this.currentMonth--; } }, nextMonth() { if (this.currentMonth === 11) { this.currentMonth = 0; this.currentYear++; } else { this.currentMonth++; } }, isToday(date) { if (!date) return false; const today = new Date(); return date.getDate() === today.getDate() && date.getMonth() === today.getMonth() && date.getFullYear() === today.getFullYear(); }, hasEvent(date) { if (!date) return false; return this.events.some(event => { const eventDate = new Date(event.date); return eventDate.getDate() === date.getDate() && eventDate.getMonth() === date.getMonth() && eventDate.getFullYear() === date.getFullYear(); }); } } }; </script> <style scoped> .calendar { max-width: 400px; margin: auto; padding: 20px; border: 1px solid #ddd; border-radius: 8px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); } .header { display: flex; justify-content: space-between; align-items: center; } .weekdays { display: flex; justify-content: space-between; margin-top: 10px; } .days { display: flex; flex-wrap: wrap; } .days div { width: calc(100% / 7); height: 40px; display: flex; justify-content: center; align-items: center; margin-top: 10px; } .today { background-color: #42b983; color: white; border-radius: 50%; } .has-event { background-color: purple; color: white; border-radius: 50%; } </style>
Schedule.vue
<template> <div class="schedule"> <h2>My Schedule</h2> <ul> <li v-for="event in events" :key="event.id"> <span @click="editEvent(event)">{{ event.date }} {{ event.time }}: {{ event.title }}</span> <button @click="deleteEvent(event.id)">Delete</button> </li> </ul> <input v-model="newEventTitle" placeholder="Event Title" /> <input v-model="newEventDate" type="date" /> <input v-model="newEventTime" type="time" /> <button @click="addEvent">Add Event</button> <button v-if="isEditing" @click="updateEvent">Update Event</button> </div> </template> <script> export default { data() { return { events: JSON.parse(localStorage.getItem('events') || '[]'), newEventTitle: '', newEventDate: '', newEventTime: '', isEditing: false, currentEvent: null }; }, methods: { addEvent() { if (this.newEventTitle && this.newEventDate && this.newEventTime) { const newEvent = { id: Date.now(), title: this.newEventTitle, date: this.newEventDate, time: this.newEventTime }; this.events.push(newEvent); this.saveEvents(); this.resetForm(); this.$emit('update-events', this.events); } }, editEvent(event) { this.isEditing = true; this.currentEvent = event; this.newEventTitle = event.title; this.newEventDate = event.date; this.newEventTime = event.time; }, updateEvent() { if (this.currentEvent) { this.currentEvent.title = this.newEventTitle; this.currentEvent.date = this.newEventDate; this.currentEvent.time = this.newEventTime; this.saveEvents(); this.resetForm(); this.$emit('update-events', this.events); } }, deleteEvent(id) { this.events = this.events.filter(event => event.id !== id); this.saveEvents(); this.$emit('update-events', this.events); }, saveEvents() { localStorage.setItem('events', JSON.stringify(this.events)); }, resetForm() { this.newEventTitle = ''; this.newEventDate = ''; this.newEventTime = ''; this.isEditing = false; this.currentEvent = null; } } }; </script> <style scoped> .schedule { max-width: 400px; margin: auto; padding: 20px; border: 1px solid #ddd; border-radius: 8px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); } input { display: block; width: 100%; padding: 8px; margin: 10px 0; border: 1px solid #ccc; border-radius: 4px; } button { padding: 10px 15px; background-color: #42b983; color: white; border: none; border-radius: 4px; cursor: pointer; } button:hover { background-color: #38a373; } ul { list-style-type: none; padding: 0; } li { margin: 10px 0; } span { cursor: pointer; } </style>
마지막으로 홈페이지 구실을 하기위해 header, menu, article, side, footer를 구성하고 side에 캘린더와 일정 관리를 재사용하였다.
SideBar.vue
<template> <div> <Calendar :events="events" /> <Schedule @update-events="updateEvents" /> </div> </template> <script> import Calendar from './Calendar.vue'; import Schedule from './Schedule.vue'; export default { name: 'SideBar', components: { Calendar, Schedule }, data() { return { events: JSON.parse(localStorage.getItem('events') || '[]') }; }, methods: { updateEvents(events) { this.events = events; } } }; </script>
결과물과 만드는 과정은 아래 링크를 통해서 확인할 수 있다. 단 이 페이지는 최종 완성물이 아니라서 최적화 과정을 거쳐서 자신만의 웹페이지를 만들 수 있으면 한다.
My Personal Website (jocular-boba-1b5d4b.netlify.app)
'정보교육 > 프런트엔드' 카테고리의 다른 글
코딩 자율학습단(Vue.js 프런트엔드 개발 입문) 7일차 (0) 2024.06.25 코딩 자율학습단(Vue.js 프런트엔드 개발 입문) 6일차 (0) 2024.06.24 코딩 자율학습단(Vue.js 프런트엔드 개발 입문) 5일차 (0) 2024.06.22 코딩 자율학습단(Vue.js 프런트엔드 개발 입문) 4일차 (0) 2024.06.20 코딩 자율학습단(Vue.js 프런트엔드 개발 입문) 3일차 (0) 2024.06.19