diff --git a/src/App.js b/src/App.js
index 3058f6f3..fbe72b81 100644
--- a/src/App.js
+++ b/src/App.js
@@ -22,4 +22,12 @@ function App() {
);
}
-export default App;
+const mapStateToProps = (state)=>{
+ return{};
+};
+const mapDispatchToProps=(dispatch)=>({
+ getUserAuth: ()=>dispatch(getUserAuth()),
+});
+
+export default connect(mapStateToProps, mapDispatchToProps)(App);
+
diff --git a/src/actions/actionType.js b/src/actions/actionType.js
new file mode 100644
index 00000000..38aacb45
--- /dev/null
+++ b/src/actions/actionType.js
@@ -0,0 +1,3 @@
+export const SET_USER ='SET_USER';
+export const SET_LOADING_STATUS ='SET_LOADING_STATUS';
+export const GET_ARTICLES ='GET_ARTICLES';
\ No newline at end of file
diff --git a/src/actions/index.js b/src/actions/index.js
new file mode 100644
index 00000000..41aae944
--- /dev/null
+++ b/src/actions/index.js
@@ -0,0 +1,109 @@
+import {auth,provider,storage} from "../firebase";
+import {SET_USER, SET_LOADING_STATUS, GET_ARTICLES} from "../actions/actionType";
+import db from "../firebase";
+
+
+export const setUser = (payload) =>({
+ type: SET_USER,
+ user:payload,
+});
+export const setLoading =(status) =>({
+ type: SET_LOADING_STATUS,
+ status:status,
+});
+
+export const getArticles=(payload) =>({
+ type: GET_ARTICLES,
+ payload:payload,
+})
+
+export function signInAPI(){
+ return(dispatch)=>{
+ auth.signInWithPopup(provider)
+ .then((payload) =>{
+ dispatch(setUser(payload.user));
+ })
+ .catch((error) => alert(error.message));
+ };
+}
+
+export function getUserAuth(){
+ return(dispatch)=>{
+ auth.onAuthStateChanged(async(user)=>{
+ if(user){
+ dispatch(setUser(user));
+ }
+ })
+ }
+}
+export function signOutAPI() {
+ return (dispatch) => {
+ auth.signOut().then(()=>{
+ dispatch(setUser(null));
+ }).catch(error => alert(error.message));
+ };
+}
+
+export function postArticleAPI(payload){
+ return (dispatch) => {
+ dispatch(setLoading(true));
+ if(payload.image !="") {
+ const upload= storage
+ .ref('image/${payload.image.name}')
+ .put(payload.image);
+ upload.on(
+ 'state_Changed',(snapshot) => {
+ const progress= (snapshot.bytesTransferred/ snapshot.totalBytes)*100;
+ console.log('Progress: ${progress}%');
+ if(snapshot.state === "RUNNING"){
+ console.log('Progress: ${progress}%');
+ }
+ },
+ (error) => console.log(error.code),
+ async () =>{
+ const downloadURL = await upload.snapshot.ref.getDownloadURL();
+ db.collection("articles").add({
+ actor:{
+ description:payload.user.email,
+ title:payload.user.displayName,
+ date:payload.timestamp,
+ image:payload.user.photoURL,
+ },
+ video:payload.video,
+ sharedImg: downloadURL,
+ comment:0,
+ description:payload.description,
+ });
+ dispatch(setLoading(false));
+ }
+ );
+ } else if (payload.video){
+ db.collection("articles").add({
+ actor:{
+ description:payload.user.email,
+ title: payload.user.displayName,
+ date: payload.timestamp,
+ image: payload.user.photoURL,
+ },
+ video:payload.video,
+ sharedImg:" ",
+ comment:0,
+ description:payload.description,
+ });
+ dispatch(setLoading(false));
+ }
+ };
+
+}
+export function getArticlesAPI(){
+ return(dispatch)=>{
+ let payload;
+
+ db.collection("articles")
+ .orderBy("actor.date","desc")
+ .onSnapshot((snapshot)=>{
+ payload = snapshot.docs.map((doc)=>doc.data());
+ dispatch(getArticles(payload));
+ });
+ }
+}
diff --git a/src/components/Main.js b/src/components/Main.js
index fd6e2d54..d9d7079e 100644
--- a/src/components/Main.js
+++ b/src/components/Main.js
@@ -1,11 +1,400 @@
import styled from "styled-components";
+import {useEffect,useState} from "react";
+import PostModal from "./PostModal";
+import {connect} from "react-redux";
+import {getArticlesAPI} from "../actions";
+import ReactPlayer from "react-player";
+
const Main = (props) => {
- return Main;
+
+ const[showModal, setShowModal] = useState("close");
+
+ useEffect(() =>{
+ props.getArticles();
+ },[]);
+
+ const handleClick = (e) => {
+ e.preventDefault();
+ if(e.target !== e.currentTarget){
+ return;
+ }
+ switch(showModal){
+ case "open":
+ setShowModal("close");
+ break;
+ case "close":
+ setShowModal("open");
+ break;
+ default:
+ setShowModal("close");
+ break;
+ }
+ };
+
+ return(
+ <>
+ {
+ props.articles.length === 0 ? (
+
There are no articles
+ ) : (
+
+
+
+ { props.user && props.user.photoURL ? (
+
+ ):(
+
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {props.loading && }
+ {props.articles.length > 0 &&
+ props.articles.map((article, key) => (
+
+
+
+
+
+ {article.actor.title}
+ {article.actor.description}
+ {article.actor.date.toDate().toLocaleString()}
+
+
+
+
+
+
+ {article.description}
+
+
+ {
+ !article.shareImg && article.video ? (
+
+
+ ) : (
+ article.sharedImg &&
+ )}
+
+
+
+
+
+
+
+ {article.comments}
+
+
+
+
+
+
+
+
+ ))}
+
+
+
+ )}
+ >
+ );
};
const Container = styled.div`
grid-area: main;
`;
-export default Main;
+
+const CommonCard = styled.div`
+ text-align: center;
+ overflow: hidden;
+ margin-bottom: 8px;
+ background-color: #fff;
+ border-radius:5px;
+ possition:relative;
+ border:none;
+ box-shadow: 0 0 0 1px rgba(0 0 0 / 15%), 0 0 0 1px rgba(0 0 / 20%);
+`;
+
+ const ShareBox= styled(CommonCard)`
+ diaply:flex;
+ flex-direction: column;
+ color: #958b7b;
+ margin: 0 0 8px;
+ background: white;
+
+ div {
+ button{
+ outline: none;
+ color: rgba(0, 0, 0, 0.6);
+ font-size:14px;
+ line-height: 1.5;
+ min-height: 48px;
+ background: transparent;
+ border: none;
+ display:flex;
+ align-items: center;
+ font-weight: 600;
+
+ }
+ &:first-child {
+ display: flex;
+ align-items: center;
+ padding: 8px 16px 0px 16px;
+ img {
+ width:48px;
+ border-radius:50%;
+ margin-right: 8px;
+ }
+ button{
+ margin:4px 0 0 0;
+ flex-grow:1;
+ border-radius: 35px;
+ padding-left:16;
+ border: 1px solid rgba(0, 0, 0, 0.15);
+ background-color:white;
+ text-align:left;
+ }
+ }
+ &:nth-child(2){
+ display: flex;
+ flex-wrap:wrap;
+ justify-content:space-around;
+ padding-bottom:4px;
+ padding-top:4px;
+
+
+ button{
+ img{
+ margin: 0 4px 0 -2px;
+ width:25px;
+ height:25px;
+
+ }
+ }
+ }
+ }
+
+ `;
+
+ const Article = styled(CommonCard)`
+ padding:0;
+ margin: 0 0 8px 0;
+ overflow:visible;
+ `;
+
+ const SharedActor = styled.div`
+ paddinh-right=40px;
+ flex-wrap:nowrap;
+ padding:12px 16px 0;
+ margin-bottom:8px;
+ align-items:center;
+ display:flex;
+ a{
+ margin-right:12px;
+ flex-grow:1;
+ overflow:hidden;
+ display:flex;
+ text-decoration:none;
+
+ img{
+ width:48px;
+ height:48px;
+ }
+ & > div{
+ display:flex;
+ flex-direction:column;
+ flex-grow:1;
+ flex-basis:0;
+ margin-left:8px;
+ overflow:hidden;
+
+ span{
+ text-align:left;
+ &:first-child{
+ font-size:14px;
+ font-weight:700;
+ color: rgba(0, 0, 0, 1);
+ }
+
+ &:nth-child(n +1){
+ font-size:12px;
+ color: rgba(0, 0, 0, 0.6);
+ }
+
+ }
+ }
+ }
+
+ button{
+ possition:absolute;
+ right: 12px;
+ top:0;
+ background:transparent;
+ border:none;
+ outline: none;
+
+
+ img{
+ width:20px;
+ height:20px;
+ padding-bottom: 20px;
+
+ }
+ }
+ `;
+
+ const Discription = styled.div`
+ padding: 0 16px;
+ overflow:hidden;
+ color: rgba(0, 0, 0, 0.9);
+ font-size:14px;
+ text-align:left;
+ `;
+
+ const SharedImg= styled.div`
+ margin-top:8px;
+ width:100%;
+ display:block;
+ position:relative;
+ background-color:#f9fafb;
+
+ img{
+ object-fit:contain;
+ width: auto;
+ height:400px;
+
+
+ }
+ `;
+
+ const SocialCount = styled.ul`
+ line-height:1.3;
+ display:flex;
+ align-items:flex-start;
+ overflow:auto;
+ margin:0 16px;
+ padding:8px 0;
+ border-bottom:1px solid #e9e5df;
+ list-style:none;
+ Button{
+ align-items:center;
+ background-color:transparent;
+ border: none;
+ }
+
+ li{
+ margin-right:5px;
+ font-size:12px;
+ button{
+ display:flex;
+ }
+ img{
+ width:25px;
+ }
+ }
+ `;
+
+ const SocialAction = styled.div`
+ align-items:center;
+ display:flex;
+ justify-content:space-between;
+ margin:0;
+ min-height:40px;
+ padding:4px 70px 8px 9px;
+
+
+ button{
+ display:inline-flex;
+ align-items:center;
+ color: #0a66c2;
+ width:50px;
+ height: 50px;
+ background-color:transparent;
+ border:none;
+
+ img{
+ width:50px;
+ height:50px;
+ }
+
+ @media(min-width:768px){
+ span{
+ margin-left:8px;
+ }
+ a{
+ margin-left:8px;
+ }
+ }
+ }
+
+ `;
+ const Content = styled.div`
+ text-align:center;
+ &>img {
+ width:30px;
+ }
+ `;
+
+ const mapStateToProps = (state) =>{
+ return{
+ loading: state.articleState.loading,
+ user: state.userState.user,
+ articles:state.articleState.articles,
+ };
+ };
+
+ const mapDispatchToProps = (dispatch) =>({
+ getArticles: () => dispatch(getArticlesAPI()),
+ });
+
+
+export default connect(mapStateToProps, mapDispatchToProps)(Main);
+
diff --git a/src/components/PostModal.js b/src/components/PostModal.js
new file mode 100644
index 00000000..7dbea8e0
--- /dev/null
+++ b/src/components/PostModal.js
@@ -0,0 +1,283 @@
+import styled from "styled-components";
+import {useState} from "react";
+import ReactPlayer from "react-player";
+import {connect } from "react-redux";
+import firebase from "firebase";
+import {postArticleAPI} from "../actions";
+
+
+const PostModal =(props) =>{
+ const [editorText, setEditorText] = useState("");
+ const [shareImage, setShareImage] = useState("");
+ const [videoLink,setVideoLink] = useState("");
+ const [assetArea, setAssetArea] = useState("");
+
+ const handleChange= (e) =>{
+ const image = e.target.files[0];
+ if(image === '' || image === undefined){
+ alert('not an image ,the file is a ${typeof image}')
+ return;
+ }
+ setShareImage(image);
+ };
+ const switchAssetArea= (area) =>{
+ setShareImage("");
+ setVideoLink("");
+ setAssetArea(area);
+ };
+
+ const postArticle=(e) =>{
+ e.preventDefault();
+ if(e.target !== e.currentTarget){
+ return;
+ }
+ const payload ={
+ image:shareImage,
+ video:videoLink,
+ user: props.user,
+ description:editorText,
+ timestamp: firebase.firestore.Timestamp.now(),
+
+ };
+ props.postArticle(payload);
+ reset(e);
+ };
+
+ const reset= (e) =>{
+ setEditorText("");
+ setShareImage("");
+ setVideoLink("");
+ setAssetArea("");
+ props.handleClick(e);
+ };
+
+ return(
+ <>
+ { props.showModal === 'open' && (
+
+
+
+ Create post
+
+
+
+
+ { props.user.photoURL ? (
+
+ ):(
+
+ )}
+ {props.user.displayName}
+
+
+
+ { assetArea === "image" ? (
+
+
+
+ {shareImage && }
+
+ ):(
+
+ assetArea === "media" && (
+
+ <> setVideoLink(e.target.value)} />
+ {videoLink &&(
+ )}
+ >))
+ }
+
+
+
+
+ switchAssetArea("image")} >
+
+
+ switchAssetArea("media")}>
+
+
+
+
+
+
+ Anyone
+
+
+ postArticle(event)}>Post
+
+
+
+ )} >
+ );
+};
+
+const Container = styled.div`
+ position :fixed ;
+ top:0;
+ left:0;
+ right:0;
+ bottom:0;
+ z-index:9999;
+ color: black;
+ background-color: rgba(0,0,0,0.8);
+ animation: fadeIn 0.3s;
+
+
+`;
+const Content = styled.div`
+ width:100%;
+ max-width:552px;
+ background-color:white;
+ max-height: 90%;
+ overflow:initial;
+ border-radius:5px;
+ position:relative;
+ flex-direction:column;
+ top:32px;
+ margin:0 auto;
+ overflow-y: scroll;
+`;
+
+
+const Header = styled.div`
+ display:block;
+ padding:16px 20px;
+ border-bottom:1px solid rgba(0,0,0,0.15);
+ font-size:16px;
+ line-height:1.5;
+ color:rgba(0,0,0,0.6);
+ font-weight:400;
+ display:flex;
+ justify-content:space-between;
+ align-items:center;
+ button{
+ height:40px;
+ width:40px;
+ min-height:auto;
+ color:rgba(0,0,0,0.15);
+ svg,
+ img {
+ pointer-events:none;
+ }
+ }
+`;
+
+const ShareContent = styled.div`
+display:flex;
+flex-direction: column;
+flex-grow:1;
+overflow-y:auto;
+vartical-align:baseline;
+padding:8px 12px;
+background:transparent;
+`;
+const UserInfo = styled.div`
+display: flex;
+align-items:center;
+padding:12px 24px;
+svg,img{
+ width:48px;
+ height:48px;
+ background-clip:content-box;
+ border:2px solid transparent;
+ border-radius:50%;
+}
+span{
+ font-weight:600;
+ font-size:16px;
+ line-height:1.5;
+ margin-left:5px;
+}
+`;
+
+const ShareCreation = styled.div`
+ display:flex;
+ justify-content:space-between;
+ padding:12px 24px 12px 16px;
+`;
+const AssetButton = styled.div`
+ display: flex;
+ align-items:center;
+ height:40px;
+ min-width:auto;
+ color: rgba(0, 0, 0,0.5);
+
+`;
+
+const AttachAssets=styled.div`
+ align-items: center;
+ display:flex;
+ padding-right:8px;
+ ${AssetButton} {
+ width:50px;
+ }
+
+`;
+const ShareComment=styled.div`
+ padding-left:8px;
+ margin-right:auto;
+ border-left:1px solid rgba(0,0,0,0.15);
+
+ ${AssetButton} {
+ margin-right: 5px;
+}
+`;
+const PostButton=styled.div`
+ min-width:60px;
+ border:2px solid rgba(0,0,0,0.15);
+ border-radius:20px;
+ padding-left:16px;
+ padding-right: 16px;
+ background: ${(props)=> (props.disabled ? "rgba(0,0,0,0.8)" :"#0a66c2")};
+ text-align:center;
+ padding-top:10px;
+ color: ${(props)=> (props.disabled ? "rgba(1,1,0,0.4)" :"White")};
+ &:hover{
+ background: ${(props)=> (props.disabled ? "rgba(0,0,0,0.08)" :"#004182")};
+ }
+`;
+
+const Editor = styled.div`
+padding:12px 24px;
+textarea{
+ width:100%;
+ min-height:100px;
+ resize:nome;
+}
+input{
+ width:100%;
+ height:35px;
+ font-size:16px;
+ margin-bottom:20px;
+}
+`;
+
+const UploadImage = styled.div`
+text-align:center;
+img{
+ width:auto;
+ height:250px;
+}
+`;
+const mapStateToProps= (state) =>{
+ return{
+ user: state.userState.user,
+ }
+};
+
+const mapDispatchToProps=(dispatch) =>({
+ postArticle: (payload) => dispatch(postArticleAPI(payload)),
+});
+
+export default connect(mapStateToProps, mapDispatchToProps)(PostModal);
\ No newline at end of file
diff --git a/src/index.js b/src/index.js
index 1bc4857e..4966d3df 100644
--- a/src/index.js
+++ b/src/index.js
@@ -2,10 +2,14 @@ import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
+import{ Provider} from "react-redux";
+import store from "./store";
ReactDOM.render(
-
+
+
+
,
document.getElementById("root")
);
diff --git a/src/reducers/articleReducer.js b/src/reducers/articleReducer.js
new file mode 100644
index 00000000..29258f7c
--- /dev/null
+++ b/src/reducers/articleReducer.js
@@ -0,0 +1,25 @@
+import { SET_LOADING_STATUS ,GET_ARTICLES} from "../actions/actionType";
+
+
+export const initState ={
+ articles:[],
+ loading:false,
+};
+
+const articleReducer=(state = initState, action) =>{
+ switch (action.type){
+ case GET_ARTICLES:
+ return{
+ ...state,
+ articles:action.payload,
+ };
+ case SET_LOADING_STATUS:
+ return{
+ ...state,
+ loading: action.status,
+ };
+ default:
+ return state;
+ }
+};
+export default articleReducer;
\ No newline at end of file
diff --git a/src/reducers/index.js b/src/reducers/index.js
new file mode 100644
index 00000000..fe9e7df1
--- /dev/null
+++ b/src/reducers/index.js
@@ -0,0 +1,12 @@
+import{combineReducers} from "redux";
+import userReducer from "./userReducer";
+import articleReducer from "./articleReducer";
+
+
+const rootReducer = combineReducers({
+
+ userState: userReducer,
+ articleState: articleReducer,
+});
+
+export default rootReducer;
\ No newline at end of file
diff --git a/src/reducers/userReducer.js b/src/reducers/userReducer.js
new file mode 100644
index 00000000..0d83eac2
--- /dev/null
+++ b/src/reducers/userReducer.js
@@ -0,0 +1,20 @@
+import {SET_USER} from '../actions/actionType';
+
+
+const INITIAL_STATE ={
+ user: null,
+};
+
+const userReducer = (state= INITIAL_STATE,action)=>{
+ switch (action.type){
+ case SET_USER:
+ return{
+ ...state,
+ user: action.user,
+ };
+ default:
+ return state;
+ }
+}
+
+export default userReducer;
\ No newline at end of file
diff --git a/src/store/index.js b/src/store/index.js
new file mode 100644
index 00000000..688838c0
--- /dev/null
+++ b/src/store/index.js
@@ -0,0 +1,9 @@
+import {createStore, applyMiddleware} from 'redux';
+import rootReducer from "../reducers";
+import thunkMiddleware from "redux-thunk";
+
+
+const store =createStore(rootReducer,applyMiddleware(thunkMiddleware));
+
+
+export default store;
\ No newline at end of file