pmtool / src /components /asset-management /AssetItemForm.tsx
devarshia5's picture
Upload 487 files
d97b8f9 verified
Raw
History Blame Contribute Delete
10.3 kB
import React from 'react';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea';
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
FormDescription,
} from '@/components/ui/form';
import { CustomDropdown } from './shared/CustomDropdown';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Loader2, Save, X, Package } from 'lucide-react';
import {
AssetItem,
AssetItemCreateRequest,
AssetItemUpdateRequest,
AssetItemSchema,
ASSET_ITEM_TYPES,
ASSET_CONDITIONS,
} from '@/types/asset-management';
interface AssetItemFormProps {
item?: AssetItem;
assetId?: number;
onSubmit: (data: AssetItemCreateRequest | AssetItemUpdateRequest) => Promise<void>;
onCancel: () => void;
isSubmitting?: boolean;
}
type AssetItemFormValues = {
itemType: string;
itemName: string;
quantity: number;
specifications: string;
serialNumber?: string;
condition: string;
notes?: string;
};
const AssetItemForm: React.FC<AssetItemFormProps> = ({
item,
assetId,
onSubmit,
onCancel,
isSubmitting = false,
}) => {
const isEditing = !!item;
const form = useForm<AssetItemFormValues>({
resolver: zodResolver(AssetItemSchema.omit({ itemID: true, assetID: true, addedDate: true })),
defaultValues: {
itemType: item?.itemType || '',
itemName: item?.itemName || '',
quantity: item?.quantity || 1,
specifications: item?.specifications || '',
serialNumber: item?.serialNumber || '',
condition: item?.condition || 'Good',
notes: item?.notes || '',
},
});
const handleSubmit = async (values: AssetItemFormValues) => {
try {
const addedDate = new Date().toISOString();
if (isEditing && item) {
const updateData: AssetItemUpdateRequest = {
itemID: item.itemID,
assetID: item.assetID,
...values,
addedDate: item.addedDate,
};
await onSubmit(updateData);
} else if (assetId) {
const createData: AssetItemCreateRequest = {
assetID: assetId,
...values,
addedDate,
};
await onSubmit(createData);
}
} catch (error) {
console.error('Form submission error:', error);
}
};
return (
<Card className="w-full mx-auto">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Package className="h-5 w-5" />
{isEditing ? 'Edit Item' : 'Add New Item'}
</CardTitle>
</CardHeader>
<CardContent>
<Form {...form}>
<form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{/* Item Type */}
<FormField
control={form.control}
name="itemType"
render={({ field }) => (
<FormItem>
<FormLabel>Item Type *</FormLabel>
<FormControl>
<CustomDropdown
options={ASSET_ITEM_TYPES.map(type => ({
value: type,
label: type
}))}
value={field.value}
onChange={field.onChange}
placeholder="Select item type"
error={!!form.formState.errors.itemType}
/>
</FormControl>
<FormDescription>
Select the type of component or item.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
{/* Item Name */}
<FormField
control={form.control}
name="itemName"
render={({ field }) => (
<FormItem>
<FormLabel>Item Name *</FormLabel>
<FormControl>
<Input
placeholder="e.g., Kingston 8GB DDR4"
{...field}
/>
</FormControl>
<FormDescription>
Enter the specific name or model of the item.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
{/* Quantity */}
<FormField
control={form.control}
name="quantity"
render={({ field }) => (
<FormItem>
<FormLabel>Quantity *</FormLabel>
<FormControl>
<Input
type="number"
min="1"
placeholder="1"
{...field}
onChange={(e) => field.onChange(parseInt(e.target.value) || 1)}
/>
</FormControl>
<FormDescription>
Number of units of this item.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
{/* Condition */}
<FormField
control={form.control}
name="condition"
render={({ field }) => (
<FormItem>
<FormLabel>Condition *</FormLabel>
<FormControl>
<CustomDropdown
options={ASSET_CONDITIONS.map(condition => ({
value: condition,
label: condition
}))}
value={field.value}
onChange={field.onChange}
placeholder="Select condition"
error={!!form.formState.errors.condition}
/>
</FormControl>
<FormDescription>
Current condition of the item.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
{/* Specifications */}
<FormField
control={form.control}
name="specifications"
render={({ field }) => (
<FormItem className="md:col-span-2">
<FormLabel>Specifications *</FormLabel>
<FormControl>
<Input
placeholder="e.g., 8GB DDR4 2666MHz"
{...field}
/>
</FormControl>
<FormDescription>
Technical specifications or details about the item.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
{/* Serial Number */}
<FormField
control={form.control}
name="serialNumber"
render={({ field }) => (
<FormItem>
<FormLabel>Serial Number</FormLabel>
<FormControl>
<Input
placeholder="Optional"
{...field}
/>
</FormControl>
<FormDescription>
Serial number if available.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* Notes */}
<FormField
control={form.control}
name="notes"
render={({ field }) => (
<FormItem>
<FormLabel>Notes</FormLabel>
<FormControl>
<Textarea
placeholder="Additional notes about this item..."
className="min-h-20"
{...field}
/>
</FormControl>
<FormDescription>
Any additional information about this item.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
{/* Form Actions */}
<div className="flex flex-col sm:flex-row justify-end gap-3 pt-4">
<Button
type="button"
variant="outline"
onClick={onCancel}
disabled={isSubmitting}
className="flex items-center justify-center gap-2 min-h-[44px] md:min-h-0 w-full sm:w-auto"
>
<X className="h-4 w-4" />
<span>Cancel</span>
</Button>
<Button
type="submit"
disabled={isSubmitting}
className="flex items-center justify-center gap-2 min-h-[44px] md:min-h-0 w-full sm:w-auto"
>
{isSubmitting ? (
<Loader2 className="h-4 w-4 animate-spin" />
) : (
<Save className="h-4 w-4" />
)}
<span>
{isSubmitting
? (isEditing ? 'Updating...' : 'Adding...')
: (isEditing ? 'Update Item' : 'Add Item')
}
</span>
</Button>
</div>
</form>
</Form>
</CardContent>
</Card>
);
};
export default AssetItemForm;