
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
<template>
<div class="w_100 h_100 layout sterech gap30">
<div class="left-zone" style="background-color: #d5dce7;">
<div class="layout center space-between">
<img src="../../../resources/img/content/feedback.svg" alt="">
<div>
<p class="feedback-title">Feedback</p>
<select name="sort" id="sort" class="form-select sm" style="border: none;min-width: 140px;">
<option value="">최근순</option>
<option value="">최근순</option>
</select>
</div>
</div>
<div class="feedback-list">
<div v-for="feedback in feedbackList" :key="feedback.id" class="feedback-item" :class="{ unread: feedback.status === 'unread' }">
<div class="feedback-card">
<h4>
<img src="../../../resources/img/content/ico_confirmed.svg" alt="" v-if="feedback.status === 'confirmed'" style="vertical-align: middle;">
<img src="../../../resources/img/content/ico_unconfirmed.svg" alt="" v-else style="vertical-align: middle;">
<span>{{ feedback.project }}</span>
</h4>
<div class="feedback-message">
<p>{{ feedback.message }}</p>
</div>
<div class="meta">
<span><img src="../../../resources/img/content/ico_clock.svg" alt="" style="vertical-align: middle;"> {{ feedback.time }}</span> | <span><img src="../../../resources/img/content/ico_feeduser.svg" alt="" style="vertical-align: middle;"> {{ feedback.user }}</span>
</div>
</div>
<div class="btn-group" v-if="feedback.status === 'unread'">
<button class="btn sm purple" @click="markAsRead(feedback.id)">확인</button>
<button class="btn sm black" @click="replyTo(feedback)">회신</button>
</div>
<div class="btn-group" v-else>
<button class="btn sm primary" @click="markAsRead(feedback.id)">확인됨</button>
</div>
</div>
</div>
</div>
<div class="right-zone feedback-detail-zone">
<div class="summary">
<p><span>일주일 간 총 피드백 수 </span> <strong>{{ feedbackSummary.total }}건</strong></p>|
<p><span class="unread">미확인</span> <strong>{{ feedbackSummary.unread }}건</strong></p> |
<p><span class="read">확인</span> <strong>{{ feedbackSummary.read }}건</strong></p>
</div>
<div class="feedback-detail" v-if="selectedFeedback">
<div class="top-zone">
<h3 class="project-name">{{ selectedFeedback.project }}</h3><span style="font-weight: 700;"> feedback message</span>
</div>
<ul >
<li v-for="feedback in feedbacDetailkList" :key="feedback.id">
<div class="layout center space-between">
<strong><img src="../../../resources/img/content/ico_feeduser.svg" alt="" style="vertical-align: middle;"> {{ feedback.name }}</strong>
<div class="right-content">
<p>{{ feedback.content }}</p>
</div>
</div>
<p style="text-align: right;"> <span>{{ feedback.date }} </span><span><img src="../../../resources/img/content/ico_clock.svg" alt="" style="vertical-align: middle;"> {{ feedback.time }}</span></p>
</li>
</ul>
<div style="position: relative;">
<input type="text" class="form-control sm" v-model="replyText" placeholder="피드백 회신 내용을 작성하세요."></input>
<button class="send-btn" @click="submitReply"><img src="../../../resources/img/content/ico_send.svg" alt="" style="vertical-align: middle;"></button>
</div>
</div>
<div class="feedback-detail first-view" v-else>
<img src="../../../resources/img/content/unfeedback.svg" alt="">
<p>피드백이 선택되지 않았습니다.</p>
<p>피드백을 선택하면 상세내용을 확인할 수 있습니다.</p>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
feedbackList: [
{
id: 1,
project: '프로젝트 C',
message: '“크기를 두 배 증가시켜 주세요..”',
time: '5분 전',
user: '김철수님',
status: 'unread' // 'unread' | 'read' | 'confirmed'
},
{
id: 2,
project: '프로젝트 B',
message: '“플라스틱 재질을 다음과 같이..”',
time: '30분 전',
user: '이영희님',
status: 'unread'
},
{
id: 3,
project: '프로젝트 B',
message: '“좀 더 밝은 색으로 바꿔주세요..”',
time: '어제',
user: '김철수님',
status: 'confirmed'
}
],
feedbackSummary: {
total: 3,
unread: 2,
read: 1
},
selectedFeedback: null, // 회신용
replyingFeedbackId: null, // 회신 폼 표시용
feedbacDetailkList: [
{
id: 1,
name: '홍길동',
content: '교육 내용이 이해하기 쉬웠습니다.',
date: '2025-06-24',
time: '14:30',
status: '미확인'
},
{
id: 2,
name: '김영희',
content: '실습 예제가 더 많았으면 좋겠습니다.',
date: '2025-06-23',
time: '10:15',
status: '확인'
},
{
id: 3,
name: '박철수',
content: '강사님 설명이 친절해서 좋았습니다.',
date: '2025-06-22',
time: '16:45',
status: '회신완료'
},
{
id: 4,
name: '이민정',
content: '온라인 자료 접근이 어려웠어요.',
date: '2025-06-21',
time: '09:05',
status: '미확인'
},
{
id: 5,
name: '최현우',
content: '교육 시간이 너무 짧은 것 같아요.',
date: '2025-06-20',
time: '13:20',
status: '확인'
}
],
replyText: '',
};
},
methods: {
async markAsRead(id) {
// 서버에 상태값 전달
try {
await axios.post(`/api/feedback/${id}/mark-read`);
const item = this.feedbackList.find(f => f.id === id);
if (item) item.status = 'read';
} catch (err) {
console.error('확인 처리 실패:', err);
}
},
async submitReply() {
if (!this.replyText.trim()) return;
try {
await axios.post(`/api/feedback/${this.replyingFeedbackId}/reply`, {
reply: this.replyText
});
alert('회신이 전송되었습니다.');
this.replyText = '';
this.selectedFeedback = null;
this.replyingFeedbackId = null;
} catch (err) {
console.error('회신 실패:', err);
}
},
replyTo(feedback) {
this.selectedFeedback = feedback;
this.replyingFeedbackId = feedback.id;
},
},
watch: {},
computed: {},
components: {},
created() {},
mounted() {},
beforeUnmount() {},
};
</script>