просмотр сезона в краткой форме (начал делать)

This commit is contained in:
THE_KONDRAT 2025-03-01 09:30:10 +03:00
parent 3b56a160fc
commit 0d0d3fd96d
15 changed files with 674 additions and 60 deletions

View File

@ -61,10 +61,10 @@ function App() {
</>
}>
<Route path='library/dictionaries' element={<Dictionaries />} />
<Route path='library/anime/title' element={<AnimeTitleCreate />} />
<Route path='library/anime/title/:id/edit' element={<AnimeTitleEdit />} />
<Route path='library/anime/title/:id/season/' element={<AnimeSeasonCreate />} />
<Route path='library/anime/title/:titleId/episode/' element={<AnimeEpisodeCreate />} />
<Route path='library/anime' element={<AnimeTitleCreate />} />
<Route path='library/anime/:id/edit' element={<AnimeTitleEdit />} />
<Route path='library/anime/:titleId/season/' element={<AnimeSeasonCreate />} />
<Route path='library/anime/:titleId/episode/' element={<AnimeEpisodeCreate />} />
{/* <Route path="about" element={<About />} /> */}
{/* <Route path="contact" element={<Contact />} /> */}
</Route>

View File

@ -10,7 +10,7 @@ const controllerUrl = 'http://localhost:5198/MediaContent/Anime/Title/';
function FillMediaInfoUrl(mediaInfo: MediaInfo | null | undefined){
if (mediaInfo != null){
mediaInfo.url = `${controllerUrl}GetMedia?objectId=${mediaInfo.objectId}`;
// console.log(`mediaInfo.url: ${mediaInfo.url}`);
// console.log(`mediaInfo.objectId${mediaInfo.objectId}\r\nmediaInfo.url: ${mediaInfo.url}`);
}
}
@ -60,12 +60,17 @@ export async function GetAnimeTitleDetail(id: string, client?: AxiosInstance | n
},
);
//console.log(JSON.stringify(data, null, 4));
// 👇️ "response status is: 200"
// console.log('response status is: ', status);
FillMediaInfoUrl(data.commonProperties.preview);
// console.log('items count: ', data.items.length);
data.items.forEach(item => FillMediaInfoUrl(item.commonProperties.preview));
// data.items.forEach(item => { console.log('aa'); FillMediaInfoUrl(item.commonProperties.preview);});
data.commonProperties.relatedContent.forEach(relatedContent => FillMediaInfoUrl(relatedContent));
// console.log('data');
// console.log(JSON.stringify(data, null, 4));
return data;
}
catch (error)
@ -91,6 +96,7 @@ export async function GetAnimeTitle(id: string, client?: AxiosInstance | null) {
// 👇️ "response status is: 200"
// console.log('response status is: ', status);
FillMediaInfoUrl(data.commonProperties.preview);
data.items.forEach(item => FillMediaInfoUrl(item.commonProperties.preview));
data.commonProperties.relatedContent.forEach(relatedContent => FillMediaInfoUrl(relatedContent));
return data;
}

View File

