From 38db7415f41126d4e3d660f9050d29eed6b0d39a Mon Sep 17 00:00:00 2001 From: lycuong99 Date: Fri, 15 Apr 2022 23:43:40 +0700 Subject: [PATCH] Complete --- pizzajoint/package-lock.json | 85 ++++++++++++++-------- pizzajoint/package.json | 2 +- pizzajoint/src/App.js | 42 ++++++----- pizzajoint/src/components/Base.js | 68 +++++++++++++++--- pizzajoint/src/components/Header.js | 48 ++++++++++--- pizzajoint/src/components/Home.js | 52 ++++++++++++-- pizzajoint/src/components/Loader.js | 42 +++++++++++ pizzajoint/src/components/Modal.js | 42 +++++++++++ pizzajoint/src/components/Order.js | 62 ++++++++++++++-- pizzajoint/src/components/Toppings.js | 57 ++++++++++++--- pizzajoint/src/index.css | 100 +++++++++++++++++++------- 11 files changed, 489 insertions(+), 111 deletions(-) create mode 100644 pizzajoint/src/components/Loader.js create mode 100644 pizzajoint/src/components/Modal.js diff --git a/pizzajoint/package-lock.json b/pizzajoint/package-lock.json index f816584..ae9915a 100644 --- a/pizzajoint/package-lock.json +++ b/pizzajoint/package-lock.json @@ -5753,9 +5753,9 @@ } }, "framer-motion": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-1.10.3.tgz", - "integrity": "sha512-VooCzGWg7brSO4Gc0YwpY5AadJe4OPS74ZyOlOHWll5rMXCoOc6Ia3uDQ6RfOJlwCP/D9TQuRGtboyJiVXjVcw==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-1.11.1.tgz", + "integrity": "sha512-CP6aYLPSivAWkq9UoSurefHBggxG85IT8ObYyWYkcZppgtjHzpwRzhaA8P0ljMGRqtcpeQAIybiGgPioBPlOSw==", "requires": { "@emotion/is-prop-valid": "^0.8.2", "@popmotion/easing": "^1.0.2", @@ -5769,12 +5769,11 @@ } }, "framesync": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/framesync/-/framesync-4.0.4.tgz", - "integrity": "sha512-mdP0WvVHe0/qA62KG2LFUAOiWLng5GLpscRlwzBxu2VXOp6B8hNs5C5XlFigsMgrfDrr2YbqTsgdWZTc4RXRMQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/framesync/-/framesync-4.1.0.tgz", + "integrity": "sha512-MmgZ4wCoeVxNbx2xp5hN/zPDCbLSKiDt4BbbslK7j/pM2lg5S0vhTNv1v8BCVb99JPIo6hXBFdwzU7Q4qcAaoQ==", "requires": { - "hey-listen": "^1.0.8", - "tslib": "^1.10.0" + "hey-listen": "^1.0.5" } }, "fresh": { @@ -7198,7 +7197,8 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true + "bundled": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -7380,11 +7380,13 @@ }, "minimist": { "version": "1.2.5", - "bundled": true + "bundled": true, + "optional": true }, "minipass": { "version": "2.9.0", "bundled": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -7401,6 +7403,7 @@ "mkdirp": { "version": "0.5.3", "bundled": true, + "optional": true, "requires": { "minimist": "^1.2.5" } @@ -7493,6 +7496,7 @@ "once": { "version": "1.4.0", "bundled": true, + "optional": true, "requires": { "wrappy": "1" } @@ -7561,7 +7565,8 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true + "bundled": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -7609,6 +7614,7 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -7647,11 +7653,13 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true + "bundled": true, + "optional": true }, "yallist": { "version": "3.1.1", - "bundled": true + "bundled": true, + "optional": true } } } @@ -12660,9 +12668,9 @@ } }, "style-value-types": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/style-value-types/-/style-value-types-3.1.7.tgz", - "integrity": "sha512-jPaG5HcAPs3vetSwOJozrBXxuHo9tjZVnbRyBjxqb00c2saIoeuBJc1/2MtvB8eRZy41u/BBDH0CpfzWixftKg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/style-value-types/-/style-value-types-3.2.0.tgz", + "integrity": "sha512-ih0mGsrYYmVvdDi++/66O6BaQPRPRMQHoZevNNdMMcPlP/cH28Rnfsqf1UEba/Bwfuw9T8BmIMwbGdzsPwQKrQ==", "requires": { "hey-listen": "^1.0.8", "tslib": "^1.10.0" @@ -13478,7 +13486,8 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true + "bundled": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -13515,7 +13524,8 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "concat-map": { "version": "0.0.1", @@ -13524,7 +13534,8 @@ }, "console-control-strings": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -13627,7 +13638,8 @@ }, "inherits": { "version": "2.0.4", - "bundled": true + "bundled": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -13637,6 +13649,7 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -13662,6 +13675,7 @@ "minipass": { "version": "2.9.0", "bundled": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -13678,6 +13692,7 @@ "mkdirp": { "version": "0.5.3", "bundled": true, + "optional": true, "requires": { "minimist": "^1.2.5" } @@ -13770,6 +13785,7 @@ "once": { "version": "1.4.0", "bundled": true, + "optional": true, "requires": { "wrappy": "1" } @@ -13838,7 +13854,8 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true + "bundled": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -13868,6 +13885,7 @@ "string-width": { "version": "1.0.2", "bundled": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -13885,6 +13903,7 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -13923,11 +13942,13 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true + "bundled": true, + "optional": true }, "yallist": { "version": "3.1.1", - "bundled": true + "bundled": true, + "optional": true } } }, @@ -14247,7 +14268,8 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true + "bundled": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -14429,11 +14451,13 @@ }, "minimist": { "version": "1.2.5", - "bundled": true + "bundled": true, + "optional": true }, "minipass": { "version": "2.9.0", "bundled": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -14450,6 +14474,7 @@ "mkdirp": { "version": "0.5.3", "bundled": true, + "optional": true, "requires": { "minimist": "^1.2.5" } @@ -14611,7 +14636,8 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true + "bundled": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -14659,6 +14685,7 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -14697,11 +14724,13 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true + "bundled": true, + "optional": true }, "yallist": { "version": "3.1.1", - "bundled": true + "bundled": true, + "optional": true } } }, diff --git a/pizzajoint/package.json b/pizzajoint/package.json index 4b5b17f..dc58912 100644 --- a/pizzajoint/package.json +++ b/pizzajoint/package.json @@ -6,7 +6,7 @@ "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.5.0", "@testing-library/user-event": "^7.2.1", - "framer-motion": "^1.10.3", + "framer-motion": "^1.11.1", "react": "^16.13.1", "react-dom": "^16.13.1", "react-router-dom": "^5.1.2", diff --git a/pizzajoint/src/App.js b/pizzajoint/src/App.js index 3ef35f0..e26a887 100644 --- a/pizzajoint/src/App.js +++ b/pizzajoint/src/App.js @@ -1,21 +1,24 @@ import React, { useState } from 'react'; -import { Route, Switch } from "react-router-dom"; +import { Route, Switch, useLocation } from "react-router-dom"; import Header from './components/Header'; import Home from './components/Home'; import Base from './components/Base'; import Toppings from './components/Toppings'; import Order from './components/Order'; +import { AnimatePresence } from 'framer-motion'; +import Modal from './components/Modal'; function App() { const [pizza, setPizza] = useState({ base: "", toppings: [] }); - + const [showModal, setShowModal] = useState(false); + const location = useLocation(); const addBase = (base) => { setPizza({ ...pizza, base }) } - + const addTopping = (topping) => { let newToppings; - if(!pizza.toppings.includes(topping)){ + if (!pizza.toppings.includes(topping)) { newToppings = [...pizza.toppings, topping]; } else { newToppings = pizza.toppings.filter(item => item !== topping); @@ -25,21 +28,24 @@ function App() { return ( <> +
- - - - - - - - - - - - - - + setShowModal(false)}> + + + + + + + + + + + + + + + ); } diff --git a/pizzajoint/src/components/Base.js b/pizzajoint/src/components/Base.js index 87a8273..d56f61a 100644 --- a/pizzajoint/src/components/Base.js +++ b/pizzajoint/src/components/Base.js @@ -1,33 +1,83 @@ import React from 'react'; import { Link } from 'react-router-dom'; - +import { motion } from 'framer-motion'; const Base = ({ addBase, pizza }) => { const bases = ['Classic', 'Thin & Crispy', 'Thick Crust']; + const containerVariants = { + hidden: { + opacity: 0, + x: '100vw' + }, + visible: { + opacity: 1, + x: 0, + transition: { + delay: 0.5, type: "spring" + } + }, + exit: { + x: '-100vw', + transition: { + ease: 'easeInOut' + } + } + }; + const nextVariants = { + hidden: { + x: '-100vw' + }, + visible: { + x: 0, + transition: { + stiffness: 120, type: "spring" + } + } + } + const buttonVariants = { + hover: { + scale: 1.1, + textShadow: '0px 0px 8px rgb(255,255,255)', + boxShadow: '0px 0px 8px rgb(255,255,255)', + transition: { + duration: 0.3, + yoyo: Infinity + } + } + } return ( -
+

Step 1: Choose Your Base

    {bases.map(base => { let spanClass = pizza.base === base ? 'active' : ''; return ( -
  • addBase(base)}> - { base } -
  • + addBase(base)} + whileHover={{ + scale: 1.3, color: '#f8e112', + originX: 0 + + }} + transition={{ + type: 'spring' + , stiffness: 300 + }}> + {base} + ) })}
{pizza.base && ( -
+ - + Next -
+
)} -
+ ) } diff --git a/pizzajoint/src/components/Header.js b/pizzajoint/src/components/Header.js index d968c69..8a7d86b 100644 --- a/pizzajoint/src/components/Header.js +++ b/pizzajoint/src/components/Header.js @@ -1,23 +1,55 @@ import React from 'react'; +import { motion } from 'framer-motion'; +const svgVariants = { + hidden: { + rotate: -180 + }, + visible: { + rotate: 0, + transition: { + duration: 1 + } + } +} + +const pathVariants = { + hidden: { + pathLength: 0, + opacity: 0, + }, + visible: { + pathLength: 1, + opacity: 1, + transition: { + duration: 2, + ease: 'easeInOut' + } + } +} const Header = () => { return (
-
- - + + - - -
-
+ + +

Pizza Joint

-
+
) } diff --git a/pizzajoint/src/components/Home.js b/pizzajoint/src/components/Home.js index 8b74cb6..49d50a7 100644 --- a/pizzajoint/src/components/Home.js +++ b/pizzajoint/src/components/Home.js @@ -1,18 +1,56 @@ import React from 'react'; import { Link } from 'react-router-dom'; - +import { motion } from 'framer-motion'; +import Loader from './Loader'; const Home = () => { + const buttonVariants = { + hover: { + scale: 1.1, + textShadow: '0px 0px 8px rgb(255,255,255)', + boxShadow: '0px 0px 8px rgb(255,255,255)', + transition: { + duration: 0.3, + yoyo: Infinity + } + } + } + + const containerVariants = { + hidden: { + opacity: 0 + }, + visible: { + opacity: 1, + transition: { + delay: 1, duration: 1 + } + }, + exit: { + x: '-100vw', + transition: { + ease: 'easeInOut' + } + } + } return ( -
-

+ + + Welcome to Pizza Joint -

+ - + -
+ + ) } diff --git a/pizzajoint/src/components/Loader.js b/pizzajoint/src/components/Loader.js new file mode 100644 index 0000000..ed4ec76 --- /dev/null +++ b/pizzajoint/src/components/Loader.js @@ -0,0 +1,42 @@ +import { motion, useCycle } from 'framer-motion'; +import React from 'react'; + +const loaderVariants = { + animationOne: { + x: [-20, 20], + y: [0, -30], + transition: { + x: { + yoyo: Infinity, + duration: 0.5 + }, + y: { + yoyo: Infinity, + duration: 0.25, + ease: 'easeOut' + } + } + }, + animationTwo: { + x: [0, 0], + y: [0, -40], + transition: { + + y: { + yoyo: Infinity, + duration: 0.25, + ease: 'easeOut' + } + } + } +} + +const Loader = () => { + const [animation, cycleAnimation] = useCycle('animationOne', 'animationTwo'); + + return <> + + +
cycleAnimation()}>Cycle Loader
+} +export default Loader; \ No newline at end of file diff --git a/pizzajoint/src/components/Modal.js b/pizzajoint/src/components/Modal.js new file mode 100644 index 0000000..a85bdd8 --- /dev/null +++ b/pizzajoint/src/components/Modal.js @@ -0,0 +1,42 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import { AnimatePresence, motion } from 'framer-motion'; + +const backdrop = { + visible: { + opacity: 1 + }, + hidden: { + opacity: 0 + }, +} + +const modal = { + hidden: { + y: '-100vh', opacity: 0 + }, + visible: { + y: '200px', opacity: 1, + transition: { + delay: 0.5 + } + } +} +const Modal = ({ showModal, setShowModal }) => { + return ( + + { + showModal && ( + +

Do you want another pizza!

+ + + +
+
) + } + +
+ ); +} +export default Modal; \ No newline at end of file diff --git a/pizzajoint/src/components/Order.js b/pizzajoint/src/components/Order.js index 275824f..5e93af4 100644 --- a/pizzajoint/src/components/Order.js +++ b/pizzajoint/src/components/Order.js @@ -1,12 +1,60 @@ -import React from 'react'; +import React, { useEffect, useState } from 'react'; +import { motion } from 'framer-motion'; + +const containerVariants = { + hidden: { + opacity: 0, + x: '100vw' + }, + visible: { + opacity: 1, + x: 0, + transition: { + + type: "spring", + mass: 0.4, + damping: 8, + when: 'beforeChildren', + staggerChildren: 0.4 + } + }, + exit: { + x: '-100vw', + transition: { + ease: 'easeInOut' + } + } +}; + +const childVariants = { + hidden: { + opacity: 0, + + }, + visible: { + opacity: 1 + } +} +const Order = ({ pizza, setShowModal }) => { + + useEffect(() => { + setTimeout(() => { + setShowModal(true); + }, 5000) + }, [setShowModal]); + -const Order = ({ pizza }) => { return ( -
-

Thank you for your order :)

-

You ordered a {pizza.base} pizza with:

- {pizza.toppings.map(topping =>
{topping}
)} -
+ + +

Thank you for your order :)

+ + + You ordered a {pizza.base} pizza with: + + {pizza.toppings.map(topping =>
{topping}
)} +
+
) } diff --git a/pizzajoint/src/components/Toppings.js b/pizzajoint/src/components/Toppings.js index d962e9f..4355ebc 100644 --- a/pizzajoint/src/components/Toppings.js +++ b/pizzajoint/src/components/Toppings.js @@ -1,31 +1,72 @@ import React from 'react'; import { Link } from 'react-router-dom'; +import { motion } from 'framer-motion'; +const containerVariants = { + hidden: { + opacity: 0, + x: '100vw' + }, + visible: { + opacity: 1, + x: 0, + transition: { + delay: 0.5, type: "spring" + } + }, + exit: { + x: '-100vw', + transition: { + ease: 'easeInOut' + } + } +}; +const buttonVariants = { + hover: { + scale: 1.1, + textShadow: '0px 0px 8px rgb(255,255,255)', + boxShadow: '0px 0px 8px rgb(255,255,255)', + transition: { + duration: 0.3, + yoyo: Infinity + } + } +} const Toppings = ({ addTopping, pizza }) => { let toppings = ['mushrooms', 'peppers', 'onions', 'olives', 'extra cheese', 'tomatoes']; return ( -
- + +

Step 2: Choose Toppings

    {toppings.map(topping => { let spanClass = pizza.toppings.includes(topping) ? 'active' : ''; return ( -
  • addTopping(topping)}> - { topping } -
  • + addTopping(topping)} + + whileHover={{ + scale: 1.3, color: '#f8e112', + originX: 0 + + }} + transition={{ + type: 'spring' + , stiffness: 300 + }}> + {topping} + ) })}
