Some checks failed
Build and Push Docker Image / build-and-push (push) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
120 lines
4.1 KiB
TypeScript
120 lines
4.1 KiB
TypeScript
'use client';
|
|
|
|
import { useState } from 'react';
|
|
import ImageUpload from '@/components/image-upload';
|
|
import PurchaseUrlFields from './PurchaseUrlFields';
|
|
import { type Item } from '@/lib/api';
|
|
|
|
interface ItemFormProps {
|
|
item?: Partial<Item>;
|
|
onSubmit: (item: Partial<Item>) => Promise<void>;
|
|
onCancel: () => void;
|
|
mode: 'create' | 'edit';
|
|
error?: string;
|
|
}
|
|
|
|
export default function ItemForm({ item, onSubmit, onCancel, mode, error }: ItemFormProps) {
|
|
const [formData, setFormData] = useState<Partial<Item>>(
|
|
item || {
|
|
name: '',
|
|
description: '',
|
|
quantity: 1,
|
|
imageUrl: '',
|
|
purchaseUrls: [],
|
|
}
|
|
);
|
|
const [isImageUploading, setIsImageUploading] = useState(false);
|
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
|
|
const handleSubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
if (isSubmitting) return;
|
|
setIsSubmitting(true);
|
|
try {
|
|
await onSubmit(formData);
|
|
} finally {
|
|
setIsSubmitting(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<form
|
|
onSubmit={handleSubmit}
|
|
className="mb-4 p-4 bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700"
|
|
>
|
|
<h5 className="text-base font-medium text-gray-900 dark:text-white mb-3">
|
|
{mode === 'create' ? 'Add New Item' : 'Edit Item'}
|
|
</h5>
|
|
{error && (
|
|
<div className="mb-4 p-3 bg-red-50 dark:bg-red-900/20 text-red-800 dark:text-red-400 rounded-lg text-base">
|
|
{error}
|
|
</div>
|
|
)}
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
|
|
<div>
|
|
<label className="block text-base font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
Name *
|
|
</label>
|
|
<input
|
|
type="text"
|
|
required
|
|
className="w-full px-2 py-1.5 text-base border border-gray-300 dark:border-gray-600 rounded focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:text-white"
|
|
value={formData.name}
|
|
onChange={(e) =>
|
|
setFormData((prev) => ({ ...prev, name: e.target.value }))
|
|
}
|
|
/>
|
|
</div>
|
|
<div className="md:col-span-2">
|
|
<label className="block text-base font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
Description
|
|
</label>
|
|
<textarea
|
|
rows={2}
|
|
className="w-full px-2 py-1.5 text-base border border-gray-300 dark:border-gray-600 rounded focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:text-white"
|
|
value={formData.description || ''}
|
|
onChange={(e) =>
|
|
setFormData((prev) => ({ ...prev, description: e.target.value }))
|
|
}
|
|
/>
|
|
</div>
|
|
<div className="md:col-span-2">
|
|
<ImageUpload
|
|
currentImageUrl={formData.imageUrl || ''}
|
|
onImageChange={(url) =>
|
|
setFormData((prev) => ({ ...prev, imageUrl: url }))
|
|
}
|
|
onUploadStateChange={setIsImageUploading}
|
|
type="item"
|
|
label="Item Image"
|
|
/>
|
|
</div>
|
|
<div className="md:col-span-2">
|
|
<PurchaseUrlFields
|
|
purchaseUrls={formData.purchaseUrls || []}
|
|
onChange={(urls) =>
|
|
setFormData((prev) => ({ ...prev, purchaseUrls: urls }))
|
|
}
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div className="mt-3 flex justify-end gap-2">
|
|
<button
|
|
type="button"
|
|
onClick={onCancel}
|
|
className="px-4 py-2 text-base border border-gray-300 dark:border-gray-600 rounded-lg text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer"
|
|
>
|
|
Cancel
|
|
</button>
|
|
<button
|
|
type="submit"
|
|
disabled={isImageUploading || isSubmitting}
|
|
className="px-4 py-2 text-base bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed"
|
|
>
|
|
{isImageUploading ? 'Uploading...' : isSubmitting ? 'Saving...' : mode === 'create' ? 'Add Item' : 'Save'}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
);
|
|
}
|