Files
web/src/components/composites/purchase/short/center.tsx

248 lines
9.0 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 {FormField} from '@/components/ui/form'
import {RadioGroup} from '@/components/ui/radio-group'
import {Input} from '@/components/ui/input'
import {Button} from '@/components/ui/button'
import {Minus, Plus} from 'lucide-react'
import FormOption from '@/components/composites/purchase/option'
import Image from 'next/image'
import check from '../_assets/check.svg'
import {useFormContext, useWatch} from 'react-hook-form'
import {Schema} from '@/components/composites/purchase/short/form'
import {Card} from '@/components/ui/card'
export default function Center({
priceMap,
liveList,
expireList,
}: {
priceMap: Map<string, string>
liveList: string[]
expireList: string[]
}) {
const form = useFormContext<Schema>()
const type = useWatch({name: 'type'})
const expire = useWatch({name: 'expire'})
const isTime = type === '1'
return (
<Card className="flex-auto p-6 flex flex-col gap-6 relative">
{/* 计费方式 */}
<FormField<Schema, 'type'>
className="flex flex-col gap-4"
name="type"
label="计费方式">
{({id, field}) => (
<RadioGroup
id={id}
value={field.value}
onValueChange={(v) => {
field.onChange(v)
if (v === '2') {
form.setValue('expire', '0')
}
else if (expireList.length > 0) {
form.setValue('expire', expireList[0])
form.setValue('daily_limit', 2000)
}
}}
className="flex gap-4 max-md:flex-col">
<FormOption
id={`${id}-2`}
value="2"
label="包量套餐"
description="适用于短期或不定期高提取业务场景"
compare={field.value}/>
<FormOption
id={`${id}-1`}
value="1"
label="包时套餐"
description="适用于每日提取量稳定的业务场景"
compare={field.value}/>
</RadioGroup>
)}
</FormField>
{/* IP 时效 */}
<FormField<Schema, 'live'>
className="space-y-4"
name="live"
label="IP 时效">
{({id, field}) => (
<RadioGroup
id={id}
value={field.value}
onValueChange={field.onChange}
className="grid grid-cols-[repeat(auto-fill,minmax(120px,1fr))] gap-4">
{liveList.map((live) => {
const params = new URLSearchParams()
params.set('mode', isTime ? 'time' : 'quota')
params.set('live', live)
params.set('expire', isTime ? expire : '0')
const price = priceMap.get(params.toString())
const minutes = Number(live)
const hours = minutes / 60
const label = minutes % 60 === 0 ? `${hours} 小时` : `${minutes} 分钟`
return (
<FormOption
key={live}
id={`${id}-${live}`}
value={live}
label={label}
description={price && `${price}${!isTime ? '/IP' : ''}`}
compare={field.value}
/>
)
})}
</RadioGroup>
)}
</FormField>
{/* 根据套餐类型显示不同表单项 */}
{!isTime ? (
/* 包量IP 购买数量 */
<FormField
className="space-y-4"
name="quota"
label="IP 购买数量">
{({id, field}) => (
<div className="flex gap-2 items-center">
<Button
theme="outline"
type="button"
className="h-10 w-10 border border-gray-200 rounded-sm flex items-center justify-center text-lg"
onClick={() => form.setValue('quota', Math.max(10000, Number(field.value) - 5000))}
disabled={Number(field.value) === 10000}>
<Minus/>
</Button>
<Input
{...field}
id={id}
type="number"
className="w-40 h-10 border border-gray-200 rounded-sm text-center"
min={10000}
step={5000}
onBlur={(e) => {
const value = Number(e.target.value)
if (value < 10000) {
form.setValue('quota', 10000)
}
}}
/>
<Button
theme="outline"
type="button"
className="h-10 w-10 border border-gray-200 rounded-sm flex items-center justify-center text-lg"
onClick={() => form.setValue('quota', Number(field.value) + 5000)}>
<Plus/>
</Button>
</div>
)}
</FormField>
) : (
<>
{/* 包时:套餐时效 */}
<FormField className="space-y-4" name="expire" label="套餐时效">
{({id, field}) => (
<RadioGroup id={id} value={field.value} onValueChange={field.onChange} className="flex gap-4 flex-wrap">
{expireList.map(day => (
<FormOption
key={day}
id={`${id}-${day}`}
value={day}
label={`${day}`}
compare={field.value}
/>
))}
</RadioGroup>
)}
</FormField>
{/* 包时:每日提取上限 */}
<FormField
className="space-y-4"
name="daily_limit"
label="每日提取上限">
{({id, field}) => (
<div className="flex gap-2 items-center">
<Button
theme="outline"
type="button"
className="h-10 w-10 border border-gray-200 rounded-sm flex items-center justify-center text-lg"
onClick={() => form.setValue('daily_limit', Math.max(2000, Number(field.value) - 1000))}
disabled={Number(field.value) === 2000}>
<Minus/>
</Button>
<Input
{...field}
id={id}
type="number"
className="w-40 h-10 border border-gray-200 rounded-sm text-center"
min={2000}
step={1000}
onBlur={(e) => {
const value = Number(e.target.value)
if (value < 2000) {
form.setValue('daily_limit', 2000)
}
}}
/>
<Button
theme="outline"
type="button"
className="h-10 w-10 border border-gray-200 rounded-sm flex items-center justify-center text-lg"
onClick={() => form.setValue('daily_limit', Number(field.value) + 1000)}>
<Plus/>
</Button>
</div>
)}
</FormField>
</>
)}
{/* 产品特性 */}
<div className="space-y-6">
<h3></h3>
<div className="grid grid-cols-2 md:grid-cols-3 auto-rows-fr gap-4 md:gap-y-6">
<p className="flex gap-2 items-center">
<Image src={check} alt="check" aria-hidden className="w-4 h-4"/>
<span className="text-sm text-gray-500"></span>
</p>
<p className="flex gap-2 items-center">
<Image src={check} alt="check" aria-hidden className="w-4 h-4"/>
<span className="text-sm text-gray-500"></span>
</p>
<p className="flex gap-2 items-center">
<Image src={check} alt="check" aria-hidden className="w-4 h-4"/>
<span className="text-sm text-gray-500"></span>
</p>
<p className="flex gap-2 items-center">
<Image src={check} alt="check" aria-hidden className="w-4 h-4"/>
<span className="text-sm text-gray-500">API接口</span>
</p>
<p className="flex gap-2 items-center">
<Image src={check} alt="check" aria-hidden className="w-4 h-4"/>
<span className="text-sm text-gray-500">IP时效3-30()</span>
</p>
<p className="flex gap-2 items-center">
<Image src={check} alt="check" aria-hidden className="w-4 h-4"/>
<span className="text-sm text-gray-500">IP资源定期筛选</span>
</p>
<p className="flex gap-2 items-center">
<Image src={check} alt="check" aria-hidden className="w-4 h-4"/>
<span className="text-sm text-gray-500">/</span>
</p>
<p className="flex gap-2 items-center">
<Image src={check} alt="check" aria-hidden className="w-4 h-4"/>
<span className="text-sm text-gray-500">500</span>
</p>
</div>
</div>
</Card>
)
}