import { useState, useEffect, useMemo, useRef, type ChangeEvent } from 'react' import { Formik } from 'formik' import * as Yup from 'yup' import { pInput as PInput, Dropdown, p as P, ImageUploader } from 'web-components' import ProductsSelector from './ProductsSelector' import { trpc } from '@/lib/trpc-client' import { useUploadToObjectStorage } from '@/hooks/useUploadToObjectStorage' import type { CreateStoreInput } from '@packages/shared' // Store form values — required description + product selection on top of CreateStoreInput export type StoreFormData = Omit & { description: string products: number[] } interface StoreFormProps { mode: 'create' | 'edit' initialValues: StoreFormData onSubmit: (values: StoreFormData) => void isLoading: boolean storeId?: number } const validationSchema = Yup.object().shape({ name: Yup.string().required('Name is required'), description: Yup.string(), imageUrl: Yup.string(), owner: Yup.number().required('Owner is required'), products: Yup.array().of(Yup.number()), }) function StoreForm({ mode, initialValues, onSubmit, isLoading, storeId }: StoreFormProps) { const { data: staffData } = trpc.admin.staffUser.getStaff.useQuery() const { data: productsData } = trpc.admin.product.getProducts.useQuery() const [formInitialValues, setFormInitialValues] = useState(initialValues) const [selectedImages, setSelectedImages] = useState<{ blob: Blob; mimeType: string }[]>([]) const [displayImages, setDisplayImages] = useState<{ uri?: string }[]>([]) const fileInputRef = useRef(null) // For edit mode, pre-select SKUs belonging to this store's products const initialSelectedProducts = useMemo(() => { if (mode !== 'edit' || !productsData?.products) return [] return productsData.products .filter(p => p.storeId === storeId) .flatMap(p => (p.skus || []).map(sku => sku.id)) }, [mode, productsData?.products, storeId]) useEffect(() => { setFormInitialValues({ ...initialValues, products: initialSelectedProducts, }) }, [initialValues, initialSelectedProducts]) const existingImageUrls = useMemo( () => (formInitialValues.imageUrl ? [formInitialValues.imageUrl] : []), [formInitialValues.imageUrl] ) const staffOptions = staffData?.staff.map((staff: { id: number; name: string }) => ({ label: staff.name, value: staff.id, })) || [] const { uploadSingle, isUploading } = useUploadToObjectStorage() const handleImagePick = () => { fileInputRef.current?.click() } const handleFileChange = (e: ChangeEvent) => { const files = Array.from(e.target.files || []) if (files.length === 0) { setSelectedImages([]) setDisplayImages([]) return } const file = files[0] setSelectedImages([{ blob: file, mimeType: file.type || 'image/jpeg' }]) setDisplayImages([{ uri: URL.createObjectURL(file) }]) e.target.value = '' } const handleRemoveImage = (uri: string) => { const index = displayImages.findIndex(img => img.uri === uri) if (index !== -1) { const newDisplay = displayImages.filter((_, i) => i !== index) const newFiles = selectedImages.filter((_, i) => i !== index) setDisplayImages(newDisplay) setSelectedImages(newFiles) } } return ( {({ handleChange, handleSubmit, values, setFieldValue, errors, touched }) => { const submit = async () => { try { let imageUrl: string | undefined if (selectedImages.length > 0) { const { blob, mimeType } = selectedImages[0] const { presignedUrl } = await uploadSingle(blob, mimeType, 'store') imageUrl = presignedUrl } onSubmit({ ...values, imageUrl }) } catch (error) { console.error('Upload error:', error) window.alert('Error: Failed to upload image') } } return (

Owner

setFieldValue('owner', Number(value))} className="mb-4" />
setFieldValue('products', value)} multiple={true} label="Products" placeholder="Select products" isDisabled={(sku) => sku.storeId !== null && sku.storeId !== storeId} labelFormat={(sku) => `${sku.productName} - ₹${sku.price}`} />

Store Image

setFormInitialValues((prev) => ({ ...prev, imageUrl: undefined, })) } allowMultiple={false} />
) }}
) } export default StoreForm