import React from 'react'; import { View, Text, TouchableOpacity, Alert } from 'react-native'; import { Formik, FieldArray } from 'formik'; import DateTimePickerMod from 'common-ui/src/components/date-time-picker'; import { tw, MyTextInput } from 'common-ui'; import { trpc } from '../src/trpc-client'; import ProductsSelector from '../components/ProductsSelector'; interface VendorSnippet { name: string; groupIds: number[]; productIds: number[]; validTill?: string; } interface SlotFormProps { onSlotAdded?: () => void; initialDeliveryTime?: Date | null; initialFreezeTime?: Date | null; initialIsActive?: boolean; slotId?: number; initialProductIds?: number[]; initialGroupIds?: number[]; } export default function SlotForm({ onSlotAdded, initialDeliveryTime, initialFreezeTime, initialIsActive = true, slotId, initialProductIds = [], initialGroupIds = [], }: SlotFormProps) { const { data: slotData } = trpc.admin.slots.getSlotById.useQuery( { id: slotId! }, { enabled: !!slotId } ); const vendorSnippetsFromSlot = (slotData?.slot?.vendorSnippets || []).map((snippet: any) => ({ name: snippet.name || '', groupIds: snippet.groupIds || [], productIds: snippet.productIds || [], validTill: snippet.validTill || undefined, })) as VendorSnippet[]; const initialValues = { deliveryTime: initialDeliveryTime || (slotData?.slot?.deliveryTime ? new Date(slotData.slot.deliveryTime) : null), freezeTime: initialFreezeTime || (slotData?.slot?.freezeTime ? new Date(slotData.slot.freezeTime) : null), selectedGroupIds: initialGroupIds.length > 0 ? initialGroupIds : (slotData?.slot?.groupIds || []), selectedProductIds: initialProductIds.length > 0 ? initialProductIds : (slotData?.slot?.products?.map((p: any) => p.id) || []), vendorSnippetList: vendorSnippetsFromSlot, }; const { mutate: createSlot, isPending: isCreating } = trpc.admin.slots.createSlot.useMutation(); const { mutate: updateSlot, isPending: isUpdating } = trpc.admin.slots.updateSlot.useMutation(); const isEditMode = !!slotId; const isPending = isCreating || isUpdating; // Fetch groups const { data: groupsData } = trpc.admin.product.getGroups.useQuery(); const handleFormSubmit = (values: typeof initialValues) => { if (!values.deliveryTime || !values.freezeTime) { Alert.alert('Error', 'Please fill all fields'); return; } const slotData = { deliveryTime: values.deliveryTime.toISOString(), freezeTime: values.freezeTime.toISOString(), isActive: initialIsActive, groupIds: values.selectedGroupIds, productIds: values.selectedProductIds, vendorSnippets: values.vendorSnippetList.map((snippet: VendorSnippet) => ({ name: snippet.name, productIds: snippet.productIds, validTill: snippet.validTill, })), }; if (isEditMode && slotId) { updateSlot( { id: slotId, ...slotData }, { onSuccess: () => { Alert.alert('Success', 'Slot updated successfully!'); onSlotAdded?.(); }, onError: (error: any) => { console.log({msg: JSON.stringify(error.message)}) Alert.alert('Error', error.message || 'Failed to update slot'); }, } ); } else { createSlot( slotData, { onSuccess: () => { Alert.alert('Success', 'Slot created successfully!'); // Reset form // Formik will handle reset onSlotAdded?.(); }, onError: (error: any) => { Alert.alert('Error', error.message || 'Failed to create slot'); }, } ); } }; return ( {({ handleSubmit, values, setFieldValue }) => { // Map groups data to match ProductsSelector types (convert price from string to number) const mappedGroups = (groupsData?.groups || []).map(group => ({ ...group, products: group.products.map(product => ({ ...product, price: parseFloat(product.price as unknown as string) || 0, })), })); return ( {isEditMode ? 'Edit Slot' : 'Create New Slot'} Delivery Date & Time setFieldValue('deliveryTime', value)} /> Freeze Date & Time setFieldValue('freezeTime', value)} /> setFieldValue('selectedProductIds', newProductIds)} groups={mappedGroups} selectedGroupIds={values.selectedGroupIds} onGroupChange={(newGroupIds) => setFieldValue('selectedGroupIds', newGroupIds)} label="Select Products" placeholder="Select products for this slot" /> {/* Vendor Snippets */} {({ push, remove }) => ( Vendor Snippets {values.vendorSnippetList.map((snippet: VendorSnippet, index: number) => ( setFieldValue(`vendorSnippetList.${index}.name`, text)} /> setFieldValue(`vendorSnippetList.${index}.productIds`, newProductIds)} groups={mappedGroups.filter(group => values.selectedGroupIds.includes(group.id) ).map(group => ({ ...group, products: group.products.filter(p => values.selectedProductIds.includes(p.id)) }))} selectedGroupIds={snippet.groupIds || []} onGroupChange={(newGroupIds) => setFieldValue(`vendorSnippetList.${index}.groupIds`, newGroupIds)} label="Select Products" placeholder="Select products for snippet" isDisabled={(product) => !values.selectedProductIds.includes(product.id)} /> remove(index)} style={tw`bg-red-500 px-4 py-2 rounded-lg self-end`} > Remove Snippet ))} push({ name: '', groupIds: [], productIds: [], validTill: '' })} style={tw`bg-blue-500 px-4 py-3 rounded-lg items-center`} > Add Vendor Snippet )} handleSubmit()} disabled={isPending} style={tw`${isPending ? 'bg-pink2' : 'bg-pink1'} p-3 rounded-lg items-center mt-6 pb-4`} > {isPending ? (isEditMode ? 'Updating...' : 'Creating...') : (isEditMode ? 'Update Slot' : 'Create Slot')} )}} ); }