From 73a5c7fae9ffbe9ada721148c8c454a643aceebe Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Sun, 20 Feb 2022 16:11:50 +0100 Subject: chore!: restructure repo I separated public files from the config/dev files. It improves repo readability. I also moved dotenv helper to public/inc directory and extract the Matomo tracker in the same directory. --- .../components/MemePreview/Headline/Headline.js | 120 +++++++++++++++++++++ .../src/components/MemePreview/MemePreview.js | 61 +++++++++++ 2 files changed, 181 insertions(+) create mode 100644 public/projects/react-small-apps/apps/meme-generator/src/components/MemePreview/Headline/Headline.js create mode 100644 public/projects/react-small-apps/apps/meme-generator/src/components/MemePreview/MemePreview.js (limited to 'public/projects/react-small-apps/apps/meme-generator/src/components/MemePreview') diff --git a/public/projects/react-small-apps/apps/meme-generator/src/components/MemePreview/Headline/Headline.js b/public/projects/react-small-apps/apps/meme-generator/src/components/MemePreview/Headline/Headline.js new file mode 100644 index 0000000..e7ed579 --- /dev/null +++ b/public/projects/react-small-apps/apps/meme-generator/src/components/MemePreview/Headline/Headline.js @@ -0,0 +1,120 @@ +import { useEffect, useRef, useState } from "react"; +import Form from "../../commons/Form"; +import Input from "../../commons/Input"; + +function Headline({ id, text, fontSize, xPos, yPos, setHeadlines }) { + const inputRef = useRef(null); + const [isEditing, setIsEditing] = useState(false); + useEffect(() => { + isEditing && inputRef.current.focus(); + }); + + const [inputValue, setInputValue] = useState(text); + useEffect(() => { + setInputValue(text); + }, [text]); + + const getXPos = () => { + let styles = {}; + switch (xPos) { + case "Left": + styles = { gridColumn: 1, textAlign: "left" }; + break; + case "Right": + styles = { gridColumn: 2, textAlign: "right" }; + break; + case "Center": + styles = { + gridColumnStart: 1, + gridColumnEnd: "span 2", + justifySelf: "center", + textAlign: "center", + }; + break; + default: + break; + } + return styles; + }; + + const getYPos = () => { + let styles = {}; + switch (yPos) { + case "Top": + styles = { gridRow: 1 }; + break; + case "Bottom": + styles = { gridRow: 3, alignSelf: "end" }; + break; + case "Middle": + styles = { gridRow: 2, alignSelf: "center" }; + break; + default: + break; + } + return styles; + }; + + const styles = { + fontSize: fontSize, + ...getYPos(), + ...getXPos(), + }; + + const onSubmit = (e) => { + e.preventDefault(); + setIsEditing(false); + }; + + const updateText = (e) => { + setInputValue(e.target.value); + }; + + useEffect(() => { + setHeadlines((previous) => { + return previous.map((headline) => { + if (headline.id !== id) return headline; + return { ...headline, text: inputValue }; + }); + }); + }, [setHeadlines, id, inputValue]); + + useEffect(() => { + setHeadlines((previous) => { + return previous.map((headline) => { + if (headline.id !== id) return headline; + return { ...headline, text: inputValue }; + }); + }); + }, [setHeadlines, id, inputValue]); + + const onBlur = () => { + setIsEditing(false); + }; + + return ( + <> + {isEditing ? ( +
+ +
+ ) : ( +

setIsEditing(true)} + style={styles} + > + {inputValue} +

+ )} + + ); +} + +export default Headline; diff --git a/public/projects/react-small-apps/apps/meme-generator/src/components/MemePreview/MemePreview.js b/public/projects/react-small-apps/apps/meme-generator/src/components/MemePreview/MemePreview.js new file mode 100644 index 0000000..6577e53 --- /dev/null +++ b/public/projects/react-small-apps/apps/meme-generator/src/components/MemePreview/MemePreview.js @@ -0,0 +1,61 @@ +import { useEffect, useState } from "react"; +import Button from "../commons/Button"; +import Headline from "./Headline/Headline"; + +async function fetchMemes() { + const response = await fetch("https://api.imgflip.com/get_memes"); + const result = await response.json(); + return await result; +} + +function MemePreview({ headlines, setHeadlines }) { + const [memesList, setMemesList] = useState([]); + const [isFetched, setIsFetched] = useState(false); + useEffect(() => { + fetchMemes().then((object) => setMemesList(object.data.memes)); + setIsFetched(true); + return () => setIsFetched(false); + }, [setIsFetched]); + + const [selectedMeme, setSelectedMeme] = useState({}); + useEffect(() => { + setSelectedMeme(memesList[5]); + }, [memesList]); + + const getRandomMeme = () => { + const randomIndex = Math.floor(Math.random() * memesList.length); + setSelectedMeme(memesList[randomIndex]); + }; + + const headlinesList = headlines.map((headline) => ( + + )); + + return ( +
+
+ {isFetched && selectedMeme ? ( + {selectedMeme.name} + ) : ( + "Loading..." + )} + {headlinesList} +
+
+ ); +} + +export default MemePreview; -- cgit v1.2.3