159 lines
5.6 KiB
TypeScript
159 lines
5.6 KiB
TypeScript
import { useMutation } from '@tanstack/react-query'
|
|
import { useState } from 'react'
|
|
import { useTranslation } from 'react-i18next'
|
|
import type { OverrideMode, OverrideRecurrence } from '@/shared/api/types'
|
|
import { Button } from '@/shared/ui/button'
|
|
import { Input } from '@/shared/ui/input'
|
|
import { Label } from '@/shared/ui/label'
|
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/shared/ui/select'
|
|
import { createOverride } from '../api'
|
|
import { NumberField } from './fields'
|
|
|
|
export function OverrideForm({
|
|
channelId,
|
|
options,
|
|
onCreated,
|
|
onError,
|
|
}: {
|
|
channelId: string
|
|
options: { id: string; name: string }[]
|
|
onCreated: () => void
|
|
onError: (e: unknown) => void
|
|
}) {
|
|
const { t } = useTranslation()
|
|
const [mode, setMode] = useState<OverrideMode>('Exclusive')
|
|
const [recurrence, setRecurrence] = useState<OverrideRecurrence>('OneTime')
|
|
const [showId, setShowId] = useState('')
|
|
const [weight, setWeight] = useState(1)
|
|
const [start, setStart] = useState('')
|
|
const [end, setEnd] = useState('')
|
|
// Weekly: день недели (0=Вс..6=Сб) + окна времени суток «HH:MM».
|
|
const [dayOfWeek, setDayOfWeek] = useState(6)
|
|
const [startTime, setStartTime] = useState('')
|
|
const [endTime, setEndTime] = useState('')
|
|
|
|
const toMinutes = (hhmm: string) => {
|
|
const [h, m] = hhmm.split(':').map(Number)
|
|
return h * 60 + m
|
|
}
|
|
const weekly = recurrence === 'Weekly'
|
|
|
|
const create = useMutation({
|
|
mutationFn: () =>
|
|
createOverride(
|
|
channelId,
|
|
weekly
|
|
? {
|
|
mode,
|
|
recurrence,
|
|
dayOfWeek,
|
|
startMinute: toMinutes(startTime),
|
|
endMinute: toMinutes(endTime),
|
|
shows: [{ showId, weight }],
|
|
}
|
|
: {
|
|
mode,
|
|
recurrence,
|
|
startsAtUtc: new Date(start).toISOString(),
|
|
endsAtUtc: new Date(end).toISOString(),
|
|
shows: [{ showId, weight }],
|
|
},
|
|
),
|
|
onSuccess: () => {
|
|
setShowId('')
|
|
setStart('')
|
|
setEnd('')
|
|
setStartTime('')
|
|
setEndTime('')
|
|
onCreated()
|
|
},
|
|
onError,
|
|
})
|
|
|
|
const valid = weekly
|
|
? showId && startTime && endTime && toMinutes(endTime) > toMinutes(startTime)
|
|
: showId && start && end && new Date(end) > new Date(start)
|
|
|
|
return (
|
|
<div className="flex flex-wrap items-end gap-2">
|
|
<div className="flex flex-col gap-1.5">
|
|
<Label>{t('admin.channels.overrideRecurrence')}</Label>
|
|
<Select value={recurrence} onValueChange={(v) => setRecurrence(v as OverrideRecurrence)}>
|
|
<SelectTrigger className="w-36">
|
|
<SelectValue />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="OneTime">{t('admin.channels.recurrenceOneTime')}</SelectItem>
|
|
<SelectItem value="Weekly">{t('admin.channels.recurrenceWeekly')}</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
<Select value={mode} onValueChange={(v) => setMode(v as OverrideMode)}>
|
|
<SelectTrigger className="w-36">
|
|
<SelectValue />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="Exclusive">{t('admin.channels.modes.Exclusive')}</SelectItem>
|
|
<SelectItem value="Boost">{t('admin.channels.modes.Boost')}</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
<Select value={showId} onValueChange={setShowId}>
|
|
<SelectTrigger className="w-44">
|
|
<SelectValue placeholder={t('admin.channels.pickShow')} />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{options.map((o) => (
|
|
<SelectItem key={o.id} value={o.id}>
|
|
{o.name}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
{mode === 'Boost' && (
|
|
<NumberField label={t('admin.channels.weight')} value={weight} onChange={setWeight} min={1} />
|
|
)}
|
|
{weekly ? (
|
|
<>
|
|
<div className="flex flex-col gap-1.5">
|
|
<Label>{t('admin.channels.weekday')}</Label>
|
|
<Select value={String(dayOfWeek)} onValueChange={(v) => setDayOfWeek(Number(v))}>
|
|
<SelectTrigger className="w-36">
|
|
<SelectValue />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{[1, 2, 3, 4, 5, 6, 0].map((d) => (
|
|
<SelectItem key={d} value={String(d)}>
|
|
{t(`admin.channels.weekdays.${d}`)}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
<div className="flex flex-col gap-1.5">
|
|
<Label>{t('admin.channels.from')}</Label>
|
|
<Input type="time" value={startTime} onChange={(e) => setStartTime(e.target.value)} className="w-32" />
|
|
</div>
|
|
<div className="flex flex-col gap-1.5">
|
|
<Label>{t('admin.channels.to')}</Label>
|
|
<Input type="time" value={endTime} onChange={(e) => setEndTime(e.target.value)} className="w-32" />
|
|
</div>
|
|
</>
|
|
) : (
|
|
<>
|
|
<div className="flex flex-col gap-1.5">
|
|
<Label>{t('admin.channels.from')}</Label>
|
|
<Input type="datetime-local" value={start} onChange={(e) => setStart(e.target.value)} className="w-60" />
|
|
</div>
|
|
<div className="flex flex-col gap-1.5">
|
|
<Label>{t('admin.channels.to')}</Label>
|
|
<Input type="datetime-local" value={end} onChange={(e) => setEnd(e.target.value)} className="w-60" />
|
|
</div>
|
|
</>
|
|
)}
|
|
<Button size="sm" disabled={!valid || create.isPending} onClick={() => create.mutate()}>
|
|
{t('common.create')}
|
|
</Button>
|
|
</div>
|
|
)
|
|
}
|