import React, { useState, useEffect } from 'react'; import { View, TouchableOpacity, Alert, ScrollView } from 'react-native'; import { useFormik } from 'formik'; import { MyText, tw, DatePicker, MyTextInput } from 'common-ui'; import BottomDropdown from 'common-ui/src/components/bottom-dropdown'; import ProductsSelector from '../components/ProductsSelector'; import { trpc } from '../src/trpc-client'; import { VendorSnippetForm as VendorSnippetFormType, VendorSnippet } from '../types/vendor-snippets'; interface VendorSnippetFormProps { snippet?: VendorSnippetFormType | null; onClose: () => void; onSuccess: () => void; showIsPermanentCheckbox?: boolean; } const VendorSnippetForm: React.FC = ({ snippet, onClose, onSuccess, showIsPermanentCheckbox = false, }) => { // Fetch slots const { data: slotsData } = trpc.user.slots.getSlots.useQuery(); const createSnippet = trpc.admin.vendorSnippets.create.useMutation(); const updateSnippet = trpc.admin.vendorSnippets.update.useMutation(); const isEditing = !!snippet; const formik = useFormik({ initialValues: { snippetCode: snippet?.snippetCode || '', slotId: snippet?.slotId?.toString() || '', isPermanent: snippet?.isPermanent || false, productIds: snippet?.productIds?.map(id => id.toString()) || [], validTill: snippet?.validTill ? new Date(snippet.validTill) : null, }, validate: (values) => { const errors: {[key: string]: string} = {}; if (!values.snippetCode.trim()) { errors.snippetCode = 'Snippet code is required'; } // Validate snippet code only contains alphanumeric characters and underscore const snippetCodeRegex = /^[a-zA-Z0-9_]+$/; if (values.snippetCode && !snippetCodeRegex.test(values.snippetCode)) { errors.snippetCode = 'Snippet code can only contain letters, numbers, and underscores'; } // Only require slotId if isPermanent is false if (!values.isPermanent && !values.slotId) { errors.slotId = 'Slot selection is required'; } if (values.productIds.length === 0) { errors.productIds = 'At least one product must be selected'; } return errors; }, onSubmit: async (values) => { try { const submitData = { snippetCode: values.snippetCode, slotId: values.isPermanent ? undefined : parseInt(values.slotId || '0'), isPermanent: values.isPermanent, productIds: values.productIds.map(id => parseInt(id)), validTill: values.validTill ? values.validTill.toISOString() : undefined, }; if (isEditing && snippet) { await updateSnippet.mutateAsync({ id: snippet.id, updates: submitData, }); Alert.alert('Success', 'Vendor snippet updated successfully'); } else { await createSnippet.mutateAsync(submitData); Alert.alert('Success', 'Vendor snippet created successfully'); } onSuccess(); onClose(); } catch (error: any) { Alert.alert('Error', error.message || 'Failed to save vendor snippet'); } }, }); // Generate unique snippet code if creating new (only on mount) useEffect(() => { if (!isEditing && !formik.values.snippetCode) { const timestamp = Date.now(); const random = Math.random().toString(36).substring(2, 8); formik.setFieldValue('snippetCode', `VS_${timestamp}_${random}`); } }, [isEditing]); // Removed formik.values.snippetCode from deps const slotOptions = slotsData?.slots.map(slot => ({ label: new Date(slot.deliveryTime).toLocaleString(), value: slot.id.toString(), })) || []; return ( {isEditing ? 'Edit Vendor Snippet' : 'Create Vendor Snippet'} {/* Snippet Code */} {formik.errors.snippetCode && formik.touched.snippetCode && ( {formik.errors.snippetCode} )} {/* Is Permanent Checkbox */} formik.setFieldValue('isPermanent', !formik.values.isPermanent)} style={tw`flex-row items-center mb-2`} > {formik.values.isPermanent && ( )} Is Permanent? Check if this snippet is permanent and not tied to a specific delivery slot {/* Slot Selection - Only show if not permanent */} {!formik.values.isPermanent && ( Delivery Slot formik.setFieldValue('slotId', value)} placeholder="Choose a delivery slot" /> {formik.errors.slotId && formik.touched.slotId && ( {formik.errors.slotId} )} )} {/* Product Selection */} parseInt(id))} onChange={(selectedProductIds) => formik.setFieldValue('productIds', (selectedProductIds as number[]).map(id => id.toString()))} multiple={true} label="Select Products" placeholder="Select products" labelFormat={(product) => `${product.name} (${product.unit})`} /> {formik.errors.productIds && formik.touched.productIds && ( {formik.errors.productIds} )} {/* Valid Till Date */} Valid Till (Optional) formik.setFieldValue('validTill', date)} placeholder="Select expiry date" showLabel={false} /> Leave empty for no expiry {/* Submit Button */} formik.handleSubmit()} disabled={formik.isSubmitting} style={tw`bg-blue-500 py-3 rounded-lg ${formik.isSubmitting ? 'opacity-50' : ''}`} > {formik.isSubmitting ? 'Saving...' : isEditing ? 'Update Snippet' : 'Create Snippet' } ); }; export default VendorSnippetForm;