-
Notifications
You must be signed in to change notification settings - Fork 3
Dacey/challenge #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,15 +1,40 @@ | ||
| import React from 'react'; | ||
| import React, { useEffect, useState } from "react"; | ||
|
|
||
| import { TextSection } from './TextSection'; | ||
| import { TextSection } from "./Components/TextSection"; | ||
| import Card from "./Components/Card"; | ||
|
|
||
| function App() { | ||
| return ( | ||
| <React.Fragment> | ||
| <TextSection id="welcome" /> | ||
| <TextSection id="blog_post" /> | ||
| <TextSection id="kitchen_sink" /> | ||
| </React.Fragment> | ||
| ); | ||
| const [slideToShow, setSlideToShow] = useState(1); | ||
|
|
||
| useEffect(() => { | ||
| setTimeout(() => { | ||
| if (slideToShow < 3) { | ||
| setSlideToShow(slideToShow + 1); | ||
| } else { | ||
| setSlideToShow(1); | ||
| } | ||
| }, 5000); | ||
| }, [slideToShow]); | ||
|
|
||
| return ( | ||
| <React.Fragment> | ||
| {slideToShow === 1 && ( | ||
| <Card> | ||
| <TextSection id="welcome" /> | ||
| </Card> | ||
| )} | ||
| {slideToShow === 2 && ( | ||
| <Card> | ||
| <TextSection id="blog_post" /> | ||
| </Card> | ||
| )} | ||
| {slideToShow === 3 && ( | ||
| <Card> | ||
| <TextSection id="kitchen_sink" /> | ||
| </Card> | ||
| )} | ||
| </React.Fragment> | ||
| ); | ||
| } | ||
|
|
||
| export default App; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| import React from "react"; | ||
| import styled from "@emotion/styled"; | ||
|
|
||
| const Container = styled.div` | ||
| margin-top: 60px; | ||
| display: flex; | ||
| flex-direction: column; | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Due to the allotted time, I was not able to experiment with emotion's annotation but wanted to show that I could use the library. |
||
| align-items: center; | ||
| `; | ||
|
|
||
| const Card = styled.div` | ||
| border-radius: 6px; | ||
| box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24); | ||
| transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); | ||
| width: 75%; | ||
| padding: 20px; | ||
| background-color: #ffffff; | ||
| `; | ||
|
|
||
| const Content = styled.div` | ||
| justify-content: center; | ||
| align-items: center; | ||
| padding: 20px; | ||
| `; | ||
|
|
||
| const Cards: React.FunctionComponent = (props) => { | ||
| return ( | ||
| <Container> | ||
| <Card> | ||
| <Content>{props.children}</Content> | ||
| </Card> | ||
| </Container> | ||
| ); | ||
| }; | ||
|
|
||
| export default Cards; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export { default } from "./Card"; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| import React from "react"; | ||
| import { NodeType } from "../../types"; | ||
|
|
||
| type Props = { | ||
| node: NodeType; | ||
| }; | ||
|
|
||
| const TAG_MAP = { | ||
| header1: "h1", | ||
| header2: "h2", | ||
| header3: "h3", | ||
| paragraph: "p", | ||
| hyperlink: "a", | ||
| numbered_list: "ol", | ||
| bullet_list: "ul", | ||
| list_item: "li", | ||
| text: React.Fragment, | ||
| bold: "strong", | ||
| italic: "em", | ||
| underline: "u", | ||
| break: "br", | ||
| image: "img", | ||
| video: "video", | ||
| }; | ||
|
|
||
| function Node({ node }: Props) { | ||
| const { attributes, nodes, type: nodeType, text } = node; | ||
| const NodeTag = TAG_MAP[nodeType]; | ||
|
|
||
| // Handle self-closing tags | ||
| if (NodeTag === "img" || NodeTag === "br") { | ||
| return <NodeTag {...attributes} />; | ||
| } | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am sure there is a better way to handle if the element is a self-closing tag. I tried different things and came up with conditionally rendering the self-closing tag. |
||
|
|
||
| return ( | ||
| <NodeTag {...attributes}> | ||
| {text} | ||
| {nodes?.map((node: NodeType, index: number) => { | ||
| return <Node node={node} key={index} />; | ||
| })} | ||
| </NodeTag> | ||
| ); | ||
| } | ||
|
|
||
| export default Node; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export { default } from "./Node"; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| import { default as Content } from "../../content.json"; | ||
| import { ErrorBoundary } from "./ErrorBoundary"; | ||
| import { NodeType } from "../../types"; | ||
| import Node from "../Node"; | ||
|
|
||
| interface Props { | ||
| id: string; | ||
| } | ||
|
|
||
| function Root(props: any) { | ||
| return props.nodes.map((node: NodeType, index: number) => { | ||
| return <Node node={node} key={index} />; | ||
| }); | ||
| } | ||
|
|
||
| export function TextSection({ id }: Props) { | ||
| const nodes: any = (Content as any)[id]; | ||
|
|
||
| return ( | ||
| <ErrorBoundary id={id}> | ||
| <Root id={id} nodes={nodes} /> | ||
| </ErrorBoundary> | ||
| ); | ||
| } |
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| export type BlockContentType = | ||
| | "header1" | ||
| | "header2" | ||
| | "header3" | ||
| | "paragraph" | ||
| | "hyperlink" | ||
| | "numbered_list" | ||
| | "bullet_list" | ||
| | "list_item"; | ||
|
|
||
| export type TextContentType = | ||
| | "bold" | ||
| | "italic" | ||
| | "underline" | ||
| | "break" | ||
| | "text"; | ||
|
|
||
| export type MediaContentType = "image" | "video"; | ||
|
|
||
| export type NodeType = { | ||
| type: BlockContentType | TextContentType | MediaContentType; | ||
| nodes: NodeType[]; | ||
| attributes?: { [key: string]: string }; | ||
| text?: string; | ||
| }; | ||
|
|
||
| // export type TextNodeType = { | ||
| // type: TextContentType; | ||
| // text: string; | ||
| // }; | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know there is a better way to be more explicit based on what attributes are required. Due to the allotted time, I decided to comment out these types, because I was not sure how to effectively use them. |
||
|
|
||
| // export type MediaNodeType = { | ||
| // type: MediaContentType; | ||
| // attributes: { [key: string]: string }; | ||
| // }; | ||
|
|
||
| // export type BlockNodeType = { | ||
| // type: BlockContentType; | ||
| // attributes?: { [key: string]: string }; | ||
| // nodes: (TextNodeType | MediaNodeType | BlockNodeType)[]; | ||
| // }; | ||
|
|
||
| // export type NodeType = TextNodeType | MediaNodeType | BlockNodeType; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Due to the allotted time, I was not able to experiment with emotion's annotation but I did include the library and added basic styling to show that I could use the library.