feat(settings): 회원 썸네일을 미리보기 중심 UI로 개편
설정 화면에서 썸네일 URL 텍스트 노출을 제거하고 아바타 미리보기와 이미지 변경/제거 액션을 중심으로 재구성해 계정 정보 확인 흐름을 직관적으로 맞춘다. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -15,6 +15,8 @@ const profileForm = reactive({
|
||||
avatarUrl: ''
|
||||
})
|
||||
|
||||
const avatarInputRef = ref(null)
|
||||
|
||||
const passwordForm = reactive({
|
||||
currentPassword: '',
|
||||
nextPassword: '',
|
||||
@@ -149,7 +151,7 @@ const uploadAvatar = async (event) => {
|
||||
body: formData
|
||||
})
|
||||
profileForm.avatarUrl = result.avatarUrl || ''
|
||||
profileMessage.value = '썸네일이 업로드되었습니다. 프로필 저장을 눌러 반영하세요.'
|
||||
profileMessage.value = '썸네일이 업로드되었습니다.'
|
||||
} catch (error) {
|
||||
profileMessage.value = error?.data?.message || '썸네일 업로드에 실패했습니다.'
|
||||
} finally {
|
||||
@@ -160,6 +162,14 @@ const uploadAvatar = async (event) => {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 썸네일 파일 선택창을 연다.
|
||||
* @returns {void}
|
||||
*/
|
||||
const openAvatarFilePicker = () => {
|
||||
avatarInputRef.value?.click()
|
||||
}
|
||||
|
||||
/**
|
||||
* 비밀번호를 변경한다.
|
||||
* @returns {Promise<void>}
|
||||
@@ -236,7 +246,54 @@ onMounted(loadProfile)
|
||||
<div v-else class="mt-5 flex flex-col gap-5">
|
||||
<section class="rounded-[10px] border border-[var(--site-line)] bg-[var(--site-bg)] p-4">
|
||||
<h2 class="text-sm font-semibold">프로필</h2>
|
||||
<div class="mt-3 flex flex-col gap-3">
|
||||
<div class="mt-3 flex flex-col gap-4">
|
||||
<div class="settings-profile-avatar-card flex items-center gap-4 rounded-[12px] border border-[var(--site-line)] bg-[var(--site-panel)] p-3">
|
||||
<div class="settings-profile-avatar-frame relative h-20 w-20 shrink-0 overflow-hidden rounded-full border border-[var(--site-line)] bg-[var(--site-bg)]">
|
||||
<img
|
||||
v-if="profileForm.avatarUrl"
|
||||
:src="profileForm.avatarUrl"
|
||||
alt="프로필 썸네일"
|
||||
class="h-full w-full object-cover"
|
||||
>
|
||||
<span
|
||||
v-else
|
||||
class="grid h-full w-full place-items-center text-sm font-semibold site-muted"
|
||||
>
|
||||
{{ (profileForm.username || profileForm.email || '@').slice(0, 1).toUpperCase() }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<p class="text-xs site-muted">
|
||||
프로필 이미지
|
||||
</p>
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<button
|
||||
type="button"
|
||||
class="rounded-[10px] border border-[var(--site-line)] px-3 py-1.5 text-xs transition-opacity hover:opacity-80 disabled:opacity-60"
|
||||
:disabled="uploadingAvatar"
|
||||
@click="openAvatarFilePicker"
|
||||
>
|
||||
{{ uploadingAvatar ? '업로드 중...' : '이미지 변경' }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="rounded-[10px] border border-[var(--site-line)] px-3 py-1.5 text-xs site-muted transition-opacity hover:opacity-80 disabled:opacity-60"
|
||||
:disabled="removingAvatar || !profileForm.avatarUrl"
|
||||
@click="removeAvatar"
|
||||
>
|
||||
{{ removingAvatar ? '제거 중...' : '이미지 제거' }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<input
|
||||
ref="avatarInputRef"
|
||||
type="file"
|
||||
accept="image/jpeg,image/png,image/webp,image/gif"
|
||||
class="hidden"
|
||||
:disabled="uploadingAvatar"
|
||||
@change="uploadAvatar"
|
||||
>
|
||||
<label class="text-xs site-muted">이메일</label>
|
||||
<input
|
||||
v-model="profileForm.email"
|
||||
@@ -250,29 +307,6 @@ onMounted(loadProfile)
|
||||
type="text"
|
||||
class="h-10 rounded-[8px] border border-[var(--site-line)] bg-transparent px-3 text-sm outline-none focus-visible:border-[var(--site-accent)]"
|
||||
>
|
||||
<label class="text-xs site-muted">썸네일 URL</label>
|
||||
<input
|
||||
v-model="profileForm.avatarUrl"
|
||||
type="text"
|
||||
class="h-10 rounded-[8px] border border-[var(--site-line)] bg-transparent px-3 text-sm outline-none focus-visible:border-[var(--site-accent)]"
|
||||
placeholder="https://..."
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="w-fit rounded-[10px] border border-[var(--site-line)] px-3 py-1.5 text-xs site-muted transition-opacity hover:opacity-80 disabled:opacity-60"
|
||||
:disabled="removingAvatar"
|
||||
@click="removeAvatar"
|
||||
>
|
||||
{{ removingAvatar ? '제거 중...' : '썸네일 제거' }}
|
||||
</button>
|
||||
<label class="text-xs site-muted">썸네일 업로드</label>
|
||||
<input
|
||||
type="file"
|
||||
accept="image/jpeg,image/png,image/webp,image/gif"
|
||||
class="block w-full text-xs site-muted file:mr-3 file:cursor-pointer file:rounded-[8px] file:border file:border-[var(--site-line)] file:bg-[var(--site-panel)] file:px-3 file:py-1.5"
|
||||
:disabled="uploadingAvatar"
|
||||
@change="uploadAvatar"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="site-accent-button mt-1 w-fit rounded-[10px] px-3 py-1.5 text-xs font-semibold disabled:opacity-60"
|
||||
|
||||
Reference in New Issue
Block a user