Prechádzať zdrojové kódy

admin-my-events-page

Marina Yakovenko 5 rokov pred
rodič
commit
68e09e6f7b

+ 9 - 1
src/actionTypes/actionTypes.js

@@ -14,4 +14,12 @@ export const SHOW_SIDEBAR = "SHOW_SIDEBAR";
 
 export const POST_REQUEST_LOGIN = "POST_REQUEST_LOGIN";
 export const POST_REQUEST_SUCCESS_LOGIN = "POST_REQUEST_SUCCESS_LOGIN";
-export const POST_REQUEST_ERROR_LOGIN = "POST_REQUEST_ERROR_LOGIN";
+export const POST_REQUEST_ERROR_LOGIN = "POST_REQUEST_ERROR_LOGIN";
+
+export const POST_REQUEST_CHECKIN = "POST_REQUEST_CHECKIN";
+export const POST_REQUEST_SUCCESS_CHECKIN = "POST_REQUEST_SUCCESS_CHECKIN";
+export const POST_REQUEST_ERROR_CHECKIN = "POST_REQUEST_ERROR_CHECKIN";
+
+export const GET_REQUEST_EVENTS = "GET_REQUEST_EVENTS";
+export const GET_REQUEST_SUCCESS_EVENTS = "GET_REQUEST_SUCCESS_EVENTS";
+export const GET_REQUEST_ERROR_EVENTS = "GET_REQUEST_ERROR_EVENTS";

+ 29 - 0
src/actions/getAllEvents.js

@@ -0,0 +1,29 @@
+import * as types from "../actionTypes/actionTypes";
+
+export const getEvents = payload => ({
+    type: types.GET_REQUEST_EVENTS,
+    payload
+});
+
+export const getEventsSuccess = payload => ({
+    type: types.GET_REQUEST_SUCCESS_EVENTS,
+    payload
+});
+
+export const getEventsError = payload => ({
+    type: types.GET_REQUEST_ERROR_EVENTS,
+    payload
+});
+
+export const getAllEvents = () => {
+    return dispatch => {
+        let promise = fetch("https://api-marathon.herokuapp.com/api/v1/event")
+
+        dispatch(getEvents())
+
+        promise.then(
+            data => data.json().then(data => dispatch(getEventsSuccess(data))),
+            error => dispatch(getEventsError(error))
+        )
+    }
+}

+ 37 - 0
src/actions/registration.js

@@ -0,0 +1,37 @@
+import * as types from "../actionTypes/actionTypes";
+
+export const postCheckIn = payload => ({
+    type: types.POST_REQUEST_CHECKIN,
+    payload
+});
+
+export const postCheckInSuccess = payload => ({
+    type: types.POST_REQUEST_SUCCESS_CHECKIN,
+    payload
+});
+
+export const postCheckInError = payload => ({
+    type: types.POST_REQUEST_ERROR_CHECKIN,
+    payload
+});
+
+export const postCheckInSubmit = payload => {
+    return dispatch => {
+        let promise = fetch("https://api-marathon.herokuapp.com/api/v1/auth/register",
+            {
+                method: 'POST',
+                body: JSON.stringify(payload),
+                headers: {
+                    "Content-type": "application/json"
+                }
+            }
+        )
+
+        dispatch(postCheckIn())
+
+        promise.then(
+            data => data.json().then(data => dispatch(postCheckInSuccess(data))),
+            error => dispatch(postCheckInError(error))
+        )
+    }
+}

BIN
src/assets/img/page-bg.jpg


+ 36 - 0
src/components/eventInfoShort/EventInfoShort.js

@@ -0,0 +1,36 @@
+import React from 'react'
+import { Link } from "react-router-dom";
+
+import './eventInfoShort.scss';
+
+export class EventInfoShort extends React.Component {
+    render() {
+        const { title, country, city, eventDate, imgSrc, id } = this.props;
+        const dateArr = new Date(eventDate).toDateString().split(' ');
+        return (
+            <div className="event-item">
+                <Link to={`/events/${id}`}>
+                    <div className="event-content">
+                        <div className="event-cap">
+                            <h3>{title}</h3>
+                            <div className="place">{country}, {city}</div>
+                        </div>
+                        <div className="event-date">
+                            {
+                                dateArr.map(
+                                    (el, ind) => ind > 0 ? <span key={ind}>{el} </span> : null
+                                )
+                            }
+                        </div>
+                        <div className="bg"></div>
+                        <div className="event-picture">
+                            <img src={imgSrc} alt={title} />
+                        </div>
+                    </div>
+                </Link>
+            </div>
+        )
+    }
+}
+
+export default EventInfoShort;