@ -0,0 +1,91 @@
import {NameItem, NameType} from "./models/Types.tsx";
export type CommonPropertiesName = {
nameInUserLanguage: string | null,
languageCodeIso3: string | null,
nameOriginal: string | null,
namesUsed: Array<NameItem>,
}
export function GetName(names: Array<NameItem> | null | undefined, primaryLanguageId?: string | null | undefined) : CommonPropertiesName | null {
if (names != null) {
const nameOriginal = names!.find(q => q.type == NameType.Original)
if ((primaryLanguageId == null || primaryLanguageId == '') || nameOriginal?.language.id == primaryLanguageId) {
if (nameOriginal != null) {
// namesUsed.push(nameOriginal);
// titleNames.titleString = `${nameOriginal.value} [${nameOriginal.language.codeIso3}]`;
return GetCommonPropertiesName(null, nameOriginal);
}
}
else {
let result = null as CommonPropertiesName | null;
const namesUsed = new Array<NameItem>();
if (nameOriginal != null) {
namesUsed.push(nameOriginal);
// titleNames.titleString = `${nameOriginal.value} [${nameOriginal.language.codeIso3}]`;
result = GetCommonPropertiesName(null, nameOriginal);
}
const originalNameInAnotherLanguage = names!.find(q => q.type == NameType.OriginalInAnotherLanguage && q.language.id == primaryLanguageId);
if (originalNameInAnotherLanguage != null) {
namesUsed.push(originalNameInAnotherLanguage);
// titleNames.titleString = `${originalNameInAnotherLanguage.value}${nameOriginal != null ? ` / ${titleNames.titleString}` : ''}`;
result = GetCommonPropertiesName(originalNameInAnotherLanguage, nameOriginal ?? null);
}
else {
const translatedName = names!.find(q => q.type == NameType.Translation && q.language.id == primaryLanguageId);
if (translatedName != null) {
namesUsed.push(translatedName);
result = GetCommonPropertiesName(translatedName, nameOriginal ?? null);
}
}
if (result != null){
result.namesUsed = namesUsed;
}
return result;
}
}
return null;
}
function GetCommonPropertiesName(nameInUserLanguage?: NameItem | null, nameOriginal?: NameItem | null) : CommonPropertiesName | null {
if (nameInUserLanguage != null){
if (nameOriginal != null){
return {
nameInUserLanguage: nameInUserLanguage.value,
nameOriginal: nameOriginal.value,
languageCodeIso3: nameOriginal!.language.codeIso3,
} as CommonPropertiesName;
// return `${nameInUserLanguage.value} / ${nameOriginal.value} [${nameOriginal!.language.codeIso3}]`;
}
else{
return {
nameInUserLanguage: nameInUserLanguage.value,
nameOriginal: null,
languageCodeIso3: null,
} as CommonPropertiesName;
}
}
else if (nameOriginal != null){
return {
nameInUserLanguage: null,
nameOriginal: nameOriginal.value,
languageCodeIso3: nameOriginal!.language.codeIso3,
} as CommonPropertiesName;
// return (
// <>
// <span className="user-select-all">{nameOriginal.value}</span> [{nameOriginal!.language.codeIso3}]
// </>
// )
}
else{
return null;
// return (
// <span>NO NAME</span>
// )
}
}

View File

