From a52cb1fe5424ac91406784885b7ebcebcde1e51e Mon Sep 17 00:00:00 2001 From: DrMint <29893320+DrMint@users.noreply.github.com> Date: Wed, 3 May 2023 03:49:14 +0200 Subject: [PATCH] Use react-collapsible for chronicles --- package-lock.json | 16 ++++++ package.json | 1 + src/components/Chronicles/ChroniclesList.tsx | 46 ++++++++++------ src/components/Chronicles/ChroniclesLists.tsx | 53 +++++++++++++++++++ src/pages/chronicles/[slug]/index.tsx | 42 +++++---------- src/pages/chronicles/index.tsx | 23 ++------ 6 files changed, 116 insertions(+), 65 deletions(-) create mode 100644 src/components/Chronicles/ChroniclesLists.tsx diff --git a/package-lock.json b/package-lock.json index 062eb52..4c7280c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,6 +28,7 @@ "patch-package": "^7.0.0", "rc-slider": "^10.1.1", "react": "^18.2.0", + "react-collapsible": "^2.10.0", "react-dom": "18.2.0", "react-hotkeys-hook": "^3.4.7", "react-swipeable": "^7.0.0", @@ -9214,6 +9215,15 @@ "node": ">=0.10.0" } }, + "node_modules/react-collapsible": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/react-collapsible/-/react-collapsible-2.10.0.tgz", + "integrity": "sha512-kEVsmlFfXBMTCnU5gwIv19MdmPAhbIPzz5Er37TiJSzRKS0IHrqAKQyQeHEmtoGIQMTcVI46FzE4z3NlVTx77A==", + "peerDependencies": { + "react": "~15 || ~16 || ~17 || ~18", + "react-dom": "~15 || ~16 || ~17 || ~18" + } + }, "node_modules/react-dom": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", @@ -17699,6 +17709,12 @@ "loose-envify": "^1.1.0" } }, + "react-collapsible": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/react-collapsible/-/react-collapsible-2.10.0.tgz", + "integrity": "sha512-kEVsmlFfXBMTCnU5gwIv19MdmPAhbIPzz5Er37TiJSzRKS0IHrqAKQyQeHEmtoGIQMTcVI46FzE4z3NlVTx77A==", + "requires": {} + }, "react-dom": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", diff --git a/package.json b/package.json index 44c3894..298a851 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "patch-package": "^7.0.0", "rc-slider": "^10.1.1", "react": "^18.2.0", + "react-collapsible": "^2.10.0", "react-dom": "18.2.0", "react-hotkeys-hook": "^3.4.7", "react-swipeable": "^7.0.0", diff --git a/src/components/Chronicles/ChroniclesList.tsx b/src/components/Chronicles/ChroniclesList.tsx index 5105ed4..3485127 100644 --- a/src/components/Chronicles/ChroniclesList.tsx +++ b/src/components/Chronicles/ChroniclesList.tsx @@ -1,15 +1,15 @@ import { useCallback } from "react"; -import { useBoolean } from "usehooks-ts"; +import Collapsible from "react-collapsible"; import { TranslatedChroniclePreview } from "./ChroniclePreview"; import { GetChroniclesChaptersQuery } from "graphql/generated"; import { filterHasAttributes } from "helpers/asserts"; import { prettyInlineTitle, prettySlug, sJoin } from "helpers/formatters"; -import { Ico } from "components/Ico"; import { compareDate } from "helpers/date"; import { TranslatedProps } from "types/TranslatedProps"; import { useSmartLanguage } from "hooks/useSmartLanguage"; import { useAtomSetter } from "helpers/atoms"; import { atoms } from "contexts/atoms"; +import { Button } from "components/Inputs/Button"; /* * ╭─────────────╮ @@ -24,27 +24,41 @@ interface Props { >["data"]; currentSlug?: string; title: string; + open?: boolean; + onTriggerClosing?: () => void; + onOpening?: () => void; } // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ -const ChroniclesList = ({ chronicles, currentSlug, title }: Props): JSX.Element => { +const ChroniclesList = ({ + chronicles, + currentSlug, + title, + open, + onTriggerClosing, + onOpening, +}: Props): JSX.Element => { const setSubPanelOpened = useAtomSetter(atoms.layout.subPanelOpened); - const { value: isOpen, toggle: toggleOpen } = useBoolean( - chronicles.some((chronicle) => chronicle.attributes?.slug === currentSlug) - ); return (
-
-
- -

{title}

-
-
-
+ +

{title}

+
+ }> {filterHasAttributes(chronicles, ["attributes.contents", "attributes.translations"]) .sort((a, b) => compareDate(a.attributes.date_start, b.attributes.date_start)) .map((chronicle) => ( @@ -104,7 +118,7 @@ const ChroniclesList = ({ chronicles, currentSlug, title }: Props): JSX.Element )}
))} - + ); }; diff --git a/src/components/Chronicles/ChroniclesLists.tsx b/src/components/Chronicles/ChroniclesLists.tsx new file mode 100644 index 0000000..e469c1d --- /dev/null +++ b/src/components/Chronicles/ChroniclesLists.tsx @@ -0,0 +1,53 @@ +import { useState } from "react"; +import { GetChroniclesChaptersQuery } from "graphql/generated"; +import { filterHasAttributes } from "helpers/asserts"; +import { TranslatedChroniclesList } from "components/Chronicles/ChroniclesList"; +import { prettySlug } from "helpers/formatters"; + +/* + * ╭─────────────╮ + * ───────────────────────────────────────╯ COMPONENT ╰─────────────────────────────────────────── + */ + +interface Props { + chapters: NonNullable["data"]; + currentChronicleSlug?: string; +} + +// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ + +export const ChroniclesLists = ({ chapters, currentChronicleSlug }: Props): JSX.Element => { + const [openedIndex, setOpenedIndex] = useState( + currentChronicleSlug + ? chapters.findIndex((chapter) => + chapter.attributes?.chronicles?.data.some( + (chronicle) => chronicle.attributes?.slug === currentChronicleSlug + ) + ) + : -1 + ); + + return ( +
+ {filterHasAttributes(chapters, ["attributes.chronicles", "id"]).map( + (chapter, chapterIndex) => ( + setOpenedIndex(chapterIndex)} + onTriggerClosing={() => setOpenedIndex(-1)} + key={chapter.id} + chronicles={chapter.attributes.chronicles.data} + translations={filterHasAttributes(chapter.attributes.titles, [ + "language.data.attributes.code", + ]).map((translation) => ({ + title: translation.title, + language: translation.language.data.attributes.code, + }))} + fallback={{ title: prettySlug(chapter.attributes.slug) }} + /> + ) + )} +
+ ); +}; diff --git a/src/pages/chronicles/[slug]/index.tsx b/src/pages/chronicles/[slug]/index.tsx index c433972..7bee657 100644 --- a/src/pages/chronicles/[slug]/index.tsx +++ b/src/pages/chronicles/[slug]/index.tsx @@ -22,6 +22,7 @@ import { Ids } from "types/ids"; import { useFormat } from "hooks/useFormat"; import { getFormat } from "helpers/i18n"; import { ElementsSeparator } from "helpers/component"; +import { ChroniclesLists } from "components/Chronicles/ChroniclesLists"; /* * ╭────────╮ @@ -65,6 +66,18 @@ const Chronicle = ({ chronicle, chapters, ...otherProps }: Props): JSX.Element = ), }); + const subPanel = ( + + + + + + ); + const contentPanel = ( ); - const subPanel = ( - - - - - -
- {filterHasAttributes(chapters, ["attributes.chronicles", "id"]).map((chapter) => ( - ({ - title: translation.title, - language: translation.language.data.attributes.code, - }))} - fallback={{ title: prettySlug(chapter.attributes.slug) }} - currentSlug={chronicle.slug} - /> - ))} -
-
- ); - return ( { const { format } = useFormat(); + const subPanel = ( { title={format("chronicles")} description={format("chronicles_description")} /> - - -
- {filterHasAttributes(chapters, ["attributes.chronicles", "id"]).map((chapter) => ( - ({ - title: translation.title, - language: translation.language.data.attributes.code, - }))} - fallback={{ title: prettySlug(chapter.attributes.slug) }} - /> - ))} -
+
);