Skip to content

Commit

Permalink
Update Series Overview to New Design. (#674)
Browse files Browse the repository at this point in the history
* Update Series Overview to New Design.

* Remove unused links code.
  • Loading branch information
ElementalCrisis authored Nov 11, 2023
1 parent bab4aff commit dfcfa85
Show file tree
Hide file tree
Showing 6 changed files with 272 additions and 329 deletions.
2 changes: 1 addition & 1 deletion src/components/Collection/Series/EpisodeDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ function EpisodeDetails({ episode }: { episode: EpisodeType }) {
 Votes)
</div>

<div className="line-clamp-3 flex">
<div className="line-clamp-3">
{episode.AniDB?.Description !== '' ? episode.AniDB?.Description : 'Episode description not available.'}
</div>
</div>
Expand Down
146 changes: 146 additions & 0 deletions src/components/Collection/SeriesInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import React, { useMemo } from 'react';
import { useParams } from 'react-router';
import { Link } from 'react-router-dom';

import { useGetSeriesQuery } from '@/core/rtkQuery/splitV3Api/seriesApi';
import { useGetSeriesOverviewQuery } from '@/core/rtkQuery/splitV3Api/webuiApi';
import { dayjs, formatThousand } from '@/core/util';

import type { SeriesDetailsType } from '@/core/types/api/series';
import type { WebuiSeriesDetailsType } from '@/core/types/api/webui';

const SeriesInfo = () => {
const { seriesId } = useParams();

// Series Data;
const seriesOverviewData = useGetSeriesOverviewQuery({ SeriesID: seriesId! }, { skip: !seriesId });
const overview = useMemo(() => seriesOverviewData?.data || {} as WebuiSeriesDetailsType, [seriesOverviewData]);
const seriesData = useGetSeriesQuery({ seriesId: seriesId!, includeDataFrom: ['AniDB'] }, { skip: !seriesId });
const series = useMemo(() => seriesData?.data ?? {} as SeriesDetailsType, [seriesData]);

const startDate = useMemo(() => dayjs(series.AniDB?.AirDate), [series]);
const endDate = useMemo(() => (series.AniDB?.EndDate !== null ? dayjs(series.AniDB?.EndDate) : null), [series]);
const airDate = () => {
if (endDate) {
if (startDate.format('MMM DD, YYYY') === endDate.format('MMM DD, YYYY')) {
return startDate.format('MMM DD, YYYY');
}
return `${startDate.format('MMM DD, YYYY')} - ${endDate.format('MMM DD, YYYY')}`;
}
return `${startDate.format('MMM DD, YYYY')} - Ongoing`;
};

return (
<div className="flex w-full max-w-[31.25rem] flex-col gap-y-8">
<div className="flex w-full flex-row justify-around gap-y-4 rounded-md border border-panel-border bg-panel-background-transparent p-8">
<div className="flex flex-col items-center">
<div className="font-semibold ">File Count</div>
<div className="flex flex-row gap-x-1">
<span>EP:</span>
<span>{formatThousand(series.Sizes.Local.Episodes)}</span>
{series.Sizes.Local.Specials !== 0 && (
<>
<span>|</span>
<span>SP:</span>
<span>{formatThousand(series.Sizes.Local.Specials)}</span>
</>
)}
</div>
</div>
<div className="flex flex-col items-center">
<div className="font-semibold ">Watched</div>
<div className="flex flex-row gap-x-1">
<span>EP:</span>
<span>{formatThousand(series.Sizes.Watched.Episodes)}</span>
{(series.Sizes.Total.Specials !== 0 && series.Sizes.Local.Specials !== 0) && (
<>
<span>|</span>
<span>SP:</span>
<span>{formatThousand(series.Sizes.Watched.Specials)}</span>
</>
)}
</div>
</div>

{(series.Sizes.Total.Episodes - series.Sizes.Local.Episodes !== 0
|| series.Sizes.Total.Specials - series.Sizes.Local.Specials !== 0) && (
<div className="flex flex-col items-center">
<div className="font-semibold ">Missing</div>
<div className="flex flex-row gap-x-1">
{series.Sizes.Total.Episodes - series.Sizes.Local.Episodes !== 0 && (
<>
<span>EP:</span>
<span>{formatThousand(series.Sizes.Total.Episodes - series.Sizes.Local.Episodes)}</span>
</>
)}
{series.Sizes.Total.Episodes - series.Sizes.Local.Episodes !== 0
&& series.Sizes.Total.Specials - series.Sizes.Local.Specials !== 0
&& <span>|</span>}
{series.Sizes.Total.Specials - series.Sizes.Local.Specials !== 0 && (
<>
<span>SP:</span>
<span>{formatThousand(series.Sizes.Total.Specials - series.Sizes.Local.Specials)}</span>
</>
)}
</div>
</div>
)}
</div>
<div className="flex w-full flex-col gap-y-3 rounded-md border border-panel-border bg-panel-background-transparent p-8">
<div className="flex justify-between capitalize">
<div className="font-semibold">Type</div>
{series.AniDB?.Type}
</div>
<div className="flex justify-between capitalize">
<div className="font-semibold">Source</div>
{overview.SourceMaterial}
</div>
<div className="flex justify-between capitalize">
<div className="font-semibold">Air Date</div>
<div>
{airDate()}
</div>
</div>
<div className="flex justify-between capitalize">
<div className="font-semibold">Status</div>
{/* TODO: Check if there are more status types */}
{(series.AniDB?.EndDate && dayjs(series.AniDB.EndDate).isAfter(dayjs())) ? 'Ongoing' : 'Finished'}
</div>
<div className="flex justify-between capitalize">
<div className="font-semibold">Episodes</div>
<div>
{series.Sizes.Total.Episodes}
&nbsp;Episodes
<span className="mx-1">|</span>
{series.Sizes.Total.Specials}
&nbsp;Specials
</div>
</div>
<div className="flex justify-between capitalize">
<div className="font-semibold">Length</div>
{/* TODO: Get episode length */}
<div>-- Minutes/Episode</div>
</div>
<div className="flex justify-between capitalize">
<div className="font-semibold">Season</div>
{overview?.FirstAirSeason
? (
<Link
className="font-semibold text-panel-text-primary"
to={`/webui/collection/filter/${overview.FirstAirSeason.IDs.ID}`}
>
{overview.FirstAirSeason.Name}
</Link>
)
: '--'}
</div>
<div className="flex justify-between capitalize">
<div className="font-semibold">Studio</div>
<div>{overview?.Studios?.[0] ? overview?.Studios?.[0].Name : 'Studio Not Listed'}</div>
</div>
</div>
</div>
);
};

export default SeriesInfo;
69 changes: 69 additions & 0 deletions src/components/Collection/SeriesMetadata.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React, { useMemo } from 'react';
import { mdiCloseCircleOutline, mdiOpenInNew, mdiPencilCircleOutline, mdiPlusCircleOutline } from '@mdi/js';
import { Icon } from '@mdi/react';

import Button from '@/components/Input/Button';

const MetadataLink = ({ id, site }: { site: string, id: number | number[] }) => {
const linkId = Array.isArray(id) ? id[0] : id;

const siteLink = useMemo(() => {
switch (site) {
case 'AniDB':
return `https://anidb.net/anime/${linkId}`;
case 'TMDB':
return `https://www.themoviedb.org/movie/${linkId}`;
case 'TvDB':
// TODO: Figure how to get trakt series link using ID
return '#';
case 'TraktTv':
// TODO: Figure how to get trakt series link using ID
return '#';
default:
return '#';
}
}, [linkId, site]);

return (
<div key={site} className="flex justify-between">
<div className="flex gap-x-4">
<div className={`metadata-link-icon ${site}`} />
{linkId
? (
<a
href={siteLink}
className="flex gap-x-2 font-semibold text-panel-text-primary"
rel="noopener noreferrer"
target="_blank"
>
{site}
<Icon className="text-panel-icon-action" path={mdiOpenInNew} size={1} />
</a>
)
: 'Series Not Linked'}
</div>
{site !== 'AniDB' && (
<div className="flex gap-x-2">
{linkId
? (
<>
<Button disabled>
<Icon className="text-panel-icon-action" path={mdiPencilCircleOutline} size={1} />
</Button>
<Button disabled>
<Icon className="text-panel-icon-danger" path={mdiCloseCircleOutline} size={1} />
</Button>
</>
)
: (
<Button disabled>
<Icon className="text-panel-icon-action" path={mdiPlusCircleOutline} size={1} />
</Button>
)}
</div>
)}
</div>
);
};

export default MetadataLink;
3 changes: 2 additions & 1 deletion src/css/common.css
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,8 @@ input:autofill {
background-position: center;
background-size: cover;

&.anidb {
/* stylelint-disable-next-line selector-class-pattern */
&.AniDB {
background-image: url('/images/community/24-AniDB.png');
}

Expand Down
Loading

0 comments on commit dfcfa85

Please sign in to comment.