201 lines
5.4 KiB
TypeScript
201 lines
5.4 KiB
TypeScript
import type { ChangeEvent } from "react"
|
||
import {
|
||
type Control,
|
||
type Path,
|
||
type UseControllerReturn,
|
||
useController,
|
||
} from "react-hook-form"
|
||
import { ProductCode } from "@/lib/base"
|
||
import {
|
||
Field,
|
||
FieldError,
|
||
FieldGroup,
|
||
FieldLabel,
|
||
FieldLegend,
|
||
} from "../ui/field"
|
||
import { Input } from "../ui/input"
|
||
import {
|
||
Select,
|
||
SelectContent,
|
||
SelectItem,
|
||
SelectTrigger,
|
||
SelectValue,
|
||
} from "../ui/select"
|
||
|
||
export function ProductCodeField<
|
||
T extends {
|
||
code: string
|
||
},
|
||
>(props: { control: Control<T>; name: Path<T>; code: ProductCode }) {
|
||
const rt = useController(props)
|
||
|
||
switch (props.code) {
|
||
case ProductCode.Short:
|
||
return <ProductShortCode {...rt} />
|
||
case ProductCode.Long:
|
||
return <ProductLongCode {...rt} />
|
||
}
|
||
|
||
return null
|
||
}
|
||
|
||
function ProductShortCode<T extends { code: string }>(
|
||
props: UseControllerReturn<T>,
|
||
) {
|
||
const { field, fieldState } = props
|
||
|
||
const params = new URLSearchParams(field.value)
|
||
const setParams = (data: {
|
||
mode?: string
|
||
live?: string
|
||
expire?: string
|
||
}) => {
|
||
if (data.mode) params.set("mode", data.mode)
|
||
if (data.live) params.set("live", data.live)
|
||
if (data.expire) params.set("expire", data.expire)
|
||
field.onChange(params.toString())
|
||
}
|
||
|
||
const onModeChange = (value: string) => {
|
||
setParams({ mode: value })
|
||
}
|
||
const onLiveChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||
let value = e.target.value || "0"
|
||
if (value.length > 1 && value[0] === "0") {
|
||
value = value.substring(1, value.length)
|
||
}
|
||
if (!/^([0-9]+)$/.test(value)) return
|
||
setParams({ live: value })
|
||
}
|
||
const onExpireChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||
let value = e.target.value || "0"
|
||
if (value.length > 1 && value[0] === "0") {
|
||
value = value.substring(1, value.length)
|
||
}
|
||
if (!/^([0-9]+)$/.test(value)) return
|
||
setParams({ expire: value })
|
||
}
|
||
|
||
return (
|
||
<FieldLegend>
|
||
<FieldLegend>短效套餐详情</FieldLegend>
|
||
<FieldGroup>
|
||
<Field>
|
||
<FieldLabel>套餐类型</FieldLabel>
|
||
<Select
|
||
defaultValue={params.get("mode") ?? "quota"}
|
||
onValueChange={onModeChange}
|
||
>
|
||
<SelectTrigger>
|
||
<SelectValue placeholder="请选择套餐类型" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="time">包时</SelectItem>
|
||
<SelectItem value="quota">包量</SelectItem>
|
||
</SelectContent>
|
||
</Select>
|
||
</Field>
|
||
<Field>
|
||
<FieldLabel>有效期(分钟)</FieldLabel>
|
||
<Input
|
||
type="number"
|
||
value={params.get("live") ?? "0"}
|
||
onChange={onLiveChange}
|
||
/>
|
||
</Field>
|
||
{params.get("mode") === "time" && (
|
||
<Field>
|
||
<FieldLabel>过期时间(天)</FieldLabel>
|
||
<Input
|
||
type="number"
|
||
value={params.get("expire") ?? "0"}
|
||
onChange={onExpireChange}
|
||
/>
|
||
</Field>
|
||
)}
|
||
{fieldState.error && <FieldError errors={[fieldState.error]} />}
|
||
</FieldGroup>
|
||
</FieldLegend>
|
||
)
|
||
}
|
||
|
||
function ProductLongCode<T extends { code: string }>(
|
||
props: UseControllerReturn<T>,
|
||
) {
|
||
const { field, fieldState } = props
|
||
|
||
const params = new URLSearchParams(field.value)
|
||
const setParams = (data: {
|
||
mode?: string
|
||
live?: string
|
||
expire?: string
|
||
}) => {
|
||
if (data.mode) params.set("mode", data.mode)
|
||
if (data.live) params.set("live", data.live)
|
||
if (data.expire) params.set("expire", data.expire)
|
||
field.onChange(params.toString())
|
||
}
|
||
|
||
const onModeChange = (value: string) => {
|
||
setParams({ mode: value })
|
||
}
|
||
const onLiveChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||
let value = e.target.value || "0"
|
||
if (value.length > 1 && value[0] === "0") {
|
||
value = value.substring(1, value.length)
|
||
}
|
||
if (!/^([0-9]+)$/.test(value)) return
|
||
setParams({ live: value })
|
||
}
|
||
const onExpireChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||
let value = e.target.value || "0"
|
||
if (value.length > 1 && value[0] === "0") {
|
||
value = value.substring(1, value.length)
|
||
}
|
||
if (!/^([0-9]+)$/.test(value)) return
|
||
setParams({ expire: value })
|
||
}
|
||
|
||
return (
|
||
<FieldLegend>
|
||
<FieldLegend>长效套餐详情</FieldLegend>
|
||
<FieldGroup>
|
||
<Field>
|
||
<FieldLabel>套餐类型</FieldLabel>
|
||
<Select
|
||
defaultValue={params.get("mode") ?? "quota"}
|
||
onValueChange={onModeChange}
|
||
>
|
||
<SelectTrigger>
|
||
<SelectValue placeholder="请选择套餐类型" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="time">包时</SelectItem>
|
||
<SelectItem value="quota">包量</SelectItem>
|
||
</SelectContent>
|
||
</Select>
|
||
</Field>
|
||
<Field>
|
||
<FieldLabel>有效期(分钟)</FieldLabel>
|
||
<Input
|
||
type="number"
|
||
value={params.get("live") ?? "0"}
|
||
onChange={onLiveChange}
|
||
/>
|
||
</Field>
|
||
{params.get("mode") === "time" && (
|
||
<Field>
|
||
<FieldLabel>过期时间(天)</FieldLabel>
|
||
<Input
|
||
type="number"
|
||
value={params.get("expire") ?? "0"}
|
||
onChange={onExpireChange}
|
||
/>
|
||
</Field>
|
||
)}
|
||
{fieldState.error && <FieldError errors={[fieldState.error]} />}
|
||
</FieldGroup>
|
||
</FieldLegend>
|
||
)
|
||
}
|