From 2555db871009f43b23c4d4e1d45347937eaca38d Mon Sep 17 00:00:00 2001 From: Meng To Date: Tue, 14 May 2019 16:31:24 -0400 Subject: [PATCH] Notifications Screen --- App.js | 4 + components/NotificationButton.js | 40 +++++ components/Notifications.js | 247 +++++++++++++++++++++++++++++++ screens/HomeScreen.js | 14 +- 4 files changed, 303 insertions(+), 2 deletions(-) create mode 100644 components/NotificationButton.js create mode 100644 components/Notifications.js diff --git a/App.js b/App.js index 4128a12..3717130 100644 --- a/App.js +++ b/App.js @@ -38,6 +38,10 @@ const reducer = (state = initialState, action) => { return { ...state, action: "openLogin" }; case "CLOSE_LOGIN": return { ...state, action: "closeLogin" }; + case "OPEN_NOTIF": + return { ...state, action: "openNotif" }; + case "CLOSE_NOTIF": + return { ...state, action: "closeNotif" }; default: return state; } diff --git a/components/NotificationButton.js b/components/NotificationButton.js new file mode 100644 index 0000000..2eb5629 --- /dev/null +++ b/components/NotificationButton.js @@ -0,0 +1,40 @@ +import React from "react"; +import styled from "styled-components"; +import { NotificationIcon } from "../components/Icons"; + +const NotificationButton = () => ( + + + + 3 + + +); + +export default NotificationButton; + +const Container = styled.View` + width: 44px; + height: 44px; + justify-content: center; + align-items: center; +`; + +const Bubble = styled.View` + width: 16px; + height: 16px; + background: #3c4560; + position: absolute; + top: 0px; + right: 5px; + border-radius: 8px; + justify-content: center; + align-items: center; + border: 1px solid white; +`; + +const Text = styled.Text` + color: white; + font-size: 12px; + font-weight: 700; +`; diff --git a/components/Notifications.js b/components/Notifications.js new file mode 100644 index 0000000..bce098a --- /dev/null +++ b/components/Notifications.js @@ -0,0 +1,247 @@ +import React from "react"; +import styled from "styled-components"; +import { + ScrollView, + SafeAreaView, + Animated, + TouchableOpacity, + Dimensions +} from "react-native"; +import { Icon } from "expo"; +import { connect } from "react-redux"; + +let screenWidth = Dimensions.get("window").width; +var cardWith = screenWidth - 40; +if (screenWidth > 500) { + cardWith = 460; +} + +function mapStateToProps(state) { + return { action: state.action }; +} + +function mapDispatchToProps(dispatch) { + return { + closeNotif: () => + dispatch({ + type: "CLOSE_NOTIF" + }) + }; +} + +class Notifications extends React.Component { + state = { + translateY: new Animated.Value(30), + opacity: new Animated.Value(0), + top: new Animated.Value(3000) + }; + + componentDidUpdate = () => { + this.toggleNotif(); + }; + + toggleNotif = () => { + if (this.props.action == "openNotif") { + Animated.parallel([ + Animated.spring(this.state.translateY, { + toValue: 0 + }), + Animated.timing(this.state.opacity, { + toValue: 1, + duration: 500 + }), + Animated.timing(this.state.top, { + toValue: 0, + duration: 0 + }) + ]).start(); + } + + if (this.props.action == "closeNotif") { + Animated.parallel([ + Animated.spring(this.state.translateY, { + toValue: 30 + }), + Animated.timing(this.state.opacity, { + toValue: 0, + duration: 500 + }), + Animated.timing(this.state.top, { + toValue: 3000, + duration: 0 + }) + ]).start(); + } + }; + + render() { + return ( + + + + + + + + + + New + {items.map((item, index) => ( + +
+ + {item.title} + + {item.date} + +
+ {item.text} +
+ ))} +
+
+
+
+ ); + } +} + +export default connect( + mapStateToProps, + mapDispatchToProps +)(Notifications); + +const Container = styled.View` + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 100; + background: #f0f3f5; +`; + +const AnimatedContainer = Animated.createAnimatedComponent(Container); + +const CloseButton = styled.View` + width: 44px; + height: 44px; + border-radius: 22px; + background: white; + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.15); + justify-content: center; + align-items: center; + margin: 10px; +`; + +const Wrapper = styled.View` + align-self: center; + width: ${cardWith}; + padding-top: 50px; +`; + +const Subtitle = styled.Text` + font-size: 15; + text-transform: uppercase; + font-weight: 600; + color: #b8bece; +`; + +const Item = styled.View` + width: 100%; + padding: 20px; + background: white; + border-radius: 10px; + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.15); + margin-top: 20px; +`; + +const AnimatedItem = Animated.createAnimatedComponent(Item); + +const Header = styled.View` + flex-direction: row; + align-items: center; +`; + +const Logo = styled.Image` + width: 24px; + height: 24px; +`; + +const DateContainer = styled.View` + background: #4775f2; + border-radius: 10px; + flex-direction: row; + align-items: center; + padding: 0 8px; + height: 20px; + position: absolute; + top: 0px; + right: 0px; +`; + +const Date = styled.Text` + color: white; + font-size: 12px; + font-weight: 600; + text-transform: uppercase; +`; + +const Title = styled.Text` + font-size: 20px; + color: #3c4560; + font-weight: bold; + margin-left: 8px; +`; + +const Text = styled.Text` + font-size: 17px; + color: #3c4560; + margin-top: 20px; + line-height: 24px; +`; + +const items = [ + { + logo: "https://cl.ly/a4d00a918f39/download/logo-vue.png", + title: "Vue.js for Designers", + text: + "Make a dashboard web-app with a complete login system, dark mode, and animated charts for your data.", + date: "23 Jan" + }, + { + logo: "https://cl.ly/5c470805a500/download/logo-invision.png", + title: "InVision Studio", + text: + "Learn how to prototype interactions directly in the design tool in this 10-section course.", + date: "27 Nov" + }, + { + logo: "https://cl.ly/cc8368bef551/download/logo-framerx.png", + title: "Framer X", + text: "Create production-ready React components right in the design tool.", + date: "26 SEP" + }, + { + logo: "https://cl.ly/c01bb29804bd/download/logo-figma.png", + title: "Design System", + text: + "Complete guide to designing a site using a collaborative and powerful design system.", + date: "4 SEP" + } +]; diff --git a/screens/HomeScreen.js b/screens/HomeScreen.js index 3ac2def..e7b7eed 100644 --- a/screens/HomeScreen.js +++ b/screens/HomeScreen.js @@ -21,6 +21,8 @@ import ApolloClient from "apollo-boost"; import gql from "graphql-tag"; import { Query } from "react-apollo"; import ModalLogin from "../components/ModalLogin"; +import NotificationButton from "../components/NotificationButton"; +import Notifications from "../components/Notifications"; const CardsQuery = gql` { @@ -69,6 +71,10 @@ function mapDispatchToProps(dispatch) { openLogin: () => dispatch({ type: "OPEN_LOGIN" + }), + openNotif: () => + dispatch({ + type: "OPEN_NOTIF" }) }; } @@ -133,6 +139,7 @@ class HomeScreen extends React.Component { return ( + Welcome back, {this.props.name} - this.props.openNotif()} style={{ position: "absolute", right: 20, top: 5 }} - /> + > + +