Compare commits
2 Commits
46a8cb5515
...
8d659ea956
| Author | SHA1 | Date | |
|---|---|---|---|
| 8d659ea956 | |||
| 970e9e14ad |
@@ -1012,8 +1012,8 @@ onMounted(async () => {
|
|||||||
<!-- 추가/수정 모달 -->
|
<!-- 추가/수정 모달 -->
|
||||||
<Teleport to="body">
|
<Teleport to="body">
|
||||||
<Transition name="fade">
|
<Transition name="fade">
|
||||||
<div v-if="formOpen" class="modal-backdrop" @click.self="formOpen = false">
|
<div v-if="formOpen" class="modal-backdrop entry-backdrop">
|
||||||
<div class="modal" role="dialog" aria-modal="true">
|
<div class="modal entry-modal" role="dialog" aria-modal="true">
|
||||||
<button class="close" type="button" @click="formOpen = false">×</button>
|
<button class="close" type="button" @click="formOpen = false">×</button>
|
||||||
<h2>{{ editId ? '내역 수정' : '내역 추가' }}</h2>
|
<h2>{{ editId ? '내역 수정' : '내역 추가' }}</h2>
|
||||||
|
|
||||||
@@ -1661,6 +1661,27 @@ button.primary {
|
|||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
|
/* 내역 추가/수정: 전체화면 모달 — 바깥 영역이 없어 실수로 닫히지 않음(× 로만 닫힘) */
|
||||||
|
.entry-backdrop {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.modal.entry-modal {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
max-width: none;
|
||||||
|
max-height: 100%;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
padding-top: calc(1.5rem + env(safe-area-inset-top));
|
||||||
|
}
|
||||||
|
/* 넓은 화면(PC)에서도 입력 내용은 읽기 좋은 폭으로 가운데 정렬 */
|
||||||
|
.modal.entry-modal > h2,
|
||||||
|
.modal.entry-modal .entry-form {
|
||||||
|
max-width: 460px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
.modal {
|
.modal {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@@ -65,6 +65,18 @@ async function reload() {
|
|||||||
// 스크롤하다 실수로 순서가 바뀌는 것 방지: 기본은 드래그 비활성, '순서변경' 버튼으로 켠다.
|
// 스크롤하다 실수로 순서가 바뀌는 것 방지: 기본은 드래그 비활성, '순서변경' 버튼으로 켠다.
|
||||||
const majorListEl = ref(null)
|
const majorListEl = ref(null)
|
||||||
const reorderMode = ref(false)
|
const reorderMode = ref(false)
|
||||||
|
|
||||||
|
// ===== 대분류 펼침(아코디언) — 삼각형 누르면 소분류 표시 =====
|
||||||
|
const expanded = ref(new Set())
|
||||||
|
function toggleExpand(id) {
|
||||||
|
const s = new Set(expanded.value)
|
||||||
|
if (s.has(id)) s.delete(id)
|
||||||
|
else s.add(id)
|
||||||
|
expanded.value = s
|
||||||
|
}
|
||||||
|
function isExpanded(id) {
|
||||||
|
return expanded.value.has(id)
|
||||||
|
}
|
||||||
let sortables = []
|
let sortables = []
|
||||||
function destroySortables() {
|
function destroySortables() {
|
||||||
sortables.forEach((s) => s.destroy())
|
sortables.forEach((s) => s.destroy())
|
||||||
@@ -128,9 +140,16 @@ async function addCategory() {
|
|||||||
if (!name) return
|
if (!name) return
|
||||||
error.value = null
|
error.value = null
|
||||||
try {
|
try {
|
||||||
await accountApi.createCategory({ type: activeType.value, name, parentId: newParent.value || null })
|
const parentId = newParent.value || null
|
||||||
|
await accountApi.createCategory({ type: activeType.value, name, parentId })
|
||||||
newName.value = ''
|
newName.value = ''
|
||||||
await reload()
|
await reload()
|
||||||
|
// 소분류를 추가했으면 그 대분류를 펼쳐 바로 보이게
|
||||||
|
if (parentId) {
|
||||||
|
const s = new Set(expanded.value)
|
||||||
|
s.add(Number(parentId))
|
||||||
|
expanded.value = s
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
showError(e, '추가에 실패했습니다.')
|
showError(e, '추가에 실패했습니다.')
|
||||||
}
|
}
|
||||||
@@ -226,12 +245,18 @@ onBeforeUnmount(destroySortables)
|
|||||||
<div class="cat-row major-row">
|
<div class="cat-row major-row">
|
||||||
<div class="cat-main">
|
<div class="cat-main">
|
||||||
<span v-show="reorderMode" class="drag-handle major-handle" title="대분류 순서 변경(소분류 함께 이동)">≡</span>
|
<span v-show="reorderMode" class="drag-handle major-handle" title="대분류 순서 변경(소분류 함께 이동)">≡</span>
|
||||||
|
<button
|
||||||
|
type="button" class="expand-btn" :class="{ open: isExpanded(g.major.id), empty: !g.children.length }"
|
||||||
|
:title="g.children.length ? (isExpanded(g.major.id) ? '소분류 접기' : '소분류 펼치기') : '소분류 없음'"
|
||||||
|
:disabled="!g.children.length" @click="toggleExpand(g.major.id)"
|
||||||
|
>▶</button>
|
||||||
<input v-model="g.major.name" class="cat-name" @keyup.enter="saveCategory(g.major)" />
|
<input v-model="g.major.name" class="cat-name" @keyup.enter="saveCategory(g.major)" />
|
||||||
|
<span v-if="g.children.length && !isExpanded(g.major.id)" class="sub-count">{{ g.children.length }}</span>
|
||||||
<IconBtn icon="check" title="저장" size="sm" @click="saveCategory(g.major)" />
|
<IconBtn icon="check" title="저장" size="sm" @click="saveCategory(g.major)" />
|
||||||
<IconBtn icon="trash" title="삭제" variant="danger" size="sm" @click="removeCategory(g.major)" />
|
<IconBtn icon="trash" title="삭제" variant="danger" size="sm" @click="removeCategory(g.major)" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ul class="sub-list" :data-parent="g.major.id">
|
<ul v-show="isExpanded(g.major.id) || reorderMode" class="sub-list" :data-parent="g.major.id">
|
||||||
<li v-for="s in g.children" :key="s.id" :data-id="s.id" class="sub-item cat-row child">
|
<li v-for="s in g.children" :key="s.id" :data-id="s.id" class="sub-item cat-row child">
|
||||||
<div class="cat-main">
|
<div class="cat-main">
|
||||||
<span v-show="reorderMode" class="drag-handle sub-handle" title="소분류 순서 변경">≡</span>
|
<span v-show="reorderMode" class="drag-handle sub-handle" title="소분류 순서 변경">≡</span>
|
||||||
@@ -440,6 +465,37 @@ button.danger {
|
|||||||
.sub-mark {
|
.sub-mark {
|
||||||
opacity: 0.45;
|
opacity: 0.45;
|
||||||
}
|
}
|
||||||
|
/* 대분류 펼침 삼각형 */
|
||||||
|
.expand-btn {
|
||||||
|
flex: none;
|
||||||
|
width: 1.4rem;
|
||||||
|
height: 1.4rem;
|
||||||
|
border: 0;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--color-text);
|
||||||
|
font-size: 0.7rem;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 0.15s ease;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
.expand-btn.open {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
.expand-btn.empty {
|
||||||
|
opacity: 0.15;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
.sub-count {
|
||||||
|
flex: none;
|
||||||
|
min-width: 1.2rem;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 0.72rem;
|
||||||
|
padding: 0.05rem 0.3rem;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: var(--color-border);
|
||||||
|
color: var(--color-text);
|
||||||
|
opacity: 0.75;
|
||||||
|
}
|
||||||
.hint.sm {
|
.hint.sm {
|
||||||
font-size: 0.78rem;
|
font-size: 0.78rem;
|
||||||
margin: 0 0 0.75rem;
|
margin: 0 0 0.75rem;
|
||||||
|
|||||||
Reference in New Issue
Block a user