|
|
@@ -265,6 +265,23 @@
|
|
|
</v-btn>
|
|
|
</div>
|
|
|
|
|
|
+ <div v-else-if="request.STATUS === 'APPROVED'" class="approved--actions">
|
|
|
+ <v-btn
|
|
|
+ class="custom-btn mini btn-outline"
|
|
|
+ @click="viewRequestHistory(request.SEQ)"
|
|
|
+ >
|
|
|
+ 이력보기
|
|
|
+ </v-btn>
|
|
|
+ <v-btn
|
|
|
+ class="custom-btn mini btn-terminate"
|
|
|
+ @click="handleTerminate(request)"
|
|
|
+ :loading="processing"
|
|
|
+ >
|
|
|
+ <v-icon left size="small">mdi-link-off</v-icon>
|
|
|
+ 해지
|
|
|
+ </v-btn>
|
|
|
+ </div>
|
|
|
+
|
|
|
<v-btn
|
|
|
v-else
|
|
|
class="custom-btn mini btn-outline"
|
|
|
@@ -398,6 +415,66 @@
|
|
|
</v-card-actions>
|
|
|
</v-card>
|
|
|
</v-dialog>
|
|
|
+
|
|
|
+ <!-- 해지 확인 모달 -->
|
|
|
+ <v-dialog v-model="terminateModal.show" max-width="500px">
|
|
|
+ <v-card>
|
|
|
+ <v-card-title class="text-h5 text-warning">
|
|
|
+ <v-icon left>mdi-link-off</v-icon>
|
|
|
+ 파트너십 해지 확인
|
|
|
+ </v-card-title>
|
|
|
+ <v-card-text>
|
|
|
+ <div class="terminate--content">
|
|
|
+ <div class="influencer--summary">
|
|
|
+ <div class="influencer--avatar--small">
|
|
|
+ <v-img
|
|
|
+ v-if="terminateModal.request?.influencerAvatar"
|
|
|
+ :src="terminateModal.request.influencerAvatar"
|
|
|
+ width="40"
|
|
|
+ height="40"
|
|
|
+ ></v-img>
|
|
|
+ <div v-else class="no-avatar--small">
|
|
|
+ {{ terminateModal.request?.influencerNickname?.charAt(0) || "U" }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <h4>{{ terminateModal.request?.influencerNickname }}</h4>
|
|
|
+ <p>{{ getCategoryText(terminateModal.request?.influencerCategory) }}</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <v-alert type="warning" class="mb-4">
|
|
|
+ <strong>주의:</strong> 파트너십을 해지하면 협업 관계가 종료되며, 이 작업은 되돌릴 수 없습니다.
|
|
|
+ </v-alert>
|
|
|
+
|
|
|
+ <p>이 인플루언서와의 파트너십을 해지하시겠습니까?</p>
|
|
|
+
|
|
|
+ <v-textarea
|
|
|
+ v-model="terminateModal.terminateReason"
|
|
|
+ label="해지 사유"
|
|
|
+ placeholder="해지 사유를 입력해주세요..."
|
|
|
+ rows="4"
|
|
|
+ counter="500"
|
|
|
+ maxlength="500"
|
|
|
+ class="mt-4"
|
|
|
+ required
|
|
|
+ ></v-textarea>
|
|
|
+ </div>
|
|
|
+ </v-card-text>
|
|
|
+ <v-card-actions>
|
|
|
+ <v-spacer></v-spacer>
|
|
|
+ <v-btn color="grey" variant="text" @click="closeTerminateModal">취소</v-btn>
|
|
|
+ <v-btn
|
|
|
+ class="btn-terminate-confirm"
|
|
|
+ @click="confirmTerminate"
|
|
|
+ :loading="processing"
|
|
|
+ >
|
|
|
+ <v-icon left>mdi-link-off</v-icon>
|
|
|
+ 해지하기
|
|
|
+ </v-btn>
|
|
|
+ </v-card-actions>
|
|
|
+ </v-card>
|
|
|
+ </v-dialog>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
@@ -448,6 +525,7 @@
|
|
|
{ title: "대기중", value: "PENDING" },
|
|
|
{ title: "승인완료", value: "APPROVED" },
|
|
|
{ title: "거부됨", value: "REJECTED" },
|
|
|
+ { title: "해지됨", value: "TERMINATED" },
|
|
|
]);
|
|
|
|
|
|
// 카테고리 옵션
|
|
|
@@ -490,6 +568,13 @@
|
|
|
rejectReason: "",
|
|
|
});
|
|
|
|
|
|
+ // 해지 모달
|
|
|
+ const terminateModal = ref({
|
|
|
+ show: false,
|
|
|
+ request: null,
|
|
|
+ terminateReason: "",
|
|
|
+ });
|
|
|
+
|
|
|
/************************************************************************
|
|
|
| computed
|
|
|
************************************************************************/
|
|
|
@@ -687,6 +772,65 @@
|
|
|
router.push(`/view/vendor/request-history/${requestSeq}`);
|
|
|
};
|
|
|
|
|
|
+ const handleTerminate = (request) => {
|
|
|
+ terminateModal.value = {
|
|
|
+ show: true,
|
|
|
+ request: request,
|
|
|
+ terminateReason: "",
|
|
|
+ };
|
|
|
+ };
|
|
|
+
|
|
|
+ const closeTerminateModal = () => {
|
|
|
+ terminateModal.value = {
|
|
|
+ show: false,
|
|
|
+ request: null,
|
|
|
+ terminateReason: "",
|
|
|
+ };
|
|
|
+ };
|
|
|
+
|
|
|
+ const confirmTerminate = async () => {
|
|
|
+ if (!terminateModal.value.terminateReason.trim()) {
|
|
|
+ $toast.error("해지 사유를 입력해주세요.");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ processing.value = true;
|
|
|
+
|
|
|
+ const params = {
|
|
|
+ mappingSeq: terminateModal.value.request.SEQ,
|
|
|
+ terminateReason: terminateModal.value.terminateReason,
|
|
|
+ terminatedBy: currentUser.value.seq,
|
|
|
+ };
|
|
|
+
|
|
|
+ console.log('🔗 파트너십 해지 처리 시작:', params);
|
|
|
+
|
|
|
+ useAxios()
|
|
|
+ .post("/api/vendor-influencer/terminate", params)
|
|
|
+ .then((res) => {
|
|
|
+ console.log('📥 해지 처리 응답:', res.data);
|
|
|
+ if (res.data.success) {
|
|
|
+ $toast.success("파트너십이 해지되었습니다.");
|
|
|
+ closeTerminateModal();
|
|
|
+ console.log('🔄 해지 후 목록 새로고침');
|
|
|
+ loadRequests();
|
|
|
+ } else {
|
|
|
+ console.error('❌ 해지 처리 실패:', res.data);
|
|
|
+ $toast.error(res.data.message || "해지 처리 중 오류가 발생했습니다.");
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch((err) => {
|
|
|
+ $toast.error(err.message || "해지 처리 중 오류가 발생했습니다.");
|
|
|
+ })
|
|
|
+ .finally(() => {
|
|
|
+ processing.value = false;
|
|
|
+ });
|
|
|
+ } catch (err) {
|
|
|
+ $toast.error(err.message || "해지 처리 중 오류가 발생했습니다.");
|
|
|
+ processing.value = false;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
// 유틸리티 함수들
|
|
|
const getCategoryText = (category) => {
|
|
|
const categoryMap = {
|
|
|
@@ -705,6 +849,7 @@
|
|
|
PENDING: "대기중",
|
|
|
APPROVED: "승인완료",
|
|
|
REJECTED: "거절됨",
|
|
|
+ TERMINATED: "해지됨",
|
|
|
EXPIRED: "만료됨",
|
|
|
};
|
|
|
return statusMap[status] || status || "알 수 없음";
|
|
|
@@ -715,6 +860,7 @@
|
|
|
PENDING: "orange",
|
|
|
APPROVED: "success",
|
|
|
REJECTED: "error",
|
|
|
+ TERMINATED: "warning",
|
|
|
EXPIRED: "grey",
|
|
|
};
|
|
|
return colorMap[status] || "grey";
|
|
|
@@ -858,6 +1004,10 @@
|
|
|
border-left-color: #f44336;
|
|
|
}
|
|
|
|
|
|
+ .request--card.request-status-terminated {
|
|
|
+ border-left-color: #ff9800;
|
|
|
+ }
|
|
|
+
|
|
|
.request--card--header {
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
@@ -987,7 +1137,8 @@
|
|
|
align-items: center;
|
|
|
}
|
|
|
|
|
|
- .approval--actions {
|
|
|
+ .approval--actions,
|
|
|
+ .approved--actions {
|
|
|
display: flex;
|
|
|
gap: 8px;
|
|
|
}
|
|
|
@@ -1139,4 +1290,80 @@
|
|
|
padding: 4px 8px;
|
|
|
border-radius: 4px;
|
|
|
}
|
|
|
+
|
|
|
+ /* 해지 버튼 전용 스타일 */
|
|
|
+ .btn-terminate {
|
|
|
+ background: linear-gradient(135deg, #ff4757 0%, #ff3742 100%) !important;
|
|
|
+ color: white !important;
|
|
|
+ font-weight: 600 !important;
|
|
|
+ border: 2px solid #ff4757 !important;
|
|
|
+ box-shadow: 0 2px 8px rgba(255, 71, 87, 0.3) !important;
|
|
|
+ transition: all 0.3s ease !important;
|
|
|
+ text-transform: none !important;
|
|
|
+ letter-spacing: 0.5px !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn-terminate:hover {
|
|
|
+ background: linear-gradient(135deg, #ff3742 0%, #ff2f3a 100%) !important;
|
|
|
+ border-color: #ff3742 !important;
|
|
|
+ box-shadow: 0 4px 12px rgba(255, 71, 87, 0.4) !important;
|
|
|
+ transform: translateY(-1px) !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn-terminate:active {
|
|
|
+ transform: translateY(0) !important;
|
|
|
+ box-shadow: 0 2px 6px rgba(255, 71, 87, 0.4) !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn-terminate .v-icon {
|
|
|
+ color: white !important;
|
|
|
+ margin-right: 4px !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn-terminate:disabled {
|
|
|
+ background: #ffbdc1 !important;
|
|
|
+ color: #999 !important;
|
|
|
+ border-color: #ffbdc1 !important;
|
|
|
+ box-shadow: none !important;
|
|
|
+ transform: none !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 해지 확인 모달 버튼 스타일 */
|
|
|
+ .btn-terminate-confirm {
|
|
|
+ background: linear-gradient(135deg, #dc2626 0%, #b91c1c 100%) !important;
|
|
|
+ color: white !important;
|
|
|
+ font-weight: 700 !important;
|
|
|
+ font-size: 14px !important;
|
|
|
+ padding: 12px 24px !important;
|
|
|
+ border-radius: 8px !important;
|
|
|
+ border: none !important;
|
|
|
+ box-shadow: 0 4px 12px rgba(220, 38, 38, 0.4) !important;
|
|
|
+ transition: all 0.3s ease !important;
|
|
|
+ text-transform: none !important;
|
|
|
+ letter-spacing: 0.5px !important;
|
|
|
+ min-width: 120px !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn-terminate-confirm:hover {
|
|
|
+ background: linear-gradient(135deg, #b91c1c 0%, #991b1b 100%) !important;
|
|
|
+ box-shadow: 0 6px 16px rgba(220, 38, 38, 0.5) !important;
|
|
|
+ transform: translateY(-2px) !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn-terminate-confirm:active {
|
|
|
+ transform: translateY(0) !important;
|
|
|
+ box-shadow: 0 3px 8px rgba(220, 38, 38, 0.4) !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn-terminate-confirm .v-icon {
|
|
|
+ color: white !important;
|
|
|
+ margin-right: 6px !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn-terminate-confirm:disabled {
|
|
|
+ background: #fca5a5 !important;
|
|
|
+ color: #9ca3af !important;
|
|
|
+ box-shadow: none !important;
|
|
|
+ transform: none !important;
|
|
|
+ }
|
|
|
</style>
|