관리자는 VIP·멤버만 수정 가능하도록 서버·UI 권한을 정리하고 소유자 권한 이전 API와 확인 모달을 추가했다. 추천 사이트 파비콘 캐시·URL 접두사·카드 편집 UI를 보강하고 확인 얼럿을 AdminConfirmModal로 통일했다. Co-authored-by: Cursor <cursoragent@cursor.com>
100 lines
3.1 KiB
Vue
100 lines
3.1 KiB
Vue
<script setup>
|
|
defineProps({
|
|
open: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
title: {
|
|
type: String,
|
|
required: true
|
|
},
|
|
confirmLabel: {
|
|
type: String,
|
|
default: '확인'
|
|
},
|
|
cancelLabel: {
|
|
type: String,
|
|
default: '취소'
|
|
},
|
|
confirmTone: {
|
|
type: String,
|
|
default: 'primary'
|
|
},
|
|
loading: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
loadingLabel: {
|
|
type: String,
|
|
default: ''
|
|
}
|
|
})
|
|
|
|
defineEmits(['confirm', 'cancel'])
|
|
|
|
/**
|
|
* 확인 버튼 스타일 클래스를 반환한다.
|
|
* @param {string} tone - 버튼 톤
|
|
* @returns {string} 클래스 문자열
|
|
*/
|
|
const getConfirmButtonClass = (tone) => {
|
|
if (tone === 'danger') {
|
|
return 'bg-[#d21a26] text-white hover:bg-[#b81620]'
|
|
}
|
|
return 'bg-[#15171a] text-white hover:bg-[#2b2f35]'
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<Teleport to="body">
|
|
<div
|
|
v-if="open"
|
|
class="admin-confirm-modal fixed inset-0 z-[100] flex items-start justify-center bg-black/35 px-4 pt-10"
|
|
role="dialog"
|
|
aria-modal="true"
|
|
:aria-labelledby="'admin-confirm-modal-title'"
|
|
>
|
|
<section class="admin-confirm-modal__panel w-full max-w-[520px] rounded-xl bg-white text-[#15171a] shadow-[0_22px_70px_rgba(15,23,42,0.25)]">
|
|
<header class="admin-confirm-modal__header flex items-center justify-between border-b border-line px-6 py-5">
|
|
<h2 id="admin-confirm-modal-title" class="admin-confirm-modal__title text-xl font-semibold">
|
|
{{ title }}
|
|
</h2>
|
|
<button
|
|
class="admin-confirm-modal__close grid h-8 w-8 place-items-center rounded-md text-[#657080] hover:bg-[#f3f5f7]"
|
|
type="button"
|
|
aria-label="닫기"
|
|
:disabled="loading"
|
|
@click="$emit('cancel')"
|
|
>
|
|
<svg class="h-4 w-4" viewBox="0 0 24 24" aria-hidden="true">
|
|
<path d="M12.707 12L23.854.854a.5.5 0 00-.707-.707L12 11.293.854.146a.5.5 0 00-.707.707L11.293 12 .146 23.146a.5.5 0 00.708.708L12 12.707l11.146 11.146a.5.5 0 10.708-.706L12.707 12z" fill="currentColor" />
|
|
</svg>
|
|
</button>
|
|
</header>
|
|
<div class="admin-confirm-modal__body grid gap-4 px-6 py-5 text-sm leading-6 text-[#657080]">
|
|
<slot />
|
|
</div>
|
|
<footer class="admin-confirm-modal__footer flex justify-end gap-2 border-t border-line px-6 py-4">
|
|
<button
|
|
class="admin-confirm-modal__cancel h-10 rounded-md border border-line bg-white px-4 text-sm font-semibold text-[#3f4650]"
|
|
type="button"
|
|
:disabled="loading"
|
|
@click="$emit('cancel')"
|
|
>
|
|
{{ cancelLabel }}
|
|
</button>
|
|
<button
|
|
class="admin-confirm-modal__confirm h-10 rounded-md px-4 text-sm font-semibold transition disabled:opacity-50"
|
|
:class="getConfirmButtonClass(confirmTone)"
|
|
type="button"
|
|
:disabled="loading"
|
|
@click="$emit('confirm')"
|
|
>
|
|
{{ loading && loadingLabel ? loadingLabel : confirmLabel }}
|
|
</button>
|
|
</footer>
|
|
</section>
|
|
</div>
|
|
</Teleport>
|
|
</template>
|