From 4a47db4b921d0f691dbf87c6cc408b4971e866d2 Mon Sep 17 00:00:00 2001 From: welvin21 Date: Tue, 28 Apr 2020 16:47:06 +0800 Subject: [PATCH 01/13] Init routes for event details --- src/App.js | 8 +++--- .../routes/event-details/EventDetails.js | 28 +++++++++++++++++++ src/components/routes/index.js | 5 ++++ 3 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 src/components/routes/event-details/EventDetails.js create mode 100644 src/components/routes/index.js diff --git a/src/App.js b/src/App.js index 6a67e01..6f42514 100644 --- a/src/App.js +++ b/src/App.js @@ -4,9 +4,8 @@ import { useQuery } from '@apollo/react-hooks'; import { makeStyles } from '@material-ui/core'; import { GET_ME } from './gql/users'; import { redirectToLogin } from './functions'; -import { Homepage } from './components/routes/homepage/Homepage'; import { Header, Loading } from './components/shared'; -import { UserProfile } from './components/routes/user-profile/UserProfile'; +import { Homepage, UserProfile, EventDetails } from './components/routes/'; const useStyles = makeStyles(theme => ({ root: { @@ -38,8 +37,9 @@ export const App = () => {
- } /> - } /> + + + diff --git a/src/components/routes/event-details/EventDetails.js b/src/components/routes/event-details/EventDetails.js new file mode 100644 index 0000000..c4b7358 --- /dev/null +++ b/src/components/routes/event-details/EventDetails.js @@ -0,0 +1,28 @@ +import React from 'react'; +import { Switch, Route } from 'react-router-dom'; +import { Loading } from '../../shared'; +import { useDataFetching } from '../../../custom-hooks'; + +export const EventDetails = () => { + const { data, loading, error } = useDataFetching(); + + if (loading) return ; + if (error) console.log(error); + + const { events } = data; + + return ( + <> + + {events.map(event => ( +
{JSON.stringify(event)}
} + /> + ))} +
+ + ); +}; diff --git a/src/components/routes/index.js b/src/components/routes/index.js new file mode 100644 index 0000000..197bc13 --- /dev/null +++ b/src/components/routes/index.js @@ -0,0 +1,5 @@ +import { Homepage } from './homepage/Homepage'; +import { UserProfile } from './user-profile/UserProfile'; +import { EventDetails } from './event-details/EventDetails'; + +export { Homepage, UserProfile, EventDetails }; From b6d362ba816c437be4002bbc6183c47a2e59f7c4 Mon Sep 17 00:00:00 2001 From: welvin21 Date: Wed, 29 Apr 2020 22:37:41 +0800 Subject: [PATCH 02/13] Separate getSubscriptionStatus function --- src/components/routes/homepage/Events.js | 9 ++------- src/functions/getSubscriptionStatus.js | 2 ++ src/functions/index.js | 4 +++- 3 files changed, 7 insertions(+), 8 deletions(-) create mode 100644 src/functions/getSubscriptionStatus.js diff --git a/src/components/routes/homepage/Events.js b/src/components/routes/homepage/Events.js index f28f289..6f6cd47 100644 --- a/src/components/routes/homepage/Events.js +++ b/src/components/routes/homepage/Events.js @@ -2,7 +2,7 @@ import React, { useState } from 'react'; import { MediaCard } from './MediaCard'; import { Container, Typography, makeStyles } from '@material-ui/core'; import { SearchBar } from './SearchBar'; -import { filterEvents, sortEvents } from '../../../functions'; +import { filterEvents, getSubscriptionStatus, sortEvents } from '../../../functions'; const useStyles = makeStyles(theme => ({ container: { @@ -35,11 +35,6 @@ export const Events = ({ events, me: { username } }) => { const filteredEvents = filterEvents({ events, filter }); const sortedEvents = sortEvents({ events: [...filteredEvents], sortParam }); - const getSubscriptionStatus = ({ subscribers }) => - subscribers - .map(({ username: subscribersUsername }) => subscribersUsername) - .includes(username); - return ( { ); diff --git a/src/functions/getSubscriptionStatus.js b/src/functions/getSubscriptionStatus.js new file mode 100644 index 0000000..238e0a3 --- /dev/null +++ b/src/functions/getSubscriptionStatus.js @@ -0,0 +1,2 @@ +export const getSubscriptionStatus = (subscribers, username) => + subscribers.map(({ username }) => username).includes(username); diff --git a/src/functions/index.js b/src/functions/index.js index 326a2c5..f0f864b 100644 --- a/src/functions/index.js +++ b/src/functions/index.js @@ -2,6 +2,7 @@ import { createModalMessage } from './createModalMessage'; import { filterEvents, selectUserEvents, sortEvents } from './filterEvents'; import { redirectToLogin } from './redirectToLogin'; import { validateEvent } from './validateEvent'; +import { getSubscriptionStatus } from './getSubscriptionStatus'; export { createModalMessage, @@ -9,5 +10,6 @@ export { validateEvent, filterEvents, selectUserEvents, - sortEvents + sortEvents, + getSubscriptionStatus }; From 8b07e929679635377de0f5d47e321e6f77feb72a Mon Sep 17 00:00:00 2001 From: welvin21 Date: Thu, 30 Apr 2020 01:48:41 +0800 Subject: [PATCH 03/13] Add event detail page for each events --- .../routes/event-details/EventDescription.js | 68 +++++++++++++++ .../routes/event-details/EventDetail.js | 27 ++++++ .../routes/event-details/EventDetails.js | 22 +++-- .../routes/event-details/EventToolbar.js | 83 +++++++++++++++++++ .../event-details/share-event/ShareEvent.js | 51 ++++++++++++ .../share-event/ShareEventDetails.js | 18 ++++ src/components/routes/homepage/MediaCard.js | 3 + src/gql/events.js | 2 + 8 files changed, 265 insertions(+), 9 deletions(-) create mode 100644 src/components/routes/event-details/EventDescription.js create mode 100644 src/components/routes/event-details/EventDetail.js create mode 100644 src/components/routes/event-details/EventToolbar.js create mode 100644 src/components/routes/event-details/share-event/ShareEvent.js create mode 100644 src/components/routes/event-details/share-event/ShareEventDetails.js diff --git a/src/components/routes/event-details/EventDescription.js b/src/components/routes/event-details/EventDescription.js new file mode 100644 index 0000000..a4c0aeb --- /dev/null +++ b/src/components/routes/event-details/EventDescription.js @@ -0,0 +1,68 @@ +import React from 'react'; +import moment from 'moment'; +import { + Container, + Typography, + makeStyles, + CardMedia +} from '@material-ui/core'; +import placeholder from '../../../assets/no_image_placeholder.png'; + +const useStyles = makeStyles(theme => ({ + root: { + display: 'grid', + gridTemplateColumns: '70% 30%', + maxHeight: 500, + padding: 0, + [theme.breakpoints.down('sm')]: { + gridTemplateColumns: '100%', + maxHeight: 'none' + } + }, + media: { + width: '100%', + paddingTop: '60%' + }, + eventDetails: { + maxHeight: 500, + overflowY: 'scroll', + padding: `min(10%, ${theme.spacing(4)}px)` + }, + descriptionDetails: { + margin: `${theme.spacing(2)}px 0px` + } +})); + +const getTimeDescription = ({ start, end }) => + moment(start).isSame(moment(end), 'd') + ? `${moment(start).format('ll')}, ${moment(start).format('LT')} - ${moment( + end + ).format('LT')}` + : `${moment(start).format('lll')} - ${moment(end).format('lll')}`; + +export const EventDescription = ({ + event: { title, image_url, subscribers, start, end, description } +}) => { + const classes = useStyles(); + + return ( + + + + + {title} + + + {getTimeDescription({ start, end })} + + + {description} + + + + ); +}; diff --git a/src/components/routes/event-details/EventDetail.js b/src/components/routes/event-details/EventDetail.js new file mode 100644 index 0000000..45b20da --- /dev/null +++ b/src/components/routes/event-details/EventDetail.js @@ -0,0 +1,27 @@ +import React from 'react'; +import { Container, makeStyles, Card } from '@material-ui/core'; +import { EventDescription } from './EventDescription'; +import { EventToolbar } from './EventToolbar'; + +const useStyles = makeStyles(theme => ({ + root: { + padding: theme.spacing(5), + width: '100%' + }, + card: { + width: '100%' + } +})); + +export const EventDetail = ({ event, me }) => { + const classes = useStyles(); + + return ( + + + + + + + ); +}; diff --git a/src/components/routes/event-details/EventDetails.js b/src/components/routes/event-details/EventDetails.js index c4b7358..c8fac5d 100644 --- a/src/components/routes/event-details/EventDetails.js +++ b/src/components/routes/event-details/EventDetails.js @@ -1,5 +1,6 @@ import React from 'react'; import { Switch, Route } from 'react-router-dom'; +import { EventDetail } from './EventDetail'; import { Loading } from '../../shared'; import { useDataFetching } from '../../../custom-hooks'; @@ -9,19 +10,22 @@ export const EventDetails = () => { if (loading) return ; if (error) console.log(error); - const { events } = data; + const { events, me } = data; return ( <> - {events.map(event => ( -
{JSON.stringify(event)}
} - /> - ))} + {events.map(event => { + const { id } = event; + return ( + } + /> + ); + })}
); diff --git a/src/components/routes/event-details/EventToolbar.js b/src/components/routes/event-details/EventToolbar.js new file mode 100644 index 0000000..2eb28b4 --- /dev/null +++ b/src/components/routes/event-details/EventToolbar.js @@ -0,0 +1,83 @@ +import React, { useState } from 'react'; +import { makeStyles, Container, Typography, Button } from '@material-ui/core'; +import { ShareEvent } from './share-event/ShareEvent'; +import { Modal } from '../../shared'; +import { useSubscribeMutations } from '../../../custom-hooks'; +import { createModalMessage, getSubscriptionStatus } from '../../../functions'; + +const useStyles = makeStyles(theme => ({ + root: { + display: 'grid', + gridTemplateColumns: '70% 30%', + padding: `${theme.spacing(2)}px 0px`, + [theme.breakpoints.down('xs')]: { + gridTemplateColumns: '100%' + } + }, + buttonsBar: { + padding: 0 + }, + subscribedButton: { + color: '#000', + backgroundColor: theme.palette.others.main, + '&:hover': { + backgroundColor: theme.palette.others.dark + } + } +})); + +export const EventToolbar = ({ + event: { + id, + organiser: { first_name, last_name, email }, + subscribers + }, + me: { username } +}) => { + const classes = useStyles(); + + const subcriptionStatus = getSubscriptionStatus(subscribers, username); + const [isSubscribed, setIsSubscribed] = useState(subcriptionStatus); + const [modal, setModal] = useState({ + isOpen: false, + title: '' + }); + + const { + methods: { subscribeEvent, unsubscribeEvent }, + loading: subscribeMutationLoading, + error: { subscribeError, unsubscribeError } + } = useSubscribeMutations(); + + const onSubscribeButtonClicked = () => { + if (!isSubscribed) + subscribeEvent({ variables: { id } }) + .then(({ data }) => setIsSubscribed(true)) + .catch(err => setModal(createModalMessage('error'))); + else + unsubscribeEvent({ variables: { id } }) + .then(({ data }) => setIsSubscribed(false)) + .catch(err => setModal(createModalMessage('error'))); + }; + + if (subscribeError || unsubscribeError) + console.log({ subscribeError, unsubscribeError }); + + return ( + + window.location.reload()} /> + {`by ${first_name} ${last_name} (${email})`} + + + + + + ); +}; diff --git a/src/components/routes/event-details/share-event/ShareEvent.js b/src/components/routes/event-details/share-event/ShareEvent.js new file mode 100644 index 0000000..0d655f5 --- /dev/null +++ b/src/components/routes/event-details/share-event/ShareEvent.js @@ -0,0 +1,51 @@ +import React, { useState } from 'react'; +import { makeStyles, Button } from '@material-ui/core'; +import { ShareEventDetails } from './ShareEventDetails'; +import { SubscribersModal } from '../../../shared/subscribers'; + +const useStyles = makeStyles(theme => ({ + shareButton: { + marginTop: theme.spacing(1), + color: theme.palette.primary.light, + backgroundColor: theme.palette.background.default, + border: `1px solid ${theme.palette.primary.light}`, + '&:hover': { + color: '#fff', + backgroundColor: theme.palette.primary.light + } + } +})); + +export const ShareEvent = () => { + const classes = useStyles(); + const defaultModalContent = { title: '', childComponent: <> }; + + const [modal, setModal] = useState({ + isOpen: false, + modalContent: defaultModalContent + }); + + const shareEventModalContent = ; + const modalContent = { + title: 'Share event', + childComponent: shareEventModalContent + }; + + return ( + <> + + setModal({ isOpen: false, modalContent: defaultModalContent }) + } + /> + + + ); +}; diff --git a/src/components/routes/event-details/share-event/ShareEventDetails.js b/src/components/routes/event-details/share-event/ShareEventDetails.js new file mode 100644 index 0000000..0215d3e --- /dev/null +++ b/src/components/routes/event-details/share-event/ShareEventDetails.js @@ -0,0 +1,18 @@ +import React from 'react'; +import { Container, makeStyles, OutlinedInput } from '@material-ui/core'; + +const useStyles = makeStyles(theme => ({ + root: { + padding: theme.spacing(1) + } +})); + +export const ShareEventDetails = () => { + const classes = useStyles(); + + return ( + + + + ); +}; diff --git a/src/components/routes/homepage/MediaCard.js b/src/components/routes/homepage/MediaCard.js index ddd6ef3..713e9e8 100644 --- a/src/components/routes/homepage/MediaCard.js +++ b/src/components/routes/homepage/MediaCard.js @@ -13,6 +13,7 @@ import placeholder from '../../../assets/no_image_placeholder.png'; import { useSubscribeMutations } from '../../../custom-hooks'; import { Modal, SubscribersList } from '../../shared'; import { createModalMessage } from '../../../functions'; +import { Link } from 'react-router-dom'; const useStyles = makeStyles(theme => ({ root: { @@ -100,6 +101,8 @@ export const MediaCard = ({ className={classes.media} image={image_url ? image_url : placeholder} title={title} + component={Link} + to={`/event/${id}`} /> diff --git a/src/gql/events.js b/src/gql/events.js index 5e6f865..e083ab0 100644 --- a/src/gql/events.js +++ b/src/gql/events.js @@ -7,6 +7,8 @@ const GET_ALL_EVENTS = gql` organiser { id username + first_name + last_name email } title From 31d1325022e8e18eef960697ab1779ddf82e0cf1 Mon Sep 17 00:00:00 2001 From: welvin21 Date: Thu, 30 Apr 2020 01:56:52 +0800 Subject: [PATCH 04/13] Refactors SubscribersModal component --- .../routes/event-details/share-event/ShareEvent.js | 4 ++-- .../SubscribersModal.js => ComplexModal.js} | 2 +- src/components/shared/index.js | 10 +++++++++- src/components/shared/subscribers/SubscribersList.js | 2 +- src/components/shared/subscribers/index.js | 3 +-- 5 files changed, 14 insertions(+), 7 deletions(-) rename src/components/shared/{subscribers/SubscribersModal.js => ComplexModal.js} (96%) diff --git a/src/components/routes/event-details/share-event/ShareEvent.js b/src/components/routes/event-details/share-event/ShareEvent.js index 0d655f5..4d51253 100644 --- a/src/components/routes/event-details/share-event/ShareEvent.js +++ b/src/components/routes/event-details/share-event/ShareEvent.js @@ -1,7 +1,7 @@ import React, { useState } from 'react'; import { makeStyles, Button } from '@material-ui/core'; import { ShareEventDetails } from './ShareEventDetails'; -import { SubscribersModal } from '../../../shared/subscribers'; +import { ComplexModal as ShareEventModal } from '../../../shared'; const useStyles = makeStyles(theme => ({ shareButton: { @@ -33,7 +33,7 @@ export const ShareEvent = () => { return ( <> - setModal({ isOpen: false, modalContent: defaultModalContent }) diff --git a/src/components/shared/subscribers/SubscribersModal.js b/src/components/shared/ComplexModal.js similarity index 96% rename from src/components/shared/subscribers/SubscribersModal.js rename to src/components/shared/ComplexModal.js index 1f85745..325eb3c 100644 --- a/src/components/shared/subscribers/SubscribersModal.js +++ b/src/components/shared/ComplexModal.js @@ -24,7 +24,7 @@ const useStyles = makeStyles(theme => ({ } })); -export const SubscribersModal = ({ +export const ComplexModal = ({ modalDetails: { isOpen, modalContent }, onClose }) => { diff --git a/src/components/shared/index.js b/src/components/shared/index.js index cbf1c92..6d73473 100644 --- a/src/components/shared/index.js +++ b/src/components/shared/index.js @@ -1,6 +1,14 @@ import { Header } from './Header'; import { Loading } from './Loading'; import { Modal } from './Modal'; +import { ComplexModal } from './ComplexModal'; import { SubscribersList, SubscribersDetails } from './subscribers'; -export { Header, Loading, Modal, SubscribersList, SubscribersDetails }; +export { + Header, + Loading, + Modal, + ComplexModal, + SubscribersList, + SubscribersDetails +}; diff --git a/src/components/shared/subscribers/SubscribersList.js b/src/components/shared/subscribers/SubscribersList.js index cb1780f..7f58d69 100644 --- a/src/components/shared/subscribers/SubscribersList.js +++ b/src/components/shared/subscribers/SubscribersList.js @@ -2,7 +2,7 @@ import React, { useState } from 'react'; import { Typography, makeStyles } from '@material-ui/core'; import { ThumbUpAltRounded as ThumbUpIcon } from '@material-ui/icons'; import { SubscribersDetails } from './SubscribersDetails'; -import { SubscribersModal } from './SubscribersModal'; +import { ComplexModal as SubscribersModal } from '../'; const useStyles = makeStyles(theme => ({ subscribersCount: { diff --git a/src/components/shared/subscribers/index.js b/src/components/shared/subscribers/index.js index 416e27c..18fa3eb 100644 --- a/src/components/shared/subscribers/index.js +++ b/src/components/shared/subscribers/index.js @@ -1,5 +1,4 @@ import { SubscribersList } from './SubscribersList'; import { SubscribersDetails } from './SubscribersDetails'; -import { SubscribersModal } from './SubscribersModal'; -export { SubscribersList, SubscribersDetails, SubscribersModal }; +export { SubscribersList, SubscribersDetails }; From 5fcfac03dcac2fe54dfc6ce55a864dd06ae34deb Mon Sep 17 00:00:00 2001 From: welvin21 Date: Thu, 30 Apr 2020 14:09:33 +0800 Subject: [PATCH 05/13] Disables card on craeteEvent form --- src/components/routes/homepage/Events.js | 2 +- src/components/routes/homepage/MediaCard.js | 6 +++--- src/components/routes/homepage/event-form/EventForm.js | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/routes/homepage/Events.js b/src/components/routes/homepage/Events.js index 6f6cd47..bb2ba73 100644 --- a/src/components/routes/homepage/Events.js +++ b/src/components/routes/homepage/Events.js @@ -57,7 +57,7 @@ export const Events = ({ events, me: { username } }) => { key={id} event={event} isEventSubscribed={getSubscriptionStatus(subscribers, username)} - disableMutation={false} + disableCard={false} /> ); })} diff --git a/src/components/routes/homepage/MediaCard.js b/src/components/routes/homepage/MediaCard.js index 713e9e8..75e2985 100644 --- a/src/components/routes/homepage/MediaCard.js +++ b/src/components/routes/homepage/MediaCard.js @@ -58,7 +58,7 @@ const useStyles = makeStyles(theme => ({ export const MediaCard = ({ event: { id, title, start, venue, image_url, subscribers }, isEventSubscribed, - disableMutation + disableCard }) => { const [elevation, setElevation] = useState(1); const [isSubscribed, setIsSubscribed] = useState(isEventSubscribed); @@ -102,7 +102,7 @@ export const MediaCard = ({ image={image_url ? image_url : placeholder} title={title} component={Link} - to={`/event/${id}`} + to={disableCard ? '#' : `/event/${id}`} /> @@ -110,7 +110,7 @@ export const MediaCard = ({ className={isSubscribed ? classes.subscribedButton : ''} size="small" onClick={() => onSubscribeButtonClicked()} - disabled={disableMutation || subscribeMutationLoading} + disabled={disableCard || subscribeMutationLoading} > {isSubscribed ? 'Subscribed' : 'Subscribe'} diff --git a/src/components/routes/homepage/event-form/EventForm.js b/src/components/routes/homepage/event-form/EventForm.js index 8b03aac..09c5787 100644 --- a/src/components/routes/homepage/event-form/EventForm.js +++ b/src/components/routes/homepage/event-form/EventForm.js @@ -145,7 +145,7 @@ export const EventForm = ({ onFormSubmit }) => { From 39f33ca928b94b5f77a86e18f461cc8420fb3ca5 Mon Sep 17 00:00:00 2001 From: welvin21 Date: Thu, 30 Apr 2020 14:32:12 +0800 Subject: [PATCH 06/13] Enable copy to clipboard functionality --- .../share-event/ShareEventDetails.js | 5 +- .../share-event/ShareEventLink.js | 46 +++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 src/components/routes/event-details/share-event/ShareEventLink.js diff --git a/src/components/routes/event-details/share-event/ShareEventDetails.js b/src/components/routes/event-details/share-event/ShareEventDetails.js index 0215d3e..74c9af9 100644 --- a/src/components/routes/event-details/share-event/ShareEventDetails.js +++ b/src/components/routes/event-details/share-event/ShareEventDetails.js @@ -1,5 +1,6 @@ import React from 'react'; -import { Container, makeStyles, OutlinedInput } from '@material-ui/core'; +import { Container, makeStyles } from '@material-ui/core'; +import { ShareEventLink } from './ShareEventLink'; const useStyles = makeStyles(theme => ({ root: { @@ -12,7 +13,7 @@ export const ShareEventDetails = () => { return ( - + ); }; diff --git a/src/components/routes/event-details/share-event/ShareEventLink.js b/src/components/routes/event-details/share-event/ShareEventLink.js new file mode 100644 index 0000000..cde085c --- /dev/null +++ b/src/components/routes/event-details/share-event/ShareEventLink.js @@ -0,0 +1,46 @@ +import React from 'react'; +import { + Container, + makeStyles, + OutlinedInput, + Tooltip +} from '@material-ui/core'; +import { Assignment as ClipboardIcon } from '@material-ui/icons'; + +const useStyles = makeStyles(theme => ({ + root: { + padding: 0, + display: 'grid', + gridTemplateColumns: '90% 10%', + justifyItems: 'center' + }, + clipboardIcon: { + height: '100%', + color: theme.palette.primary.dark, + '&:hover': { + cursor: 'pointer' + } + } +})); + +const copyEventLinkToClipboard = () => { + const copyText = document.getElementById('event-link'); + copyText.select(); + document.execCommand('copy'); +}; + +export const ShareEventLink = () => { + const classes = useStyles(); + + return ( + + + + copyEventLinkToClipboard()} + /> + + + ); +}; From 54b77bc56c8abd218dee839731040c8740834013 Mon Sep 17 00:00:00 2001 From: welvin21 Date: Thu, 30 Apr 2020 17:29:58 +0800 Subject: [PATCH 07/13] Add alert animation when event link is copied to clipboard --- .../share-event/ShareEventLink.js | 29 +++++++++++++------ src/components/shared/Alert.js | 29 +++++++++++++++++++ src/components/shared/index.js | 2 ++ 3 files changed, 51 insertions(+), 9 deletions(-) create mode 100644 src/components/shared/Alert.js diff --git a/src/components/routes/event-details/share-event/ShareEventLink.js b/src/components/routes/event-details/share-event/ShareEventLink.js index cde085c..18cb202 100644 --- a/src/components/routes/event-details/share-event/ShareEventLink.js +++ b/src/components/routes/event-details/share-event/ShareEventLink.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState } from 'react'; import { Container, makeStyles, @@ -6,6 +6,7 @@ import { Tooltip } from '@material-ui/core'; import { Assignment as ClipboardIcon } from '@material-ui/icons'; +import { Alert as ShareEventAlert } from '../../../shared'; const useStyles = makeStyles(theme => ({ root: { @@ -16,26 +17,36 @@ const useStyles = makeStyles(theme => ({ }, clipboardIcon: { height: '100%', - color: theme.palette.primary.dark, '&:hover': { cursor: 'pointer' } } })); -const copyEventLinkToClipboard = () => { - const copyText = document.getElementById('event-link'); - copyText.select(); - document.execCommand('copy'); -}; - export const ShareEventLink = () => { + const defaultAlertContent = { + isOpen: false, + alertContent: '' + }; + + const [alert, setAlert] = useState(defaultAlertContent); const classes = useStyles(); + const copyEventLinkToClipboard = () => { + const copyText = document.getElementById('event-link'); + copyText.select(); + document.execCommand('copy'); + setAlert({ isOpen: true, alertContent: 'Copied to clipboard' }); + }; + return ( + setAlert(defaultAlertContent)} + /> - + copyEventLinkToClipboard()} diff --git a/src/components/shared/Alert.js b/src/components/shared/Alert.js new file mode 100644 index 0000000..0cc3530 --- /dev/null +++ b/src/components/shared/Alert.js @@ -0,0 +1,29 @@ +import React from 'react'; +import { Snackbar, IconButton, Slide } from '@material-ui/core'; +import { Close as CloseIcon } from '@material-ui/icons'; + +const TransitionDown = props => ; + +export const Alert = ({ alertDetails: { isOpen, alertContent }, onClose }) => ( + + + + } + /> +); diff --git a/src/components/shared/index.js b/src/components/shared/index.js index 6d73473..8cab96c 100644 --- a/src/components/shared/index.js +++ b/src/components/shared/index.js @@ -2,6 +2,7 @@ import { Header } from './Header'; import { Loading } from './Loading'; import { Modal } from './Modal'; import { ComplexModal } from './ComplexModal'; +import { Alert } from './Alert'; import { SubscribersList, SubscribersDetails } from './subscribers'; export { @@ -9,6 +10,7 @@ export { Loading, Modal, ComplexModal, + Alert, SubscribersList, SubscribersDetails }; From 5ac6aee3b4b1f7058ea5cffe60672405fd2cd329 Mon Sep 17 00:00:00 2001 From: welvin21 Date: Thu, 30 Apr 2020 18:54:33 +0800 Subject: [PATCH 08/13] Add organiser info in event details page --- .../routes/event-details/EventToolbar.js | 14 ++- .../event-organiser/EventOrganiser.js | 93 +++++++++++++++++++ .../event-organiser/EventOrganiserInfo.js | 85 +++++++++++++++++ .../share-event/ShareEventLink.js | 4 +- src/gql/events.js | 2 + 5 files changed, 188 insertions(+), 10 deletions(-) create mode 100644 src/components/routes/event-details/event-organiser/EventOrganiser.js create mode 100644 src/components/routes/event-details/event-organiser/EventOrganiserInfo.js diff --git a/src/components/routes/event-details/EventToolbar.js b/src/components/routes/event-details/EventToolbar.js index 2eb28b4..23386b6 100644 --- a/src/components/routes/event-details/EventToolbar.js +++ b/src/components/routes/event-details/EventToolbar.js @@ -1,15 +1,17 @@ import React, { useState } from 'react'; -import { makeStyles, Container, Typography, Button } from '@material-ui/core'; +import { makeStyles, Container, Button } from '@material-ui/core'; import { ShareEvent } from './share-event/ShareEvent'; +import { EventOrganiser } from './event-organiser/EventOrganiser'; import { Modal } from '../../shared'; import { useSubscribeMutations } from '../../../custom-hooks'; import { createModalMessage, getSubscriptionStatus } from '../../../functions'; const useStyles = makeStyles(theme => ({ root: { + padding: `${theme.spacing(2)}px 0px`, display: 'grid', gridTemplateColumns: '70% 30%', - padding: `${theme.spacing(2)}px 0px`, + alignItems: 'center', [theme.breakpoints.down('xs')]: { gridTemplateColumns: '100%' } @@ -27,11 +29,7 @@ const useStyles = makeStyles(theme => ({ })); export const EventToolbar = ({ - event: { - id, - organiser: { first_name, last_name, email }, - subscribers - }, + event: { id, organiser, subscribers }, me: { username } }) => { const classes = useStyles(); @@ -66,7 +64,7 @@ export const EventToolbar = ({ return ( window.location.reload()} /> - {`by ${first_name} ${last_name} (${email})`} + - + ); diff --git a/src/components/routes/event-details/share-event/ShareEvent.js b/src/components/routes/event-details/share-event/ShareEvent.js index 4d51253..9be09c8 100644 --- a/src/components/routes/event-details/share-event/ShareEvent.js +++ b/src/components/routes/event-details/share-event/ShareEvent.js @@ -16,7 +16,7 @@ const useStyles = makeStyles(theme => ({ } })); -export const ShareEvent = () => { +export const ShareEvent = ({ event }) => { const classes = useStyles(); const defaultModalContent = { title: '', childComponent: <> }; @@ -25,7 +25,7 @@ export const ShareEvent = () => { modalContent: defaultModalContent }); - const shareEventModalContent = ; + const shareEventModalContent = ; const modalContent = { title: 'Share event', childComponent: shareEventModalContent diff --git a/src/components/routes/event-details/share-event/ShareEventDetails.js b/src/components/routes/event-details/share-event/ShareEventDetails.js index 74c9af9..e9aec6f 100644 --- a/src/components/routes/event-details/share-event/ShareEventDetails.js +++ b/src/components/routes/event-details/share-event/ShareEventDetails.js @@ -1,6 +1,7 @@ import React from 'react'; import { Container, makeStyles } from '@material-ui/core'; import { ShareEventLink } from './ShareEventLink'; +import { ShareEventQRCode } from './ShareEventQRCode'; const useStyles = makeStyles(theme => ({ root: { @@ -8,12 +9,13 @@ const useStyles = makeStyles(theme => ({ } })); -export const ShareEventDetails = () => { +export const ShareEventDetails = ({ event }) => { const classes = useStyles(); return ( + ); }; diff --git a/src/components/routes/event-details/share-event/ShareEventLink.js b/src/components/routes/event-details/share-event/ShareEventLink.js index b1b391b..511ec2a 100644 --- a/src/components/routes/event-details/share-event/ShareEventLink.js +++ b/src/components/routes/event-details/share-event/ShareEventLink.js @@ -45,7 +45,11 @@ export const ShareEventLink = () => { alertDetails={alert} onClose={() => setAlert(defaultAlertContent)} /> - + ({ + root: { + padding: 0, + display: 'grid', + justifyItems: 'center' + }, + qrCode: { + margin: `${theme.spacing(2)}px 0px`, + borderRadius: 5, + width: 256, + height: 256, + maxWidth: '70vw' + }, + saveButton: { + width: 256, + maxWidth: '70vw' + } +})); + +const downloadQRCode = ({ eventId }) => { + const img = document.createElement('img'); + const canvas = document.createElement('canvas'); + + // Get SVG data and convert it to base64 formst + const svg = document.getElementById('qr-code'); + const xml = new XMLSerializer().serializeToString(svg); + const svg64 = 'data:image/svg+xml;base64,' + btoa(xml); + + img.onload = () => { + canvas.getContext('2d').drawImage(img, 0, 0); + const link = document.createElement('a'); + link.download = `raven_${eventId}.png`; + link.href = canvas.toDataURL(); + link.click(); + }; + img.src = svg64; +}; + +export const ShareEventQRCode = ({ event: { id } }) => { + const classes = useStyles(); + + return ( + + + + + ); +}; From 2d12c4298b174721badb81ce4610da9c5d291379 Mon Sep 17 00:00:00 2001 From: welvin21 Date: Sat, 9 May 2020 02:51:24 +0800 Subject: [PATCH 11/13] Minor ui improvement --- src/components/routes/homepage/SearchBar.js | 22 +++++++++++++-------- src/components/shared/ComplexModal.js | 2 +- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/components/routes/homepage/SearchBar.js b/src/components/routes/homepage/SearchBar.js index 91a7f9b..f0568fc 100644 --- a/src/components/routes/homepage/SearchBar.js +++ b/src/components/routes/homepage/SearchBar.js @@ -19,7 +19,7 @@ const useStyles = makeStyles(theme => ({ gridGap: theme.spacing(1), alignItems: 'center' }, - searchBar: { + searchInput: { width: 'min(100%, 300px)', color: theme.palette.primary.main }, @@ -43,13 +43,19 @@ export const SearchBar = ({ setFilter, sortParam, setSortParam }) => { return ( - } - onChange={({ target: { value } }) => setFilter(value)} - /> - + + } + onChange={({ target: { value } }) => setFilter(value)} + /> + + Sort by diff --git a/src/components/shared/ComplexModal.js b/src/components/shared/ComplexModal.js index 325eb3c..4f1e7ad 100644 --- a/src/components/shared/ComplexModal.js +++ b/src/components/shared/ComplexModal.js @@ -10,7 +10,7 @@ import { const useStyles = makeStyles(theme => ({ root: { height: 'fit-content', - marginTop: '15%' + marginTop: '10%' }, title: { color: theme.palette.primary.dark, From 969cbdb28c800d82425ffeb0717ee54f88c1eae8 Mon Sep 17 00:00:00 2001 From: welvin21 Date: Sat, 9 May 2020 03:16:12 +0800 Subject: [PATCH 12/13] Refactor some code --- .../routes/event-details/EventDescription.js | 9 +----- .../routes/event-details/EventDetails.js | 28 +++++++++---------- src/components/routes/homepage/MediaCard.js | 2 +- .../routes/homepage/event-form/EventForm.js | 2 +- src/functions/{ => events}/filterEvents.js | 0 .../{ => events}/getSubscriptionStatus.js | 0 src/functions/events/index.js | 11 ++++++++ src/functions/{ => events}/quickSort.js | 0 src/functions/{ => events}/validateEvent.js | 0 src/functions/getTimeDescription.js | 8 ++++++ src/functions/index.js | 14 +++++++--- 11 files changed, 45 insertions(+), 29 deletions(-) rename src/functions/{ => events}/filterEvents.js (100%) rename src/functions/{ => events}/getSubscriptionStatus.js (100%) create mode 100644 src/functions/events/index.js rename src/functions/{ => events}/quickSort.js (100%) rename src/functions/{ => events}/validateEvent.js (100%) create mode 100644 src/functions/getTimeDescription.js diff --git a/src/components/routes/event-details/EventDescription.js b/src/components/routes/event-details/EventDescription.js index 7d8870c..9938ede 100644 --- a/src/components/routes/event-details/EventDescription.js +++ b/src/components/routes/event-details/EventDescription.js @@ -1,11 +1,11 @@ import React from 'react'; -import moment from 'moment'; import { Container, Typography, makeStyles, CardMedia } from '@material-ui/core'; +import { getTimeDescription } from '../../../functions'; import placeholder from '../../../assets/no_image_placeholder.png'; const useStyles = makeStyles(theme => ({ @@ -36,13 +36,6 @@ const useStyles = makeStyles(theme => ({ } })); -const getTimeDescription = ({ start, end }) => - moment(start).isSame(moment(end), 'd') - ? `${moment(start).format('ll')}, ${moment(start).format('LT')} - ${moment( - end - ).format('LT')}` - : `${moment(start).format('lll')} - ${moment(end).format('lll')}`; - export const EventDescription = ({ event: { title, image_url, subscribers, start, end, description } }) => { diff --git a/src/components/routes/event-details/EventDetails.js b/src/components/routes/event-details/EventDetails.js index c8fac5d..1d1f708 100644 --- a/src/components/routes/event-details/EventDetails.js +++ b/src/components/routes/event-details/EventDetails.js @@ -13,20 +13,18 @@ export const EventDetails = () => { const { events, me } = data; return ( - <> - - {events.map(event => { - const { id } = event; - return ( - } - /> - ); - })} - - + + {events.map(event => { + const { id } = event; + return ( + } + /> + ); + })} + ); }; diff --git a/src/components/routes/homepage/MediaCard.js b/src/components/routes/homepage/MediaCard.js index 75e2985..c633e9a 100644 --- a/src/components/routes/homepage/MediaCard.js +++ b/src/components/routes/homepage/MediaCard.js @@ -9,11 +9,11 @@ import { Typography, makeStyles } from '@material-ui/core'; +import { Link } from 'react-router-dom'; import placeholder from '../../../assets/no_image_placeholder.png'; import { useSubscribeMutations } from '../../../custom-hooks'; import { Modal, SubscribersList } from '../../shared'; import { createModalMessage } from '../../../functions'; -import { Link } from 'react-router-dom'; const useStyles = makeStyles(theme => ({ root: { diff --git a/src/components/routes/homepage/event-form/EventForm.js b/src/components/routes/homepage/event-form/EventForm.js index 09c5787..3c309f8 100644 --- a/src/components/routes/homepage/event-form/EventForm.js +++ b/src/components/routes/homepage/event-form/EventForm.js @@ -14,7 +14,7 @@ import { EventTimePicker } from './EventTimePicker'; import { ImagePicker } from './ImagePicker'; import { MediaCard } from '../MediaCard'; import { Modal } from '../../../shared'; -import { validateEvent } from '../../../../functions/validateEvent'; +import { validateEvent } from '../../../../functions'; import imagePlaceholder from '../../../../assets/no_image_placeholder.png'; const useStyles = makeStyles(theme => ({ diff --git a/src/functions/filterEvents.js b/src/functions/events/filterEvents.js similarity index 100% rename from src/functions/filterEvents.js rename to src/functions/events/filterEvents.js diff --git a/src/functions/getSubscriptionStatus.js b/src/functions/events/getSubscriptionStatus.js similarity index 100% rename from src/functions/getSubscriptionStatus.js rename to src/functions/events/getSubscriptionStatus.js diff --git a/src/functions/events/index.js b/src/functions/events/index.js new file mode 100644 index 0000000..1699faa --- /dev/null +++ b/src/functions/events/index.js @@ -0,0 +1,11 @@ +import { filterEvents, selectUserEvents, sortEvents } from './filterEvents'; +import { validateEvent } from './validateEvent'; +import { getSubscriptionStatus } from './getSubscriptionStatus'; + +export { + filterEvents, + selectUserEvents, + sortEvents, + validateEvent, + getSubscriptionStatus +}; diff --git a/src/functions/quickSort.js b/src/functions/events/quickSort.js similarity index 100% rename from src/functions/quickSort.js rename to src/functions/events/quickSort.js diff --git a/src/functions/validateEvent.js b/src/functions/events/validateEvent.js similarity index 100% rename from src/functions/validateEvent.js rename to src/functions/events/validateEvent.js diff --git a/src/functions/getTimeDescription.js b/src/functions/getTimeDescription.js new file mode 100644 index 0000000..787deb8 --- /dev/null +++ b/src/functions/getTimeDescription.js @@ -0,0 +1,8 @@ +import moment from 'moment'; + +export const getTimeDescription = ({ start, end }) => + moment(start).isSame(moment(end), 'd') + ? `${moment(start).format('ll')}, ${moment(start).format('LT')} - ${moment( + end + ).format('LT')}` + : `${moment(start).format('lll')} - ${moment(end).format('lll')}`; diff --git a/src/functions/index.js b/src/functions/index.js index f0f864b..c907cac 100644 --- a/src/functions/index.js +++ b/src/functions/index.js @@ -1,8 +1,13 @@ +import { + filterEvents, + selectUserEvents, + sortEvents, + validateEvent, + getSubscriptionStatus +} from './events'; import { createModalMessage } from './createModalMessage'; -import { filterEvents, selectUserEvents, sortEvents } from './filterEvents'; import { redirectToLogin } from './redirectToLogin'; -import { validateEvent } from './validateEvent'; -import { getSubscriptionStatus } from './getSubscriptionStatus'; +import { getTimeDescription } from './getTimeDescription'; export { createModalMessage, @@ -11,5 +16,6 @@ export { filterEvents, selectUserEvents, sortEvents, - getSubscriptionStatus + getSubscriptionStatus, + getTimeDescription }; From fd103cfdd146519f5d4a86dc49eca8b61ed6db5b Mon Sep 17 00:00:00 2001 From: welvin21 Date: Sat, 9 May 2020 20:41:25 +0800 Subject: [PATCH 13/13] Add slide animation on modal --- src/components/shared/ComplexModal.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/components/shared/ComplexModal.js b/src/components/shared/ComplexModal.js index 4f1e7ad..7789ee0 100644 --- a/src/components/shared/ComplexModal.js +++ b/src/components/shared/ComplexModal.js @@ -1,10 +1,11 @@ -import React from 'react'; +import React, { forwardRef } from 'react'; import { Typography, makeStyles, Dialog, DialogTitle, - DialogContent + DialogContent, + Slide } from '@material-ui/core'; const useStyles = makeStyles(theme => ({ @@ -24,6 +25,10 @@ const useStyles = makeStyles(theme => ({ } })); +const Transition = forwardRef((props, ref) => ( + +)); + export const ComplexModal = ({ modalDetails: { isOpen, modalContent }, onClose @@ -39,6 +44,7 @@ export const ComplexModal = ({ onClose={onClose} fullWidth maxWidth="xs" + TransitionComponent={Transition} className={classes.root} >