+ 127 - 0
src/components/eventInfoShort/eventInfoShort.scss

@@ -0,0 +1,127 @@
+@import "../../styles/variables";
+
+.event {
+    &-item {
+        padding: 0 5px 20px 5px;
+
+        a {
+            display: block;
+            height: 100%;
+
+            &:hover {
+                .event-cap,
+                .event-date {
+                    color: $color-white;
+                }
+
+                .bg,
+                .event-picture {
+                    display: block;
+                }
+            }
+        }
+    }
+
+    &-content {
+        position: relative;
+        display: flex;
+        flex-direction: column;
+        justify-content: space-between;
+        height: 100%;
+        padding: 10px;
+        border-top: solid 3px $color-blue;
+        background: $color-grey-light;
+
+        h3 {
+            font-size: 1.3rem;
+            text-transform: uppercase;
+        }
+
+        .place {
+            font-size: 1.4rem;
+        }
+
+        .bg {
+            display: block;
+            position: absolute;
+            top: 0;
+            left: 0;
+            right: 0;
+            bottom: 0;
+            background: rgba(0, 0, 0, 0.6);
+            z-index: 2;
+        }
+    }
+
+    &-cap {
+        position: relative;
+        z-index: 3;
+        color: $color-white;
+    }
+
+    &-date {
+        position: relative;
+        text-align: right;
+        z-index: 3;
+        font-size: 1.4rem;
+        color: $color-white;
+
+        span {
+            &:first-child {
+                font-weight: $semi-bold;
+            }
+
+            &:last-child {
+                display: block;
+                font-size: 1.1rem;
+            }
+        }
+    }
+
+    &-picture {
+        display: block;
+        position: absolute;
+        top: 0;
+        left: 0;
+        right: 0;
+        bottom: 0;
+        overflow: hidden;
+
+        img {
+            position: absolute;
+            left: 50%;
+            top: 50%;
+            transform: translate(-50%,-50%);
+            width: 100%;
+        }
+    }
+
+    @media (min-width: 768px) {
+        &-item {
+            width: 50%;
+
+            a {
+                &:hover {
+                    .event-cap,
+                    .event-date {
+                        color: $color-white;
+                    }
+
+                    .bg,
+                    .event-picture {
+                        display: block;
+                    }
+                }
+            }
+        }
+
+        &-date,
+        &-cap {
+            color: $color-black;
+        }
+
+        &-picture, &-content .bg {
+            display: none;
+        }
+    }
+}

+ 47 - 0
src/components/filtersEvents/FiltersEvents.js

@@ -0,0 +1,47 @@
+import React from 'react'
+import { Field, reduxForm } from 'redux-form';
+
+import './filtersEvents.scss';
+
+let FiltersEvents = props => {
+    const { handleSubmit } = props;
+
+    const submit = value => {
+        console.log(value);
+        //postLoginSubmit(value);
+    };
+
+    return (
+        <form className="form" onSubmit={handleSubmit(submit)}>
+            <div>
+                <label htmlFor="country">Country</label>
+                <Field name="country" component="select">
+                    <option value="country1">country1</option>
+                    <option value="country2">country2</option>
+                </Field>
+            </div>
+            <div>
+                <label htmlFor="city">City</label>
+                <Field name="city" component="select">
+                    <option value="city1">city1</option>
+                    <option value="city2">city2</option>
+                </Field>
+            </div>
+            <div>
+                <label htmlFor="typeEvent">Type event</label>
+                <Field name="typeEvent" component="select">
+                    <option value="Marathon">Marathon</option>
+                    <option value="Triathlon">Triathlon</option>
+                    <option value="Cycling">Cycling</option>
+                </Field>
+            </div>
+            <button type="submit">Search</button>
+        </form>
+    )
+};
+
+FiltersEvents = reduxForm({
+    form: 'filters'
+})(FiltersEvents)
+
+export default FiltersEvents