- + -
+ ) } diff --git a/pizzajoint/src/index.css b/pizzajoint/src/index.css index f0d693b..8121074 100644 --- a/pizzajoint/src/index.css +++ b/pizzajoint/src/index.css @@ -1,28 +1,40 @@ /* fonts */ @font-face { - font-family: 'Quicksand'; - src: url('/Quicksand-Light.woff2') format('woff2'), - url('/Quicksand-Light.woff') format('woff'); + font-family: "Quicksand"; + src: url("/Quicksand-Light.woff2") format("woff2"), + url("/Quicksand-Light.woff") format("woff"); font-weight: 300; font-style: normal; } /* reset & common styles */ -body, ul, h1, h2, h3, p, button, a, div{ +body, +ul, +h1, +h2, +h3, +p, +button, +a, +div { margin: 0; padding: 0; color: white; - font-family: 'Quicksand'; + font-family: "Quicksand"; letter-spacing: 2px; list-style-type: none; text-decoration: none; } -body{ - background: rgb(100,0,123); - background: radial-gradient(circle, rgba(100,0,123,1) 0%, rgba(62,20,86,1) 100%); +body { + background: rgb(100, 0, 123); + background: radial-gradient( + circle, + rgba(100, 0, 123, 1) 0%, + rgba(62, 20, 86, 1) 100% + ); overflow: hidden; } -button{ +button { color: white; padding: 10px 30px; font-size: 1em; @@ -33,33 +45,33 @@ button{ cursor: pointer; opacity: 0.7; } -.container{ +.container { max-width: 300px; margin: 100px auto 40px; } -.container h3{ +.container h3 { padding-bottom: 10px; margin-bottom: 10px; - border-bottom: 1px solid rgba(255,255,255,0.2); + border-bottom: 1px solid rgba(255, 255, 255, 0.2); } -.container li{ +.container li { padding: 10px; cursor: pointer; } /* header */ -header{ +header { display: flex; padding: 40px; align-items: center; } -header .title{ +header .title { flex-grow: 1; margin-left: 20px; font-size: 0.6em; } -header h1{ - border-bottom: 1px solid rgba(255,255,255,0.2); +header h1 { + border-bottom: 1px solid rgba(255, 255, 255, 0.2); padding-bottom: 10px; } header .pizza-svg { @@ -72,11 +84,11 @@ header .pizza-svg { } /* lists */ -li span.active{ +li span.active { font-weight: bold; } -li span.active::before{ - content: '>'; +li span.active::before { + content: ">"; position: relative; top: -2px; margin-right: 6px; @@ -85,22 +97,60 @@ li span.active::before{ } /* pages */ -.home h2{ +.home h2 { font-size: 2em; margin-bottom: 30px; } -.home.container, -.order.container{ +.home.container, +.order.container { text-align: center; max-width: 800px; } -.home button{ +.home button { color: white; padding: 15px 30px; font-size: 1.6em; border: 3px solid white; margin: 30px 20px; } -.order p{ +.order p { margin: 20px auto; } + +.backdrop { + position: fixed; + top: 0; + left: 0; + height: 100vh; + width: 100vw; + background-color: rgba(0, 0, 0, 0.3); + z-index: 1; +} + +.modal { + max-width: 400px; + margin: 0 auto; + padding: 40px 20px; + background: white; + border-radius: 10px; + text-align: center; +} +.modal button { + color: #444; + border-color: #444; + font-weight: bold; + margin-top: 20px; +} +.modal p { + color: #444; + font-weight: bold; +} + +/* loader */ +.loader { + width: 10px; + height: 10px; + margin: 40px auto; + border-radius: 50%; + background: #fff; +}