271
resources/client/admin/titles/title-editor/title-primary-facts-form.tsx
Executable file
271
resources/client/admin/titles/title-editor/title-primary-facts-form.tsx
Executable file
@@ -0,0 +1,271 @@
|
||||
import {FormImageSelector} from '@common/ui/images/image-selector';
|
||||
import {Trans} from '@common/i18n/trans';
|
||||
import {FileUploadProvider} from '@common/uploads/uploader/file-upload-provider';
|
||||
import {FormTextField} from '@common/ui/forms/input-field/text-field/text-field';
|
||||
import {FormSwitch} from '@common/ui/forms/toggle/switch';
|
||||
import {FormDatePicker} from '@common/ui/forms/input-field/date/date-picker/date-picker';
|
||||
import {FormSelect, Option} from '@common/ui/forms/select/select';
|
||||
import {useValueLists} from '@common/http/value-lists';
|
||||
import {useForm} from 'react-hook-form';
|
||||
import {
|
||||
CreateTitlePayload,
|
||||
useCreateTitle,
|
||||
} from '@app/admin/titles/requests/use-create-title';
|
||||
import {Title} from '@app/titles/models/title';
|
||||
import {Form} from '@common/ui/forms/form';
|
||||
import {useUpdateTitle} from '@app/admin/titles/requests/use-update-title';
|
||||
import {toast} from '@common/ui/toast/toast';
|
||||
import {message} from '@common/i18n/message';
|
||||
import {useNavigate} from '@common/utils/hooks/use-navigate';
|
||||
import {useOutletContext} from 'react-router-dom';
|
||||
import React, {Fragment} from 'react';
|
||||
import {TitleEditorLayout} from '@app/admin/titles/title-editor/title-editor-layout';
|
||||
import {Button} from '@common/ui/buttons/button';
|
||||
import {useCurrentDateTime} from '@common/i18n/use-current-date-time';
|
||||
import {FormComboBox} from '@common/ui/forms/combobox/form-combobox';
|
||||
|
||||
export function TitlePrimaryFactsForm() {
|
||||
const title = useOutletContext<Title>();
|
||||
|
||||
return (
|
||||
<FileUploadProvider>
|
||||
{title ? <EditTitleForm title={title} /> : <CreateTitleForm />}
|
||||
</FileUploadProvider>
|
||||
);
|
||||
}
|
||||
|
||||
function CreateTitleForm() {
|
||||
const now = useCurrentDateTime();
|
||||
const navigate = useNavigate();
|
||||
const form = useForm<CreateTitlePayload>({
|
||||
defaultValues: {
|
||||
release_date: now.toAbsoluteString(),
|
||||
certification: 'pg',
|
||||
language: 'en',
|
||||
},
|
||||
});
|
||||
const createTitle = useCreateTitle(form);
|
||||
const isDirty = Object.keys(form.formState.dirtyFields).length > 0;
|
||||
|
||||
return (
|
||||
<Form
|
||||
form={form}
|
||||
onSubmit={values => {
|
||||
createTitle.mutate(values, {
|
||||
onSuccess: response => {
|
||||
toast(message('Title created'));
|
||||
navigate(`../${response.title.id}/edit`, {
|
||||
relative: 'path',
|
||||
replace: true,
|
||||
});
|
||||
},
|
||||
});
|
||||
}}
|
||||
>
|
||||
<TitleEditorLayout
|
||||
actions={
|
||||
<Button
|
||||
variant="flat"
|
||||
color="primary"
|
||||
type="submit"
|
||||
disabled={createTitle.isPending || !isDirty}
|
||||
>
|
||||
<Trans message="Create" />
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
<FormFields />
|
||||
</TitleEditorLayout>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
|
||||
interface EditTitleFormProps {
|
||||
title: Title;
|
||||
}
|
||||
function EditTitleForm({title}: EditTitleFormProps) {
|
||||
const navigate = useNavigate();
|
||||
const form = useForm<CreateTitlePayload>({
|
||||
defaultValues: {
|
||||
name: title.name,
|
||||
is_series: title.is_series,
|
||||
original_title: title.original_title,
|
||||
poster: title.poster,
|
||||
backdrop: title.backdrop,
|
||||
release_date: title.release_date,
|
||||
tagline: title.tagline,
|
||||
description: title.description,
|
||||
runtime: title.runtime,
|
||||
certification: title.certification,
|
||||
budget: title.budget,
|
||||
revenue: title.revenue,
|
||||
language: title.language,
|
||||
popularity: title.popularity,
|
||||
},
|
||||
});
|
||||
const updateTitle = useUpdateTitle(form);
|
||||
|
||||
return (
|
||||
<Form
|
||||
form={form}
|
||||
onSubmit={values => {
|
||||
updateTitle.mutate(values, {
|
||||
onSuccess: () => {
|
||||
toast(message('Title updated'));
|
||||
navigate('../../../', {relative: 'path', replace: true});
|
||||
},
|
||||
});
|
||||
}}
|
||||
>
|
||||
<TitleEditorLayout
|
||||
actions={
|
||||
<Button
|
||||
variant="flat"
|
||||
color="primary"
|
||||
type="submit"
|
||||
disabled={updateTitle.isPending || !form.formState.isDirty}
|
||||
>
|
||||
<Trans message="Save" />
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
<FormFields />
|
||||
</TitleEditorLayout>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
|
||||
function FormFields() {
|
||||
return (
|
||||
<Fragment>
|
||||
<div className="gap-24 md:flex">
|
||||
<FormImageSelector
|
||||
variant="square"
|
||||
previewSize="w-204 aspect-poster"
|
||||
name="poster"
|
||||
diskPrefix="title-posters"
|
||||
label={<Trans message="Poster" />}
|
||||
showRemoveButton
|
||||
/>
|
||||
<div className="flex-auto max-md:mt-24">
|
||||
<FormImageSelector
|
||||
name="backdrop"
|
||||
variant="square"
|
||||
diskPrefix="title-backdrops"
|
||||
label={<Trans message="Backdrop" />}
|
||||
stretchPreview
|
||||
previewSize="min-h-124"
|
||||
className="mb-24"
|
||||
/>
|
||||
<FormTextField
|
||||
name="name"
|
||||
label={<Trans message="Title" />}
|
||||
className="mb-24"
|
||||
required
|
||||
/>
|
||||
<FormTextField
|
||||
name="original_title"
|
||||
label={<Trans message="Original title" />}
|
||||
className="mb-24"
|
||||
/>
|
||||
<FormSwitch name="is_series" className="mb-24">
|
||||
<Trans message="Series" />
|
||||
</FormSwitch>
|
||||
</div>
|
||||
</div>
|
||||
<FormDatePicker
|
||||
name="release_date"
|
||||
label={<Trans message="Release date" />}
|
||||
className="mb-24"
|
||||
granularity="day"
|
||||
/>
|
||||
<FormTextField
|
||||
name="tagline"
|
||||
label={<Trans message="Tagline" />}
|
||||
className="mb-24"
|
||||
/>
|
||||
<FormTextField
|
||||
name="description"
|
||||
label={<Trans message="Overview" />}
|
||||
inputElementType="textarea"
|
||||
rows={4}
|
||||
className="mb-24"
|
||||
/>
|
||||
<div className="mb-24 items-center gap-24 md:flex">
|
||||
<FormTextField
|
||||
name="runtime"
|
||||
label={<Trans message="Runtime" />}
|
||||
type="number"
|
||||
min={1}
|
||||
className="flex-1 max-md:mb-24"
|
||||
/>
|
||||
<CertificationCombobox />
|
||||
</div>
|
||||
<div className="mb-24 items-center gap-24 md:flex">
|
||||
<FormTextField
|
||||
name="budget"
|
||||
label={<Trans message="Budget (US dollars)" />}
|
||||
type="number"
|
||||
min={1}
|
||||
className="flex-1 max-md:mb-24"
|
||||
/>
|
||||
<FormTextField
|
||||
name="revenue"
|
||||
label={<Trans message="Revenue (US dollars)" />}
|
||||
type="number"
|
||||
min={1}
|
||||
className="flex-1 max-md:mb-24"
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-24 items-center gap-24 md:flex">
|
||||
<FormTextField
|
||||
name="popularity"
|
||||
label={<Trans message="Popularity" />}
|
||||
type="number"
|
||||
min={1}
|
||||
className="flex-1 max-md:mb-24"
|
||||
/>
|
||||
<LanguageSelect />
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
function CertificationCombobox() {
|
||||
const {data} = useValueLists(['titleFilterAgeRatings']);
|
||||
return (
|
||||
<FormComboBox
|
||||
name="certification"
|
||||
selectionMode="single"
|
||||
label={<Trans message="Certification" />}
|
||||
className="flex-1"
|
||||
allowCustomValue
|
||||
>
|
||||
{data?.titleFilterAgeRatings.map(({name, value}) => (
|
||||
<Option key={value} value={value}>
|
||||
<Trans message={name} />
|
||||
</Option>
|
||||
))}
|
||||
</FormComboBox>
|
||||
);
|
||||
}
|
||||
|
||||
function LanguageSelect() {
|
||||
const {data} = useValueLists(['tmdbLanguages']);
|
||||
return (
|
||||
<FormSelect
|
||||
name="language"
|
||||
selectionMode="single"
|
||||
label={<Trans message="Language" />}
|
||||
showSearchField
|
||||
searchPlaceholder="Search languages"
|
||||
className="flex-1"
|
||||
>
|
||||
{data?.tmdbLanguages.map(language => (
|
||||
<Option key={language.code} value={language.code}>
|
||||
<Trans message={language.name} />
|
||||
</Option>
|
||||
))}
|
||||
</FormSelect>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user