+ 127 - 0
src/components/filtersEvents/filtersEvents.scss

@@ -0,0 +1,127 @@
+@import "../../styles/variables";
+
+.event {
+    &-item {
+        padding: 0 5px 20px 5px;
+
+        a {
+            display: block;
+            height: 100%;
+
+            &:hover {
+                .event-cap,
+                .event-date {
+                    color: $color-white;
+                }
+
+                .bg,
+                .event-picture {
+                    display: block;
+                }
+            }
+        }
+    }
+
+    &-content {
+        position: relative;
+        display: flex;
+        flex-direction: column;
+        justify-content: space-between;
+        height: 100%;
+        padding: 10px;
+        border-top: solid 3px $color-blue;
+        background: $color-grey-2;
+
+        h3 {
+            font-size: 1.3rem;
+            text-transform: uppercase;
+        }
+
+        .place {
+            font-size: 1.4rem;
+        }
+
+        .bg {
+            display: block;
+            position: absolute;
+            top: 0;
+            left: 0;
+            right: 0;
+            bottom: 0;
+            background: rgba(0, 0, 0, 0.6);
+            z-index: 2;
+        }
+    }
+
+    &-cap {
+        position: relative;
+        z-index: 3;
+        color: $color-white;
+    }
+
+    &-date {
+        position: relative;
+        text-align: right;
+        z-index: 3;
+        font-size: 1.4rem;
+        color: $color-white;
+
+        span {
+            &:first-child {
+                font-weight: $semi-bold;
+            }
+
+            &:last-child {
+                display: block;
+                font-size: 1.1rem;
+            }
+        }
+    }
+
+    &-picture {
+        display: block;
+        position: absolute;
+        top: 0;
+        left: 0;
+        right: 0;
+        bottom: 0;
+        overflow: hidden;
+
+        img {
+            position: absolute;
+            left: 50%;
+            top: 50%;
+            transform: translate(-50%,-50%);
+            width: 100%;
+        }
+    }
+
+    @media (min-width: 768px) {
+        &-item {
+            width: 50%;
+
+            a {
+                &:hover {
+                    .event-cap,
+                    .event-date {
+                        color: $color-white;
+                    }
+
+                    .bg,
+                    .event-picture {
+                        display: block;
+                    }
+                }
+            }
+        }
+
+        &-date,
+        &-cap {
+            color: $color-black;
+        }
+
+        &-picture, &-content .bg {
+            display: none;
+        }
+    }
+}

+ 1 - 1
src/components/login-form/LoginForm.js

@@ -21,7 +21,7 @@ let LoginForm = props => {
                 <label htmlFor="password">Password</label>
                 <Field name="password" component="input" type="text" />
             </div>
-            <button type="submit">Submit</button>
+            <button type="submit">Sign in</button>
         </form>
         )
 };

+ 58 - 0
src/components/registration-form/RegistrationForm.js

@@ -0,0 +1,58 @@
+import React from 'react'
+import { Field, reduxForm } from 'redux-form';
+
+import './registrationForm.scss';
+
+let RegistrationForm = props => {
+    const { handleSubmit, postCheckInSubmit } = props;
+
+    const submit = value => {
+        console.log(value);        
+        postCheckInSubmit(value);
+    };
+
+    return (
+        <form className="form" onSubmit={handleSubmit(submit)}>
+            <div>
+                <label htmlFor="name">Full name</label>
+                <Field name="name" component="input" type="text" />
+            </div>
+            <div>
+                <label htmlFor="male">male</label>
+                <Field name="sex" component="input" type="radio" id="male" value="male" checked="checked"/>
+
+                <label htmlFor="female">female</label>
+                <Field name="sex" component="input" type="radio" id="female" value="female"/>
+
+                {/*<Field name="sex" component="select">
+                    <option value="male">male</option>
+                    <option value="female">female</option>
+                </Field>*/}
+            </div>
+            <div>
+                <label htmlFor="phone">Phone</label>
+                <Field name="phone" component="input" type="phone" />
+            </div>
+            <div>
+                <label htmlFor="email">E-mail</label>
+                <Field name="email" component="input" type="email" />
+            </div>
+            <div>
+                <label htmlFor="password">Password</label>
+                <Field name="password" component="input" type="text" />
+            </div>
+            <div>
+                <label htmlFor="confirmPassword">Confirm Password</label>
+                <Field name="confirmPassword" component="input" type="text" />
+            </div>
+            
+            <button type="submit">Check in</button>
+        </form>
+        )
+};
+
+RegistrationForm = reduxForm({
+    form: 'registration'
+})(RegistrationForm)
+
+export default RegistrationForm

