From 917d83bfb70d863944df62fb3ca254ba74e67e6e Mon Sep 17 00:00:00 2001 From: eug-vs Date: Fri, 14 Aug 2020 04:09:56 +0300 Subject: feat: add EmptyState component --- package-lock.json | 2 +- package.json | 2 +- src/assets/noContent.svg | 1 + src/components/EmptyState/EmptyState.tsx | 33 +++++++++++++++++++++ src/containers/Feed/Feed.tsx | 12 ++++++-- src/containers/Feed/types.ts | 7 ----- src/containers/Home/Home.tsx | 50 +++++++++++++++++--------------- src/containers/Profile/Profile.tsx | 15 ++++++---- src/containers/Profile/ProfileInfo.tsx | 5 ++-- src/hooks/APIClient.ts | 16 +++------- 10 files changed, 88 insertions(+), 55 deletions(-) create mode 100644 src/assets/noContent.svg create mode 100644 src/components/EmptyState/EmptyState.tsx delete mode 100644 src/containers/Feed/types.ts diff --git a/package-lock.json b/package-lock.json index d0b962b..4d959da 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "which", - "version": "1.2.0", + "version": "1.2.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index c2d414f..1c11638 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "which", - "version": "1.2.0", + "version": "1.2.1", "homepage": "https://which-ecosystem.github.io/", "dependencies": { "@material-ui/core": "^4.10.1", diff --git a/src/assets/noContent.svg b/src/assets/noContent.svg new file mode 100644 index 0000000..e022f88 --- /dev/null +++ b/src/assets/noContent.svg @@ -0,0 +1 @@ +Tree_swing \ No newline at end of file diff --git a/src/components/EmptyState/EmptyState.tsx b/src/components/EmptyState/EmptyState.tsx new file mode 100644 index 0000000..b103e3c --- /dev/null +++ b/src/components/EmptyState/EmptyState.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import Typography from '@material-ui/core/Typography'; +import { makeStyles } from '@material-ui/core/styles'; +import noContentIcon from '../../assets/noContent.svg'; + +const useStyles = makeStyles(theme => ({ + root: { + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center' + }, + img: { + margin: theme.spacing(2), + width: theme.spacing(24) + } + +})); + +const EmptyState: React.FC = () => { + const classes = useStyles(); + + return ( +
+ No content + + No content + +
+ ); +}; + +export default EmptyState; diff --git a/src/containers/Feed/Feed.tsx b/src/containers/Feed/Feed.tsx index 10b1adc..337f4c1 100644 --- a/src/containers/Feed/Feed.tsx +++ b/src/containers/Feed/Feed.tsx @@ -3,18 +3,26 @@ import { Container } from '@material-ui/core/'; import PollsList from '../../components/PollsList/PollsList'; import Fab from '../../components/Fab/Fab'; +import Loading from '../../components/Loading/Loading'; +import EmptyState from '../../components/EmptyState/EmptyState'; import { useAuth } from '../../hooks/useAuth'; import { useFeed } from '../../hooks/APIClient'; const Feed: React.FC = () => { - const { data: polls, mutate } = useFeed(); + const { data: polls, isValidating, mutate } = useFeed(); const { isAuthenticated } = useAuth(); return ( {isAuthenticated && } - + { + polls + ? polls.length + ? + : + : isValidating && + } ); }; diff --git a/src/containers/Feed/types.ts b/src/containers/Feed/types.ts deleted file mode 100644 index 24ace4e..0000000 --- a/src/containers/Feed/types.ts +++ /dev/null @@ -1,7 +0,0 @@ -export interface ImageData { - url: string; -} -export interface Contents { - left: ImageData; - right: ImageData; -} diff --git a/src/containers/Home/Home.tsx b/src/containers/Home/Home.tsx index 203b380..c0ca00e 100644 --- a/src/containers/Home/Home.tsx +++ b/src/containers/Home/Home.tsx @@ -48,10 +48,10 @@ const Home: React.FC = () => { const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down('sm')); - const rating = feedbacks.length && feedbacks.reduce( + const rating = feedbacks?.length ? feedbacks.reduce( (acc: number, feedback: Feedback) => acc + feedback.score, 0 - ) / feedbacks.length; + ) / feedbacks.length : 0; const handleLetsGo = () => { history.push('/feed'); @@ -70,36 +70,38 @@ const Home: React.FC = () => { const Reviews = (
- {feedbacks.map((feedback: Feedback) => )} + {feedbacks?.map((feedback: Feedback) => )}
); - const FeedbackSection = feedbacks.findIndex((feedback: Feedback) => feedback.author._id === user?._id) >= 0 ? ( + const FeedbackSection = feedbacks && feedbacks.findIndex( + (feedback: Feedback) => feedback.author._id === user?._id + ) >= 0 ? (

You have already left feedback for this version. If you have more to say, please open GitHub issue or contact us directly via email: {EmailLink}. Alternatively, you can just wait for another application patch to come out.

- ) : ( - <> -

- Here you can share your thougts about Which with us! - Note that you can ony leave feedback once per application version (there will be plenty of them later). -

- {isAuthenticated ? : ( - <> -

You must be authorized to leave feedback.

- - - )} - - ); + ) : ( + <> +

+ Here you can share your thougts about Which with us! + Note that you can ony leave feedback once per application version (there will be plenty of them later). +

+ {isAuthenticated ? : ( + <> +

You must be authorized to leave feedback.

+ + + )} + + ); return (
diff --git a/src/containers/Profile/Profile.tsx b/src/containers/Profile/Profile.tsx index 33abfc2..fe77ff2 100644 --- a/src/containers/Profile/Profile.tsx +++ b/src/containers/Profile/Profile.tsx @@ -7,6 +7,7 @@ import ProfileInfo from './ProfileInfo'; import PollsList from '../../components/PollsList/PollsList'; import Loading from '../../components/Loading/Loading'; import Fab from '../../components/Fab/Fab'; +import EmptyState from '../../components/EmptyState/EmptyState'; import { useAuth } from '../../hooks/useAuth'; import { useUser, useProfile } from '../../hooks/APIClient'; @@ -27,25 +28,27 @@ const Profile: React.FC = () => { }, [username, history, user]); - const totalVotes = useMemo(() => polls.reduce( + const totalVotes = useMemo(() => polls?.reduce( (total: number, current: Poll) => { const { left, right } = current.contents; return total + left.votes + right.votes; }, 0 - ), [polls]); + ) || 0, [polls]); return ( { - isValidating && !polls - ? - : + polls + ? polls.length + ? + : + : isValidating && } {user?.username === username && } diff --git a/src/containers/Profile/ProfileInfo.tsx b/src/containers/Profile/ProfileInfo.tsx index 82f640d..c5c5454 100644 --- a/src/containers/Profile/ProfileInfo.tsx +++ b/src/containers/Profile/ProfileInfo.tsx @@ -21,7 +21,8 @@ interface PropTypes { const useStyles = makeStyles(theme => ({ root: { - position: 'relative' + position: 'relative', + marginBottom: theme.spacing(2) }, avatar: { width: 150, @@ -43,7 +44,7 @@ const useStyles = makeStyles(theme => ({ display: 'flex', width: '100%', height: 50, - margin: '50px 0', + marginTop: theme.spacing(6), borderBottom: '1px solid lightgray' }, menuButton: { diff --git a/src/hooks/APIClient.ts b/src/hooks/APIClient.ts index 9563bd6..f66ef2e 100644 --- a/src/hooks/APIClient.ts +++ b/src/hooks/APIClient.ts @@ -2,18 +2,10 @@ import useSWR, { responseInterface } from 'swr'; import { User, Poll, Feedback } from 'which-types'; import { get } from '../requests'; - -interface Response extends responseInterface { - data: T; -} +type Response = responseInterface; const fetcher = (endpoint: string) => get(endpoint).then(response => response.data); -const arrayOptions = { - initialData: [], - revalidateOnMount: true -}; - export const useUser = (username: string | null): Response => { return useSWR( username && `/users?username=${username}`, @@ -22,13 +14,13 @@ export const useUser = (username: string | null): Response => { }; export const useProfile = (id: string): Response => { - return useSWR(id && `/profiles/${id}`, fetcher, arrayOptions) as Response; + return useSWR(id && `/profiles/${id}`, fetcher) as Response; }; export const useFeed = (): Response => { - return useSWR('/feed', fetcher, { ...arrayOptions, revalidateOnFocus: false }) as Response; + return useSWR('/feed', fetcher, { revalidateOnFocus: false }) as Response; }; export const useFeedback = (): Response => { - return useSWR('/feedback', fetcher, arrayOptions) as Response; + return useSWR('/feedback', fetcher) as Response; }; -- cgit v1.2.3 From c30f59c85d8c57a9250635d96e3a295345c45ba7 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Fri, 14 Aug 2020 04:31:15 +0300 Subject: feat: add message to EmptyState --- src/components/EmptyState/EmptyState.tsx | 11 ++++++++++- src/containers/Profile/Profile.tsx | 5 +++-- src/containers/Profile/ProfileInfo.tsx | 2 +- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/components/EmptyState/EmptyState.tsx b/src/components/EmptyState/EmptyState.tsx index b103e3c..f6a6363 100644 --- a/src/components/EmptyState/EmptyState.tsx +++ b/src/components/EmptyState/EmptyState.tsx @@ -3,6 +3,10 @@ import Typography from '@material-ui/core/Typography'; import { makeStyles } from '@material-ui/core/styles'; import noContentIcon from '../../assets/noContent.svg'; +interface PropTypes { + message?: string; +} + const useStyles = makeStyles(theme => ({ root: { display: 'flex', @@ -17,7 +21,7 @@ const useStyles = makeStyles(theme => ({ })); -const EmptyState: React.FC = () => { +const EmptyState: React.FC = ({ message }) => { const classes = useStyles(); return ( @@ -26,6 +30,11 @@ const EmptyState: React.FC = () => { No content + +

+ {message} +

+
); }; diff --git a/src/containers/Profile/Profile.tsx b/src/containers/Profile/Profile.tsx index fe77ff2..701aa06 100644 --- a/src/containers/Profile/Profile.tsx +++ b/src/containers/Profile/Profile.tsx @@ -27,6 +27,7 @@ const Profile: React.FC = () => { } }, [username, history, user]); + const isOwnProfile = useMemo(() => user?.username === username, [user, username]); const totalVotes = useMemo(() => polls?.reduce( (total: number, current: Poll) => { @@ -47,10 +48,10 @@ const Profile: React.FC = () => { polls ? polls.length ? - : + : : isValidating && } - {user?.username === username && } + {isOwnProfile && } ); }; diff --git a/src/containers/Profile/ProfileInfo.tsx b/src/containers/Profile/ProfileInfo.tsx index c5c5454..c9831f3 100644 --- a/src/containers/Profile/ProfileInfo.tsx +++ b/src/containers/Profile/ProfileInfo.tsx @@ -22,7 +22,7 @@ interface PropTypes { const useStyles = makeStyles(theme => ({ root: { position: 'relative', - marginBottom: theme.spacing(2) + marginBottom: theme.spacing(4) }, avatar: { width: 150, -- cgit v1.2.3 From 1d35dd8a80f0ea72306e96c2229a27798ec75ce9 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Fri, 14 Aug 2020 04:59:45 +0300 Subject: feat: use EmptyState variants --- src/assets/construction.svg | 1 + src/components/EmptyState/EmptyState.tsx | 22 +++++++++++++++++++--- src/containers/Notifications/Notifications.tsx | 11 +++++------ 3 files changed, 25 insertions(+), 9 deletions(-) create mode 100644 src/assets/construction.svg diff --git a/src/assets/construction.svg b/src/assets/construction.svg new file mode 100644 index 0000000..bdb9eaa --- /dev/null +++ b/src/assets/construction.svg @@ -0,0 +1 @@ +towing \ No newline at end of file diff --git a/src/components/EmptyState/EmptyState.tsx b/src/components/EmptyState/EmptyState.tsx index f6a6363..214bb56 100644 --- a/src/components/EmptyState/EmptyState.tsx +++ b/src/components/EmptyState/EmptyState.tsx @@ -2,8 +2,11 @@ import React from 'react'; import Typography from '@material-ui/core/Typography'; import { makeStyles } from '@material-ui/core/styles'; import noContentIcon from '../../assets/noContent.svg'; +import constructionIcon from '../../assets/construction.svg'; + interface PropTypes { + variant?: 'default' | 'construction'; message?: string; } @@ -21,14 +24,27 @@ const useStyles = makeStyles(theme => ({ })); -const EmptyState: React.FC = ({ message }) => { +const CONTEXT = { + default: { + icon: noContentIcon, + tagline: 'No content' + }, + construction: { + icon: constructionIcon, + tagline: 'Coming soon' + } +}; + +const EmptyState: React.FC = ({ variant = 'default', message }) => { const classes = useStyles(); + const { icon, tagline } = CONTEXT[variant]; + return (
- No content + No content - No content + {tagline}

diff --git a/src/containers/Notifications/Notifications.tsx b/src/containers/Notifications/Notifications.tsx index 0648eb5..2a9ea13 100644 --- a/src/containers/Notifications/Notifications.tsx +++ b/src/containers/Notifications/Notifications.tsx @@ -1,11 +1,10 @@ import React from 'react'; import { makeStyles } from '@material-ui/core/styles'; -import { Typography } from '@material-ui/core'; +import EmptyState from '../../components/EmptyState/EmptyState'; const useStyles = makeStyles(theme => ({ root: { - marginTop: theme.spacing(25), - textAlign: 'center' + marginTop: theme.spacing(25) } })); @@ -13,9 +12,9 @@ const Notifications: React.FC = () => { const classes = useStyles(); return ( - - Sorry, this page is being constructed yet. - +

+ +
); }; -- cgit v1.2.3