From 3217a8d5947016c26cc0268588f5954f47e28cf8 Mon Sep 17 00:00:00 2001 From: louiscklaw Date: Fri, 6 Jun 2025 11:50:25 +0800 Subject: [PATCH] update, --- 03_source/mobile/.prettierrc | 12 +- .../mobile/android/app/capacitor.build.gradle | 1 + .../mobile/android/capacitor.settings.gradle | 3 + 03_source/mobile/ios/App/Podfile | 1 + 03_source/mobile/package.json | 3 +- 03_source/mobile/src/App.tsx | 81 ++++- .../src/pages/DemoAccordionTutorial/index.tsx | 14 +- 03_source/mobile/src/pages/DemoList/index.tsx | 313 ++++++++++++++++++ .../src/pages/DemoReactShop/Favourites.jsx | 2 +- .../src/pages/DemoReactShop/ProductType.jsx | 4 +- .../pages/DemoReactTravelApp/AllRoutes.jsx | 4 +- .../pages/DemoWeatherApp/AppPages/Tab1.jsx | 26 +- .../src/pages/components/AddToCartButton.jsx | 58 ---- .../src/pages/components/Breadcrumbs.jsx | 23 -- .../mobile/src/pages/components/CartModal.jsx | 82 ----- .../src/pages/components/FilterModal.jsx | 36 -- .../src/pages/components/ProductModal.css | 88 ----- .../src/pages/components/ProductModal.jsx | 76 ----- .../src/pages/components/ProductReviews.jsx | 23 -- .../ProductSpecificationsAccordion.jsx | 58 ---- 03_source/mobile/src/paths.ts | 48 ++- 03_source/mobile/yarn.lock | 39 +++ 22 files changed, 501 insertions(+), 494 deletions(-) delete mode 100644 03_source/mobile/src/pages/components/AddToCartButton.jsx delete mode 100644 03_source/mobile/src/pages/components/Breadcrumbs.jsx delete mode 100644 03_source/mobile/src/pages/components/CartModal.jsx delete mode 100644 03_source/mobile/src/pages/components/FilterModal.jsx delete mode 100644 03_source/mobile/src/pages/components/ProductModal.css delete mode 100644 03_source/mobile/src/pages/components/ProductModal.jsx delete mode 100644 03_source/mobile/src/pages/components/ProductReviews.jsx delete mode 100644 03_source/mobile/src/pages/components/ProductSpecificationsAccordion.jsx diff --git a/03_source/mobile/.prettierrc b/03_source/mobile/.prettierrc index 2da2a72..212cd92 100644 --- a/03_source/mobile/.prettierrc +++ b/03_source/mobile/.prettierrc @@ -3,13 +3,5 @@ "semi": true, "singleQuote": true, "trailingComma": "es5", - "printWidth": 160, - "overrides": [ - { - "files": "src/App.tsx", - "options": { - "printWidth": 240 - } - } - ] -} + "printWidth": 100 +} \ No newline at end of file diff --git a/03_source/mobile/android/app/capacitor.build.gradle b/03_source/mobile/android/app/capacitor.build.gradle index ea6fc3b..ca48bc2 100644 --- a/03_source/mobile/android/app/capacitor.build.gradle +++ b/03_source/mobile/android/app/capacitor.build.gradle @@ -12,6 +12,7 @@ dependencies { implementation project(':capacitor-barcode-scanner') implementation project(':capacitor-clipboard') implementation project(':capacitor-geolocation') + implementation project(':capacitor-google-maps') implementation project(':capacitor-preferences') implementation project(':capacitor-share') diff --git a/03_source/mobile/android/capacitor.settings.gradle b/03_source/mobile/android/capacitor.settings.gradle index fd55fca..4d859e4 100644 --- a/03_source/mobile/android/capacitor.settings.gradle +++ b/03_source/mobile/android/capacitor.settings.gradle @@ -11,6 +11,9 @@ project(':capacitor-clipboard').projectDir = new File('../node_modules/@capacito include ':capacitor-geolocation' project(':capacitor-geolocation').projectDir = new File('../node_modules/@capacitor/geolocation/android') +include ':capacitor-google-maps' +project(':capacitor-google-maps').projectDir = new File('../node_modules/@capacitor/google-maps/android') + include ':capacitor-preferences' project(':capacitor-preferences').projectDir = new File('../node_modules/@capacitor/preferences/android') diff --git a/03_source/mobile/ios/App/Podfile b/03_source/mobile/ios/App/Podfile index fd27c63..d7565c9 100644 --- a/03_source/mobile/ios/App/Podfile +++ b/03_source/mobile/ios/App/Podfile @@ -14,6 +14,7 @@ def capacitor_pods pod 'CapacitorBarcodeScanner', :path => '../../node_modules/@capacitor/barcode-scanner' pod 'CapacitorClipboard', :path => '../../node_modules/@capacitor/clipboard' pod 'CapacitorGeolocation', :path => '../../node_modules/@capacitor/geolocation' + pod 'CapacitorGoogleMaps', :path => '../../node_modules/@capacitor/google-maps' pod 'CapacitorPreferences', :path => '../../node_modules/@capacitor/preferences' pod 'CapacitorShare', :path => '../../node_modules/@capacitor/share' end diff --git a/03_source/mobile/package.json b/03_source/mobile/package.json index 5954c78..62c3f24 100644 --- a/03_source/mobile/package.json +++ b/03_source/mobile/package.json @@ -11,6 +11,7 @@ "@capacitor/clipboard": "^7.0.1", "@capacitor/core": "^7.0.0", "@capacitor/geolocation": "^7.1.2", + "@capacitor/google-maps": "^7.0.2", "@capacitor/ios": "7.0.1", "@capacitor/preferences": "^7.0.0", "@capacitor/share": "^7.0.1", @@ -49,7 +50,7 @@ }, "scripts": { "start": "npm run dev", - "dev": "vite --host 0.0.0.0 --cors", + "dev": "vite --force --host 0.0.0.0 --cors", "ionic:serve": "vite", "ionic:build": "tsc && vite build", "build": "tsc && vite build", diff --git a/03_source/mobile/src/App.tsx b/03_source/mobile/src/App.tsx index 7c82616..f6215d6 100644 --- a/03_source/mobile/src/App.tsx +++ b/03_source/mobile/src/App.tsx @@ -90,7 +90,12 @@ import DemoRestaurantFinder from './pages/DemoRestaurantFinder'; import DemoReactOverlayHooks from './pages/DemoReactOverlayHooks'; import DemoReactSwitchTabs from './pages/DemoReactSwitchTabs'; import DemoReactPollApp from './pages/DemoReactPollApp'; -// import DemoReactWhatsAppClone from './pages/DemoReactWhatsAppClone'; +import DemoReactWhatsAppClone from './pages/DemoReactWhatsAppClone'; +import Demo2FaExample from './pages/Demo2FaExample'; +import DemoAccordionTutorial from './pages/DemoAccordionTutorial'; +import DemoBankingUi from './pages/DemoBankingUi'; +import DemoCapacitorGoogleMapsTutorial from './pages/DemoCapacitorGoogleMapsTutorial'; +import DemoColorTutorial from './pages/DemoColorTutorial'; setupIonicReact(); @@ -116,7 +121,14 @@ interface DispatchProps { interface IonicAppProps extends StateProps, DispatchProps {} -const IonicApp: React.FC = ({ darkMode, schedule, setIsLoggedIn, setUsername, loadConfData, loadUserData }) => { +const IonicApp: React.FC = ({ + darkMode, + schedule, + setIsLoggedIn, + setUsername, + loadConfData, + loadUserData, +}) => { useEffect(() => { loadUserData(); loadConfData(); @@ -145,8 +157,66 @@ const IonicApp: React.FC = ({ darkMode, schedule, setIsLoggedIn, {/* */} {/* */} {/* */} + {/* */} + {/* */} + {/* */} + {/* */} + {/* */} - {/* TODO: review DemoReactWhatsAppClone */} + } /> + {/* */} + {/* */} + {/* */} + {/* */} + {/* */} + {/* */} + + } /> + } + /> + + } /> + + {/* + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + */} + + } /> + + {/* have problemx` */} {/* } /> */} } /> @@ -154,7 +224,10 @@ const IonicApp: React.FC = ({ darkMode, schedule, setIsLoggedIn, } /> } /> } /> - } /> + } + /> } /> } /> } /> diff --git a/03_source/mobile/src/pages/DemoAccordionTutorial/index.tsx b/03_source/mobile/src/pages/DemoAccordionTutorial/index.tsx index 2b2c87c..c1f670a 100644 --- a/03_source/mobile/src/pages/DemoAccordionTutorial/index.tsx +++ b/03_source/mobile/src/pages/DemoAccordionTutorial/index.tsx @@ -6,8 +6,8 @@ import { Route, Redirect } from 'react-router'; // import Tab1 from './AppPages/Tab1'; // import Tab2 from './AppPages/Tab2'; -import Topic from './pages/Topic.jsx'; -import Home from './pages/Home.jsx'; +import Topic from './pages/Topic'; +import Home from './pages/Home'; import './style.scss'; @@ -15,12 +15,14 @@ function DemoAccordionTutorial() { return ( - {/* + {/* + - */} + + */} @@ -30,7 +32,9 @@ function DemoAccordionTutorial() { - + + + {/* */} {/* diff --git a/03_source/mobile/src/pages/DemoList/index.tsx b/03_source/mobile/src/pages/DemoList/index.tsx index 235e22e..80ba1af 100644 --- a/03_source/mobile/src/pages/DemoList/index.tsx +++ b/03_source/mobile/src/pages/DemoList/index.tsx @@ -51,11 +51,13 @@ import { book, car, cart, + cashOutline, chatbubbleEllipses, chatbubbleOutline, chevronBackOutline, chevronForward, chevronForwardOutline, + colorPaletteOutline, createOutline, document, documentTextOutline, @@ -63,9 +65,12 @@ import { giftOutline, globeSharp, heart, + keyOutline, languageOutline, layers, + list, listCircle, + mapOutline, menuOutline, people, person, @@ -202,6 +207,313 @@ const SettingsPage: React.FC = ({ speakers, speakerSessions, logo {/* */} {/* */} {/* */} + + + router.push(paths.DEMO_ACCORDION_TUTORIAL, 'forward')}> + + Demo Accordion Tutorial + + + + + + router.push(paths.DEMO_BANKING_UI, 'forward')}> + + + Demo Banking UI (in the middle, style outstanding) + + + + + + + router.push(paths.DEMO_CAPACITOR_GOOGLE_MAPS_TUTORIAL, 'forward')}> + + + Demo Capacitor Google Maps Tutorial need a google map api key + + + + + + + router.push(paths.DEMO_COLOR_TUTORIAL, 'forward')}> + + Demo Color Tutorial + + + + + {/* + + + + router.push(paths.DEMO_ECOMMERCE_EXAMPLE, 'forward')}> + + Demo Ecommerce Example + + + + + + router.push(paths.DEMO_FACEBOOK_CLONE, 'forward')}> + + Demo Facebook Clone + + + + + + router.push(paths.DEMO_FAST_FOOD_APP, 'forward')}> + + Demo Fast Food App + + + + + + router.push(paths.DEMO_FLOATING_TABS, 'forward')}> + + Demo Floating Tabs + + + + + + router.push(paths.DEMO_INSTAGRAM_CLONE, 'forward')}> + + Demo Instagram Clone + + + + + + router.push(paths.DEMO_KANBAN_BOARD, 'forward')}> + + Demo Kanban Board + + + + + + router.push(paths.DEMO_ORDERING_APP, 'forward')}> + + Demo Ordering App + + + + + + router.push(paths.DEMO_PROFILE_EXAMPLE, 'forward')}> + + Demo Profile Example + + + + + + router.push(paths.DEMO_PULLSTATE_TUTORIAL, 'forward')}> + + Demo Pullstate Tutorial + + + + + + router.push(paths.DEMO_REACT_ADD_TO_CART, 'forward')}> + + Demo React Add to Cart + + + + + + router.push(paths.DEMO_REACT_CALCULATOR, 'forward')}> + + Demo React Calculator + + + + + + router.push(paths.DEMO_REACT_DRAWING_CANVAS, 'forward')}> + + Demo React Drawing Canvas + + + + + + router.push(paths.DEMO_REACT_HOOK_FORM_EXAMPLE, 'forward')}> + + Demo React Hook Form Example + + + + + + router.push(paths.DEMO_REACT_ITEM_LIST, 'forward')}> + + Demo React Item List + + + + + + router.push(paths.DEMO_REACT_LIFECYCLES, 'forward')}> + + Demo React Lifecycles + + + + + + router.push(paths.DEMO_REACT_LOGIN, 'forward')}> + + Demo React Login + + + + + + router.push(paths.DEMO_REACT_MARVEL_APP, 'forward')}> + + Demo React Marvel App + + + + + + router.push(paths.DEMO_REACT_MOVIE_APP_WITH_ALGOLIA, 'forward')}> + + Demo React Movie App with Algolia + + + + + + router.push(paths.DEMO_REACT_NOTES, 'forward')}> + + Demo React Notes + + + + + + router.push(paths.DEMO_REACT_ONBOARDING_UI, 'forward')}> + + Demo React Onboarding UI + + + + + + router.push(paths.DEMO_REACT_PROFILE_DASHBOARD_UI, 'forward')): + + Demo React Profile Dashboard UI + + + + + + router.push(paths.DEMO_REACT_QR_CODE, 'forward')}> + + Demo React QR Code + + + + + + router.push(paths.DEMO_REACT_QUOTES, 'forward')): + + Demo React Quotes + + + + + + router.push(paths.DEMO_REACT_SHOP_UI, 'forward')): + + Demo React Shop UI + + + + + + router.push(paths.DEMO_REACT_TABS_MENUS_CUSTOM, 'forward')): + + Demo React Tabs Menus Custom + + + + + + router.push(paths.DEMO_REACT_THEME_SWITCHER, 'forward')): + + Demo React Theme Switcher + + + + + + router.push(paths.DEMO_REACT_WHATSAPP_CLONE, 'forward')): + + Demo React WhatsApp Clone + + + + + + router.push(paths.DEMO_SKELETON_TEXT, 'forward')): + + Demo Skeleton Text + + + + + + router.push(paths.DEMO_STICKY_BOTTOM_SHEET_EXAMPLE, 'forward')): + + Demo Sticky Bottom Sheet Example + + + + + + router.push(paths.DEMO_STORAGE_EXAMPLE, 'forward')): + + Demo Storage Example + + + + + + router.push(paths.DEMO_SWIPERJS_TUTORIAL, 'forward')): + + Demo SwiperJS Tutorial + + + + + + router.push(paths.DEMO_WEATHER_APP_UI, 'forward')): + + Demo Weather App UI + + + + + */} + + + router.push(paths.DEMO_2FA_EXAMPLE, 'forward')}> + + Demo 2FA Example + + + + + {/* router.push(paths.DEMO_REACT_WHATSAPP_CLONE, 'forward')}> @@ -211,6 +523,7 @@ const SettingsPage: React.FC = ({ speakers, speakerSessions, logo + */} router.push(paths.DEMO_REACT_POLL_APP, 'forward')}> diff --git a/03_source/mobile/src/pages/DemoReactShop/Favourites.jsx b/03_source/mobile/src/pages/DemoReactShop/Favourites.jsx index ef53bd7..64d8c6e 100644 --- a/03_source/mobile/src/pages/DemoReactShop/Favourites.jsx +++ b/03_source/mobile/src/pages/DemoReactShop/Favourites.jsx @@ -16,7 +16,7 @@ import { import { heartOutline } from 'ionicons/icons'; import { useStoreState } from 'pullstate'; import { useState } from 'react'; -import { ProductModal } from '../components/ProductModal'; +import { ProductModal } from '../TestComponents/ProductModal'; import { FavouritesStore } from '../store'; import { getFavourites } from '../store/Selectors'; diff --git a/03_source/mobile/src/pages/DemoReactShop/ProductType.jsx b/03_source/mobile/src/pages/DemoReactShop/ProductType.jsx index 8921dab..230a62b 100644 --- a/03_source/mobile/src/pages/DemoReactShop/ProductType.jsx +++ b/03_source/mobile/src/pages/DemoReactShop/ProductType.jsx @@ -23,8 +23,8 @@ import { chevronBack, filter } from 'ionicons/icons'; import { useRef } from 'react'; import { useEffect, useState } from 'react'; import { useParams } from 'react-router'; -import { FilterModal } from '../components/FilterModal'; -import { ProductModal } from '../components/ProductModal'; +import { FilterModal } from '../TestComponents/FilterModal'; +import { ProductModal } from '../TestComponents/ProductModal'; import { capitalize, productInfo } from '../utils'; const ProductType = () => { diff --git a/03_source/mobile/src/pages/DemoReactTravelApp/AllRoutes.jsx b/03_source/mobile/src/pages/DemoReactTravelApp/AllRoutes.jsx index 3857cfd..55c9d33 100644 --- a/03_source/mobile/src/pages/DemoReactTravelApp/AllRoutes.jsx +++ b/03_source/mobile/src/pages/DemoReactTravelApp/AllRoutes.jsx @@ -13,8 +13,8 @@ import Place from '../pages/Place'; // If using ionicons, import here and pass as ref to tabRoutes // Import custom tab menu -import Tabs from '../components/Tabs'; -import SubPages from '../components/SubPages'; +import Tabs from '../TestComponents/Tabs'; +import SubPages from '../TestComponents/SubPages'; // Array of objects representing tab pages // These will be the main tabs across the app diff --git a/03_source/mobile/src/pages/DemoWeatherApp/AppPages/Tab1.jsx b/03_source/mobile/src/pages/DemoWeatherApp/AppPages/Tab1.jsx index 54ab2b9..8a6c62f 100644 --- a/03_source/mobile/src/pages/DemoWeatherApp/AppPages/Tab1.jsx +++ b/03_source/mobile/src/pages/DemoWeatherApp/AppPages/Tab1.jsx @@ -1,16 +1,4 @@ -import { - IonButton, - IonButtons, - IonCol, - IonContent, - IonHeader, - IonIcon, - IonPage, - IonRow, - IonTitle, - IonToolbar, - useIonRouter, -} from '@ionic/react'; +import { IonButton, IonButtons, IonCol, IonContent, IonHeader, IonIcon, IonPage, IonRow, IonTitle, IonToolbar, useIonRouter } from '@ionic/react'; import { Geolocation } from '@capacitor/geolocation'; import { useEffect, useState } from 'react'; @@ -35,9 +23,7 @@ function Tab1() { const getAddress = async (coords) => { const query = `${coords.latitude},${coords.longitude}`; - const response = await fetch( - `https://api.weatherapi.com/v1/current.json?key=f93eb660b2424258bf5155016210712&q=${query}` - ); + const response = await fetch(`https://api.weatherapi.com/v1/current.json?key=f93eb660b2424258bf5155016210712&q=${query}`); const data = await response.json(); console.log(data); @@ -81,13 +67,7 @@ function Tab1() { -
- {currentWeather ? ( - - ) : ( - - )} -
+
{currentWeather ? : }
); diff --git a/03_source/mobile/src/pages/components/AddToCartButton.jsx b/03_source/mobile/src/pages/components/AddToCartButton.jsx deleted file mode 100644 index 33810a5..0000000 --- a/03_source/mobile/src/pages/components/AddToCartButton.jsx +++ /dev/null @@ -1,58 +0,0 @@ -import { CreateAnimation, IonButton, IonIcon } from "@ionic/react"; -import { cartOutline } from "ionicons/icons"; -import { useRef, useState } from "react"; -import { addToCart } from "../store/CartStore"; - -export const AddToCartButton = ({product}) => { - - const animationRef = useRef(); - 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.5)" - }; - - const colorAnimation = { - - property: "color", - fromValue: "green", - toValue: "green" - }; - - const mainAnimation = { - - duration: 1500, - iterations: "1", - fromTo: [ floatGrowAnimation, colorAnimation ], - easing: "cubic-bezier(0.25, 0.7, 0.25, 0.7)" - }; - - const handleAddToCart = async product => { - - setHidden(false); - await animationRef.current.animation.play(); - setHidden(true); - addToCart(product); - } - - return ( - - handleAddToCart(product)}> -   - Add to Cart - - - - - - ); -} \ No newline at end of file diff --git a/03_source/mobile/src/pages/components/Breadcrumbs.jsx b/03_source/mobile/src/pages/components/Breadcrumbs.jsx deleted file mode 100644 index a5b3263..0000000 --- a/03_source/mobile/src/pages/components/Breadcrumbs.jsx +++ /dev/null @@ -1,23 +0,0 @@ -import { IonBreadcrumb, IonBreadcrumbs, IonIcon } from "@ionic/react"; -import { fastFoodOutline } from "ionicons/icons"; -import { useState } from "react"; - -export const Breadcrumbs = () => { - - const [maxItems, setMaxItems] = useState(2); - - const handleClick = () => { - - setMaxItems(undefined); - } - - return ( - - - Page 1 - Page 2 - Page 3 - Page 4 - - ); -} \ No newline at end of file diff --git a/03_source/mobile/src/pages/components/CartModal.jsx b/03_source/mobile/src/pages/components/CartModal.jsx deleted file mode 100644 index ce7c030..0000000 --- a/03_source/mobile/src/pages/components/CartModal.jsx +++ /dev/null @@ -1,82 +0,0 @@ -import { useStoreState } from "pullstate"; -import { useEffect, useState } from "react"; -import { CartStore } from "../store"; -import { addToCart } from "../store/CartStore"; -import { getCart } from "../store/Selectors"; - -const { IonPage, IonHeader, IonToolbar, IonTitle, IonButtons, IonIcon, IonContent, IonGrid, IonRow, IonItem, IonLabel, IonText, IonThumbnail, IonFooter, IonCol, IonButton, IonItemSliding, IonItemOptions, IonItemOption } = require("@ionic/react"); -const { close } = require("ionicons/icons"); - -export const CartModal = props => { - - const cart = useStoreState(CartStore, getCart); - const [totalPrice, setTotalPrice] = useState(0); - - useEffect(() => { - - let total = 0; - cart.forEach(item => total += parseInt(item.price.replace("£", ""))); - setTotalPrice(total); - }, [cart]); - - return ( - - - - Cart - - - - - - - - - - - -

{cart.length} products in your cart

- -

Review products and checkout

-
-
-
-
-
- - {cart.map((item, index) => ( - - - - item - - -

{item.title}

-

{item.price}

-
-
- - - addToCart(item)}> - Remove - - -
- ))} -
- - - - -

