fix: edit table and migrations
This commit is contained in:
164
bo/src/stores/admin/addProduct.ts
Normal file
164
bo/src/stores/admin/addProduct.ts
Normal file
@@ -0,0 +1,164 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref, reactive } from 'vue'
|
||||
import { useFetchJson } from '@/composable/useFetchJson'
|
||||
import type {
|
||||
ProductCategory,
|
||||
ProductRelated,
|
||||
ProductForm,
|
||||
ProductFormProduct,
|
||||
ProductFormPrice,
|
||||
ProductFormVariant,
|
||||
ProductVariantForm,
|
||||
ProductImage,
|
||||
} from '@/types/product'
|
||||
import type { MenuItem } from '@/types'
|
||||
import { settings } from '@/router/settings'
|
||||
|
||||
// ── Default values ────────────────────────────────────────────────────────────
|
||||
|
||||
function emptyForm(): ProductForm {
|
||||
return {
|
||||
product: {
|
||||
reference: '',
|
||||
base_price: 0,
|
||||
quantity: 0,
|
||||
minimal_quantity: 1,
|
||||
available_for_order: true,
|
||||
available_date: '',
|
||||
out_of_stock_behavior: 2,
|
||||
on_sale: false,
|
||||
show_price: true,
|
||||
condition: 'new',
|
||||
is_virtual: false,
|
||||
weight: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
depth: 0,
|
||||
delivery_days: null,
|
||||
active: true,
|
||||
visibility: 'both',
|
||||
indexed: true,
|
||||
date_add: '',
|
||||
date_upd: '',
|
||||
name: '',
|
||||
description: '',
|
||||
description_short: '',
|
||||
manufacturer: '',
|
||||
category: '',
|
||||
is_favorite: false,
|
||||
is_oem: false,
|
||||
is_new: false,
|
||||
},
|
||||
price: {
|
||||
base: 0,
|
||||
final_tax_excl: 0,
|
||||
final_tax_incl: 0,
|
||||
tax_rate: 0,
|
||||
priority: 0,
|
||||
},
|
||||
variants: [],
|
||||
}
|
||||
}
|
||||
|
||||
// ── Store ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
export const useAddProductStore = defineStore('addProduct', () => {
|
||||
const loading = ref(false)
|
||||
const saving = ref(false)
|
||||
const error = ref<string | null>(null)
|
||||
const successMessage = ref<string | null>(null)
|
||||
|
||||
// Form data for creating / editing a product
|
||||
const form = reactive<ProductForm>(emptyForm())
|
||||
|
||||
// Variants loaded when editing an existing product
|
||||
const variants = ref<ProductVariantForm[]>([])
|
||||
const variantSaving = ref<Record<number, boolean>>({})
|
||||
const variantErrors = ref<Record<number, string>>({})
|
||||
|
||||
// Images
|
||||
const images = ref<ProductImage[]>([])
|
||||
|
||||
// Categories & related products
|
||||
const selectedCategories = ref<ProductCategory[]>([])
|
||||
const relatedProducts = ref<ProductRelated[]>([])
|
||||
|
||||
// ── Product ─────────────────────────────────────────────────────────
|
||||
async function loadProduct(productId: number) {
|
||||
loading.value = true
|
||||
error.value = null
|
||||
try {
|
||||
// const resp = await useFetchJson<ProductForm>(`/api/v1/restricted/admin/product/${productId}`)
|
||||
// Object.assign(form, resp.items)
|
||||
console.log('[addProduct] loadProduct – API not connected yet', productId)
|
||||
} catch (e: unknown) {
|
||||
error.value = e instanceof Error ? e.message : 'Failed to load product'
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// ── Images ────────────────────────────────────────────────────────────────
|
||||
function addImageFiles(files: FileList | File[]) {
|
||||
const incoming = Array.from(files)
|
||||
for (const file of incoming) {
|
||||
const previewUrl = URL.createObjectURL(file)
|
||||
images.value.push({ previewUrl, file, cover: false, uploading: false })
|
||||
}
|
||||
if (!images.value.some(i => i.cover) && images.value.length > 0) {
|
||||
images.value[0]!.cover = true
|
||||
}
|
||||
}
|
||||
|
||||
function removeImage(index: number) {
|
||||
const img = images.value[index]!
|
||||
if (img.previewUrl.startsWith('blob:')) URL.revokeObjectURL(img.previewUrl)
|
||||
const wasCover = img.cover
|
||||
images.value.splice(index, 1)
|
||||
if (wasCover && images.value.length > 0) {
|
||||
images.value[0]!.cover = true
|
||||
}
|
||||
}
|
||||
|
||||
function setCover(index: number) {
|
||||
images.value.forEach((img, i) => { img.cover = i === index })
|
||||
}
|
||||
|
||||
|
||||
function resetForm() {
|
||||
Object.assign(form, emptyForm())
|
||||
variants.value = []
|
||||
images.value = []
|
||||
selectedCategories.value = []
|
||||
relatedProducts.value = []
|
||||
error.value = null
|
||||
successMessage.value = null
|
||||
}
|
||||
|
||||
const categories = ref<MenuItem[]>([])
|
||||
async function loadCategories() {
|
||||
const resp = await useFetchJson<MenuItem>(`/api/v1/restricted/menu/get-category-tree?root_category_id=${settings['app'].category_tree_root_id}`);
|
||||
categories.value = resp.items.children
|
||||
}
|
||||
|
||||
return {
|
||||
loading,
|
||||
saving,
|
||||
error,
|
||||
successMessage,
|
||||
form,
|
||||
images,
|
||||
selectedCategories,
|
||||
relatedProducts,
|
||||
variants,
|
||||
variantSaving,
|
||||
variantErrors,
|
||||
categories,
|
||||
loadProduct,
|
||||
addImageFiles,
|
||||
removeImage,
|
||||
setCover,
|
||||
resetForm,
|
||||
loadCategories
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user