feat: 강아지 관리 화면 (프로필 CRUD + 댕비티아이 편집)

- dogs 스토어: 내 강아지 로드/등록/수정/삭제, 대표견(currentDog)
- ProfilePage: 강아지 등록/선택/삭제, 성향 태그 편집·저장, 회원 티어 표시
- HomePage 체크인/매칭 주체를 대표견으로 전환(미등록 시 안내)
- http 클라이언트 put/del 추가, 임시 session 스토어 제거
- 로그아웃 시 강아지 상태 리셋, Dialog 플러그인 등록

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
sb
2026-07-11 09:00:19 +09:00
parent 85c925008a
commit d2e5495619
6 changed files with 357 additions and 77 deletions
+64
View File
@@ -0,0 +1,64 @@
import { defineStore } from 'pinia'
import { computed, ref } from 'vue'
import { dogsApi, traitTagsApi, type Dog, type DogSaveRequest, type TraitTag } from '@/api/dogs'
/**
* 내 강아지 상태. 로그인 후 loadMyDogs 로 채운다.
* currentDogId 는 체크인/매칭의 주체(대표 강아지).
*/
export const useDogsStore = defineStore('dogs', () => {
const myDogs = ref<Dog[]>([])
const traitTags = ref<TraitTag[]>([])
const currentDogId = ref<number | null>(null)
const currentDog = computed(() => myDogs.value.find((d) => d.id === currentDogId.value) ?? null)
async function loadMyDogs(): Promise<void> {
myDogs.value = await dogsApi.list()
if (currentDogId.value == null || !myDogs.value.some((d) => d.id === currentDogId.value)) {
currentDogId.value = myDogs.value[0]?.id ?? null
}
}
async function loadTraitTags(): Promise<void> {
if (traitTags.value.length === 0) {
traitTags.value = await traitTagsApi.list()
}
}
async function createDog(body: DogSaveRequest): Promise<Dog> {
const dog = await dogsApi.create(body)
await loadMyDogs()
currentDogId.value = dog.id
return dog
}
async function updateDog(id: number, body: DogSaveRequest): Promise<Dog> {
const dog = await dogsApi.update(id, body)
await loadMyDogs()
return dog
}
async function removeDog(id: number): Promise<void> {
await dogsApi.remove(id)
await loadMyDogs()
}
function reset(): void {
myDogs.value = []
currentDogId.value = null
}
return {
myDogs,
traitTags,
currentDogId,
currentDog,
loadMyDogs,
loadTraitTags,
createDog,
updateDog,
removeDog,
reset,
}
})
-13
View File
@@ -1,13 +0,0 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
/**
* 임시 세션 스토어 (인증 도입 전까지 사용).
* local 시드 데이터 기준: 내 유저=1, 내 강아지(몽이)=1.
* 인증(4번) 도입 시 로그인 응답으로 대체.
*/
export const useSessionStore = defineStore('session', () => {
const userId = ref<number>(1)
const dogId = ref<number>(1)
return { userId, dogId }
})