Files
mtdb_movie/resources/client/admin/people/crupdate/person-credits-editor.tsx
maher 703f50a09d
Some checks failed
Build / run (push) Has been cancelled
first commit
2025-10-29 11:42:25 +01:00

157 lines
4.6 KiB
TypeScript
Executable File

import {ColumnConfig} from '@common/datatable/column-config';
import {PersonCredit, TitleCredit} from '@app/titles/models/title';
import {Trans} from '@common/i18n/trans';
import React, {Fragment, useContext, useMemo} from 'react';
import {Table, TableBodyProps} from '@common/ui/tables/table';
import {TableRow} from '@common/ui/tables/table-row';
import {TableContext} from '@common/ui/tables/table-context';
import {TitlePoster} from '@app/titles/title-poster/title-poster';
import {DialogTrigger} from '@common/ui/overlays/dialog/dialog-trigger';
import {IconButton} from '@common/ui/buttons/icon-button';
import {DeleteIcon} from '@common/icons/material/Delete';
import {ConfirmationDialog} from '@common/ui/overlays/dialog/confirmation-dialog';
import {useOutletContext} from 'react-router-dom';
import {GetPersonResponse} from '@app/people/requests/use-person';
import {IllustratedMessage} from '@common/ui/images/illustrated-message';
import {RecentActorsIcon} from '@common/icons/material/RecentActors';
import {TitleLink} from '@app/titles/title-link';
import {useDeletePersonCredit} from '@app/admin/people/requests/use-delete-person-credit';
const columnConfig: ColumnConfig<PersonCredit>[] = [
{
key: 'name',
header: () => <Trans message="Credit" />,
visibleInMode: 'all',
width: 'flex-3',
body: credit => (
<div className="flex items-center gap-12">
<TitlePoster title={credit} srcSize="sm" size="w-32" />
<div className="overflow-hidden min-w-0">
<div className="overflow-hidden overflow-ellipsis">
<TitleLink title={credit} target="_blank" />
</div>
<div className="text-muted text-xs overflow-hidden overflow-ellipsis">
{credit.is_series ? (
<Trans message="Series" />
) : (
<Trans message="Movie" />
)}
</div>
</div>
</div>
),
},
{
key: 'year',
header: () => <Trans message="Year" />,
body: credit => credit.year,
},
{
key: 'character',
header: () => <Trans message="Character" />,
body: credit => (credit.pivot.character ? credit.pivot.character : '-'),
},
{
key: 'department',
header: () => <Trans message="Department" />,
body: credit => (
<span className="capitalize">{credit.pivot.department}</span>
),
},
{
key: 'job',
header: () => <Trans message="Job" />,
body: credit => <span className="capitalize">{credit.pivot.job}</span>,
},
{
key: 'actions',
header: () => <Trans message="Actions" />,
hideHeader: true,
align: 'end',
width: 'w-42 flex-shrink-0',
visibleInMode: 'all',
body: item => (
<div className="text-muted">
<DeleteButton credit={item} />
</div>
),
},
];
export function PersonCreditsEditor() {
const data = useOutletContext<GetPersonResponse>();
const credits = useMemo(() => {
return Object.values(data.credits)
.flat()
.filter(credit => credit.pivot != null);
}, [data.credits]);
return (
<Fragment>
<Table
enableSelection={false}
columns={columnConfig}
data={credits}
cellHeight="h-54"
tableBody={<CreditsTableBody />}
/>
{!credits.length && <NoCreditsMessage />}
</Fragment>
);
}
function CreditsTableBody({renderRowAs}: TableBodyProps) {
const {data} = useContext(TableContext);
return (
<Fragment>
{data.map((item, rowIndex) => (
<TableRow
item={item}
index={rowIndex}
// use pivot id for key because some person might
// appear multiple times with different department
key={(item as TitleCredit).pivot.id}
renderAs={renderRowAs}
/>
))}
</Fragment>
);
}
function NoCreditsMessage() {
return (
<IllustratedMessage
className="mt-40"
imageMargin="mb-8"
image={
<div className="text-muted">
<RecentActorsIcon size="xl" />
</div>
}
imageHeight="h-auto"
title={<Trans message="No credits have been added yet" />}
/>
);
}
interface DeleteButtonProps {
credit: PersonCredit;
}
function DeleteButton({credit}: DeleteButtonProps) {
const deleteCredit = useDeletePersonCredit(credit);
return (
<DialogTrigger type="modal">
<IconButton>
<DeleteIcon />
</IconButton>
<ConfirmationDialog
isDanger
title={<Trans message="Delete credit" />}
body={<Trans message="Are you sure you want to delete this credit?" />}
confirm={<Trans message="Delete" />}
isLoading={deleteCredit.isPending}
onConfirm={() => deleteCredit.mutate()}
/>
</DialogTrigger>
);
}