Files
planner.sori.studio/src/components/SettingsDashboard.vue

225 lines
8.5 KiB
Vue

<script setup>
import { computed } from 'vue'
const props = defineProps({
user: {
type: Object,
required: true,
},
profileForm: {
type: Object,
required: true,
},
passwordForm: {
type: Object,
required: true,
},
profileBusy: {
type: Boolean,
default: false,
},
passwordBusy: {
type: Boolean,
default: false,
},
profileMessage: {
type: String,
default: '',
},
passwordMessage: {
type: String,
default: '',
},
guideTooltipResetMessage: {
type: String,
default: '',
},
carryoverCheckPolicy: {
type: String,
default: 'ask',
},
})
const emit = defineEmits([
'update:profile-field',
'update:password-field',
'submit:profile',
'submit:password',
'reset-guide-tooltips',
'update:carryover-check-policy',
])
const initials = computed(() =>
`${props.user.nickname?.slice(0, 1) ?? ''}${props.user.email?.slice(0, 1) ?? ''}`.toUpperCase(),
)
function updateProfileField(field, event) {
emit('update:profile-field', {
field,
value: event.target.value,
})
}
function updatePasswordField(field, event) {
emit('update:password-field', {
field,
value: event.target.value,
})
}
</script>
<template>
<section class="grid gap-6 xl:grid-cols-[360px_minmax(0,1fr)]">
<aside class="rounded-[28px] border border-white/60 bg-white/70 p-6">
<p class="text-[11px] font-bold uppercase tracking-[0.28em] text-stone-500">Settings</p>
<div class="mt-6 flex items-center gap-4">
<div class="flex h-20 w-20 items-center justify-center rounded-full bg-stone-900 text-2xl font-bold tracking-[0.04em] text-white">
{{ initials || 'U' }}
</div>
<div>
<p class="text-xl font-semibold tracking-[-0.04em] text-stone-900">{{ user.nickname }}</p>
<p class="mt-1 text-sm font-semibold text-stone-500">{{ user.email }}</p>
</div>
</div>
<!-- <div class="mt-6 space-y-3 rounded-[24px] border border-stone-200 bg-[#fbf7f0] p-4">
<p class="text-[10px] font-bold tracking-[0.18em] text-stone-500">PROFILE NOTE</p>
<p class="text-sm font-semibold leading-6 text-stone-700">
...
</p>
</div> -->
<div class="mt-6 rounded-[24px] border border-stone-200 bg-white/80 p-4">
<p class="text-[10px] font-bold tracking-[0.18em] text-stone-500">GUIDE TOOLTIPS</p>
<p class="mt-3 text-sm font-semibold leading-6 text-stone-700">
숨긴 가이드 툴팁을 다시 표시합니다.
</p>
<button
type="button"
class="mt-4 rounded-full border border-stone-900 px-4 py-3 text-xs font-bold tracking-[0.14em] text-stone-900 transition hover:bg-stone-900 hover:text-white"
@click="emit('reset-guide-tooltips')"
>
가이드 다시 보기
</button>
<p
v-if="guideTooltipResetMessage"
class="mt-3 rounded-2xl border border-stone-200 bg-[#fbf7f0] px-4 py-3 text-xs font-semibold leading-5 text-stone-600"
>
{{ guideTooltipResetMessage }}
</p>
</div>
<div class="mt-4 rounded-[24px] border border-stone-200 bg-white/80 p-4">
<p class="text-[10px] font-bold tracking-[0.18em] text-stone-500">CARRYOVER CHECK</p>
<p class="mt-3 text-sm font-semibold leading-6 text-stone-700">
이월된 일을 완료할 이전 날짜 항목까지 함께 체크할지 정합니다.
</p>
<div class="mt-4 grid gap-2">
<button
v-for="option in [
{ value: 'ask', label: '항상 물어보기' },
{ value: 'all', label: '항상 이전까지 체크' },
{ value: 'current', label: '항상 오늘만 체크' },
]"
:key="option.value"
type="button"
class="rounded-2xl border px-4 py-3 text-left text-xs font-bold tracking-[0.12em] transition"
:class="carryoverCheckPolicy === option.value ? 'border-stone-900 bg-stone-900 text-white' : 'border-stone-200 bg-white text-stone-600 hover:border-stone-400 hover:text-stone-900'"
@click="emit('update:carryover-check-policy', option.value)"
>
{{ option.label }}
</button>
</div>
</div>
</aside>
<div class="grid gap-6">
<form class="rounded-[28px] border border-white/60 bg-white/75 p-6" @submit.prevent="emit('submit:profile')">
<p class="text-[11px] font-bold uppercase tracking-[0.24em] text-stone-500">Account Profile</p>
<div class="mt-5 grid gap-4 md:grid-cols-2">
<div class="space-y-2">
<label class="text-[11px] font-bold tracking-[0.16em] text-stone-600">닉네임</label>
<input
:value="profileForm.nickname"
type="text"
class="w-full rounded-2xl border border-stone-300 bg-white px-4 py-3 text-sm font-semibold text-stone-800 outline-none transition focus:border-stone-500"
@input="updateProfileField('nickname', $event)"
/>
</div>
<div class="space-y-2">
<label class="text-[11px] font-bold tracking-[0.16em] text-stone-600">이메일</label>
<input
:value="profileForm.email"
type="email"
class="w-full rounded-2xl border border-stone-300 bg-white px-4 py-3 text-sm font-semibold text-stone-800 outline-none transition focus:border-stone-500"
@input="updateProfileField('email', $event)"
/>
</div>
</div>
<p
v-if="profileMessage"
class="mt-4 rounded-2xl border border-stone-300 bg-white/80 px-4 py-3 text-sm font-semibold leading-6 text-stone-700"
>
{{ profileMessage }}
</p>
<button
type="submit"
class="mt-5 rounded-full bg-stone-900 px-5 py-3 text-xs font-bold tracking-[0.18em] text-white transition hover:bg-stone-700 disabled:cursor-not-allowed disabled:bg-stone-400"
:disabled="profileBusy"
>
{{ profileBusy ? '저장 중...' : '프로필 저장' }}
</button>
</form>
<form class="rounded-[28px] border border-white/60 bg-white/75 p-6" @submit.prevent="emit('submit:password')">
<p class="text-[11px] font-bold uppercase tracking-[0.24em] text-stone-500">Password</p>
<div class="mt-5 grid gap-4 md:grid-cols-2">
<div class="space-y-2 md:col-span-2">
<label class="text-[11px] font-bold tracking-[0.16em] text-stone-600">현재 비밀번호</label>
<input
:value="passwordForm.currentPassword"
type="password"
class="w-full rounded-2xl border border-stone-300 bg-white px-4 py-3 text-sm font-semibold text-stone-800 outline-none transition focus:border-stone-500"
@input="updatePasswordField('currentPassword', $event)"
/>
</div>
<div class="space-y-2">
<label class="text-[11px] font-bold tracking-[0.16em] text-stone-600">새 비밀번호</label>
<input
:value="passwordForm.newPassword"
type="password"
class="w-full rounded-2xl border border-stone-300 bg-white px-4 py-3 text-sm font-semibold text-stone-800 outline-none transition focus:border-stone-500"
@input="updatePasswordField('newPassword', $event)"
/>
</div>
<div class="space-y-2">
<label class="text-[11px] font-bold tracking-[0.16em] text-stone-600">새 비밀번호 확인</label>
<input
:value="passwordForm.confirmPassword"
type="password"
class="w-full rounded-2xl border border-stone-300 bg-white px-4 py-3 text-sm font-semibold text-stone-800 outline-none transition focus:border-stone-500"
@input="updatePasswordField('confirmPassword', $event)"
/>
</div>
</div>
<p
v-if="passwordMessage"
class="mt-4 rounded-2xl border border-stone-300 bg-white/80 px-4 py-3 text-sm font-semibold leading-6 text-stone-700"
>
{{ passwordMessage }}
</p>
<button
type="submit"
class="mt-5 rounded-full border border-stone-900 px-5 py-3 text-xs font-bold tracking-[0.18em] text-stone-900 transition hover:bg-stone-900 hover:text-white disabled:cursor-not-allowed disabled:border-stone-300 disabled:text-stone-400"
:disabled="passwordBusy"
>
{{ passwordBusy ? '변경 중...' : '비밀번호 변경' }}
</button>
</form>
</div>
</section>
</template>