Use new content groups instead of previous/next
This commit is contained in:
parent
461bd08a3d
commit
2e62f25fb5
|
@ -28,7 +28,7 @@ interface Props {
|
|||
topChips?: string[];
|
||||
bottomChips?: string[];
|
||||
keepInfoVisible?: boolean;
|
||||
stackEffect?: boolean;
|
||||
stackNumber?: number;
|
||||
metadata?: {
|
||||
currencies?: AppStaticProps["currencies"];
|
||||
release_date?: DatePickerFragment | null;
|
||||
|
@ -53,7 +53,7 @@ export function PreviewCard(props: Immutable<Props>): JSX.Element {
|
|||
title,
|
||||
subtitle,
|
||||
description,
|
||||
stackEffect = false,
|
||||
stackNumber = 0,
|
||||
topChips,
|
||||
bottomChips,
|
||||
keepInfoVisible,
|
||||
|
@ -117,20 +117,27 @@ export function PreviewCard(props: Immutable<Props>): JSX.Element {
|
|||
hover:[--play-opacity:100] transition-transform
|
||||
[--stacked-top:0] hover:[--stacked-top:1]"
|
||||
>
|
||||
{thumbnail && stackEffect && (
|
||||
{thumbnail && stackNumber > 0 && (
|
||||
<>
|
||||
<Img
|
||||
className={`rounded-t-md absolute -top-[var(--stacked-top)*1.3rem]
|
||||
opacity-30 scale-[0.88] transition-[top]`}
|
||||
image={thumbnail}
|
||||
quality={ImageQuality.Medium}
|
||||
/>
|
||||
<Img
|
||||
className={`rounded-t-md absolute -top-[var(--stacked-top)*0.6rem]
|
||||
opacity-60 scale-95 transition-[top]`}
|
||||
className="opacity-30 rounded-t-md overflow-hidden absolute transition-[top_transform]
|
||||
-top-[var(--stacked-top)*1.5rem]
|
||||
scale-[calc(1-0.15*var(--stacked-top))]"
|
||||
image={thumbnail}
|
||||
quality={ImageQuality.Medium}
|
||||
/>
|
||||
|
||||
<div
|
||||
className="bg-light rounded-t-md overflow-hidden absolute transition-[top_transform]
|
||||
-top-[var(--stacked-top)*0.7rem]
|
||||
scale-[calc(1-0.06*var(--stacked-top))]"
|
||||
>
|
||||
<Img
|
||||
className="opacity-70"
|
||||
image={thumbnail}
|
||||
quality={ImageQuality.Medium}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
|
@ -145,6 +152,14 @@ export function PreviewCard(props: Immutable<Props>): JSX.Element {
|
|||
image={thumbnail}
|
||||
quality={ImageQuality.Medium}
|
||||
/>
|
||||
{stackNumber > 0 && (
|
||||
<div
|
||||
className="absolute right-2 top-2 text-light bg-black
|
||||
bg-opacity-60 px-2 rounded-full"
|
||||
>
|
||||
{stackNumber}
|
||||
</div>
|
||||
)}
|
||||
{hoverlay && hoverlay.__typename === "Video" && (
|
||||
<>
|
||||
<div
|
||||
|
|
|
@ -1,75 +1,64 @@
|
|||
query devGetContents {
|
||||
contents(pagination: { limit: -1 }) {
|
||||
data {
|
||||
id
|
||||
attributes {
|
||||
slug
|
||||
categories {
|
||||
data {
|
||||
id
|
||||
}
|
||||
}
|
||||
type {
|
||||
data {
|
||||
id
|
||||
}
|
||||
}
|
||||
contents(pagination: { limit: -1 }) {
|
||||
data {
|
||||
id
|
||||
attributes {
|
||||
slug
|
||||
categories {
|
||||
data {
|
||||
id
|
||||
}
|
||||
}
|
||||
type {
|
||||
data {
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
ranged_contents {
|
||||
data {
|
||||
id
|
||||
}
|
||||
}
|
||||
translations {
|
||||
language {
|
||||
data {
|
||||
id
|
||||
}
|
||||
}
|
||||
title
|
||||
description
|
||||
text_set {
|
||||
source_language {
|
||||
data {
|
||||
id
|
||||
}
|
||||
}
|
||||
status
|
||||
transcribers {
|
||||
data {
|
||||
id
|
||||
}
|
||||
}
|
||||
translators {
|
||||
data {
|
||||
id
|
||||
}
|
||||
}
|
||||
proofreaders {
|
||||
data {
|
||||
id
|
||||
}
|
||||
}
|
||||
text
|
||||
}
|
||||
}
|
||||
|
||||
thumbnail {
|
||||
data {
|
||||
id
|
||||
}
|
||||
}
|
||||
next_recommended {
|
||||
data {
|
||||
id
|
||||
}
|
||||
}
|
||||
previous_recommended {
|
||||
data {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ranged_contents {
|
||||
data {
|
||||
id
|
||||
}
|
||||
}
|
||||
translations {
|
||||
language {
|
||||
data {
|
||||
id
|
||||
}
|
||||
}
|
||||
title
|
||||
description
|
||||
text_set {
|
||||
source_language {
|
||||
data {
|
||||
id
|
||||
}
|
||||
}
|
||||
status
|
||||
transcribers {
|
||||
data {
|
||||
id
|
||||
}
|
||||
}
|
||||
translators {
|
||||
data {
|
||||
id
|
||||
}
|
||||
}
|
||||
proofreaders {
|
||||
data {
|
||||
id
|
||||
}
|
||||
}
|
||||
text
|
||||
}
|
||||
}
|
||||
thumbnail {
|
||||
data {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,192 +1,161 @@
|
|||
query getContentText($slug: String, $language_code: String) {
|
||||
contents(filters: { slug: { eq: $slug } }) {
|
||||
data {
|
||||
id
|
||||
attributes {
|
||||
slug
|
||||
contents(filters: { slug: { eq: $slug } }) {
|
||||
data {
|
||||
id
|
||||
attributes {
|
||||
slug
|
||||
|
||||
categories {
|
||||
data {
|
||||
id
|
||||
attributes {
|
||||
name
|
||||
short
|
||||
}
|
||||
}
|
||||
}
|
||||
type {
|
||||
data {
|
||||
attributes {
|
||||
slug
|
||||
titles(filters: { language: { code: { eq: $language_code } } }) {
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ranged_contents {
|
||||
data {
|
||||
id
|
||||
attributes {
|
||||
slug
|
||||
scan_set {
|
||||
id
|
||||
}
|
||||
library_item {
|
||||
data {
|
||||
attributes {
|
||||
slug
|
||||
title
|
||||
subtitle
|
||||
thumbnail {
|
||||
data {
|
||||
attributes {
|
||||
...uploadImage
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
translations {
|
||||
language {
|
||||
data {
|
||||
attributes {
|
||||
code
|
||||
}
|
||||
}
|
||||
}
|
||||
pre_title
|
||||
title
|
||||
subtitle
|
||||
description
|
||||
text_set {
|
||||
status
|
||||
text
|
||||
source_language {
|
||||
data {
|
||||
attributes {
|
||||
code
|
||||
}
|
||||
}
|
||||
}
|
||||
transcribers {
|
||||
data {
|
||||
id
|
||||
attributes {
|
||||
...recorderChip
|
||||
}
|
||||
}
|
||||
}
|
||||
translators {
|
||||
data {
|
||||
id
|
||||
attributes {
|
||||
...recorderChip
|
||||
}
|
||||
}
|
||||
}
|
||||
proofreaders {
|
||||
data {
|
||||
id
|
||||
attributes {
|
||||
...recorderChip
|
||||
}
|
||||
}
|
||||
}
|
||||
notes
|
||||
}
|
||||
}
|
||||
categories {
|
||||
data {
|
||||
id
|
||||
attributes {
|
||||
name
|
||||
short
|
||||
}
|
||||
}
|
||||
}
|
||||
type {
|
||||
data {
|
||||
attributes {
|
||||
slug
|
||||
titles(filters: { language: { code: { eq: $language_code } } }) {
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ranged_contents {
|
||||
data {
|
||||
id
|
||||
attributes {
|
||||
slug
|
||||
scan_set {
|
||||
id
|
||||
}
|
||||
library_item {
|
||||
data {
|
||||
attributes {
|
||||
slug
|
||||
title
|
||||
subtitle
|
||||
thumbnail {
|
||||
data {
|
||||
attributes {
|
||||
...uploadImage
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
translations {
|
||||
language {
|
||||
data {
|
||||
attributes {
|
||||
code
|
||||
}
|
||||
}
|
||||
}
|
||||
pre_title
|
||||
title
|
||||
subtitle
|
||||
description
|
||||
text_set {
|
||||
status
|
||||
text
|
||||
source_language {
|
||||
data {
|
||||
attributes {
|
||||
code
|
||||
}
|
||||
}
|
||||
}
|
||||
transcribers {
|
||||
data {
|
||||
id
|
||||
attributes {
|
||||
...recorderChip
|
||||
}
|
||||
}
|
||||
}
|
||||
translators {
|
||||
data {
|
||||
id
|
||||
attributes {
|
||||
...recorderChip
|
||||
}
|
||||
}
|
||||
}
|
||||
proofreaders {
|
||||
data {
|
||||
id
|
||||
attributes {
|
||||
...recorderChip
|
||||
}
|
||||
}
|
||||
}
|
||||
notes
|
||||
}
|
||||
}
|
||||
|
||||
thumbnail {
|
||||
data {
|
||||
attributes {
|
||||
...uploadImage
|
||||
}
|
||||
}
|
||||
}
|
||||
previous_recommended {
|
||||
data {
|
||||
attributes {
|
||||
slug
|
||||
translations {
|
||||
pre_title
|
||||
title
|
||||
subtitle
|
||||
}
|
||||
categories {
|
||||
data {
|
||||
id
|
||||
attributes {
|
||||
short
|
||||
}
|
||||
}
|
||||
}
|
||||
type {
|
||||
data {
|
||||
attributes {
|
||||
slug
|
||||
titles(
|
||||
filters: { language: { code: { eq: $language_code } } }
|
||||
) {
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
thumbnail {
|
||||
data {
|
||||
attributes {
|
||||
...uploadImage
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
next_recommended {
|
||||
data {
|
||||
attributes {
|
||||
slug
|
||||
translations {
|
||||
pre_title
|
||||
title
|
||||
subtitle
|
||||
}
|
||||
categories {
|
||||
data {
|
||||
id
|
||||
attributes {
|
||||
short
|
||||
}
|
||||
}
|
||||
}
|
||||
type {
|
||||
data {
|
||||
attributes {
|
||||
slug
|
||||
titles(
|
||||
filters: { language: { code: { eq: $language_code } } }
|
||||
) {
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
thumbnail {
|
||||
data {
|
||||
attributes {
|
||||
...uploadImage
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
thumbnail {
|
||||
data {
|
||||
attributes {
|
||||
...uploadImage
|
||||
}
|
||||
}
|
||||
}
|
||||
group {
|
||||
data {
|
||||
attributes {
|
||||
contents {
|
||||
data {
|
||||
attributes {
|
||||
slug
|
||||
translations {
|
||||
pre_title
|
||||
title
|
||||
subtitle
|
||||
}
|
||||
categories {
|
||||
data {
|
||||
id
|
||||
attributes {
|
||||
short
|
||||
}
|
||||
}
|
||||
}
|
||||
type {
|
||||
data {
|
||||
attributes {
|
||||
slug
|
||||
titles(
|
||||
filters: {
|
||||
language: { code: { eq: $language_code } }
|
||||
}
|
||||
) {
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
thumbnail {
|
||||
data {
|
||||
attributes {
|
||||
...uploadImage
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,13 +5,6 @@ query getContents($language_code: String) {
|
|||
attributes {
|
||||
slug
|
||||
translations {
|
||||
language {
|
||||
data {
|
||||
attributes {
|
||||
code
|
||||
}
|
||||
}
|
||||
}
|
||||
pre_title
|
||||
title
|
||||
subtitle
|
||||
|
@ -62,14 +55,16 @@ query getContents($language_code: String) {
|
|||
}
|
||||
}
|
||||
}
|
||||
next_recommended {
|
||||
group {
|
||||
data {
|
||||
id
|
||||
}
|
||||
}
|
||||
previous_recommended {
|
||||
data {
|
||||
id
|
||||
attributes {
|
||||
combine
|
||||
contents {
|
||||
data {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
thumbnail {
|
||||
|
|
|
@ -34,6 +34,48 @@ interface Props extends AppStaticProps {
|
|||
content: ContentWithTranslations;
|
||||
}
|
||||
|
||||
function getPreviousContent(
|
||||
group: Immutable<
|
||||
NonNullable<
|
||||
NonNullable<
|
||||
NonNullable<
|
||||
NonNullable<ContentWithTranslations["group"]>["data"]
|
||||
>["attributes"]
|
||||
>["contents"]
|
||||
>["data"]
|
||||
>,
|
||||
currentSlug: string
|
||||
) {
|
||||
for (let index = 0; index < group.length; index += 1) {
|
||||
const content = group[index];
|
||||
if (content.attributes?.slug === currentSlug && index > 0) {
|
||||
return group[index - 1];
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getNextContent(
|
||||
group: Immutable<
|
||||
NonNullable<
|
||||
NonNullable<
|
||||
NonNullable<
|
||||
NonNullable<ContentWithTranslations["group"]>["data"]
|
||||
>["attributes"]
|
||||
>["contents"]
|
||||
>["data"]
|
||||
>,
|
||||
currentSlug: string
|
||||
) {
|
||||
for (let index = 0; index < group.length; index += 1) {
|
||||
const content = group[index];
|
||||
if (content.attributes?.slug === currentSlug && index < group.length - 1) {
|
||||
return group[index + 1];
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export default function Content(props: Immutable<Props>): JSX.Element {
|
||||
const { langui, content, languages } = props;
|
||||
const isMobile = useMediaMobile();
|
||||
|
@ -44,6 +86,17 @@ export default function Content(props: Immutable<Props>): JSX.Element {
|
|||
languageExtractor: (item) => item.language?.data?.attributes?.code,
|
||||
});
|
||||
|
||||
const previousContent = content.group?.data?.attributes?.contents
|
||||
? getPreviousContent(
|
||||
content.group.data.attributes.contents.data,
|
||||
content.slug
|
||||
)
|
||||
: undefined;
|
||||
|
||||
const nextContent = content.group?.data?.attributes?.contents
|
||||
? getNextContent(content.group.data.attributes.contents.data, content.slug)
|
||||
: undefined;
|
||||
|
||||
const subPanel = (
|
||||
<SubPanel>
|
||||
<ReturnButton
|
||||
|
@ -210,42 +263,37 @@ export default function Content(props: Immutable<Props>): JSX.Element {
|
|||
languageSwitcher={<LanguageSwitcher />}
|
||||
/>
|
||||
|
||||
{content.previous_recommended?.data?.attributes && (
|
||||
{previousContent?.attributes && (
|
||||
<div className="mt-12 mb-8 w-full">
|
||||
<h2 className="text-center text-2xl mb-4">Previous content</h2>
|
||||
<PreviewLine
|
||||
href={`/contents/${content.previous_recommended.data.attributes.slug}`}
|
||||
href={`/contents/${previousContent.attributes.slug}`}
|
||||
pre_title={
|
||||
content.previous_recommended.data.attributes.translations?.[0]
|
||||
?.pre_title
|
||||
previousContent.attributes.translations?.[0]?.pre_title
|
||||
}
|
||||
title={
|
||||
content.previous_recommended.data.attributes.translations?.[0]
|
||||
?.title ??
|
||||
prettySlug(content.previous_recommended.data.attributes.slug)
|
||||
previousContent.attributes.translations?.[0]?.title ??
|
||||
prettySlug(previousContent.attributes.slug)
|
||||
}
|
||||
subtitle={
|
||||
content.previous_recommended.data.attributes.translations?.[0]
|
||||
?.subtitle
|
||||
previousContent.attributes.translations?.[0]?.subtitle
|
||||
}
|
||||
thumbnail={
|
||||
content.previous_recommended.data.attributes.thumbnail?.data
|
||||
?.attributes
|
||||
previousContent.attributes.thumbnail?.data?.attributes
|
||||
}
|
||||
thumbnailAspectRatio="3/2"
|
||||
topChips={
|
||||
isMobile
|
||||
? undefined
|
||||
: content.previous_recommended.data.attributes.type?.data
|
||||
?.attributes
|
||||
: previousContent.attributes.type?.data?.attributes
|
||||
? [
|
||||
content.previous_recommended.data.attributes.type.data
|
||||
.attributes.titles?.[0]
|
||||
? content.previous_recommended.data.attributes.type
|
||||
.data.attributes.titles[0]?.title
|
||||
previousContent.attributes.type.data.attributes
|
||||
.titles?.[0]
|
||||
? previousContent.attributes.type.data.attributes
|
||||
.titles[0]?.title
|
||||
: prettySlug(
|
||||
content.previous_recommended.data.attributes.type
|
||||
.data.attributes.slug
|
||||
previousContent.attributes.type.data.attributes
|
||||
.slug
|
||||
),
|
||||
]
|
||||
: undefined
|
||||
|
@ -253,7 +301,7 @@ export default function Content(props: Immutable<Props>): JSX.Element {
|
|||
bottomChips={
|
||||
isMobile
|
||||
? undefined
|
||||
: content.previous_recommended.data.attributes.categories?.data.map(
|
||||
: previousContent.attributes.categories?.data.map(
|
||||
(category) => category.attributes?.short ?? ""
|
||||
)
|
||||
}
|
||||
|
@ -265,43 +313,30 @@ export default function Content(props: Immutable<Props>): JSX.Element {
|
|||
|
||||
<Markdawn text={selectedTranslation?.text_set?.text ?? ""} />
|
||||
|
||||
{content.next_recommended?.data?.attributes && (
|
||||
{nextContent?.attributes && (
|
||||
<>
|
||||
<HorizontalLine />
|
||||
<h2 className="text-center text-2xl mb-4">Follow-up content</h2>
|
||||
<PreviewLine
|
||||
href={`/contents/${content.next_recommended.data.attributes.slug}`}
|
||||
pre_title={
|
||||
content.next_recommended.data.attributes.translations?.[0]
|
||||
?.pre_title
|
||||
}
|
||||
href={`/contents/${nextContent.attributes.slug}`}
|
||||
pre_title={nextContent.attributes.translations?.[0]?.pre_title}
|
||||
title={
|
||||
content.next_recommended.data.attributes.translations?.[0]
|
||||
?.title ??
|
||||
prettySlug(content.next_recommended.data.attributes.slug)
|
||||
}
|
||||
subtitle={
|
||||
content.next_recommended.data.attributes.translations?.[0]
|
||||
?.subtitle
|
||||
}
|
||||
thumbnail={
|
||||
content.next_recommended.data.attributes.thumbnail?.data
|
||||
?.attributes
|
||||
nextContent.attributes.translations?.[0]?.title ??
|
||||
prettySlug(nextContent.attributes.slug)
|
||||
}
|
||||
subtitle={nextContent.attributes.translations?.[0]?.subtitle}
|
||||
thumbnail={nextContent.attributes.thumbnail?.data?.attributes}
|
||||
thumbnailAspectRatio="3/2"
|
||||
topChips={
|
||||
isMobile
|
||||
? undefined
|
||||
: content.next_recommended.data.attributes.type?.data
|
||||
?.attributes
|
||||
: nextContent.attributes.type?.data?.attributes
|
||||
? [
|
||||
content.next_recommended.data.attributes.type.data
|
||||
.attributes.titles?.[0]
|
||||
? content.next_recommended.data.attributes.type.data
|
||||
.attributes.titles[0]?.title
|
||||
nextContent.attributes.type.data.attributes.titles?.[0]
|
||||
? nextContent.attributes.type.data.attributes
|
||||
.titles[0]?.title
|
||||
: prettySlug(
|
||||
content.next_recommended.data.attributes.type.data
|
||||
.attributes.slug
|
||||
nextContent.attributes.type.data.attributes.slug
|
||||
),
|
||||
]
|
||||
: undefined
|
||||
|
@ -309,7 +344,7 @@ export default function Content(props: Immutable<Props>): JSX.Element {
|
|||
bottomChips={
|
||||
isMobile
|
||||
? undefined
|
||||
: content.next_recommended.data.attributes.categories?.data.map(
|
||||
: nextContent.attributes.categories?.data.map(
|
||||
(category) => category.attributes?.short ?? ""
|
||||
)
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ import { GetStaticPropsContext } from "next";
|
|||
import { useEffect, useState } from "react";
|
||||
|
||||
interface Props extends AppStaticProps {
|
||||
contents: Exclude<GetContentsQuery["contents"], null | undefined>["data"];
|
||||
contents: NonNullable<GetContentsQuery["contents"]>["data"];
|
||||
}
|
||||
|
||||
type GroupContentItems = Map<string, Immutable<Props["contents"]>>;
|
||||
|
@ -119,11 +119,12 @@ export default function Contents(props: Immutable<Props>): JSX.Element {
|
|||
subtitle={item.attributes.translations?.[0]?.subtitle}
|
||||
thumbnail={item.attributes.thumbnail?.data?.attributes}
|
||||
thumbnailAspectRatio="3/2"
|
||||
stackEffect={
|
||||
item.attributes.next_recommended?.data?.id !== null &&
|
||||
item.attributes.next_recommended?.data?.id !==
|
||||
undefined &&
|
||||
combineRelatedContent
|
||||
stackNumber={
|
||||
combineRelatedContent &&
|
||||
item.attributes.group?.data?.attributes?.combine
|
||||
? item.attributes.group?.data?.attributes.contents
|
||||
?.data.length
|
||||
: 0
|
||||
}
|
||||
topChips={
|
||||
item.attributes.type?.data?.attributes
|
||||
|
@ -263,7 +264,11 @@ function filterContents(
|
|||
): Immutable<Props["contents"]> {
|
||||
if (combineRelatedContent) {
|
||||
return [...contents].filter(
|
||||
(content) => !content.attributes?.previous_recommended?.data?.id
|
||||
(content) =>
|
||||
!content.attributes?.group?.data?.attributes ||
|
||||
!content.attributes.group.data.attributes.combine ||
|
||||
content.attributes.group.data.attributes.contents?.data?.[0].id ===
|
||||
content.id
|
||||
);
|
||||
}
|
||||
return contents;
|
||||
|
|
Loading…
Reference in New Issue