+ 1 - 0
src/components/registration-form/registrationForm.scss

@@ -0,0 +1 @@
+@import "../../styles/variables";

+ 2 - 2
src/components/sidebar/Sidebar.js

@@ -11,8 +11,8 @@ const siteMenu = [
         id: 0
     },
     {
-        text: 'Races',
-        href: '/races',
+        text: 'Events',
+        href: '/events',
         id: 1
     },
     {

+ 2 - 2
src/components/sidebar/sidebar.scss

@@ -1,7 +1,7 @@
 @import "../../styles/variables";
 
 .menu {
-    position: absolute;
+    position: fixed;
     top: 0;
     left: 0;
     z-index: 1000;
@@ -17,7 +17,7 @@
         }
 
         .menu-skew {
-            left: -160px;
+            left: -200px;
             opacity: 1;
 
             .img-bg {

+ 65 - 0
src/conteiners/events/Events.js

@@ -0,0 +1,65 @@
+import React from 'react';
+import { connect } from "react-redux";
+//import { Link } from "react-router-dom";
+
+import { getAllEvents } from "../../actions/getAllEvents";
+
+import './events.scss';
+
+import Sidebar from '../../components/sidebar/Sidebar';
+import FiltersEvents from '../../components/filtersEvents/FiltersEvents';
+import EventInfoShort from '../../components/eventInfoShort/EventInfoShort';
+
+export class Events extends React.Component {
+    componentDidMount() {
+        this.props.getAllEvents();
+    }
+
+    render() {
+        const { events } = this.props;
+        console.log("events", events , this.props);
+        return (
+            <>
+                <Sidebar />
+                <div className="container-wrap events">
+                    <div className="caption-page">
+                        <h2>Events</h2>
+                    </div>
+                    <div className="events-filters">
+                        <h4>Events filters</h4>
+                        <FiltersEvents />
+                    </div>
+                    
+                    <div className="events-content">
+                        <h4>Events</h4>
+
+                        <div className="events-list">
+                            {
+                                events.map(event => <EventInfoShort
+                                    key={event._id}
+                                    title={event.title}
+                                    country={event.country}
+                                    city={event.city}
+                                    id={event._id}
+                                    eventDate={event.eventDate}
+                                    imgSrc={event.mainBannerPicture} />
+                                )
+                            }
+                        </div>
+                    </div>                    
+                </div>
+            </>
+        )
+    }
+}
+
+const mapStateToProps = state => {
+    return {
+        events: state.getEvents.events
+    };
+};
+
+export default connect(
+    mapStateToProps,
+    { getAllEvents }
+)(Events);

+ 35 - 0
src/conteiners/events/events.scss

@@ -0,0 +1,35 @@
+@import "../../styles/variables";
+
+.events {
+    background-image: url('../../assets/img/page-bg.jpg');
+    background-repeat: no-repeat;
+    background-size: cover;
+    background-attachment: fixed;
+    background-position: center;
+
+    h4 {
+        margin-bottom: 15px;
+        text-align: center;
+        font-size: 1.4rem;
+    }
+
+    &-filters {
+        background: $color-white;
+        margin: 0 0 15px;
+        padding: 16px;
+    }
+
+    &-content {
+        background: $color-white;
+        padding: 30px 16px 50px 16px;
+    }
+
+    &-list {
+        margin: 0 -5px;
+
+        @media (min-width: 768px) {
+            display: flex;
+            flex-wrap: wrap;
+        }
+    }
+}

+ 13 - 11
src/conteiners/home/Home.js

@@ -12,19 +12,21 @@ export default class Home extends React.Component {
     render() {
         return (
             <>
-            <Sidebar/>
-            <div className="hero">
-                <h1>International triathlon competitions among professionals and amateurs</h1>
+                <Sidebar/>
+                <div className="hero">
+                    <div className="container-wrap">
+                        <h1>International competitions among professionals and amateurs</h1>                       
+                    </div>                    
 
-                <div className="bg"></div>
-                <div className="bg-img"></div>
+                    <div className="bg"></div>
+                    <div className="bg-img"></div>
 
-                <video id="background-video" loop autoPlay>
-                    <source src={this.state.videoURL} type="video/mp4" />
-                    <source src={this.state.videoURL} type="video/ogg" />
-                    Your browser does not support the video tag.
-                </video>
-            </div>
+                    <video id="background-video" loop autoPlay>
+                        <source src={this.state.videoURL} type="video/mp4" />
+                        <source src={this.state.videoURL} type="video/ogg" />
+                        Your browser does not support the video tag.
+                    </video>
+                </div>
             </>
         )
     }

+ 8 - 1
src/conteiners/login/Login.js

@@ -1,5 +1,6 @@
 import React from 'react';
 import { connect } from "react-redux";
+import { Link } from "react-router-dom";
 
 import { postLoginSubmit } from "../../actions/login";
 
@@ -7,7 +8,13 @@ import LoginForm from '../../components/login-form/LoginForm';
 
 export class Login extends React.Component {
     render() {
-        return ( <LoginForm postLoginSubmit={ this.props.postLoginSubmit }/> )
+        const { postLoginSubmit } = this.props;
+        return (
+            <div>
+                <LoginForm postLoginSubmit={postLoginSubmit} />
+                <p>Don't have an account? <Link to="/registration">Sign up now</Link></p>
+            </div>
+        )
     }
 }
 

+ 29 - 0
src/conteiners/registrationPage/RegistrationPage.js

@@ -0,0 +1,29 @@
+import React from 'react';
+import { connect } from "react-redux";
+import { Link } from "react-router-dom";
+
+import { postCheckInSubmit } from "../../actions/registration";
+
+import RegistrationForm from '../../components/registration-form/RegistrationForm';
+
+export class Login extends React.Component {
+    render() {
+        return (
+            <div>
+                <RegistrationForm postCheckInSubmit={this.props.postCheckInSubmit}/>
+                <p>You have an account? <Link to="/login">Login now</Link></p>
+            </div>
+        )
+    }
+}
+
+const mapStateToProps = state => {
+    return {
+        user: state.registration.user
+    };
+};
+
+export default connect(
+    mapStateToProps,
+    { postCheckInSubmit }
+)(Login);

+ 5 - 1
src/reducers/combineReducers.js

@@ -4,9 +4,13 @@ import { reducer as formReducer } from "redux-form";
 import adminMainPageReducer from "./adminMainPageReducer";
 //import Sidebar from "./show-sidebar";
 import login from "./login";
+import registration from "./registration";
+import getEvents from "./getAllEvents";
 
 export default combineReducers({
 	form: formReducer,
 	adminMainPageReducer,
-	login
+    login,
+    registration,
+    getEvents
 });

+ 29 - 0
src/reducers/getAllEvents.js

@@ -0,0 +1,29 @@
+import * as types from "../actionTypes/actionTypes";
+
+const initialState = {
+    events: []
+}
+
+export default (state = initialState, action) => {
+    switch (action.type) {
+        case types.GET_REQUEST_EVENTS: {
+            return state;
+        }
+
+        case types.GET_REQUEST_SUCCESS_EVENTS: {
+            console.log('events',action.payload.events);
+            return {
+                ...state,
+                events: action.payload.events
+            };
+        }
+
+        case types.GET_REQUEST_ERROR_EVENTS: {
+            console.log('error events');
+            return state;
+        }
+
+        default:
+            return state;
+    }
+}

+ 7 - 2
src/reducers/login.js

@@ -11,11 +11,16 @@ export default (state = initialState, action) => {
         }
 
         case types.POST_REQUEST_SUCCESS_LOGIN: {
-            console.log('some',action.payload.user);
-            return state;
+            //action.payload.message
+            console.log('user:', action.payload.user);
+            return {
+                ...state,
+                user: action.payload.user
+            };
         }
 
         case types.POST_REQUEST_ERROR_LOGIN: {
+            console.log('error');
             return state;
         }
 

+ 26 - 0
src/reducers/registration.js

@@ -0,0 +1,26 @@
+import * as types from "../actionTypes/actionTypes";
+
+const initialState = {
+    user: {}
+}
+
+export default (state = initialState, action) => {
+    switch (action.type) {
+        case types.POST_REQUEST_CHECKIN: {
+            return state;
+        }
+
+        case types.POST_REQUEST_SUCCESS_CHECKIN: {
+            console.log('some', action.payload );
+            return state;
+        }
+
+        case types.POST_REQUEST_ERROR_CHECKIN: {
+            console.log('error');
+            return state;
+        }
+
+        default:
+            return state;
+    }
+}

+ 10 - 13
src/router.js

@@ -6,6 +6,8 @@ import AdminAddEventPage from './conteiners/adminAddEventPage/adminAddEventPage'
 import AdminMyEventsPage from './conteiners/adminMyEventsPage/adminMyEventsPage';
 import Home from './conteiners/home/Home';
 import Login from './conteiners/login/Login';
+import RegistrationPage from './conteiners/registrationPage/RegistrationPage';
+import Events from './conteiners/events/Events';
 
 import AdminAddPhotogalarytPage from "./conteiners/adminPhotogalaryPage/adminPhotogalaryPage"
 import Sidebar from './components/sidebar/Sidebar';
@@ -15,21 +17,14 @@ export default class Router extends React.Component {
 		return(
 			<div className="container">
 			    <Switch>
-			        <Route exact path="/" component={Home} />
+                    <Route exact path="/" component={Home} />
 
-	                <Route exact path="/races" render={() => (
-						<>
-							<Sidebar />
-							<div className="text-center">
-								Races
-							</div>
-						</>
-	                )} />
+                    <Route exact path="/events" component={Events} />
 
 	                <Route exact path="/result" render={() => (
 						<>
 							<Sidebar />
-							<div className="text-center">
+                            <div className="container-wrap">
 								Result
 							</div>
 						</>
@@ -38,7 +33,7 @@ export default class Router extends React.Component {
 	                <Route exact path="/gallery" render={() => (
 						<>
 							<Sidebar />
-							<div className= "text-center">
+                            <div className= "container-wrap">
 								Gallery
 							</div>
 						</>
@@ -47,13 +42,15 @@ export default class Router extends React.Component {
 	                <Route exact path="/reviews" render={() => (
 						<>
 							<Sidebar />
-							<div className="text-center">
+                            <div className="container-wrap">
 								Reviews
 							</div>
 						</>
 	                )} />
 
-	                <Route exact path="/login" component={Login} />
+                    <Route exact path="/login" component={Login} />
+                    <Route exact path="/registration" component={RegistrationPage} />
+                    
 			           
 			        <Route exact path = '/admin' component = {AdminMainPage} />
 			        <Route exact path = '/admin/add_new_event' component = {AdminAddEventPage} />

+ 18 - 4
src/styles/base.scss

@@ -97,7 +97,7 @@ acronym {
 
 body {
     font-family: $typo-1;
-    line-height: 1.7 !important;
+    line-height: 1.5 !important;
     font-size: inherit !important;
     box-sizing: border-box;
     min-width: 320px;
@@ -113,7 +113,7 @@ button {
     box-shadow: none;
 }
 
-.button-position-bottom{
+.button-position-bottom {
 	max-width: 1000px;
 	position: fixed;
     bottom: 5px;
@@ -123,6 +123,20 @@ button {
 	z-index: 1;
 }
 
-.stop-scroling {
-	overflow: hidden;
+.container {
+    &-wrap {
+        width: 100%;
+        //padding-left: 16px;
+        padding-right: 50px;
+        padding-left: 320px;
+    }
+}
+
+.caption-page {
+    padding: 60px 0;
+
+    h2 {
+        color: $color-white;
+        font-size: 5rem;
+    }
 }

+ 1 - 0
src/styles/variables.scss

@@ -4,6 +4,7 @@ $color-white: #ffffff;
 $color-black: #000000;
 $color-grey-light: #eeeeee;
 $color-mint: #5acec2;
+$color-grey-2: #f5f5f5;
 
 //font-weight
 $light: 300;