feat: 홈 일별 캘린더·시세 갱신·게시판 카테고리·약관동의·계좌 마스킹
- 홈: 6월 예산 아래 일별 수입/지출 캘린더(마우스오버/탭 시 내역 목록) - 투자: 시세 자동조회 버튼/진입 시 갱신, 보유종목 2줄 표기, 평가액 직접입력 - 게시판: 커뮤니티/짠테크 수다방/재테크 팁 분리, 사이드바 영역 구분선 - 회원가입: 이용약관·개인정보 수집 동의(필수 체크) - 보안: 계좌번호 화면 마스킹(끝 4자리+눈 토글) - 정기→고정지출, 내역/정기 라디오·sticky 저장, 태그 드래그 정렬 - fix: 모바일웹 새로고침 시 로그인 팝업(restore localStorage 우선) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -363,7 +363,7 @@ function todayStr() {
|
||||
function openCreate() {
|
||||
editId.value = null
|
||||
editingPending.value = false
|
||||
Object.assign(form, { entryDate: todayStr(), type: 'EXPENSE', category: '', amount: null, memo: '', walletKind: '', walletId: '', toWalletKind: '', toWalletId: '', principal: null, interest: null, installmentMonths: '' })
|
||||
Object.assign(form, { entryDate: todayStr(), type: 'EXPENSE', category: '', amount: null, memo: '', walletKind: 'BANK', walletId: '', toWalletKind: '', toWalletId: '', principal: null, interest: null, installmentMonths: '' })
|
||||
selectedTagIds.value = []
|
||||
cancelAddCategory()
|
||||
formError.value = null
|
||||
@@ -378,7 +378,7 @@ function openEdit(e) {
|
||||
category: e.category || '',
|
||||
amount: e.amount,
|
||||
memo: e.memo || '',
|
||||
walletKind: walletKindOf(e.walletId),
|
||||
walletKind: e.walletId ? walletKindOf(e.walletId) : (e.type === 'TRANSFER' ? '' : 'CASH'),
|
||||
walletId: e.walletId || '',
|
||||
toWalletKind: walletKindOf(e.toWalletId),
|
||||
toWalletId: e.toWalletId || '',
|
||||
@@ -653,21 +653,27 @@ onMounted(async () => {
|
||||
<option v-if="!editId" value="REPAYMENT">상환/납부</option>
|
||||
</select>
|
||||
</label>
|
||||
<!-- 계좌 종류 먼저 선택 → 해당 종류만 목록에 -->
|
||||
<label>계좌 종류
|
||||
<select v-model="form.walletKind" :disabled="submitting" @change="onWalletKindChange">
|
||||
<option value="">{{ form.type === 'INCOME' || form.type === 'EXPENSE' ? '(선택 안 함)' : '(선택)' }}</option>
|
||||
<option v-for="k in WALLET_KINDS" :key="k.value" :value="k.value">{{ k.label }}</option>
|
||||
</select>
|
||||
</label>
|
||||
<label v-if="form.walletKind">{{ form.type === 'INCOME' || form.type === 'EXPENSE' ? '계좌/카드' : '출금 계좌' }}
|
||||
<select v-model="form.walletId" :disabled="submitting">
|
||||
<option value="">(선택)</option>
|
||||
<!-- 계좌 종류 먼저 선택(라디오) → 해당 종류만 셀렉트에 -->
|
||||
<div class="field">
|
||||
<div class="field-row">
|
||||
<span class="field-label">계좌 종류</span>
|
||||
<div class="wallet-radios">
|
||||
<label v-for="k in WALLET_KINDS" :key="k.value" class="radio">
|
||||
<input type="radio" :value="k.value" v-model="form.walletKind" :disabled="submitting" @change="onWalletKindChange" />
|
||||
{{ k.label }}
|
||||
</label>
|
||||
<label v-if="form.type !== 'TRANSFER'" class="radio">
|
||||
<input type="radio" value="CASH" v-model="form.walletKind" :disabled="submitting" @change="onWalletKindChange" /> 현금
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<select v-if="form.walletKind && form.walletKind !== 'CASH'" v-model="form.walletId" :disabled="submitting">
|
||||
<option value="">{{ form.type === 'INCOME' || form.type === 'EXPENSE' ? '계좌/카드 선택' : '출금 계좌 선택' }}</option>
|
||||
<option v-for="w in walletsOfKind" :key="w.id" :value="w.id">
|
||||
{{ w.name }}{{ w.issuer ? ` (${w.issuer})` : '' }}
|
||||
</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<!-- 카드 지출: 할부 개월수 (일시불 또는 2~24개월) -->
|
||||
<label v-if="showInstallment">할부
|
||||
<select v-model="form.installmentMonths" :disabled="submitting">
|
||||
@@ -677,20 +683,23 @@ onMounted(async () => {
|
||||
<small v-if="installmentMonthly" class="install-hint">월 약 {{ won(installmentMonthly) }}원</small>
|
||||
</label>
|
||||
<template v-if="form.type === 'TRANSFER'">
|
||||
<label>입금 종류
|
||||
<select v-model="form.toWalletKind" :disabled="submitting" @change="onToWalletKindChange">
|
||||
<option value="">(선택)</option>
|
||||
<option v-for="k in WALLET_KINDS" :key="k.value" :value="k.value">{{ k.label }}</option>
|
||||
</select>
|
||||
</label>
|
||||
<label v-if="form.toWalletKind">입금 계좌
|
||||
<select v-model="form.toWalletId" :disabled="submitting">
|
||||
<option value="">(선택)</option>
|
||||
<div class="field">
|
||||
<div class="field-row">
|
||||
<span class="field-label">입금 종류</span>
|
||||
<div class="wallet-radios">
|
||||
<label v-for="k in WALLET_KINDS" :key="k.value" class="radio">
|
||||
<input type="radio" :value="k.value" v-model="form.toWalletKind" :disabled="submitting" @change="onToWalletKindChange" />
|
||||
{{ k.label }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<select v-if="form.toWalletKind" v-model="form.toWalletId" :disabled="submitting">
|
||||
<option value="">입금 계좌 선택</option>
|
||||
<option v-for="w in toWalletsOfKind" :key="w.id" :value="w.id">
|
||||
{{ w.name }}{{ w.issuer ? ` (${w.issuer})` : '' }}
|
||||
</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 상환/납부: 대상(대출/카드) + 원금 + 이자 -->
|
||||
@@ -1071,7 +1080,10 @@ button.primary {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: 360px;
|
||||
padding: 1.75rem 1.5rem 1.5rem;
|
||||
/* 폼이 길어도 모달 안에서 스크롤되도록 + 하단 소프트키/제스처바 안전영역 확보 */
|
||||
max-height: calc(100vh - 2rem);
|
||||
overflow-y: auto;
|
||||
padding: 1.75rem 1.5rem calc(1.5rem + env(safe-area-inset-bottom));
|
||||
background: var(--color-background);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 8px;
|
||||
@@ -1207,6 +1219,41 @@ button.primary {
|
||||
background: var(--color-background-soft);
|
||||
color: var(--color-text);
|
||||
}
|
||||
/* 계좌 종류 라디오 (라벨+라디오 한 줄, 선택 종류는 셀렉트로 아래) */
|
||||
.field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.3rem;
|
||||
}
|
||||
.field-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
.field-label {
|
||||
font-size: 0.82rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.wallet-radios {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.3rem 0.5rem;
|
||||
}
|
||||
.wallet-radios .radio {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 0.15rem;
|
||||
font-size: 0.82rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
.wallet-radios .radio input {
|
||||
padding: 0;
|
||||
width: auto;
|
||||
margin: 0;
|
||||
}
|
||||
.cat-input {
|
||||
display: flex;
|
||||
gap: 0.4rem;
|
||||
@@ -1287,6 +1334,11 @@ button.primary {
|
||||
justify-content: flex-end;
|
||||
gap: 0.5rem;
|
||||
margin-top: 0.5rem;
|
||||
/* 폼이 길 때도 저장/취소 버튼이 항상 보이도록 하단 고정 */
|
||||
position: sticky;
|
||||
bottom: calc(-1.5rem - env(safe-area-inset-bottom));
|
||||
padding: 0.6rem 0 0.2rem;
|
||||
background: var(--color-background);
|
||||
}
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
|
||||
Reference in New Issue
Block a user