diff --git a/03_source/mobile/src/pages/DemoReactAddToCart/TestComponents/CurrentWeather/WeatherProperty.tsx b/03_source/mobile/src/pages/DemoReactAddToCart/TestComponents/CurrentWeather/WeatherProperty.tsx index 52949af..950c702 100644 --- a/03_source/mobile/src/pages/DemoReactAddToCart/TestComponents/CurrentWeather/WeatherProperty.tsx +++ b/03_source/mobile/src/pages/DemoReactAddToCart/TestComponents/CurrentWeather/WeatherProperty.tsx @@ -8,7 +8,7 @@ export const WeatherProperty = ({ type, currentWeather }: { type: any; currentWe const properties = { wind: { isIcon: false, - icon: '/assets/WeatherDemo/wind.png', + icon: '/assets/DemoReactAddToCart/WeatherDemo/wind.png', alt: 'wind', label: 'Wind', value: `${currentWeather.current.wind_mph}mph`, diff --git a/03_source/mobile/src/pages/DemoReactAddToCart/TestComponents/SkeletonDashboard/index.tsx b/03_source/mobile/src/pages/DemoReactAddToCart/TestComponents/SkeletonDashboard/index.tsx index 234fb9b..455cec6 100644 --- a/03_source/mobile/src/pages/DemoReactAddToCart/TestComponents/SkeletonDashboard/index.tsx +++ b/03_source/mobile/src/pages/DemoReactAddToCart/TestComponents/SkeletonDashboard/index.tsx @@ -51,7 +51,12 @@ export const SkeletonDashboard = () => ( - wind + wind diff --git a/03_source/mobile/src/pages/DemoReactAddToCart/components/AddToCartButton.module.css b/03_source/mobile/src/pages/DemoReactAddToCart/components/AddToCartButton.module.css new file mode 100644 index 0000000..3af5d30 --- /dev/null +++ b/03_source/mobile/src/pages/DemoReactAddToCart/components/AddToCartButton.module.css @@ -0,0 +1,14 @@ +.buttonContainer { + display: flex; + flex-direction: column; + justify-content: center; + align-content: center; + align-items: center; +} + +.button { + --padding-top: 1.75rem; + --padding-bottom: 1.75rem; + --padding-start: 1.75rem; + --padding-end: 1.75rem; +} diff --git a/03_source/mobile/src/pages/DemoReactAddToCart/components/AddToCartButton.tsx b/03_source/mobile/src/pages/DemoReactAddToCart/components/AddToCartButton.tsx new file mode 100644 index 0000000..82a1789 --- /dev/null +++ b/03_source/mobile/src/pages/DemoReactAddToCart/components/AddToCartButton.tsx @@ -0,0 +1,60 @@ +import { CreateAnimation, IonButton, IonIcon } from '@ionic/react'; +import React, { useRef, useState } from 'react'; + +import styles from './AddToCartButton.module.css'; +import { cartOutline } from 'ionicons/icons'; + +const AddToCartButton = ({ + icon = true, + color = 'primary', + customOnClick = null, +}): React.JSX.Element => { + const iconRef = useRef(null); + const [hidden, setHidden] = useState(true); + + const floatStyle = { + display: hidden ? 'none' : '', + position: 'absolute', + }; + + const floatGrowAnimation = { + property: 'transform', + fromValue: 'translateY(0) scale(1)', + toValue: 'translateY(-55px) scale(1.2)', + }; + + const colorAnimation = { + property: 'color', + fromValue: 'white', + toValue: `var(--ion-color-${color}`, + }; + + const mainAnimation = { + duration: 700, + iterations: '1', + fromTo: [floatGrowAnimation, colorAnimation], + easing: 'cubic-bezier(0.25, 0.7, 0.25, 0.7)', + }; + + const handleClick = async () => { + setHidden(false); + await iconRef.current.animation.play(); + setHidden(true); + customOnClick && customOnClick(); + }; + + return ( +
+ + {!icon && 'Add to cart'} + {icon && } + + + + + +
+ ); +}; + +export default AddToCartButton; diff --git a/03_source/mobile/src/pages/DemoReactAddToCart/components/Product.module.css b/03_source/mobile/src/pages/DemoReactAddToCart/components/Product.module.css new file mode 100644 index 0000000..fa0f815 --- /dev/null +++ b/03_source/mobile/src/pages/DemoReactAddToCart/components/Product.module.css @@ -0,0 +1,19 @@ +.priceContainer { + + display: flex; + flex-direction: row; + align-content: center; + justify-content: space-between; + align-items: center; +} + +.price { + + margin-top: 0.7rem; + border: 1px solid var(--ion-color-primary); + color: var(--ion-color-primary); + width: fit-content; + padding: 1rem; + border-radius: 10px; + font-weight: 600; +} \ No newline at end of file diff --git a/03_source/mobile/src/pages/DemoReactAddToCart/components/Product.tsx b/03_source/mobile/src/pages/DemoReactAddToCart/components/Product.tsx new file mode 100644 index 0000000..272efcb --- /dev/null +++ b/03_source/mobile/src/pages/DemoReactAddToCart/components/Product.tsx @@ -0,0 +1,61 @@ +import { + IonCard, + IonCardContent, + IonCardHeader, + IonCardSubtitle, + IonCardTitle, + IonCol, + IonGrid, + IonRow, + IonText, +} from '@ionic/react'; +import AddToCartButton from './AddToCartButton'; + +import styles from './Product.module.css'; + +const Product = ({ product }): React.JSX.Element => { + const handleAdd = (product) => { + console.log(`Product added: ${product.name}`); + console.log({ product }); + + // Do something + // Update Main Cart + // Global State Stuff + // API Call + // etc etc + }; + + return ( + + + {product.name} + {product.description} + + + + + + product + + + + + Product Features + {product.features.map((feature, index) => { + return

{feature}

; + })} +
+
+
+ + +
{product.price}
+ handleAdd(product)} /> +
+
+
+
+ ); +}; + +export default Product; diff --git a/03_source/mobile/src/pages/DemoReactAddToCart/index.tsx b/03_source/mobile/src/pages/DemoReactAddToCart/index.tsx index a84db3f..c0009af 100644 --- a/03_source/mobile/src/pages/DemoReactAddToCart/index.tsx +++ b/03_source/mobile/src/pages/DemoReactAddToCart/index.tsx @@ -1,38 +1,29 @@ -import { IonIcon, IonLabel, IonRouterOutlet, IonTabBar, IonTabButton, IonTabs } from '@ionic/react'; +import { IonRouterOutlet, IonTabs } from '@ionic/react'; -import { cloudOutline, searchOutline } from 'ionicons/icons'; import { Route, Redirect } from 'react-router'; -import Tab1 from './AppPages/Tab1'; -import Tab2 from './AppPages/Tab2'; - -import './style.scss'; +import './theme/variables.scss'; +import Home from './pages/Home'; function DemoReactAddToCart() { return ( - + + {/* + */} - + + + + + - - {/* */} - - - - Dashboard - - - - Search - - ); } diff --git a/03_source/mobile/src/pages/DemoReactAddToCart/module.d.ts b/03_source/mobile/src/pages/DemoReactAddToCart/module.d.ts new file mode 100644 index 0000000..d774364 --- /dev/null +++ b/03_source/mobile/src/pages/DemoReactAddToCart/module.d.ts @@ -0,0 +1,4 @@ +declare module '*.module.css' { + const classes: { readonly [key: string]: string }; + export default classes; +} diff --git a/03_source/mobile/src/pages/DemoReactAddToCart/pages/Home.css b/03_source/mobile/src/pages/DemoReactAddToCart/pages/Home.css new file mode 100644 index 0000000..2877bc5 --- /dev/null +++ b/03_source/mobile/src/pages/DemoReactAddToCart/pages/Home.css @@ -0,0 +1,19 @@ +.price-container { + + display: flex; + flex-direction: row; + align-content: center; + justify-content: space-between; + align-items: center; +} + +.price { + + margin-top: 0.7rem; + border: 1px solid var(--ion-color-primary); + color: var(--ion-color-primary); + width: fit-content; + padding: 1rem; + border-radius: 10px; + font-weight: 600; +} \ No newline at end of file diff --git a/03_source/mobile/src/pages/DemoReactAddToCart/pages/Home.tsx b/03_source/mobile/src/pages/DemoReactAddToCart/pages/Home.tsx new file mode 100644 index 0000000..50ee6ee --- /dev/null +++ b/03_source/mobile/src/pages/DemoReactAddToCart/pages/Home.tsx @@ -0,0 +1,45 @@ +import { + IonButton, + IonButtons, + IonContent, + IonHeader, + IonIcon, + IonPage, + IonTitle, + IonToolbar, + useIonRouter, +} from '@ionic/react'; +import './Home.css'; +import Product from '../components/Product'; +import { products } from './products'; +import React from 'react'; +import { chevronBackOutline } from 'ionicons/icons'; + +const Home = (): React.JSX.Element => { + const router = useIonRouter(); + function handleBackClick() { + router.goBack(); + } + return ( + + + + Add To Cart Animation + + + handleBackClick()}> + + + + + + + {products.map((product) => { + return ; + })} + + + ); +}; + +export default Home; diff --git a/03_source/mobile/src/pages/DemoReactAddToCart/pages/products.ts b/03_source/mobile/src/pages/DemoReactAddToCart/pages/products.ts new file mode 100644 index 0000000..8dbab04 --- /dev/null +++ b/03_source/mobile/src/pages/DemoReactAddToCart/pages/products.ts @@ -0,0 +1,44 @@ +export const products = [ + { + id: 1, + name: 'Macbook Pro', + description: "13.3' (2020) - M1, 256 GB SSD, Space Grey", + price: '£1,199', + image: '/assets/DemoReactAddToCart/macbook.jpeg', + features: [ + 'macOS 11.0 Big Sur', + 'Apple M1 chip', + 'RAM: 8 GB / Storage: 256 GB SSD', + 'Retina display', + 'Battery life: Up to 20 hours', + ], + }, + { + id: 2, + name: 'SONY A7', + description: 'SONY a7 III Mirrorless Camera - Black', + price: '£1,699', + image: '/assets/DemoReactAddToCart/camera.jpeg', + features: [ + '24.2 megapixels', + 'Full-frame 35 mm / 35.6 x 23.8 mm CMOS sensor', + 'Built-in WiFi / Bluetooth / NFC', + "3' tiltable LCD touchscreen", + '10 fps in continuous shooting mode', + ], + }, + { + id: 3, + name: 'HISENSE 55', + description: "55' Smart 4K Ultra HD HDR LED TV", + price: '£429', + image: '/assets/DemoReactAddToCart/tv.jpeg', + features: [ + 'Picture quality: 1600 PCI', + 'HDR: HDR10 / Hybrid Log-Gamma (HLG)', + 'Catch-up TV & 4K streaming', + 'Freeview HD with Freeview Play', + 'HDMI 2.0 x 3', + ], + }, +]; diff --git a/03_source/mobile/src/pages/DemoReactAddToCart/style.scss b/03_source/mobile/src/pages/DemoReactAddToCart/style.scss index 37c1e1a..e5ac297 100644 --- a/03_source/mobile/src/pages/DemoReactAddToCart/style.scss +++ b/03_source/mobile/src/pages/DemoReactAddToCart/style.scss @@ -41,19 +41,19 @@ } .about-header .madison { - background-image: url('/assets/WeatherDemo/img/about/madison.jpg'); + background-image: url('/assets/DemoReactAddToCart/WeatherDemo/img/about/madison.jpg'); } .about-header .austin { - background-image: url('/assets/WeatherDemo/img/about/austin.jpg'); + background-image: url('/assets/DemoReactAddToCart/WeatherDemo/img/about/austin.jpg'); } .about-header .chicago { - background-image: url('/assets/WeatherDemo/img/about/chicago.jpg'); + background-image: url('/assets/DemoReactAddToCart/WeatherDemo/img/about/chicago.jpg'); } .about-header .seattle { - background-image: url('/assets/WeatherDemo/img/about/seattle.jpg'); + background-image: url('/assets/DemoReactAddToCart/WeatherDemo/img/about/seattle.jpg'); } .about-info { diff --git a/03_source/mobile/src/pages/DemoReactAddToCart/theme/variables.scss b/03_source/mobile/src/pages/DemoReactAddToCart/theme/variables.scss new file mode 100644 index 0000000..d9a2c52 --- /dev/null +++ b/03_source/mobile/src/pages/DemoReactAddToCart/theme/variables.scss @@ -0,0 +1,79 @@ +.demo-react-add-to-cart { + /* Ionic Variables and Theming. For more info, please see: +http://ionicframework.com/docs/theming/ */ + + /** Ionic CSS Variables **/ + :root { + /** primary **/ + --ion-color-primary: #3880ff; + --ion-color-primary-rgb: 56, 128, 255; + --ion-color-primary-contrast: #ffffff; + --ion-color-primary-contrast-rgb: 255, 255, 255; + --ion-color-primary-shade: #3171e0; + --ion-color-primary-tint: #4c8dff; + + /** secondary **/ + --ion-color-secondary: #3dc2ff; + --ion-color-secondary-rgb: 61, 194, 255; + --ion-color-secondary-contrast: #ffffff; + --ion-color-secondary-contrast-rgb: 255, 255, 255; + --ion-color-secondary-shade: #36abe0; + --ion-color-secondary-tint: #50c8ff; + + /** tertiary **/ + --ion-color-tertiary: #5260ff; + --ion-color-tertiary-rgb: 82, 96, 255; + --ion-color-tertiary-contrast: #ffffff; + --ion-color-tertiary-contrast-rgb: 255, 255, 255; + --ion-color-tertiary-shade: #4854e0; + --ion-color-tertiary-tint: #6370ff; + + /** success **/ + --ion-color-success: #2dd36f; + --ion-color-success-rgb: 45, 211, 111; + --ion-color-success-contrast: #ffffff; + --ion-color-success-contrast-rgb: 255, 255, 255; + --ion-color-success-shade: #28ba62; + --ion-color-success-tint: #42d77d; + + /** warning **/ + --ion-color-warning: #ffc409; + --ion-color-warning-rgb: 255, 196, 9; + --ion-color-warning-contrast: #000000; + --ion-color-warning-contrast-rgb: 0, 0, 0; + --ion-color-warning-shade: #e0ac08; + --ion-color-warning-tint: #ffca22; + + /** danger **/ + --ion-color-danger: #eb445a; + --ion-color-danger-rgb: 235, 68, 90; + --ion-color-danger-contrast: #ffffff; + --ion-color-danger-contrast-rgb: 255, 255, 255; + --ion-color-danger-shade: #cf3c4f; + --ion-color-danger-tint: #ed576b; + + /** dark **/ + --ion-color-dark: #222428; + --ion-color-dark-rgb: 34, 36, 40; + --ion-color-dark-contrast: #ffffff; + --ion-color-dark-contrast-rgb: 255, 255, 255; + --ion-color-dark-shade: #1e2023; + --ion-color-dark-tint: #383a3e; + + /** medium **/ + --ion-color-medium: #92949c; + --ion-color-medium-rgb: 146, 148, 156; + --ion-color-medium-contrast: #ffffff; + --ion-color-medium-contrast-rgb: 255, 255, 255; + --ion-color-medium-shade: #808289; + --ion-color-medium-tint: #9d9fa6; + + /** light **/ + --ion-color-light: #f4f5f8; + --ion-color-light-rgb: 244, 245, 248; + --ion-color-light-contrast: #000000; + --ion-color-light-contrast-rgb: 0, 0, 0; + --ion-color-light-shade: #d7d8da; + --ion-color-light-tint: #f5f6f9; + } +}