update demo-react-travel-app,

This commit is contained in:
louiscklaw
2025-06-08 19:08:00 +08:00
parent 6419567005
commit 9aeb58379d

View File

@@ -1,99 +1,102 @@
import { IonCard, IonCardHeader, IonCardTitle, IonNote, useIonToast, CreateAnimation, IonIcon } from "@ionic/react"; import {
import { useState } from "react"; IonCard,
import { useRef } from "react"; IonCardHeader,
import { Iconly } from "react-iconly"; IonCardTitle,
import { heart, trashBin } from "ionicons/icons"; IonNote,
import { addFavourite } from "../store/PlacesStore"; useIonToast,
CreateAnimation,
IonIcon,
} from '@ionic/react';
import { useState } from 'react';
import { useRef } from 'react';
import { Iconly } from 'react-iconly';
import { heart, trashBin } from 'ionicons/icons';
import { addFavourite } from '../store/PlacesStore';
import styles from "../styles/Home.module.scss"; import styles from '../styles/Home.module.scss';
const PlaceCard = ({ place = false, fromFavourites = false }) => { const PlaceCard = ({ place = false, fromFavourites = false }) => {
const animationRef = useRef(null);
const animationRef = useRef(); const cardRef = useRef(null);
const cardRef = useRef(); const [presentToast] = useIonToast();
const [ presentToast ] = useIonToast(); const [hideAnimatedIcon, setHideAnimatedIcon] = useState(true);
const [ hideAnimatedIcon, setHideAnimatedIcon ] = useState(true);
const floatStyle = { const floatStyle = {
display: hideAnimatedIcon ? 'none' : '',
display: hideAnimatedIcon ? "none" : "", position: 'absolute',
position: "absolute", zIndex: '10',
zIndex: "10"
}; };
const floatGrowAnimation = { const floatGrowAnimation = {
property: 'transform',
property: "transform", fromValue: 'translateY(0) scale(1)',
fromValue: "translateY(0) scale(1)", toValue: 'translateY(-20px) scale(2)',
toValue: "translateY(-20px) scale(2)"
}; };
const mainAnimation = { const mainAnimation = {
duration: 600, duration: 600,
iterations: "1", iterations: '1',
fromTo: [ floatGrowAnimation ], fromTo: [floatGrowAnimation],
easing: "cubic-bezier(0.25, 0.7, 0.25, 0.7)" easing: 'cubic-bezier(0.25, 0.7, 0.25, 0.7)',
}; };
const handleAddFavourite = async (e, place) => { const handleAddFavourite = async (e, place) => {
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
if (fromFavourites) { if (fromFavourites) {
// Add a fadeOut animation before removing // Add a fadeOut animation before removing
cardRef.current.classList.add("animate__fadeOut"); cardRef.current.classList.add('animate__fadeOut');
setTimeout(() => { setTimeout(() => {
addFavourite(place, fromFavourites); addFavourite(place, fromFavourites);
}, 500); }, 500);
} else { } else {
addFavourite(place, fromFavourites); addFavourite(place, fromFavourites);
} }
presentToast({ presentToast({
header: `Favourite ${fromFavourites ? 'removed' : 'added'}!`,
header: `Favourite ${ fromFavourites ? "removed" : "added" }!`,
buttons: [ buttons: [
{ {
text: "♡", text: '♡',
} },
], ],
message: `${ place.name } has been ${ fromFavourites ? "removed from" : "added to" } your favourites.`, message: `${place.name} has been ${fromFavourites ? 'removed from' : 'added to'} your favourites.`,
duration: 1500, duration: 1500,
color: "success" color: 'success',
}); });
setHideAnimatedIcon(false); setHideAnimatedIcon(false);
await animationRef.current.animation.play(); await animationRef.current.animation.play();
setHideAnimatedIcon(true); setHideAnimatedIcon(true);
} };
return ( return (
<IonCard ref={ cardRef } className={ `${ styles.slide } animate__animated animate__fadeIn animate__faster` } routerLink={ `/view-place/${ place.id }` }> <IonCard
<div className={ styles.imageHeader }> ref={cardRef}
<img src={ place ? place.image : "/assets/nonefound.png" } /> className={`${styles.slide} animate__animated animate__fadeIn animate__faster`}
{ place && routerLink={`/view-place/${place.id}`}
<div className="favouriteButton" onClick={ e => handleAddFavourite(e, place) }> >
<div className={styles.imageHeader}>
<img src={place ? place.image : '/assets/nonefound.png'} />
{place && (
<div className="favouriteButton" onClick={(e) => handleAddFavourite(e, place)}>
<Iconly set="bold" name={fromFavourites ? 'Delete' : 'Heart'} color="red" />
<Iconly set="bold" name={ fromFavourites ? "Delete" : "Heart" } color="red" /> <CreateAnimation ref={animationRef} {...mainAnimation}>
<IonIcon icon={fromFavourites ? trashBin : heart} style={floatStyle} color="danger" />
<CreateAnimation ref={ animationRef } { ...mainAnimation }>
<IonIcon icon={ fromFavourites ? trashBin : heart } style={ floatStyle } color="danger" />
</CreateAnimation> </CreateAnimation>
</div> </div>
} )}
</div> </div>
<IonCardHeader> <IonCardHeader>
<IonCardTitle>{ place ? place.name : "Sorry" }</IonCardTitle> <IonCardTitle>{place ? place.name : 'Sorry'}</IonCardTitle>
<IonNote>{ place ? place.destination : "No results found" }</IonNote> <IonNote>{place ? place.destination : 'No results found'}</IonNote>
</IonCardHeader> </IonCardHeader>
</IonCard> </IonCard>
); );
} };
export default PlaceCard; export default PlaceCard;