2025-06-24 10:56:21 +08:00

315 lines
11 KiB
TypeScript

'use client';
import { useState } from 'react';
import { useRouter } from 'next/navigation';
import { ArrowLeft, Save } from 'lucide-react';
export default function AddBookPage() {
const router = useRouter();
const [saving, setSaving] = useState(false);
const [formData, setFormData] = useState({
isbn: '',
title: '',
authors: '',
publisher: '',
publishDate: '',
price: '',
classificationNo: '',
location: '',
totalCopies: '1',
availableCopies: '1',
status: 'normal',
description: '',
coverUrl: '',
});
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setSaving(true);
try {
const createData = {
isbn: formData.isbn,
title: formData.title,
authors: formData.authors.split(',').map(author => author.trim()).filter(Boolean),
publisher: formData.publisher || null,
publishDate: formData.publishDate || null,
price: formData.price ? parseFloat(formData.price) : null,
classificationNo: formData.classificationNo || null,
location: formData.location || null,
totalCopies: parseInt(formData.totalCopies),
availableCopies: parseInt(formData.availableCopies),
status: formData.status,
description: formData.description || null,
coverUrl: formData.coverUrl || null,
};
const response = await fetch('/api/books', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(createData),
});
if (response.ok) {
const book = await response.json();
router.push(`/admin/books/${book.bookId}`);
} else {
const errorData = await response.json();
alert(`添加失败: ${errorData.error || 'Unknown error'}`);
}
} catch (error) {
console.error('Create error:', error);
alert('添加失败');
} finally {
setSaving(false);
}
};
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
const { name, value } = e.target;
setFormData(prev => ({
...prev,
[name]: value
}));
};
return (
<div className="min-h-screen bg-gray-50">
<div className="max-w-4xl mx-auto p-6">
{/* Header */}
<div className="flex items-center justify-between mb-6">
<div className="flex items-center gap-4">
<button
onClick={() => router.back()}
className="flex items-center gap-2 text-gray-600 hover:text-gray-900"
>
<ArrowLeft size={20} />
</button>
<h1 className="text-2xl font-bold text-gray-900"></h1>
</div>
</div>
{/* Form */}
<div className="bg-white rounded-lg shadow-sm border p-6">
<form onSubmit={handleSubmit} className="space-y-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
ISBN *
</label>
<input
type="text"
name="isbn"
value={formData.isbn}
onChange={handleChange}
required
placeholder="978-7-111-12345-6"
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
*
</label>
<input
type="text"
name="title"
value={formData.title}
onChange={handleChange}
required
placeholder="请输入书名"
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
* ()
</label>
<input
type="text"
name="authors"
value={formData.authors}
onChange={handleChange}
required
placeholder="张三, 李四"
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
</label>
<input
type="text"
name="publisher"
value={formData.publisher}
onChange={handleChange}
placeholder="请输入出版社"
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
</label>
<input
type="date"
name="publishDate"
value={formData.publishDate}
onChange={handleChange}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
</label>
<input
type="number"
name="price"
value={formData.price}
onChange={handleChange}
step="0.01"
min="0"
placeholder="0.00"
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
</label>
<input
type="text"
name="classificationNo"
value={formData.classificationNo}
onChange={handleChange}
placeholder="TP312"
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
</label>
<input
type="text"
name="location"
value={formData.location}
onChange={handleChange}
placeholder="A区1楼书架001"
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
*
</label>
<input
type="number"
name="totalCopies"
value={formData.totalCopies}
onChange={handleChange}
required
min="1"
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
*
</label>
<input
type="number"
name="availableCopies"
value={formData.availableCopies}
onChange={handleChange}
required
min="0"
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
*
</label>
<select
name="status"
value={formData.status}
onChange={handleChange}
required
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
>
<option value="normal"></option>
<option value="damaged"></option>
<option value="removed"></option>
</select>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
</label>
<input
type="url"
name="coverUrl"
value={formData.coverUrl}
onChange={handleChange}
placeholder="https://example.com/cover.jpg"
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
/>
</div>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
</label>
<textarea
name="description"
value={formData.description}
onChange={handleChange}
rows={4}
placeholder="请输入图书描述"
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
/>
</div>
<div className="flex justify-end gap-4">
<button
type="button"
onClick={() => router.back()}
className="px-6 py-2 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50"
>
</button>
<button
type="submit"
disabled={saving}
className="flex items-center gap-2 px-6 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50"
>
<Save size={16} />
{saving ? '添加中...' : '添加'}
</button>
</div>
</form>
</div>
</div>
</div>
);
}