- usePurchases: user_id 필터링으로 타 사용자 데이터 접근 차단 - usePurchases: bulkCreatePurchases() 일괄 저장 메서드 추가 - PurchaseModal: submit 시 중복 닫힘 방지 (부모에서 제어) - purchases/index: 엑셀 업로드 버튼 및 모달 연동 - purchases/index: 중고 판매 등록(태그 아이콘) 버튼 및 모달 연동 - purchases/index: 판매 상태 뱃지를 장비명 옆에 표시 - PurchaseExcelUpload: xlsx 파일 파싱 후 일괄 저장 컴포넌트 추가 - SellFromPurchaseModal: 구매 장비에서 중고 판매 등록 모달 추가 - xlsx 패키지 추가
105 lines
3.3 KiB
Vue
105 lines
3.3 KiB
Vue
<script setup lang="ts">
|
|
import { z } from 'zod'
|
|
import type { FormSubmitEvent } from '@nuxt/ui'
|
|
import { PLATFORM_OPTIONS } from '~/types/used-sale'
|
|
import type { SalePlatform } from '~/types/used-sale'
|
|
import type { Purchase } from '~/types/purchase'
|
|
|
|
const props = defineProps<{
|
|
open: boolean
|
|
purchase: Purchase | null
|
|
}>()
|
|
|
|
const emit = defineEmits<{
|
|
'update:open': [value: boolean]
|
|
done: []
|
|
}>()
|
|
|
|
const { createSale, loading, error: saleError } = useUsedSales()
|
|
|
|
const schema = z.object({
|
|
item_name: z.string().min(1, '장비명을 입력하세요'),
|
|
sale_price: z.number().min(0, '희망가격을 입력하세요'),
|
|
platform: z.string().min(1, '판매 플랫폼을 선택하세요')
|
|
})
|
|
|
|
type Schema = z.output<typeof schema>
|
|
|
|
const state = reactive({
|
|
item_name: '',
|
|
sale_price: 0,
|
|
platform: undefined as SalePlatform | undefined
|
|
})
|
|
|
|
// 선택된 구매 장비로 폼 초기화
|
|
watch(() => props.purchase, (p) => {
|
|
if (p) {
|
|
state.item_name = p.name
|
|
state.sale_price = p.price
|
|
state.platform = undefined
|
|
}
|
|
}, { immediate: true })
|
|
|
|
async function onSubmit(event: FormSubmitEvent<Schema>) {
|
|
if (!props.purchase) return
|
|
await createSale({
|
|
item_name: event.data.item_name,
|
|
sale_price: event.data.sale_price,
|
|
platform: event.data.platform as SalePlatform,
|
|
status: 'listing',
|
|
listed_at: new Date().toISOString().split('T')[0] ?? '',
|
|
purchase_id: props.purchase.id
|
|
})
|
|
if (!saleError.value) {
|
|
emit('update:open', false)
|
|
emit('done')
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<UModal
|
|
:open="props.open"
|
|
title="중고 판매 등록"
|
|
@update:open="emit('update:open', $event)"
|
|
>
|
|
<template #body>
|
|
<div v-if="purchase" class="space-y-4">
|
|
<!-- 연결된 구매 장비 안내 -->
|
|
<div class="flex items-center gap-2 p-3 bg-gray-50 dark:bg-gray-800 rounded-lg text-sm text-gray-600 dark:text-gray-400">
|
|
<UIcon name="i-lucide-link" class="shrink-0 text-primary-500" />
|
|
<span>구매 장비 <strong class="text-gray-900 dark:text-white">{{ purchase.name }}</strong> 와 연결됩니다</span>
|
|
</div>
|
|
|
|
<UAlert v-if="saleError" color="error" :description="saleError" />
|
|
|
|
<UForm :schema="schema" :state="state" class="space-y-4" @submit="onSubmit">
|
|
<UFormField label="장비명" name="item_name" required>
|
|
<UInput v-model="state.item_name" class="w-full" />
|
|
</UFormField>
|
|
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<UFormField label="희망가격 (원)" name="sale_price" required>
|
|
<UInput v-model.number="state.sale_price" type="number" min="0" class="w-full" />
|
|
</UFormField>
|
|
|
|
<UFormField label="판매 플랫폼" name="platform" required>
|
|
<USelect v-model="state.platform" :items="PLATFORM_OPTIONS" placeholder="선택..." class="w-full" />
|
|
</UFormField>
|
|
</div>
|
|
|
|
<div class="flex justify-end gap-3 pt-2">
|
|
<UButton label="취소" color="neutral" variant="ghost" @click="emit('update:open', false)" />
|
|
<UButton
|
|
type="submit"
|
|
label="중고 등록"
|
|
icon="i-lucide-tag"
|
|
:loading="loading"
|
|
/>
|
|
</div>
|
|
</UForm>
|
|
</div>
|
|
</template>
|
|
</UModal>
|
|
</template>
|