파일
wbx-spring/wtm-frontend-vue/src/modules/auth/views/ChangePasswordView.vue
accura0117 cda5f9591e feat: React 18 프론트엔드 추가 및 프로젝트 구조 정리
- wtm-frontend → wtm-frontend-vue 이름 변경
- wtm-frontend-react 추가 (React 18 + PrimeReact + Zustand)
  - 동일한 모듈 구조 및 API 연동 (Vue 버전과 기능 동일)
  - Vue:5173 / React:5174 포트 분리
- 개발자 가이드에 React 프론트엔드 안내 추가
- .gitignore: Claude/OMC, 문서 생성 스크립트, package-lock 제외
- 불필요 파일 git 추적 제거 (.omc, generate_*.py, regenerate_*.py)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 20:50:23 +09:00

134 줄
3.5 KiB
Vue

<script setup lang="ts">
import { ref } from 'vue';
import { useRouter } from 'vue-router';
import Password from 'primevue/password';
import Button from 'primevue/button';
import Card from 'primevue/card';
import Message from 'primevue/message';
import { authApi } from '../auth.service';
const router = useRouter();
const currentPassword = ref('');
const newPassword = ref('');
const confirmPassword = ref('');
const error = ref('');
const success = ref('');
const loading = ref(false);
async function onSubmit() {
error.value = '';
success.value = '';
if (newPassword.value !== confirmPassword.value) {
error.value = '새 비밀번호가 일치하지 않습니다.';
return;
}
if (newPassword.value.length < 8) {
error.value = '비밀번호는 최소 8자 이상이어야 합니다.';
return;
}
loading.value = true;
try {
await authApi.changePassword({
currentPassword: currentPassword.value,
newPassword: newPassword.value,
});
success.value = '비밀번호가 변경되었습니다.';
currentPassword.value = '';
newPassword.value = '';
confirmPassword.value = '';
setTimeout(() => router.push('/dashboard'), 1500);
} catch (e: any) {
error.value = e?.response?.data?.detail ?? '비밀번호 변경에 실패했습니다.';
} finally {
loading.value = false;
}
}
</script>
<template>
<div class="change-password-page">
<Card class="change-password-page__card">
<template #title>비밀번호 변경</template>
<template #content>
<Message v-if="error" severity="error" :closable="false" style="width: 100%; margin-bottom: 1rem;">
{{ error }}
</Message>
<Message v-if="success" severity="success" :closable="false" style="width: 100%; margin-bottom: 1rem;">
{{ success }}
</Message>
<form class="change-password-page__form" @submit.prevent="onSubmit">
<div class="form-field">
<label class="form-field__label">현재 비밀번호</label>
<Password
v-model="currentPassword"
placeholder="현재 비밀번호 입력"
:feedback="false"
toggleMask
fluid
:inputStyle="{ width: '100%' }"
/>
</div>
<div class="form-field">
<label class="form-field__label"> 비밀번호</label>
<Password
v-model="newPassword"
placeholder="새 비밀번호 입력"
toggleMask
fluid
:inputStyle="{ width: '100%' }"
/>
</div>
<div class="form-field">
<label class="form-field__label"> 비밀번호 확인</label>
<Password
v-model="confirmPassword"
placeholder="새 비밀번호 다시 입력"
:feedback="false"
toggleMask
fluid
:inputStyle="{ width: '100%' }"
/>
</div>
<Button
type="submit"
label="비밀번호 변경"
icon="pi pi-check"
:loading="loading"
fluid
style="margin-top: 0.5rem;"
/>
</form>
</template>
</Card>
</div>
</template>
<style lang="scss" scoped>
.change-password-page {
display: flex;
align-items: center;
justify-content: center;
min-height: 80vh;
padding: 1rem;
&__card {
width: 100%;
max-width: 480px;
}
&__form {
display: flex;
flex-direction: column;
gap: 1rem;
}
}
</style>