2025-11-03 21:45:23 +08:00

289 lines
11 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'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>
)
}