"feat: update data APIs to fetch orders and events via fetch instead of axios, add Order and Event models, update selectors and reducers, add EventDetail page with joined members display"
This commit is contained in:
@@ -26,14 +26,31 @@ import {
|
||||
IonText,
|
||||
IonFooter,
|
||||
useIonRouter,
|
||||
IonAvatar,
|
||||
} from '@ionic/react';
|
||||
import './style.scss';
|
||||
import {
|
||||
accessibility,
|
||||
accessibilityOutline,
|
||||
chevronBackOutline,
|
||||
ellipsisHorizontal,
|
||||
ellipsisVertical,
|
||||
heart,
|
||||
locationOutline,
|
||||
locationSharp,
|
||||
logoIonic,
|
||||
man,
|
||||
manOutline,
|
||||
people,
|
||||
peopleOutline,
|
||||
timer,
|
||||
timerOutline,
|
||||
timerSharp,
|
||||
wallet,
|
||||
walletOutline,
|
||||
walletSharp,
|
||||
woman,
|
||||
womanOutline,
|
||||
} from 'ionicons/icons';
|
||||
import AboutPopover from '../../components/AboutPopover';
|
||||
import { format, parseISO } from 'date-fns';
|
||||
@@ -44,28 +61,46 @@ import { connect } from '../../data/connect';
|
||||
import * as selectors from '../../data/selectors';
|
||||
import { Event } from '../../models/Event';
|
||||
import { RouteComponentProps } from 'react-router';
|
||||
import AvatarRow from './AvatarRow';
|
||||
|
||||
const leftShift: number = -25;
|
||||
|
||||
interface OwnProps extends RouteComponentProps {
|
||||
event?: Event;
|
||||
event_detail?: Event;
|
||||
}
|
||||
|
||||
interface StateProps {}
|
||||
|
||||
interface DispatchProps {}
|
||||
|
||||
interface SpeakerDetailProps extends OwnProps, StateProps, DispatchProps {}
|
||||
interface EventDetailProps extends OwnProps, StateProps, DispatchProps {}
|
||||
|
||||
interface AboutProps {}
|
||||
const showJoinedMembers = (joinMembers: Record<string, any>[]) => {
|
||||
const avatars = joinMembers.map((jm) => jm.avatar);
|
||||
|
||||
console.log({ joinMembers });
|
||||
|
||||
return (
|
||||
<>
|
||||
<AvatarRow avatars={avatars} />
|
||||
<IonButton style={{ '--padding-start': '20px', '--padding-end': '20px' }} shape="round">
|
||||
More
|
||||
</IonButton>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const EventDetail: React.FC<EventDetailProps> = ({ event_detail }) => {
|
||||
const router = useIonRouter();
|
||||
|
||||
const EventDetail: React.FC<SpeakerDetailProps> = () => {
|
||||
const [showPopover, setShowPopover] = useState(false);
|
||||
const [popoverEvent, setPopoverEvent] = useState<MouseEvent>();
|
||||
const [location, setLocation] = useState<
|
||||
'madison' | 'austin' | 'chicago' | 'seattle'
|
||||
>('madison');
|
||||
const [conferenceDate, setConferenceDate] = useState(
|
||||
'2047-05-17T00:00:00-05:00'
|
||||
);
|
||||
const [location, setLocation] = useState<'madison' | 'austin' | 'chicago' | 'seattle'>('madison');
|
||||
const [conferenceDate, setConferenceDate] = useState('2047-05-17T00:00:00-05:00');
|
||||
|
||||
const [totalJoinMembers, setTotalJoinMembers] = useState<number>(0);
|
||||
const [maleMembers, setMaleMembers] = useState<number>(0);
|
||||
const [femaleMembers, setFemaleMembers] = useState<number>(0);
|
||||
|
||||
const selectOptions = {
|
||||
header: 'Select a Location',
|
||||
@@ -80,6 +115,14 @@ const EventDetail: React.FC<SpeakerDetailProps> = () => {
|
||||
return format(parseISO(date), dateFormat);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (event_detail) {
|
||||
setTotalJoinMembers(event_detail.joinMembers.length);
|
||||
setMaleMembers(event_detail.joinMembers.filter((m) => m.sex == 'M').length);
|
||||
setFemaleMembers(event_detail.joinMembers.filter((m) => m.sex == 'F').length);
|
||||
}
|
||||
}, [event_detail]);
|
||||
|
||||
const [eventDetail, setEventDetail] = useState<Event | null>(null);
|
||||
useEffect(() => {
|
||||
Helloworld();
|
||||
@@ -89,15 +132,14 @@ const EventDetail: React.FC<SpeakerDetailProps> = () => {
|
||||
});
|
||||
}, []);
|
||||
|
||||
const router = useIonRouter();
|
||||
function handleBackOnClick() {
|
||||
router.goBack();
|
||||
}
|
||||
|
||||
if (!eventDetail) return <>loading</>;
|
||||
if (!event_detail) return <>loading</>;
|
||||
|
||||
return (
|
||||
<IonPage id="about-page">
|
||||
<IonPage id="event-detail-page">
|
||||
<IonContent>
|
||||
<IonHeader className="ion-no-border">
|
||||
<IonToolbar>
|
||||
@@ -109,63 +151,110 @@ const EventDetail: React.FC<SpeakerDetailProps> = () => {
|
||||
</IonButtons>
|
||||
<IonButtons slot="end">
|
||||
<IonButton onClick={presentPopover}>
|
||||
<IonIcon
|
||||
slot="icon-only"
|
||||
ios={ellipsisHorizontal}
|
||||
md={ellipsisVertical}
|
||||
></IonIcon>
|
||||
<IonIcon slot="icon-only" ios={ellipsisHorizontal} md={ellipsisVertical}></IonIcon>
|
||||
</IonButton>
|
||||
</IonButtons>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
|
||||
<div className="about-header">
|
||||
<div className="about-image madison" style={{ opacity: 1 }}></div>
|
||||
</div>
|
||||
|
||||
<div>{eventDetail.avatar}</div>
|
||||
|
||||
<div>
|
||||
<div>{format(new Date(eventDetail.eventDate), 'yyyy-MM-dd')}</div>
|
||||
<h1>{eventDetail.title}</h1>
|
||||
|
||||
<div style={{ display: 'flex', gap: '1rem', alignItems: 'center' }}>
|
||||
<div>members place holder</div>
|
||||
<IonButton shape="round">More</IonButton>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
marginBottom: '1rem',
|
||||
paddingTop: '1rem',
|
||||
borderBottom: '1px solid black',
|
||||
}}
|
||||
className="about-image madison"
|
||||
style={{ opacity: 1, backgroundImage: `url(${event_detail.avatar[0]})` }}
|
||||
></div>
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
|
||||
<div style={{ display: 'flex', gap: '1rem' }}>
|
||||
<div>{eventDetail.currency}</div>
|
||||
<div>{eventDetail.price}</div>
|
||||
per person
|
||||
|
||||
<div style={{ paddingLeft: '0.5rem', paddingRight: '0.5rem' }}>
|
||||
<div>
|
||||
<div style={{ paddingTop: '0.25rem', color: '#007AFF' }}>
|
||||
{format(new Date(event_detail.eventDate), 'EEE, dd MMM yyyy, hh:mm a')}
|
||||
</div>
|
||||
<div style={{ paddingTop: '0.25rem', fontSize: '1.8rem', fontWeight: '500' }}>
|
||||
{event_detail.title}
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
gap: '1rem',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
{event_detail.joinMembers && event_detail.joinMembers.length > 0 ? (
|
||||
showJoinedMembers(event_detail.joinMembers)
|
||||
) : (
|
||||
<>join fast !</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
marginBottom: '1rem',
|
||||
paddingTop: '1rem',
|
||||
borderBottom: '1px solid gray',
|
||||
}}
|
||||
></div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
paddingLeft: '0.5rem',
|
||||
paddingRight: '0.5rem',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: '1rem',
|
||||
}}
|
||||
>
|
||||
<div style={{ display: 'flex', gap: '0.5rem', alignItems: 'center' }}>
|
||||
<IonIcon icon={walletSharp} style={{ fontSize: '1.5rem' }}></IonIcon>
|
||||
<div style={{ display: 'flex', gap: '0.15rem', alignItems: 'center' }}>
|
||||
<div style={{ fontWeight: 'bold' }}>{event_detail.currency}</div>
|
||||
<div style={{ fontWeight: 'bold' }}>{event_detail.price}</div>
|
||||
per person
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>{eventDetail.duration_m}</div>
|
||||
|
||||
<div style={{ display: 'flex', gap: '1rem' }}>
|
||||
<div>{eventDetail.ageBottom}</div>
|
||||
<div>{eventDetail.ageTop}</div>
|
||||
<div>years old</div>
|
||||
<div style={{ display: 'flex', gap: '0.5rem', alignItems: 'center' }}>
|
||||
<IonIcon icon={timerSharp} style={{ fontSize: '1.5rem' }}></IonIcon>
|
||||
<div style={{ display: 'flex', gap: '0.15rem', alignItems: 'center' }}>
|
||||
{event_detail.duration_m}
|
||||
<div>mins</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>{eventDetail.location}</div>
|
||||
<div style={{ display: 'flex', gap: '1rem' }}>
|
||||
<IonIcon icon={logoIonic}></IonIcon>
|
||||
<div>40</div>
|
||||
<div style={{ display: 'flex', gap: '0.5rem', alignItems: 'center' }}>
|
||||
<IonIcon icon={people} style={{ fontSize: '1.5rem' }}></IonIcon>
|
||||
<div style={{ display: 'flex', gap: '0.15rem', alignItems: 'center' }}>
|
||||
<div>{event_detail.ageBottom}</div>~<div>{event_detail.ageTop}</div>
|
||||
<div>years old</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<IonIcon icon={logoIonic}></IonIcon>
|
||||
<div>20</div>
|
||||
<div style={{ display: 'flex', gap: '0.5rem', alignItems: 'center' }}>
|
||||
<IonIcon icon={locationSharp} style={{ fontSize: '1.5rem' }}></IonIcon>
|
||||
{event_detail.location}
|
||||
</div>
|
||||
|
||||
<IonIcon icon={logoIonic}></IonIcon>
|
||||
<div>20</div>
|
||||
<div style={{ display: 'flex', gap: '0.5rem', alignItems: 'center' }}>
|
||||
<IonIcon
|
||||
icon={accessibility}
|
||||
style={{ fontSize: '1.5rem', color: 'rgb(139, 44, 245)' }}
|
||||
></IonIcon>
|
||||
<div>{totalJoinMembers}</div>
|
||||
|
||||
<IonIcon
|
||||
icon={man}
|
||||
style={{ fontSize: '1.5rem', color: 'rgb(67, 110, 205)' }}
|
||||
></IonIcon>
|
||||
<div>{maleMembers}</div>
|
||||
|
||||
<IonIcon
|
||||
icon={woman}
|
||||
style={{ fontSize: '1.5rem', color: 'rgb(235, 50, 35)' }}
|
||||
></IonIcon>
|
||||
<div>{femaleMembers}</div>
|
||||
</div>
|
||||
</div>
|
||||
</IonContent>
|
||||
@@ -197,8 +286,11 @@ const EventDetail: React.FC<SpeakerDetailProps> = () => {
|
||||
};
|
||||
|
||||
export default connect({
|
||||
mapStateToProps: (state, ownProps) => ({
|
||||
event: selectors.getEvent(state, ownProps),
|
||||
}),
|
||||
mapStateToProps: (state, ownProps) => {
|
||||
console.log({ t1: selectors.getEvents(state) });
|
||||
return {
|
||||
event_detail: selectors.getEvent(state, ownProps),
|
||||
};
|
||||
},
|
||||
component: EventDetail,
|
||||
});
|
||||
|
Reference in New Issue
Block a user