289 lines
11 KiB
TypeScript
289 lines
11 KiB
TypeScript
'use client'
|
||
|
||
import { useState } from 'react'
|
||
import { useRouter } from 'next/navigation'
|
||
import { Button } from '@/components/ui/button'
|
||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
||
import { Input } from '@/components/ui/input'
|
||
import { Label } from '@/components/ui/label'
|
||
import { ProductSelector } from '@/components/product-selector'
|
||
import {
|
||
ArrowLeft,
|
||
Package,
|
||
Droplets,
|
||
Plus,
|
||
Minus,
|
||
Beaker,
|
||
Clock
|
||
} from 'lucide-react'
|
||
|
||
interface SplitOption {
|
||
volume: number // ml
|
||
price: number
|
||
quantity: number // 可分装数量
|
||
}
|
||
|
||
interface Product {
|
||
id: string
|
||
name: string
|
||
brand: string
|
||
price: number
|
||
originalPrice: number
|
||
image: string
|
||
category: string
|
||
tags: string[]
|
||
rating: number
|
||
reviews: number
|
||
stock: number
|
||
description: string
|
||
volume?: string
|
||
}
|
||
|
||
export default function CreatePerfumeSplitPage() {
|
||
const router = useRouter()
|
||
const [selectedProduct, setSelectedProduct] = useState<Product | null>(null)
|
||
const [formData, setFormData] = useState({
|
||
originalVolume: '100', // 原装容量 ml
|
||
duration: '14', // 分装活动持续天数
|
||
})
|
||
|
||
const [splitOptions, setSplitOptions] = useState<SplitOption[]>([
|
||
{ volume: 5, price: 0, quantity: 10 },
|
||
{ volume: 10, price: 0, quantity: 8 },
|
||
{ volume: 20, price: 0, quantity: 4 }
|
||
])
|
||
|
||
const handleInputChange = (field: string, value: string) => {
|
||
setFormData(prev => ({ ...prev, [field]: value }))
|
||
}
|
||
|
||
const addSplitOption = () => {
|
||
const lastOption = splitOptions[splitOptions.length - 1]
|
||
setSplitOptions(prev => [...prev, {
|
||
volume: lastOption.volume + 5,
|
||
price: 0,
|
||
quantity: 1
|
||
}])
|
||
}
|
||
|
||
const removeSplitOption = (index: number) => {
|
||
if (splitOptions.length > 1) {
|
||
setSplitOptions(prev => prev.filter((_, i) => i !== index))
|
||
}
|
||
}
|
||
|
||
const updateSplitOption = (index: number, field: keyof SplitOption, value: number) => {
|
||
setSplitOptions(prev => prev.map((option, i) =>
|
||
i === index ? { ...option, [field]: value } : option
|
||
))
|
||
}
|
||
|
||
const handleSubmit = () => {
|
||
console.log('创建香水分装:', { selectedProduct, formData, splitOptions })
|
||
router.push('/create')
|
||
}
|
||
|
||
return (
|
||
<div className="min-h-screen bg-gray-50">
|
||
{/* 头部 */}
|
||
<div className="bg-gradient-to-br from-indigo-500 via-purple-600 to-pink-600 relative overflow-hidden">
|
||
<div className="absolute inset-0 bg-black/10"></div>
|
||
<div className="relative z-10 px-4 py-6">
|
||
<div className="flex items-center gap-3 mb-4">
|
||
<Button
|
||
variant="ghost"
|
||
size="sm"
|
||
onClick={() => router.back()}
|
||
className="text-white hover:bg-white/20 p-2"
|
||
>
|
||
<ArrowLeft className="w-5 h-5" />
|
||
</Button>
|
||
<div>
|
||
<h1 className="text-xl font-bold text-white">创建香水分装</h1>
|
||
<p className="text-purple-100 text-sm">选择香水,设置分装规格</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 表单内容 */}
|
||
<div className="px-4 py-6 space-y-6 max-w-2xl mx-auto">
|
||
{/* 商品选择 */}
|
||
<Card className="bg-white shadow-lg border-0 rounded-2xl overflow-hidden">
|
||
<CardHeader className="pb-3">
|
||
<CardTitle className="flex items-center gap-2 text-lg font-semibold text-gray-900">
|
||
<Droplets className="w-5 h-5 text-purple-600" />
|
||
选择香水
|
||
</CardTitle>
|
||
</CardHeader>
|
||
<CardContent>
|
||
<ProductSelector
|
||
selectedProduct={selectedProduct}
|
||
onProductSelect={setSelectedProduct}
|
||
/>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
{/* 分装设置 */}
|
||
<Card className="bg-white shadow-lg border-0 rounded-2xl overflow-hidden">
|
||
<CardHeader className="pb-3">
|
||
<CardTitle className="flex items-center gap-2 text-lg font-semibold text-gray-900">
|
||
<Beaker className="w-5 h-5 text-indigo-600" />
|
||
分装设置
|
||
</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="space-y-4">
|
||
<div className="grid grid-cols-2 gap-4">
|
||
<div>
|
||
<Label htmlFor="originalVolume" className="text-sm font-medium text-gray-700">原装容量 (ml)</Label>
|
||
<Input
|
||
id="originalVolume"
|
||
type="number"
|
||
value={formData.originalVolume}
|
||
onChange={(e) => handleInputChange('originalVolume', e.target.value)}
|
||
className="mt-1"
|
||
/>
|
||
</div>
|
||
<div>
|
||
<Label htmlFor="duration" className="text-sm font-medium text-gray-700">持续天数</Label>
|
||
<Input
|
||
id="duration"
|
||
type="number"
|
||
value={formData.duration}
|
||
onChange={(e) => handleInputChange('duration', e.target.value)}
|
||
className="mt-1"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
{/* 分装规格 */}
|
||
<Card className="bg-white shadow-lg border-0 rounded-2xl overflow-hidden">
|
||
<CardHeader className="pb-3">
|
||
<div className="flex items-center justify-between">
|
||
<CardTitle className="flex items-center gap-2 text-lg font-semibold text-gray-900">
|
||
<Package className="w-5 h-5 text-purple-600" />
|
||
分装规格
|
||
</CardTitle>
|
||
<Button
|
||
variant="outline"
|
||
size="sm"
|
||
onClick={addSplitOption}
|
||
className="text-purple-600 border-purple-200 hover:bg-purple-50"
|
||
>
|
||
<Plus className="w-4 h-4 mr-1" />
|
||
添加规格
|
||
</Button>
|
||
</div>
|
||
</CardHeader>
|
||
<CardContent className="space-y-3">
|
||
{splitOptions.map((option, index) => (
|
||
<div key={index} className="flex items-center gap-3 p-3 bg-gray-50 rounded-lg">
|
||
<div className="flex-1 grid grid-cols-3 gap-3">
|
||
<div>
|
||
<Label className="text-xs text-gray-600">容量 (ml)</Label>
|
||
<Input
|
||
type="number"
|
||
value={option.volume}
|
||
onChange={(e) => updateSplitOption(index, 'volume', parseInt(e.target.value) || 0)}
|
||
className="mt-1 h-8"
|
||
/>
|
||
</div>
|
||
<div>
|
||
<Label className="text-xs text-gray-600">价格 (¥)</Label>
|
||
<Input
|
||
type="number"
|
||
value={option.price}
|
||
onChange={(e) => updateSplitOption(index, 'price', parseInt(e.target.value) || 0)}
|
||
className="mt-1 h-8"
|
||
/>
|
||
</div>
|
||
<div>
|
||
<Label className="text-xs text-gray-600">数量</Label>
|
||
<Input
|
||
type="number"
|
||
value={option.quantity}
|
||
onChange={(e) => updateSplitOption(index, 'quantity', parseInt(e.target.value) || 0)}
|
||
className="mt-1 h-8"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
{splitOptions.length > 1 && (
|
||
<Button
|
||
variant="ghost"
|
||
size="sm"
|
||
onClick={() => removeSplitOption(index)}
|
||
className="p-1 text-red-500 hover:bg-red-50"
|
||
>
|
||
<Minus className="w-4 h-4" />
|
||
</Button>
|
||
)}
|
||
</div>
|
||
))}
|
||
</CardContent>
|
||
</Card>
|
||
|
||
{/* 分装预览 */}
|
||
{selectedProduct && splitOptions.some(opt => opt.price > 0) && (
|
||
<Card className="bg-white shadow-lg border-0 rounded-2xl overflow-hidden">
|
||
<CardHeader className="pb-3">
|
||
<CardTitle className="flex items-center gap-2 text-lg font-semibold text-gray-900">
|
||
<Package className="w-5 h-5 text-purple-600" />
|
||
分装预览
|
||
</CardTitle>
|
||
</CardHeader>
|
||
<CardContent>
|
||
<div className="bg-gradient-to-br from-purple-50 via-white to-indigo-50 rounded-xl p-4 border border-purple-100">
|
||
<div className="flex items-center gap-4 mb-4">
|
||
<div className="w-16 h-16 bg-purple-100 rounded-lg flex items-center justify-center">
|
||
<Droplets className="w-8 h-8 text-purple-600" />
|
||
</div>
|
||
<div className="flex-1">
|
||
<h3 className="font-semibold text-gray-900">{selectedProduct.name}</h3>
|
||
<p className="text-sm text-gray-600">{selectedProduct.brand}</p>
|
||
<div className="mt-1 text-sm text-gray-500">
|
||
原装 {formData.originalVolume}ml · 分装 {formData.duration}天
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="space-y-2">
|
||
{splitOptions.filter(opt => opt.price > 0).map((option, index) => (
|
||
<div key={index} className="flex items-center justify-between p-3 bg-white rounded-lg border border-purple-100">
|
||
<div className="flex items-center gap-3">
|
||
<div className="w-8 h-8 bg-indigo-100 rounded-full flex items-center justify-center">
|
||
<Droplets className="w-4 h-4 text-indigo-600" />
|
||
</div>
|
||
<div>
|
||
<div className="font-medium text-gray-900">{option.volume}ml</div>
|
||
<div className="text-xs text-gray-500">限量 {option.quantity} 份</div>
|
||
</div>
|
||
</div>
|
||
<div className="text-right">
|
||
<div className="font-bold text-purple-600">¥{option.price}</div>
|
||
<div className="text-xs text-gray-500">¥{(option.price / option.volume).toFixed(1)}/ml</div>
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
)}
|
||
|
||
{/* 创建按钮 */}
|
||
<div className="pt-4">
|
||
<Button
|
||
onClick={handleSubmit}
|
||
className="w-full bg-gradient-to-r from-indigo-500 to-purple-600 hover:opacity-90 text-white py-3 text-lg font-semibold"
|
||
disabled={!selectedProduct}
|
||
>
|
||
创建香水分装
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)
|
||
} |