Total

-
- - -

£{totalPrice.toFixed(2)}

-
-
- Checkout → -
-
- ); -} \ No newline at end of file diff --git a/03_source/mobile/src/pages/components/FilterModal.jsx b/03_source/mobile/src/pages/components/FilterModal.jsx deleted file mode 100644 index 067aac7..0000000 --- a/03_source/mobile/src/pages/components/FilterModal.jsx +++ /dev/null @@ -1,36 +0,0 @@ -import { IonButton, IonCol, IonContent, IonGrid, IonHeader, IonRow, IonTitle, IonToolbar } from "@ionic/react"; - -export const FilterModal = ({productsRef, filterCriteria, setFilterCriteria, dismiss, filters}) => { - - const filterProducts = async filter => { - - await productsRef.current.classList.add("animate__fadeOutLeft"); - - setTimeout(() => { - productsRef.current.classList.remove("animate__fadeOutLeft"); - productsRef.current.classList.add("animate__fadeInRight"); - setFilterCriteria(filter); - }, 500); - dismiss(); - } - - return ( - - - - - Filter - - - - - {filters.map(f => ( - - filterProducts(f)}>{f} - - ))} - - - - ); - } \ No newline at end of file diff --git a/03_source/mobile/src/pages/components/ProductModal.css b/03_source/mobile/src/pages/components/ProductModal.css deleted file mode 100644 index 8884088..0000000 --- a/03_source/mobile/src/pages/components/ProductModal.css +++ /dev/null @@ -1,88 +0,0 @@ -ion-card { - margin: 0; - /* margin-top: var(--ion-safe-area-top); */ - z-index: -1; - - border-radius: 0px; - - background-size: cover; - background-position: center; - background-repeat: no-repeat; - box-shadow: none; - aspect-ratio: 1 / 1; -} - -@supports not (aspect-ratio: 1 / 1) { - ion-card::before { - float: left; - padding-top: 100%; - content: ''; - } - - ion-card::after { - display: block; - content: ''; - clear: both; - } -} - -ion-card-header { - position: absolute; - bottom: 0; - width: 100%; - - /* background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.7) 100%); */ - background: rgba(0, 0, 0, 0.5) -} - -ion-card-title, -ion-card-subtitle { - color: white; -} - -ion-card-header ion-card-title { - - margin: 0 0 6px 0; - font-size: 22px; -} - -ion-card-header ion-card-subtitle { - - text-transform: none; - font-weight: 500; - font-size: 16px; -} - -ion-card-content { - height: calc(60px + var(--ion-safe-area-top)); - background: linear-gradient(0deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.5) 100%); -} - -#close-button { - position: fixed; - - top: max(var(--ion-safe-area-top), 16px); - right: 8px; -} - -#fave-button { - position: fixed; - - top: max(var(--ion-safe-area-top), 16px); - left: 8px; -} - -#product-view-buttons { - - z-index: 10; - background: linear-gradient(360deg, rgba(0, 0, 0, 0) 0%, rgba(82, 82, 82, 0.9) 100%) !important; - position: absolute; - width: 100%; - height: 4rem; -} - -.sticky-bottom { - - position: fixed; - bottom: 0; -} \ No newline at end of file diff --git a/03_source/mobile/src/pages/components/ProductModal.jsx b/03_source/mobile/src/pages/components/ProductModal.jsx deleted file mode 100644 index a519b87..0000000 --- a/03_source/mobile/src/pages/components/ProductModal.jsx +++ /dev/null @@ -1,76 +0,0 @@ -import { IonButton, IonButtons, IonCard, IonCardHeader, IonCardSubtitle, IonCardTitle, IonCol, IonContent, IonFooter, IonIcon, IonLabel, IonNote, IonRow, IonText, IonToolbar } from "@ionic/react"; -import { closeCircle, heart, heartOutline } from "ionicons/icons"; -import { useStoreState } from "pullstate"; -import { useRef } from "react"; - -import { checkFavourites } from "../store/Selectors"; -import { addToFavourites } from "../store/FavouritesStore"; -import { FavouritesStore } from "../store"; - -import "./ProductModal.css"; -import { ProductReviews } from "./ProductReviews"; -import { ProductSpecificationsAccordion } from "./ProductSpecificationsAccordion"; -import { AddToCartButton } from "./AddToCartButton"; - -export const ProductModal = props => { - - const { dismiss, category = false, product } = props; - const isFavourite = useStoreState(FavouritesStore, checkFavourites(product)); - const contentRef = useRef(null); - - return ( - <> - - - - - - - addToFavourites(product, category)} id="fave-button"> - - - - - - - {product.title} - {product.price} - - - -
- - - - - shop - {category ? category : "Favourite"} - - - - - -

