update demo-shop-app-ui,

This commit is contained in:
louiscklaw
2025-06-08 19:08:01 +08:00
parent 592a099f7b
commit 15f8d2e6aa
3 changed files with 97 additions and 60 deletions

View File

@@ -1,4 +1,22 @@
import { IonBackButton, IonBreadcrumb, IonBreadcrumbs, IonButtons, IonCol, IonContent, IonGrid, IonHeader, IonPage, IonRow, IonSearchbar, IonTitle, IonToolbar, useIonViewWillEnter, useIonViewWillLeave, IonRouterLink, useIonModal } from '@ionic/react'; import {
IonBackButton,
IonBreadcrumb,
IonBreadcrumbs,
IonButtons,
IonCol,
IonContent,
IonGrid,
IonHeader,
IonPage,
IonRow,
IonSearchbar,
IonTitle,
IonToolbar,
useIonViewWillEnter,
useIonViewWillLeave,
IonRouterLink,
useIonModal,
} from '@ionic/react';
import { useStoreState } from 'pullstate'; import { useStoreState } from 'pullstate';
import { useRef } from 'react'; import { useRef } from 'react';
import { useState } from 'react'; import { useState } from 'react';
@@ -9,49 +27,43 @@ import { ProductStore } from '../store';
import { getCategoryProducts } from '../store/Selectors'; import { getCategoryProducts } from '../store/Selectors';
import { capitalizeWords } from '../utils'; import { capitalizeWords } from '../utils';
import styles from "./Category.module.scss"; import styles from './Category.module.scss';
const Category = () => { const Category = () => {
const pageRef = useRef(null);
const pageRef = useRef();
const { name } = useParams(); const { name } = useParams();
const products = useStoreState(ProductStore, getCategoryProducts(name)); const products = useStoreState(ProductStore, getCategoryProducts(name));
const [ selectedProduct, setSelectedProduct ] = useState(false); const [selectedProduct, setSelectedProduct] = useState(false);
const handleShowModal = product => {
const handleShowModal = (product) => {
setSelectedProduct(product); setSelectedProduct(product);
present({ present({
cssClass: 'product-modal',
cssClass: "product-modal", presentingElement: pageRef.current,
presentingElement: pageRef.current
}); });
} };
const [ present, dismiss ] = useIonModal(ProductModal, {
const [present, dismiss] = useIonModal(ProductModal, {
dismiss: () => dismiss(), dismiss: () => dismiss(),
product: selectedProduct product: selectedProduct,
}); });
useIonViewWillEnter(() => { useIonViewWillEnter(() => {
document.querySelector('ion-tab-bar').style.display = 'none';
document.querySelector("ion-tab-bar").style.display = "none";
}); });
useIonViewWillLeave(() => { useIonViewWillLeave(() => {
document.querySelector('ion-tab-bar').style.display = '';
document.querySelector("ion-tab-bar").style.display = ""; });
})
return ( return (
<IonPage ref={ pageRef }> <IonPage ref={pageRef}>
<IonHeader> <IonHeader>
<IonToolbar> <IonToolbar>
<IonButtons slot="start"> <IonButtons slot="start">
<IonBackButton /> <IonBackButton />
</IonButtons> </IonButtons>
<IonTitle>{ capitalizeWords(name) }</IonTitle> <IonTitle>{capitalizeWords(name)}</IonTitle>
</IonToolbar> </IonToolbar>
</IonHeader> </IonHeader>
<IonContent fullscreen> <IonContent fullscreen>
@@ -60,25 +72,33 @@ const Category = () => {
{/* <IonTitle size="large">{ capitalizeWords(name) }</IonTitle> */} {/* <IonTitle size="large">{ capitalizeWords(name) }</IonTitle> */}
<IonBreadcrumbs> <IonBreadcrumbs>
<IonBreadcrumb color="dark"> <IonBreadcrumb color="dark">
<IonRouterLink routerLink="/home" routerDirection="back" color="dark">Shop</IonRouterLink> <IonRouterLink routerLink="/home" routerDirection="back" color="dark">
Shop
</IonRouterLink>
</IonBreadcrumb>
<IonBreadcrumb color="primary" active>
{capitalizeWords(name)}
</IonBreadcrumb> </IonBreadcrumb>
<IonBreadcrumb color="primary" active>{ capitalizeWords(name) }</IonBreadcrumb>
</IonBreadcrumbs> </IonBreadcrumbs>
</IonToolbar> </IonToolbar>
</IonHeader> </IonHeader>
<IonGrid className="ion-padding"> <IonGrid className="ion-padding">
<IonRow className={styles.searchContainer}>
<IonRow className={ styles.searchContainer }>
<IonCol size="12"> <IonCol size="12">
<IonSearchbar animated placeholder="Search for a product" /> <IonSearchbar animated placeholder="Search for a product" />
</IonCol> </IonCol>
</IonRow> </IonRow>
<IonRow> <IonRow>
{ products.map((product, index) => { {products.map((product, index) => {
return (
return <Product product={ product } key={ `product_${ index }` } click={ () => handleShowModal(product) } />; <Product
product={product}
key={`product_${index}`}
click={() => handleShowModal(product)}
/>
);
})} })}
</IonRow> </IonRow>
</IonGrid> </IonGrid>

View File

@@ -25,7 +25,7 @@ import { chevronBackOutline, refreshOutline } from 'ionicons/icons';
const Home = () => { const Home = () => {
const router = useIonRouter(); const router = useIonRouter();
const pageRef = useRef(); const pageRef = useRef(null);
const [showModal, setShowModal] = useState(false); const [showModal, setShowModal] = useState(false);
const [selectedProduct, setSelectedProduct] = useState(false); const [selectedProduct, setSelectedProduct] = useState(false);

View File

@@ -1,38 +1,46 @@
import { IonBadge, IonButton, IonButtons, IonCard, IonCardContent, IonCol, IonContent, IonGrid, IonHeader, IonIcon, IonPage, IonRow, IonTitle, IonToolbar } from '@ionic/react'; import {
IonBadge,
IonButton,
IonButtons,
IonCard,
IonCardContent,
IonCol,
IonContent,
IonGrid,
IonHeader,
IonIcon,
IonPage,
IonRow,
IonTitle,
IonToolbar,
} from '@ionic/react';
import { cart, star } from 'ionicons/icons'; import { cart, star } from 'ionicons/icons';
import { useRef } from 'react'; import { useRef } from 'react';
import { addToCart } from '../store/CartStore'; import { addToCart } from '../store/CartStore';
import { capitalizeWords } from '../utils'; import { capitalizeWords } from '../utils';
import styles from "./ProductModal.module.scss"; import styles from './ProductModal.module.scss';
export const ProductModal = ({ dismiss, product }) => { export const ProductModal = ({ dismiss, product }) => {
const cartRef = useRef(null);
const cartRef = useRef();
const handleAddToCart = () => { const handleAddToCart = () => {
cartRef.current.style.display = 'inline';
cartRef.current.style.display = "inline";
addToCart(product); addToCart(product);
setTimeout(() => { setTimeout(() => {
cartRef.current.style.display = 'none';
cartRef.current.style.display = "none";
}, 750); }, 750);
};
}
return ( return (
<IonPage> <IonPage>
<IonHeader> <IonHeader>
<IonToolbar> <IonToolbar>
<IonTitle>View Product</IonTitle> <IonTitle>View Product</IonTitle>
<IonButtons slot="end"> <IonButtons slot="end">
<IonButton onClick={ dismiss }> <IonButton onClick={dismiss}>Close</IonButton>
Close
</IonButton>
</IonButtons> </IonButtons>
</IonToolbar> </IonToolbar>
</IonHeader> </IonHeader>
@@ -40,27 +48,29 @@ export const ProductModal = ({ dismiss, product }) => {
<IonGrid> <IonGrid>
<IonRow className="animate__animated animate__faster animate__slideInUp"> <IonRow className="animate__animated animate__faster animate__slideInUp">
<IonCol size="12"> <IonCol size="12">
<IonCard className={styles.productCard}>
<IonCard className={ styles.productCard }>
<IonCardContent> <IonCardContent>
<div className={ styles.productTopInfo }> <div className={styles.productTopInfo}>
<img src={ product.image } alt="product" /> <img src={product.image} alt="product" />
<div className={ styles.productDetails }> <div className={styles.productDetails}>
<IonBadge color="primary">{ capitalizeWords(product.category) }</IonBadge> <IonBadge color="primary">{capitalizeWords(product.category)}</IonBadge>
<h3>{ product.title }</h3> <h3>{product.title}</h3>
</div> </div>
</div> </div>
<div className={ styles.productDescription }> <div className={styles.productDescription}>
<h3>Product Description</h3> <h3>Product Description</h3>
<p>{ product.description }</p> <p>{product.description}</p>
</div> </div>
<div className={ styles.productDescription }> <div className={styles.productDescription}>
<h3>Product Rating</h3> <h3>Product Rating</h3>
<div> <div>
<p>{ product.rating.count} people have bought this item from the IonShop and have rated an average of { product.rating.rate }.</p> <p>
<IonIcon icon={ star } color="primary" /> {product.rating.count} people have bought this item from the IonShop and
have rated an average of {product.rating.rate}.
</p>
<IonIcon icon={star} color="primary" />
</div> </div>
</div> </div>
</IonCardContent> </IonCardContent>
@@ -69,15 +79,22 @@ export const ProductModal = ({ dismiss, product }) => {
</IonRow> </IonRow>
</IonGrid> </IonGrid>
<IonGrid className={ `${ styles.bottom } animate__animated animate__slideInUp` }> <IonGrid className={`${styles.bottom} animate__animated animate__slideInUp`}>
<IonRow> <IonRow>
<IonCol size="12"> <IonCol size="12">
<div className={ styles.price }> <div className={styles.price}>
Buy now for Buy now for
<IonBadge color="dark" className="ion-padding-left">£{ product.price.toFixed(2) }</IonBadge> <IonBadge color="dark" className="ion-padding-left">
£{product.price.toFixed(2)}
</IonBadge>
</div> </div>
<IonIcon ref={ cartRef } className={ `${ styles.animatedCart } animate__animated animate__slideInUp` } icon={ cart } color="dark" /> <IonIcon
<IonButton onClick={ handleAddToCart }>Add to Cart</IonButton> ref={cartRef}
className={`${styles.animatedCart} animate__animated animate__slideInUp`}
icon={cart}
color="dark"
/>
<IonButton onClick={handleAddToCart}>Add to Cart</IonButton>
</IonCol> </IonCol>
</IonRow> </IonRow>
</IonGrid> </IonGrid>