erp-cicd/my-access-hub-main/src/components/assets/AssetForm.tsx
Ali 20e95c2fb6
Some checks failed
Build & Deploy Frontend / build-push-deploy (push) Failing after 15s
pushing all
2025-08-30 11:51:11 +05:30

335 lines
12 KiB
TypeScript

import { useState } from 'react';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea';
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@/components/ui/form';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
import { Asset, useAssets } from '@/hooks/useAssets';
const assetSchema = z.object({
asset_code: z.string().min(1, 'Asset code is required'),
name: z.string().min(1, 'Asset name is required'),
description: z.string().optional(),
asset_category_id: z.string().optional(),
condition: z.enum(['new', 'used', 'refurbished', 'damaged']),
status: z.enum(['in_use', 'available', 'maintenance', 'disposed', 'lost']),
assigned_to_department: z.string().optional(),
location_id: z.string().optional(),
purchase_cost: z.number().min(0, 'Purchase cost must be positive'),
current_book_value: z.number().min(0, 'Book value must be positive'),
model_number: z.string().optional(),
serial_number: z.string().optional(),
sub_category: z.string().optional(),
});
type AssetFormData = z.infer<typeof assetSchema>;
interface AssetFormProps {
asset?: Asset;
onSuccess?: () => void;
onCancel?: () => void;
}
export function AssetForm({ asset, onSuccess, onCancel }: AssetFormProps) {
const { createAsset, updateAsset, categories, locations, isCreating, isUpdating } = useAssets();
const [isSubmitting, setIsSubmitting] = useState(false);
const form = useForm<AssetFormData>({
resolver: zodResolver(assetSchema),
defaultValues: {
asset_code: asset?.asset_code || '',
name: asset?.name || '',
description: asset?.description || '',
asset_category_id: asset?.asset_category_id || '',
condition: asset?.condition || 'new',
status: asset?.status || 'available',
assigned_to_department: asset?.assigned_to_department || '',
location_id: asset?.location_id || '',
purchase_cost: asset?.purchase_cost || 0,
current_book_value: asset?.current_book_value || 0,
model_number: asset?.model_number || '',
serial_number: asset?.serial_number || '',
sub_category: asset?.sub_category || '',
},
});
const onSubmit = async (data: AssetFormData) => {
setIsSubmitting(true);
try {
if (asset) {
updateAsset({ id: asset.id, ...data } as Partial<Asset> & { id: string });
} else {
createAsset(data as Omit<Asset, 'id' | 'user_id' | 'created_at' | 'updated_at'>);
}
onSuccess?.();
} catch (error) {
console.error('Error saving asset:', error);
} finally {
setIsSubmitting(false);
}
};
return (
<Card className="w-full max-w-2xl mx-auto">
<CardHeader>
<CardTitle>{asset ? 'Edit Asset' : 'Create New Asset'}</CardTitle>
</CardHeader>
<CardContent>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<FormField
control={form.control}
name="asset_code"
render={({ field }) => (
<FormItem>
<FormLabel>Asset Code *</FormLabel>
<FormControl>
<Input placeholder="e.g., LAP-001" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem>
<FormLabel>Asset Name *</FormLabel>
<FormControl>
<Input placeholder="e.g., Dell Laptop" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
<FormField
control={form.control}
name="description"
render={({ field }) => (
<FormItem>
<FormLabel>Description</FormLabel>
<FormControl>
<Textarea
placeholder="Detailed description of the asset..."
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<FormField
control={form.control}
name="asset_category_id"
render={({ field }) => (
<FormItem>
<FormLabel>Category</FormLabel>
<Select onValueChange={field.onChange} defaultValue={field.value}>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="Select category" />
</SelectTrigger>
</FormControl>
<SelectContent>
{categories?.map((category) => (
<SelectItem key={category.id} value={category.id}>
{category.name}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="location_id"
render={({ field }) => (
<FormItem>
<FormLabel>Location</FormLabel>
<Select onValueChange={field.onChange} defaultValue={field.value}>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="Select location" />
</SelectTrigger>
</FormControl>
<SelectContent>
{locations?.map((location) => (
<SelectItem key={location.id} value={location.id}>
{location.location_name}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<FormField
control={form.control}
name="condition"
render={({ field }) => (
<FormItem>
<FormLabel>Condition</FormLabel>
<Select onValueChange={field.onChange} defaultValue={field.value}>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="Select condition" />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value="new">New</SelectItem>
<SelectItem value="used">Used</SelectItem>
<SelectItem value="refurbished">Refurbished</SelectItem>
<SelectItem value="damaged">Damaged</SelectItem>
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="status"
render={({ field }) => (
<FormItem>
<FormLabel>Status</FormLabel>
<Select onValueChange={field.onChange} defaultValue={field.value}>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="Select status" />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value="available">Available</SelectItem>
<SelectItem value="in_use">In Use</SelectItem>
<SelectItem value="maintenance">Maintenance</SelectItem>
<SelectItem value="disposed">Disposed</SelectItem>
<SelectItem value="lost">Lost</SelectItem>
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<FormField
control={form.control}
name="purchase_cost"
render={({ field }) => (
<FormItem>
<FormLabel>Purchase Cost</FormLabel>
<FormControl>
<Input
type="number"
step="0.01"
{...field}
onChange={(e) => field.onChange(parseFloat(e.target.value) || 0)}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="current_book_value"
render={({ field }) => (
<FormItem>
<FormLabel>Current Book Value</FormLabel>
<FormControl>
<Input
type="number"
step="0.01"
{...field}
onChange={(e) => field.onChange(parseFloat(e.target.value) || 0)}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<FormField
control={form.control}
name="model_number"
render={({ field }) => (
<FormItem>
<FormLabel>Model Number</FormLabel>
<FormControl>
<Input placeholder="e.g., Latitude 5520" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="serial_number"
render={({ field }) => (
<FormItem>
<FormLabel>Serial Number</FormLabel>
<FormControl>
<Input placeholder="e.g., DL5520123456" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
<div className="flex justify-end space-x-2">
{onCancel && (
<Button type="button" variant="outline" onClick={onCancel}>
Cancel
</Button>
)}
<Button
type="submit"
disabled={isSubmitting || isCreating || isUpdating}
>
{isSubmitting || isCreating || isUpdating ? 'Saving...' : 'Save Asset'}
</Button>
</div>
</form>
</Form>
</CardContent>
</Card>
);
}