Product Description

- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam elit felis, molestie id venenatis at, commodo ac tortor. Pellentesque tempus aliquet purus, sed vulputate elit tempus ut. - -

Product Specifications

- -
-
- - - - - - {product.price} - - - - - - - - - - ); -} \ No newline at end of file diff --git a/03_source/mobile/src/pages/components/ProductReviews.jsx b/03_source/mobile/src/pages/components/ProductReviews.jsx deleted file mode 100644 index d564773..0000000 --- a/03_source/mobile/src/pages/components/ProductReviews.jsx +++ /dev/null @@ -1,23 +0,0 @@ -import { IonCol, IonIcon, IonNote } from "@ionic/react"; -import { star } from "ionicons/icons"; -import { useEffect, useState } from "react"; -import { randomCount } from "../utils"; - -export const ProductReviews = () => { - - // This count could come from the product (if real data was fed) - const [reviewCount, setReviewCount] = useState(0); - - useEffect(() => { - - setReviewCount(randomCount()); - }, []); - - return ( - - -    - {reviewCount} review{reviewCount > 1 && "s"} - - ); -} \ No newline at end of file diff --git a/03_source/mobile/src/pages/components/ProductSpecificationsAccordion.jsx b/03_source/mobile/src/pages/components/ProductSpecificationsAccordion.jsx deleted file mode 100644 index 77ede79..0000000 --- a/03_source/mobile/src/pages/components/ProductSpecificationsAccordion.jsx +++ /dev/null @@ -1,58 +0,0 @@ -import { IonAccordion, IonAccordionGroup, IonItem, IonLabel, IonList, IonNote } from "@ionic/react"; -import { useRef } from "react"; -import { productSpecs } from "../utils"; - -export const ProductSpecificationsAccordion = ({type, contentRef}) => { - - const accordionGroupRef = useRef(null); - - const log = () => { - - const selectedAccordion = accordionGroupRef.current.value; - - if (selectedAccordion) { - - setTimeout(() => contentRef.current.scrollToBottom(400), 200); - } - } - - return ( - - {Object.keys(productSpecs).map((spec, index) => { - - const {header, options, wrapText = false, noteColor = false} = productSpecs[spec]; - - return ( - - - - {header} - - - - - {options.map((option, index2) => { - - const {label, value} = option; - - return ( - - - -

{label}

-
- - - {noteColor ? (value ? "In stock" : "Out of stock") : value} - - -
- ); - })} -
-
- ); - })} -
- ); -} \ No newline at end of file diff --git a/03_source/mobile/src/paths.ts b/03_source/mobile/src/paths.ts index b1beba5..ed225bb 100644 --- a/03_source/mobile/src/paths.ts +++ b/03_source/mobile/src/paths.ts @@ -29,9 +29,53 @@ const paths = { // // // - DEMO_REACT_WHATSAPP_CLONE: '/demo-react-whatsapp-clone', + // + // + // + // + // + // + // + // + // + DEMO_ACCORDION_TUTORIAL: '/demo-accordion-tutorial', + DEMO_BANKING_UI: '/demo-banking-ui', + DEMO_CAPACITOR_GOOGLE_MAPS_TUTORIAL: '/demo-capacitor-google-maps-tutorial', + DEMO_COLOR_TUTORIAL: '/demo-color-tutorial', + // DEMO_ECOMMERCE_EXAMPLE: '/demo-ecommerce-example', + // DEMO_FACEBOOK_CLONE: '/demo-facebook-clone', + // DEMO_FAST_FOOD_APP: '/demo-fast-food-app', + // DEMO_FLOATING_TABS: '/demo-floating-tabs', + // DEMO_INSTAGRAM_CLONE: '/demo-instagram-clone', + // DEMO_KANBAN_BOARD: '/demo-kanban-board', + // DEMO_ORDERING_APP: '/demo-ordering-app', + // DEMO_PROFILE_EXAMPLE: '/demo-profile-example', + // DEMO_PULLSTATE_TUTORIAL: '/demo-pullstate-tutorial', + // DEMO_REACT_ADD_TO_CART: '/demo-react-add-to-cart', + // DEMO_REACT_CALCULATOR: '/demo-react-calculator', + // DEMO_REACT_DRAWING_CANVAS: '/demo-react-drawing-canvas', + // DEMO_REACT_HOOK_FORM_EXAMPLE: '/demo-react-hook-form-example', + // DEMO_REACT_ITEM_LIST: '/demo-react-item-list', + // DEMO_REACT_LIFECYCLES: '/demo-react-lifecycles', + // DEMO_REACT_LOGIN: '/demo-react-login', + // DEMO_REACT_MARVEL_APP: '/demo-react-marvel-app', + // DEMO_REACT_MOVIE_APP_WITH_ALGOLIA: '/demo-react-movie-app-with-algolia', + // DEMO_REACT_NOTES: '/demo-react-notes', + // DEMO_REACT_ONBOARDING_UI: '/demo-react-onboarding-ui', + // DEMO_REACT_PROFILE_DASHBOARD_UI: '/demo-react-profile-dashboard-ui', + // DEMO_REACT_QR_CODE: '/demo-react-qr-code', + // DEMO_REACT_QUOTES: '/demo-react-quotes', + // DEMO_REACT_SHOP_UI: '/demo-react-shop-ui', + // DEMO_REACT_TABS_MENUS_CUSTOM: '/demo-react-tabs-menus-custom', + // DEMO_REACT_THEME_SWITCHER: '/demo-react-theme-switcher', + // DEMO_SKELETON_TEXT: '/demo-skeleton-text', + // DEMO_STICKY_BOTTOM_SHEET_EXAMPLE: '/demo-sticky-bottom-sheet-example', + // DEMO_STORAGE_EXAMPLE: '/demo-storage-example', + // DEMO_SWIPERJS_TUTORIAL: '/demo-swiperjs-tutorial', + // DEMO_WEATHER_APP_UI: '/demo-weather-app-ui', - DEMO_REACT_POLL_APP: '/demo-react-poll-app', + DEMO_2FA_EXAMPLE: '/demo-2fa-example', + DEMO_REACT_WHATSAPP_CLONE: '/demo-react-whatsapp-clone', DEMO_BLOG_POST_UI: '/demo-blog-post-ui', DEMO_CLUB_HOUSE: '/demo-club-house', diff --git a/03_source/mobile/yarn.lock b/03_source/mobile/yarn.lock index 35b66f8..169ec54 100644 --- a/03_source/mobile/yarn.lock +++ b/03_source/mobile/yarn.lock @@ -229,6 +229,15 @@ dependencies: "@capacitor/synapse" "^1.0.1" +"@capacitor/google-maps@^7.0.2": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@capacitor/google-maps/-/google-maps-7.0.2.tgz#1fc79bece5afe452431289d080043745ddb406cf" + integrity sha512-OLwOB3vhXTpvV3OxJe+PEJld/U9VWYYl8LHkciV4rSoMn+/xKsUdfiztEpi+LhpbB4idTAO1H/D/IIxMqJcc4A== + dependencies: + "@googlemaps/js-api-loader" "~1.16.8" + "@googlemaps/markerclusterer" "~2.5.3" + "@types/google.maps" "~3.58.1" + "@capacitor/ios@7.0.1": version "7.0.1" resolved "https://registry.npmjs.org/@capacitor/ios/-/ios-7.0.1.tgz" @@ -374,6 +383,19 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz#0b17ec8a70b2385827d52314c1253160a0b9bacc" integrity sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ== +"@googlemaps/js-api-loader@~1.16.8": + version "1.16.8" + resolved "https://registry.yarnpkg.com/@googlemaps/js-api-loader/-/js-api-loader-1.16.8.tgz#1595a2af80ca07e551fc961d921a2437d1cb3643" + integrity sha512-CROqqwfKotdO6EBjZO/gQGVTbeDps5V7Mt9+8+5Q+jTg5CRMi3Ii/L9PmV3USROrt2uWxtGzJHORmByxyo9pSQ== + +"@googlemaps/markerclusterer@~2.5.3": + version "2.5.3" + resolved "https://registry.yarnpkg.com/@googlemaps/markerclusterer/-/markerclusterer-2.5.3.tgz#9f891ce7e8e161775f3a3e2c9f66956810284591" + integrity sha512-x7lX0R5yYOoiNectr10wLgCBasNcXFHiADIBdmn7jQllF2B5ENQw5XtZK+hIw4xnV0Df0xhN4LN98XqA5jaiOw== + dependencies: + fast-deep-equal "^3.1.3" + supercluster "^8.0.1" + "@hookform/resolvers@^4.1.3": version "4.1.3" resolved "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-4.1.3.tgz" @@ -899,6 +921,11 @@ resolved "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz" integrity sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg== +"@types/google.maps@~3.58.1": + version "3.58.1" + resolved "https://registry.yarnpkg.com/@types/google.maps/-/google.maps-3.58.1.tgz#71ce3dec44de1452f56641d2c87c7dd8ea964b4d" + integrity sha512-X9QTSvGJ0nCfMzYOnaVs/k6/4L+7F5uCS+4iUmkLEls6J9S/Phv+m/i3mDeyc49ZBgwab3EFO1HEoBY7k98EGQ== + "@types/hast@^3.0.0": version "3.0.4" resolved "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz" @@ -2041,6 +2068,11 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" +kdbush@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/kdbush/-/kdbush-4.0.2.tgz#2f7b7246328b4657dd122b6c7f025fbc2c868e39" + integrity sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA== + kleur@^3.0.3: version "3.0.3" resolved "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz" @@ -3285,6 +3317,13 @@ stylis@^4.3.0: resolved "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz" integrity sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ== +supercluster@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/supercluster/-/supercluster-8.0.1.tgz#9946ba123538e9e9ab15de472531f604e7372df5" + integrity sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ== + dependencies: + kdbush "^4.0.2" + supports-color@^7.1.0: version "7.2.0" resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz"