OrganizedContent requires only the current section's Content

This commit is contained in:
Aditya Thakral 2021-08-22 01:23:24 -04:00
parent d6adf8e526
commit f350403ed1
2 changed files with 53 additions and 29 deletions

View File

@ -13,7 +13,6 @@ type Link = ComponentType<LinkProps>;
interface Section { interface Section {
id: string; id: string;
title: string; title: string;
Content: ComponentType;
} }
const READ_ALL_TITLE = "Read All"; const READ_ALL_TITLE = "Read All";
@ -21,16 +20,23 @@ export const READ_ALL_ID = "read-all";
interface Props { interface Props {
sections: Section[]; sections: Section[];
currentId: string; id: string;
children: ReactNode;
link: Link; link: Link;
} }
export function OrganizedContent(props: Props) { export function OrganizedContent({
const sections = createSections(props.sections); sections,
const currentIndex = sections.findIndex(({ id }) => id === props.currentId); id,
children,
link: Link,
}: Props) {
const currentIndex = sections.findIndex(
({ id: sectionId }) => sectionId === id
);
if (currentIndex < 0) { if (currentIndex < 0) {
throw new Error(`Section with ID ${props.currentId} was not found`); throw new Error(`Section with ID ${id} was not found`);
} }
const section = sections[currentIndex]; const section = sections[currentIndex];
@ -38,20 +44,20 @@ export function OrganizedContent(props: Props) {
return ( return (
<div className={styles.wrapper}> <div className={styles.wrapper}>
<Nav sections={sections} currentIndex={currentIndex} link={props.link} /> <Nav sections={sections} currentIndex={currentIndex} link={Link} />
<div className={styles.content}> <div className={styles.content}>
{isReadAll ? ( {isReadAll ? (
<section.Content /> children
) : ( ) : (
<> <>
<div> <div>
<h1>{section.title}</h1> <h1>{section.title}</h1>
<section.Content /> {children}
</div> </div>
<Footer <Footer
sections={sections} sections={sections}
currentIndex={currentIndex} currentIndex={currentIndex}
link={props.link} link={Link}
/> />
</> </>
)} )}
@ -136,26 +142,32 @@ function Footer({ sections, currentIndex, link: Link }: FooterProps) {
); );
} }
function createSections(sections: Section[]) { export interface SectionWithContent {
return [ section: Section;
{ Content: ComponentType;
}
export function createReadAllSection(
sections: SectionWithContent[]
): SectionWithContent {
return {
section: {
id: READ_ALL_ID, id: READ_ALL_ID,
title: READ_ALL_TITLE, title: READ_ALL_TITLE,
Content() {
return (
<>
{sections.map(({ id, title, Content: SectionContent }) => (
<div key={id}>
<h1>{title}</h1>
<SectionContent />
</div>
))}
</>
);
},
}, },
...sections, Content: function ReadAllContent() {
]; return (
<>
{sections.map(({ section: { id, title }, Content }) => (
<div key={id}>
<h1>{title}</h1>
<Content />
</div>
))}
</>
);
},
};
} }
function Arrow({ direction }: { direction: "left" | "right" }) { function Arrow({ direction }: { direction: "left" | "right" }) {

View File

@ -45,7 +45,11 @@ import { Link } from "./Link";
import { MiniEventCard } from "./MiniEventCard"; import { MiniEventCard } from "./MiniEventCard";
import { MiniTechTalkCard } from "./MiniTechTalkCard"; import { MiniTechTalkCard } from "./MiniTechTalkCard";
import { NewsCard } from "./NewsCard"; import { NewsCard } from "./NewsCard";
import { OrganizedContent, LinkProps } from "./OrganizedContent"; import {
OrganizedContent,
LinkProps,
createReadAllSection,
} from "./OrganizedContent";
import { TeamMember } from "./TeamMember"; import { TeamMember } from "./TeamMember";
import { TeamMemberCard } from "./TeamMemberCard"; import { TeamMemberCard } from "./TeamMemberCard";
import { TechTalkCard } from "./TechTalkCard"; import { TechTalkCard } from "./TechTalkCard";
@ -217,8 +221,16 @@ export function OrganizedContentDemo() {
); );
} }
const Content =
sections.find(({ id: sectionId }) => sectionId === id)?.Content ??
createReadAllSection(
sections.map((section) => ({ section, Content: section.Content }))
).Content;
return ( return (
<OrganizedContent sections={sections} currentId={id} link={FakeLink} /> <OrganizedContent sections={sections} id={id} link={FakeLink}>
<Content />
</OrganizedContent>
); );
} }