@ -91,14 +91,6 @@ export function DateToString(date: Date | undefined | null): string {
}
}
export function GetDuration(durationString: string | null | undefined) : Date | null{
}
export function DurationToString(){
}
export function GetNumericValue(percentage: number | null | undefined, valueMax: number) : number | undefined{
// if (!(percentage != undefined && percentage != null && percentage > 0)) return undefined;
if (!IsNumericValueDefined(percentage)) return undefined;

View File

@ -96,12 +96,6 @@ export default function AddAnimeSeasonOrEpisodeModalWindowComponent(props: IAddA
</li>
</ul>
{/*{addItemType == ItemType.Season &&*/}
{/* <>*/}
{/* Добавить сезон */}
{/* </>*/}
{/*}*/}
{addItemType == ItemType.Episode &&
<>
<div className='input-group mb-2'>

View File

@ -99,7 +99,7 @@ export default function AnimeItemAddComponent(props : IAnimeItemAddComponentProp
>
<li>
{/*<Link to='/' className='dropdown-item'>*/}
<Link to={`/admin/library/anime/title/${props.titleId}/season/`}
<Link to={`/admin/library/anime/${props.titleId}/season/`}
className='dropdown-item-text link-light link-offset-2 link-body-emphasis link-underline-opacity-25 link-underline-opacity-75-hover'>
<div className='row justify-content-between'>
<div className='col-auto pe-0'>Добавить сезон</div>
@ -109,7 +109,7 @@ export default function AnimeItemAddComponent(props : IAnimeItemAddComponentProp
</li>
<li>
{/*<Link to='/' className='dropdown-item'>*/}
<Link to={`/admin/library/anime/title/${props.titleId}/episode/`}
<Link to={`/admin/library/anime/${props.titleId}/episode/`}
className='dropdown-item-text link-light link-offset-2 link-body-emphasis link-underline-opacity-25 link-underline-opacity-75-hover'>
<div className='row justify-content-between'>
<div className='col-auto pe-0'>Добавить эпизод</div>

View File

@ -30,6 +30,7 @@ export default function AnimeItemShortComponent(props: IAnimeSeasonsShortCompone
{props.animeItem.number} ({props.animeItem.order}).
</div>
<div className='col-1'>
sdfsdf
<MediaInfoComponent mediaInfo={props.animeItem.commonProperties.preview?.url == null ? null : {
type: props.animeItem.commonProperties.preview.type,
data: props.animeItem.commonProperties.preview.url,
@ -44,7 +45,6 @@ export default function AnimeItemShortComponent(props: IAnimeSeasonsShortCompone
<h3 className='text-primary' role='button'>
{Name(props.animeItem.commonProperties.names, props.user?.languageId)}
</h3>
id: [{props.animeItem.id}] df
</div>
<div className='col-auto'>
<span className='me-2'>season.hasViews: {props.animeItem.completed ? 'TRUE' : 'FALSE'}</span>
@ -89,6 +89,7 @@ function AnimeItemShort(animeItem: Season | Episode, goToDetailPage: () => void,
<div className='row mb-2 border rounded py-2 bg-body-secondary'>
{animeItem.commonProperties.preview != null &&
<div className='col-1'>
animeItem.commonProperties.preview?.url: {animeItem.commonProperties.preview?.url}
<MediaInfoComponent mediaInfo={animeItem.commonProperties.preview?.url == null ? null : {
type: animeItem.commonProperties.preview.type,
data: animeItem.commonProperties.preview.url,

View File

@ -3,8 +3,8 @@ import MediaInfoComponent, { MediaInfoModel } from '../../common/view/MediaInfoC
import NamesViewComponent from '../../common/view/NamesViewComponent';
import DescriptionViewComponent from '../../common/view/DescriptionViewComponent';
import GenreListView from '../../library/view/GenreListView';
import { AnimeTitle } from '../../../api/models/Types';
import RateComponent from '../../common/view/RateComponent';
import { AnimeTitleDetail} from '../../../api/models/Types';
import RatingComponent from '../../common/view/RatingComponent.tsx';
import { TfiPencil } from 'react-icons/tfi';
import { useNavigate } from 'react-router-dom';
import useUser from '../../../api/hooks/useUser';
@ -14,7 +14,7 @@ import { UserInfo } from '../../../api/models/AccountTypes';
export interface IAnimeTitleDetailComponentProps{
user?: UserInfo | null | undefined,
animeTitle: AnimeTitle,
animeTitle: AnimeTitleDetail,
setRate: (value: number | null) => Promise<string | undefined>,
deleteRate: () => Promise<string | undefined>,
forceRefresh?: () => void,
@ -25,7 +25,7 @@ export default function AnimeTitleDetailComponent(props: IAnimeTitleDetailCompon
const { data: user } = useQuery(userQueryKey, getUser);
const titleNames = GetTitleNames(props.animeTitle.commonProperties.names, props.user?.languageId);
const navigate = useNavigate();
const goToEditPage = () => navigate(`/admin/library/anime/title/${props.animeTitle.id}/edit`);
const goToEditPage = () => navigate(`/admin/library/anime/${props.animeTitle.id}/edit`);
const canUserEdit = user != null;
// const canUserEdit = true;
return (
@ -102,7 +102,7 @@ export default function AnimeTitleDetailComponent(props: IAnimeTitleDetailCompon
{/* <div className='card-header'>
<h3 className='card-heading'>Оценка</h3>
</div> */}
<RateComponent
<RatingComponent
user={props.user}
rateObjectId={props.animeTitle.id}
ratePercentage={props.animeTitle.rate}

View File

@ -1,6 +1,6 @@
import { AnimeTitleShort } from '../../../api/models/Types'
import MediaInfoComponent, { MediaInfoModel } from '../../common/view/MediaInfoComponent'
import RateComponent from '../../common/view/RateComponent';
import RatingComponent from '../../common/view/RatingComponent.tsx';
// import { atom, useAtom } from 'jotai';
import { useNavigate } from 'react-router-dom';
@ -63,7 +63,7 @@ export default function AnimeTitleShortComponent(props: IAnimeTitleShortComponen
</div> */}
<div className='row'>
<div className='col-12 p-0'>
<RateComponent
<RatingComponent
user={props.user}
rateObjectId={props.item.id}
ratePercentage={props.item.rate}

View File

@ -5,15 +5,9 @@ import {GetName} from "../../../api/CommonPropertiesHelper.tsx";
import {Link} from "react-router-dom";
import {MdVideoLibrary} from "react-icons/md";
export type TitleNames = {
titleElement: ReactNode | null
// titleString: string
namesUsed: Array<NameItem>,
};
export interface IGetTitleNamesProps {
titleNames: Array<NameItem>,
titleId: string,
titleId: string | null | undefined,
titleNames: Array<NameItem> | null | undefined,
seasonNames?: Array<NameItem> | null | undefined,
seasonId?: string | null | undefined,
episodeNames?: Array<NameItem> | null | undefined,
@ -22,11 +16,13 @@ export interface IGetTitleNamesProps {
returnToEdit?: boolean | null | undefined,
}
export function NameBreadcrumpsComponent(props: IGetTitleNamesProps){
export function NameBreadcrumbsComponent(props: IGetTitleNamesProps){
const [titleExists, setTitleExists] = useState<boolean>(false);
const [seasonExists, setSeasonExists] = useState<boolean>(false);
const [episodeExists, setEpisodeExists] = useState<boolean>(false);
useEffect(() => {
setTitleExists(props.titleNames != null && props.titleId != null && props.titleId != '');
setSeasonExists(props.seasonNames != null && props.seasonId != null && props.seasonId != '');
setEpisodeExists(props.episodeNames != null && props.episodeId != null && props.episodeId != '');
}, [props])
@ -40,15 +36,21 @@ export function NameBreadcrumpsComponent(props: IGetTitleNamesProps){
</Link>
</li>
<li className="breadcrumb-item active" aria-current="page">
<Link to={`/library/anime/${props.titleId}`} className=''>
{GetItemName(props.titleNames, props.userLanguageId)}
</Link>
</li>
{titleExists &&
<li className="breadcrumb-item active" aria-current="page">
<Link
to={`${props.returnToEdit == true ? '/admin' : ''}/library/anime/${props.titleId}${props.returnToEdit == true ? '/edit' : ''}`}
className=''>
{GetItemName(props.titleNames ?? [], props.userLanguageId)}
</Link>
</li>
}
{seasonExists &&
<li className="breadcrumb-item active" aria-current="page">
<Link to={`${(props.returnToEdit == true) ? '/admin' : ''}/library/anime/${props.titleId}/season/${props.seasonId}`} className=''>
<Link
to={`${props.returnToEdit == true ? '/admin' : ''}/library/anime/${props.titleId}/season/${props.seasonId}${props.returnToEdit == true ? '/edit' : ''}`}
className=''>
{GetItemName(props.seasonNames ?? [], props.userLanguageId)}
</Link>
</li>

View File

@ -1,5 +1,7 @@
import { ReactNode } from "react";
import { NameItem, NameType } from "../../../api/models/Types";
// import { NameItem, NameType } from "../../../api/models/Types";
import { NameItem } from "../../../api/models/Types";
import {GetName} from "../../../api/CommonPropertiesHelper.tsx";
export type TitleNames = {
titleElement: ReactNode | null
@ -8,7 +10,54 @@ export type TitleNames = {
};
export function GetTitleNames(names: Array<NameItem> | null | undefined, primaryLanguageId?: string | null | undefined){
const titleNames = names == undefined || names == null
const titleNames = GetName(names, primaryLanguageId);
if (titleNames != null){
if (titleNames.nameInUserLanguage != null){
if (titleNames.nameOriginal != null){
return {
titleElement: (
<>
<span className="user-select-all">{titleNames.nameInUserLanguage}</span> / <span className="user-select-all">{titleNames.nameOriginal}</span> [{titleNames.languageCodeIso3}]
</>
),
namesUsed: titleNames.namesUsed,
} as TitleNames;
}
else{
return {
titleElement: (
<>
<span className="user-select-all">{titleNames.nameInUserLanguage}</span>
</>
),
namesUsed: titleNames.namesUsed,
} as TitleNames
}
}
else if (titleNames.nameOriginal != null){
return {
titleElement: (
<>
<span className="user-select-all">{titleNames.nameOriginal}</span> [{titleNames.languageCodeIso3}]
</>
),
namesUsed: titleNames.namesUsed,
} as TitleNames
}
}
return {
titleElement: (
<span>NO NAME</span>
),
namesUsed: [],
} as TitleNames
}
/*
export function GetTitleNames(names: Array<NameItem> | null | undefined, primaryLanguageId?: string | null | undefined){
const titleNames = names == null
? null
: {
titleElement: NameComponent(null, null),
@ -16,7 +65,7 @@ export function GetTitleNames(names: Array<NameItem> | null | undefined, primary
} as TitleNames;
if (titleNames != null){
const nameOriginal = names!.find(q => q.type == NameType.Original)
if ((primaryLanguageId == undefined || primaryLanguageId == null) || nameOriginal?.language.id == primaryLanguageId){
if ((primaryLanguageId == null || primaryLanguageId == '') || nameOriginal?.language.id == primaryLanguageId){
if (nameOriginal != null){
titleNames.namesUsed.push(nameOriginal);
// titleNames.titleString = `${nameOriginal.value} [${nameOriginal.language.codeIso3}]`;
@ -43,7 +92,7 @@ export function GetTitleNames(names: Array<NameItem> | null | undefined, primary
titleNames.titleElement = NameComponent(translatedName, nameOriginal ?? null);
}
}
}
}
}
return titleNames == null
@ -83,4 +132,5 @@ function NameComponent(nameInUserLanguage?: NameItem | null, nameOriginal?: Name
<span>NO NAME</span>
)
}
}
}
*/

View File

@ -23,7 +23,7 @@ export interface IRateComponentProps{
forceRefresh?: () => void | null | undefined,
}
export default function RateComponent(props: IRateComponentProps) {
export default function RatingComponent(props: IRateComponentProps) {
const [ratePercentage, setRatePercentage] = useState<number | null>(null);
const [userRatePercentage, setUserRatePercentage] = useState<number | null>(null);
const [rateEditId, setRateEditId] = useAtom(expandedRatingAtom);

View File

@ -2,7 +2,7 @@ import { useParams } from 'react-router-dom'
import { GetAnimeTitleDetail, VoteAnimeTitle, UnvoteAnimeTitle } from '../../../api/AnimeTitleApi';
import { QueryClient, useQuery, useQueryClient } from 'react-query';
import AnimeTitleDetailComponent from '../../../components/MediaContent/view/AnimeTitleDetailComponent';
import { VoteDeleteModel, VoteEditModel } from '../../../api/models/Types';
import { VoteDeleteModel, VoteEditModel} from '../../../api/models/Types';
import { libraryClient } from '../../../api/axios';
import useUser from '../../../api/hooks/useUser';
import { userQueryKey } from '../../../components/common/UserShortComponent';
@ -64,4 +64,6 @@ export default function AnimeTitleDetail() {
}
function InvalidateGenres(queryClient: QueryClient) { queryClient.invalidateQueries({ queryKey: [queryKey] }); }
function InvalidateGenres(queryClient: QueryClient) {
return queryClient.invalidateQueries({ queryKey: [queryKey] });
}

View File

@ -1,11 +1,489 @@
import {useParams} from "react-router-dom";
import {useNavigate, useParams} from "react-router-dom";
import {useEffect, useState} from "react";
import {
AnimeSeasonCreateModel,
AnimeTitleCreateModel,
CreateDescriptionModel, CreateGenreProportionModel,
CreateMediaInfoModel,
CreateNameModel,
Description,
GenreProportion,
Language, MediaInfoType,
NameItem
} from "../../../api/models/Types.tsx";
import {MediaInfoEditModel} from "../../../components/common/edit/MediaInfoTypes.tsx";
import {AddSeason, CreateAnimeTitle, GetAnimeTitle} from "../../../api/AnimeTitleApi.tsx";
import MediaInfoEditComponent from "../../../components/common/edit/MediaInfoEditComponent.tsx";
import DateEditComponent from "../../../components/common/edit/DateEditComponent.tsx";
import {GetDate} from "../../../common/Helper.tsx";
import NamesEditComponent from "../../../components/MediaContent/edit/Names/NamesEditComponent.tsx";
import DescriptionsEditComponent
from "../../../components/MediaContent/edit/Descriptions/DescriptionsEditComponent.tsx";
import GenreProportionEditComponent
from "../../../components/MediaContent/edit/Genres/GenreProportionEditComponent.tsx";
import {TfiSave} from "react-icons/tfi";
import useUser from "../../../api/hooks/useUser.tsx";
import {useQuery} from "react-query";
import {userQueryKey} from "../../../components/common/UserShortComponent.tsx";
import {NameBreadcrumbsComponent} from "../../../components/common/view/NameBreadcrumbsComponent.tsx";
export default function AnimeSeasonCreate(){
const { id } = useParams();
const client = null;
const navigate = useNavigate();
const { getUser } = useUser();
const { data: user } = useQuery(userQueryKey, getUser);
const { titleId } = useParams();
const [ titleNames, setTitleNames ] = useState<Array<NameItem> | null>(null);
const [ names, setNames ] = useState<Array<NameItem>>([]);
const [ preview, setPreview ] = useState<MediaInfoEditModel | null>(null);
const [ descriptions, setDescriptions ] = useState<Array<Description>>([]);
const [ genres, setGenres ] = useState<Array<GenreProportion>>([]);
// const [ relatedContent, setRelatedContent ] = useState<Array<MediaInfo>>([]);
const [ announcementDate, setAnnouncementDate ] = useState<string | null>(null);
const [ estimatedReleaseDate, setEstimatedReleaseDate ] = useState<string | null>(null);
const [ releaseDate, setReleaseDate ] = useState<string | null>(null);
// const [duration, setDuration] = useState<number | null>(null);
const AddName = (nameItem: NameItem) => {
if (names.find(q => q.language.id == nameItem.language.id && q.type == nameItem.type && q.value == nameItem.value)){
return 'Name already exists';
}
else {
const obj = names;
names.push(nameItem);
setNames(obj);
return '';
}
};
const EditName = (nameItem: NameItem, newValue: string | null, newLanguage: Language | null) => {
const obj = names;
const name = obj.find(q => q.language == nameItem.language && q.type == nameItem.type && q.value == nameItem.value);
if (name != null){
if (newValue != null) name.value = newValue;
if (newLanguage != null) name.language = newLanguage;
setNames(obj);
}
};
const DeleteName = (nameItem: NameItem) => {
const obj = names;
setNames(obj.filter(q => !(q.language == nameItem.language && q.type == nameItem.type && q.value == nameItem.value)));
};
const AddDescription = (description: Description) => {
if (descriptions.find(q => q.language.id == description.language.id && q.isOriginal == description.isOriginal && q.value == description.value)){
return 'Description already exists';
}
else {
const obj = descriptions
obj.push(description);
setDescriptions(obj);
return '';
}
};
const EditDescription = (descriptionItem: Description, newValue: string | null, newLanguage: Language | null) => {
const obj = descriptions;
const description = obj.find(q => q.language == descriptionItem.language && q.isOriginal == descriptionItem.isOriginal && q.value == descriptionItem.value);
if (description != null){
if (newValue != null) description.value = newValue;
if (newLanguage != null) description.language = newLanguage;
setDescriptions(obj);
}
};
const DeleteDescription = (description: Description) => {
const obj = descriptions;
setDescriptions(obj.filter(q => !(q.language == description.language && q.isOriginal == description.isOriginal && q.value == description.value)));
};
const AddGenre = (genreProportionItem: GenreProportion) => {
if (genres.find(q => q.genre.id == genreProportionItem.genre.id && q.proportion == genreProportionItem.proportion)){
return 'Genre already exists';
}
else {
const obj = genres;
obj.push(genreProportionItem);
setGenres(obj);
return '';
}
};
const EditGenre = (genreProportionItem: GenreProportion, proportionPercentage: number | null) => {
const obj = genres;
const genreProportion = obj.find(q => q.genre == genreProportionItem.genre && q.proportion == genreProportionItem.proportion);
if (genreProportion != null){
if (proportionPercentage != null) genreProportion.proportion = proportionPercentage;
setGenres(obj);
}
};
const DeleteGenre = (genreProportionItem: GenreProportion) => {
const obj = genres;
setGenres(obj.filter(q => !(q.genre == genreProportionItem.genre && q.proportion == genreProportionItem.proportion)));
};
const SetAnnouncementDate = (date: Date | null) => setAnnouncementDate(date == null ? null : date.toISOString());
const SetEstimatedReleaseDate = (date: Date | null) => setEstimatedReleaseDate(date == null ? null : date.toISOString());
const SetReleaseDate = (date: Date | null) => setReleaseDate(date == null ? null : date.toISOString());
// const SetPreview = (preview: MediaInfoEditModel | null) => setPreview(preview);
const [ isEditing, setIsEditingValue ] = useState<Array<string>>([]);
const setEditing = (elementName: string, value: boolean) => {
const alreadyEditing = isEditing.find(q => q == elementName) != null;
if (value){
if (!alreadyEditing){
setIsEditingValue(isEditing.concat([elementName]))
}
}
else{
if (alreadyEditing){
setIsEditingValue(isEditing.filter(q => q != elementName))
}
}
};
const [ isDeleting, setIsDeletingValue ] = useState<Array<string>>([]);
const setDeleting = (elementName: string, value: boolean) => {
const alreadyDeleting = isDeleting.find(q => q == elementName) != null;
if (value){
// console.log('a');
// console.log('alreadyDeleting');
// console.log(alreadyDeleting ? 'TR' : 'FA');
if (!alreadyDeleting){
setIsDeletingValue(isDeleting.concat([elementName]))
}
}
else{
if (alreadyDeleting){
setIsDeletingValue(isDeleting.filter(q => q != elementName))
}
}
};
const Save = () =>{
const model = {
animeTitleId: titleId,
preview: preview == null ? null : {
newType: preview.type,
// newUrl: preview.objectId,
newUrl: preview.url,
newFile: preview.data
} as CreateMediaInfoModel,
names: names.map(q => {
return {
languageId: q.language.id,
value: q.value,
type: q.type,
} as CreateNameModel
}),
descriptions: descriptions.map(q => {
return {
languageId: q.language.id,
isOriginal: q.isOriginal,
value: q.value,
} as CreateDescriptionModel
}),
// relatedContent: relatedContent.map(q => {
// return {
// type: q.type,
// contentType: q.contentType,
// url: q.url,
// } as CreateMediaInfoModel
// }),
relatedContent: [],
genres: genres.map(q => {
return {
genreId: q.genre.id,
proportion: q.proportion,
} as CreateGenreProportionModel
}),
announcementDate: announcementDate,
estimatedReleaseDate: estimatedReleaseDate,
releaseDate: releaseDate,
} as AnimeSeasonCreateModel;
AddSeason(model)
.then(() => navigate(`/admin/library/anime/${titleId}/edit`))
// .then(() => navigate(`/admin/library/anime/${titleId}/season/${seasonId}/edit`))
.catch((err) => { console.error(err);});
};
useEffect(() =>{
if (titleId == null || titleId == ''){
setTitleNames(null);
}
else{
GetAnimeTitle(titleId ?? '', client)
.then((data) =>{
if (data == null){
setTitleNames(null);
}
else{
// const name = GetTitleNames(names, user?.languageId)?.titleElement;
setTitleNames(data.commonProperties.names);
}
// setDataLoadingError(null);
})
.catch((error) => {
setTitleNames(null);
console.log(error);
// setDataLoadingError(error);
});
}
}, [ titleId ]);
return (
<>
title id: { id }
</>
<NameBreadcrumbsComponent titleId={titleId} titleNames={titleNames} returnToEdit={true}
userLanguageId={user?.languageId} />
номер сезона
вариант сезона
<div className='row overflow-x-hidden overflow-y-visible'>
<div className='col-4'>
<MediaInfoEditComponent
mediaInfo={preview}
classes={'card-img-top rounded-3 border border-5 border-secondary'}
isEditing={isEditing.find(q => q == 'preview') != null}
setEditing={(_, value) => setEditing('preview', value)}
// editMediaInfo={(mediaInfo, newUrl, newFile) =>{
editMediaInfo={(_, newUrl, newFile) => {
// console.log(`new url: ${newUrl}`)
// SetPreview(mediaInfo == null ? null :
setPreview((newUrl == null && newFile == null) ? null :
{
// type: mediaInfo?.type ?? MediaInfoType.Image,
type: MediaInfoType.Image,
url: newUrl,
data: newFile,
objectId: null,
// isNew: false,
} as MediaInfoEditModel);
return Promise.resolve('');
}}
isDeleting={isDeleting.find(q => q == 'preview') != null}
setDeleting={(_, value) => setDeleting('preview', value)}
deleteMediaInfo={() => {
setPreview(null);
return Promise.resolve('');
}}
dataLoadingError={null}
forceRefresh={Plug}
/>
<div className='card p-0 mt-2'>
<div className='card-body p-0'>
<div className='table-responsive'>
{/* <table className="table m-0 table-bordered"> */}
<table className="table m-0">
{/* <thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead> */}
<tbody>
<tr>
{/* <th className='text-nowrap'>Дата анонса</th>
<td className='w-100 text-center'>{data.commonProperties.announcementDate?.toString() ?? '—//—'}</td> */}
<th>Дата анонса</th>
<td className='text-end'>
<DateEditComponent
placeholder={'Дата анонса'}
required={true}
isEditing={isEditing.find(q => q == 'announcementDate') != null}
enabled={true}
date={GetDate(announcementDate)}
editDate={(value: Date | null) => {
SetAnnouncementDate(value);
return Promise.resolve();
}}
setEditing={(value: boolean) => setEditing('announcementDate', value)}
// setDeleting: (genreId: string, value: boolean) => void,
dataLoadingError={null}
forceRefresh={Plug}
/>
{/* {props.animeTitle.commonProperties.announcementDate?.toString() ?? '—//—'} */}
</td>
</tr>
<tr>
{/* <th className='text-nowrap'>Предполагаемая дата выхода</th>
<td className='w-100 text-center'>{data.commonProperties.estimatedReleaseDate?.toString() ?? '—//—'}</td> */}
<th>Предполагаемая дата выхода</th>
<td className='text-end'>
<DateEditComponent
placeholder={'Предполагаемая дата выхода'}
required={true}
isEditing={isEditing.find(q => q == 'estimatedReleaseDate') != null}
enabled={true}
date={estimatedReleaseDate != null ? new Date(estimatedReleaseDate) : null}
editDate={(value: Date | null) => {
SetEstimatedReleaseDate(value);
return Promise.resolve();
}}
setEditing={(value: boolean) => setEditing('estimatedReleaseDate', value)}
// setDeleting: (genreId: string, value: boolean) => void,
dataLoadingError={null}
forceRefresh={Plug}
/>
{/* {props.animeTitle.commonProperties.estimatedReleaseDate?.toString() ?? '—//—'} */}
</td>
</tr>
<tr>
{/* <th className='text-nowrap'>Предполагаемая дата выхода</th>
<td className='w-100 text-center'>{data.commonProperties.estimatedReleaseDate?.toString() ?? '—//—'}</td> */}
<th>Дата выхода</th>
<td className='text-end'>
<DateEditComponent
placeholder={'Дата выхода'}
required={true}
isEditing={isEditing.find(q => q == 'releaseDate') != null}
enabled={true}
date={releaseDate != null ? new Date(releaseDate) : null}
editDate={(value: Date | null) => {
SetReleaseDate(value);
return Promise.resolve();
}}
setEditing={(value: boolean) => setEditing('releaseDate', value)}
// setDeleting: (genreId: string, value: boolean) => void,
dataLoadingError={null}
forceRefresh={Plug}
/>
{/* {props.animeTitle.commonProperties.estimatedReleaseDate?.toString() ?? '—//—'} */}
</td>
</tr>
{/*<tr>*/}
{/* <th>Продолжительность</th>*/}
{/* <td className='text-end'>*/}
{/* <TimespanComponent*/}
{/* title="Продолжительность"*/}
{/* value={TimespanFromTicks(addEpisodeDuration)}*/}
{/* onChange={(ts) => setAddEpisodeDuration(TimespanToTicks(ts))}*/}
{/* />*/}
{/* </td>*/}
{/*</tr>*/}
</tbody>
</table>
</div>
</div>
</div>
</div>
<div className='col p-0 pe-2'>
<NamesEditComponent
names={names}
createName={(name) => {
const error = AddName({
language: name.language,
value: name.value,
type: name.type
} as NameItem);
return error.length == 0 ? Promise.resolve('') : Promise.reject({message: error} as Error);
}}
editName={(name, newValue, newLanguage) => {
EditName({
language: name.language,
value: name.value,
type: name.type
} as NameItem, newValue, newLanguage);
return Promise.resolve('');
}}
deleteName={(name) => {
DeleteName({
language: name.language,
value: name.value,
type: name.type
} as NameItem);
return Promise.resolve('');
}}
dataLoadingError={null}
forceRefresh={Plug}
/>
{/* <DescriptionViewComponent descriptions={props.animeTitle.commonProperties.descriptions} userLanguageId={props.userLanguageId} /> */}
<DescriptionsEditComponent
descriptions={descriptions}
createDescription={(description) => {
const error = AddDescription({
language: description.language,
value: description.value,
isOriginal: description.isOriginal
} as Description);
return error.length == 0 ? Promise.resolve('') : Promise.reject({message: error} as Error);
}}
editDescription={(description, newValue, newLanguage) => {
EditDescription({
language: description.language,
value: description.value,
isOriginal: description.isOriginal
} as Description, newValue, newLanguage);
return Promise.resolve('');
}}
deleteDescription={(description) => {
DeleteDescription({
language: description.language,
value: description.value,
isOriginal: description.isOriginal
} as Description);
return Promise.resolve('');
}}
dataLoadingError={null}
forceRefresh={Plug}
/>
<div className='card p-0'>
<div className='card-header'>
<h3 className='card-heading'>Жанры</h3>
</div>
<div className='card-body'>
<GenreProportionEditComponent
genresProportions={genres}
createGenreProportionPercentage={(genreProportionItem) => {
const error = AddGenre(genreProportionItem);
return error.length == 0 ? Promise.resolve('') : Promise.reject({message: error} as Error);
}}
editGenreProportionPercentage={(genreProportionItem, proportionPercentage) => {
EditGenre(genreProportionItem, proportionPercentage);
return Promise.resolve('');
}}
deleteGenreProportionPercentage={(genreProportionItem) => {
DeleteGenre(genreProportionItem);
return Promise.resolve('');
}}
dataLoadingError={null}
forceRefresh={Plug}
/>
</div>
</div>
</div>
</div>
{/* <div className='bg-success'>
<div>Содержимое</div>
<div>сезоны</div>
<div>эпизоды</div>
</div> */}
<hr/>
<div className='row g-2 justify-content-end'>
<div className="col">
<div className='btn btn-primary w-100' onClick={Save}>Save <TfiSave/></div>
</div>
</div>
</>
);
}
function Plug() {
}

View File

@ -57,8 +57,6 @@ export default function AnimeTitleEdit() {
const fetchData = () => {
GetAnimeTitle(id ?? '', client)
.then((data) =>{
console.log('data');
console.log(data);
setData(data ?? null);
setDataLoadingError(null);
})