diff --git a/components/admin/AdminMemberForm.vue b/components/admin/AdminMemberForm.vue index 1f191cf..bd5889e 100644 --- a/components/admin/AdminMemberForm.vue +++ b/components/admin/AdminMemberForm.vue @@ -17,6 +17,8 @@ const saveMessage = ref('') const saveError = ref('') const isSaving = ref(false) const savedMemberSnapshot = ref('') +const avatarInputRef = ref(null) +const isUploadingAvatar = ref(false) const form = reactive({ username: '', @@ -146,6 +148,57 @@ const { leaveUnsavedPage } = useAdminUnsavedChangesGuard(hasUnsavedMemberChanges) +/** + * 썸네일 파일 선택창을 연다. + * @returns {void} + */ +const openAvatarFilePicker = () => { + avatarInputRef.value?.click() +} + +/** + * 회원 썸네일 파일을 업로드하고 폼에 반영한다. + * @param {Event} event - 파일 선택 이벤트 + * @returns {Promise} + */ +const uploadAvatar = async (event) => { + const target = event.target instanceof HTMLInputElement ? event.target : null + const file = target?.files?.[0] + + if (!file || isUploadingAvatar.value) { + return + } + + isUploadingAvatar.value = true + saveError.value = '' + saveMessage.value = '' + + try { + const formData = new FormData() + formData.append('files', file) + const result = await $fetch('/admin/api/uploads', { + method: 'POST', + body: formData + }) + form.avatarUrl = result.files?.[0]?.url || '' + } catch (error) { + saveError.value = error?.data?.message || '썸네일 업로드에 실패했습니다.' + } finally { + isUploadingAvatar.value = false + if (target) { + target.value = '' + } + } +} + +/** + * 회원 썸네일 연결을 제거한다. + * @returns {void} + */ +const removeAvatar = () => { + form.avatarUrl = '' +} + /** * 회원 기본 정보를 저장한다. * @returns {Promise} @@ -221,15 +274,39 @@ watch(() => props.member, () => {