From 21c6bffdeb4db7aa7ac9f7c841853b6d72b2f118 Mon Sep 17 00:00:00 2001 From: TBS093A Date: Mon, 13 Jan 2020 23:40:40 +0100 Subject: [PATCH] Add Front-End for Comments/Ratings and half Subjects --- src/components/admin/adminPanel.js | 18 ++ src/components/exchange/indexExchange.js | 19 ++ src/components/forum/forumCommentUpdate.js | 75 +++++ src/components/forum/forumComments.js | 149 ++++++++++ src/components/forum/forumRatings.js | 186 ++++++++++++ src/components/forum/forumSubjects.js | 148 ++++++++++ src/components/forum/indexForum.js | 71 +++++ src/components/index.js | 28 ++ src/components/indexForm.js | 28 ++ src/components/indexInterface.js | 324 +++++++++++++++++++++ src/components/menuBar/menuBar.js | 69 +++++ src/pages/index.js | 16 + src/stores/comments/duck/actions.js | 9 + src/stores/comments/duck/index.js | 5 + src/stores/comments/duck/operations.js | 87 ++++++ src/stores/comments/duck/reducers.js | 19 ++ src/stores/comments/duck/types.js | 5 + src/stores/movements/duck/actions.js | 34 +++ src/stores/movements/duck/index.js | 5 + src/stores/movements/duck/reducers.js | 66 +++++ src/stores/movements/duck/types.js | 15 + src/stores/reducers.js | 16 + src/stores/store.js | 10 + src/stores/subjects/duck/actions.js | 19 ++ src/stores/subjects/duck/index.js | 5 + src/stores/subjects/duck/operations.js | 68 +++++ src/stores/subjects/duck/reducers.js | 42 +++ src/stores/subjects/duck/types.js | 9 + src/stores/threads/duck/actions.js | 24 ++ src/stores/threads/duck/index.js | 5 + src/stores/threads/duck/operations.js | 43 +++ src/stores/threads/duck/reducers.js | 46 +++ src/stores/threads/duck/types.js | 11 + src/stores/user/duck/actions.js | 14 + src/stores/user/duck/index.js | 5 + src/stores/user/duck/operations.js | 77 +++++ src/stores/user/duck/reducers.js | 34 +++ src/stores/user/duck/types.js | 9 + src/styles/elements.scss | 91 ++++++ src/styles/forumRatings.scss | 59 ++++ src/styles/general.scss | 22 ++ src/styles/index.scss | 102 +++++++ src/styles/indexForum.scss | 242 +++++++++++++++ src/styles/menuBar.scss | 58 ++++ 44 files changed, 2387 insertions(+) create mode 100644 src/components/admin/adminPanel.js create mode 100644 src/components/exchange/indexExchange.js create mode 100644 src/components/forum/forumCommentUpdate.js create mode 100644 src/components/forum/forumComments.js create mode 100644 src/components/forum/forumRatings.js create mode 100644 src/components/forum/forumSubjects.js create mode 100644 src/components/forum/indexForum.js create mode 100644 src/components/index.js create mode 100644 src/components/indexForm.js create mode 100644 src/components/indexInterface.js create mode 100644 src/components/menuBar/menuBar.js create mode 100644 src/pages/index.js create mode 100644 src/stores/comments/duck/actions.js create mode 100644 src/stores/comments/duck/index.js create mode 100644 src/stores/comments/duck/operations.js create mode 100644 src/stores/comments/duck/reducers.js create mode 100644 src/stores/comments/duck/types.js create mode 100644 src/stores/movements/duck/actions.js create mode 100644 src/stores/movements/duck/index.js create mode 100644 src/stores/movements/duck/reducers.js create mode 100644 src/stores/movements/duck/types.js create mode 100644 src/stores/reducers.js create mode 100644 src/stores/store.js create mode 100644 src/stores/subjects/duck/actions.js create mode 100644 src/stores/subjects/duck/index.js create mode 100644 src/stores/subjects/duck/operations.js create mode 100644 src/stores/subjects/duck/reducers.js create mode 100644 src/stores/subjects/duck/types.js create mode 100644 src/stores/threads/duck/actions.js create mode 100644 src/stores/threads/duck/index.js create mode 100644 src/stores/threads/duck/operations.js create mode 100644 src/stores/threads/duck/reducers.js create mode 100644 src/stores/threads/duck/types.js create mode 100644 src/stores/user/duck/actions.js create mode 100644 src/stores/user/duck/index.js create mode 100644 src/stores/user/duck/operations.js create mode 100644 src/stores/user/duck/reducers.js create mode 100644 src/stores/user/duck/types.js create mode 100644 src/styles/elements.scss create mode 100644 src/styles/forumRatings.scss create mode 100644 src/styles/general.scss create mode 100644 src/styles/index.scss create mode 100644 src/styles/indexForum.scss create mode 100644 src/styles/menuBar.scss diff --git a/src/components/admin/adminPanel.js b/src/components/admin/adminPanel.js new file mode 100644 index 0000000..775436e --- /dev/null +++ b/src/components/admin/adminPanel.js @@ -0,0 +1,18 @@ +import React from 'react' +import { connect } from 'react-redux' + +import '../../styles/index.scss' + +const AdminPanel = ({ user }) => { + + return ( +
+
+ ) +} + +const mapStateToProps = state => ({ + user: state.user, +}) + +export default connect(mapStateToProps, null)(AdminPanel) diff --git a/src/components/exchange/indexExchange.js b/src/components/exchange/indexExchange.js new file mode 100644 index 0000000..f48e357 --- /dev/null +++ b/src/components/exchange/indexExchange.js @@ -0,0 +1,19 @@ +import React from 'react' +import { connect } from 'react-redux' + +import '../../styles/index.scss' + +const IndexExchange = ({ user }) => { + + return ( +
+
+ ) +} + +const mapStateToProps = state => ({ + user: state.user, +}) + + +export default connect(mapStateToProps,null)(IndexExchange) diff --git a/src/components/forum/forumCommentUpdate.js b/src/components/forum/forumCommentUpdate.js new file mode 100644 index 0000000..f2b2016 --- /dev/null +++ b/src/components/forum/forumCommentUpdate.js @@ -0,0 +1,75 @@ +import React, { useEffect, useState } from 'react' +import { connect } from 'react-redux' + +import { getCommentRatings, updateComment } from '../../stores/comments/duck/operations' +import { refreshSubjectComments } from '../../stores/subjects/duck/operations' + +import actions from '../../stores/subjects/duck/actions' + +import '../../styles/indexForum.scss' + +const ForumCommentUpdate = ({ + user, + subjects, refreshSubjectComments, deactivate, + comment, comments, updateComment, getCommentRatings, + thisComment }) => { + + const updateCommentTextArea = React.createRef() + + const updateOldComment = (event) => { + event.preventDefault() + if ( updateCommentTextArea.current.value !== '' ) { + let commentData = { + id: comment.id, + token: user.token, + text: updateCommentTextArea.current.value + } + updateCommentTextArea.current.value = '' + updateComment(commentData) + } + } + + const [commentText, setCommentText] = useState(0) + + if ( thisComment.isActive === true && thisComment.comment_id === comment.id) { + return ( +
+
+ +

{commentText}/1000

+ +
+
+ ) + } else { + return ( +
+
+ ) + } +} + +const mapStateToProps = state => ({ + user: state.user, + subjects: state.subjects, + comments: state.comments +}) + +const mapDispatchToProps = dispatch => ({ + updateComment: comments => dispatch( updateComment(comments) ), + getCommentRatings: comments => dispatch( getCommentRatings(comments) ), + refreshSubjectComments: subjects => dispatch( refreshSubjectComments(subjects) ), + + deactivate: () => dispatch( actions.deactivate() ) +}) + +export default connect(mapStateToProps, mapDispatchToProps)(ForumCommentUpdate) diff --git a/src/components/forum/forumComments.js b/src/components/forum/forumComments.js new file mode 100644 index 0000000..7df49d6 --- /dev/null +++ b/src/components/forum/forumComments.js @@ -0,0 +1,149 @@ +import React, { useEffect, useState } from 'react' +import { connect } from 'react-redux' + +import { getCommentRatings, addComment, deleteComment } from '../../stores/comments/duck/operations' +import { refreshSubjectComments } from '../../stores/subjects/duck/operations' + +import actions from '../../stores/subjects/duck/actions' + +import '../../styles/indexForum.scss' + +import ForumRatings from './forumRatings' +import ForumCommentUpdate from './forumCommentUpdate' + +const ForumComments = ({ + user, + subjects, refreshSubjectComments, deactivate, + comments, addComment, deleteComment, getCommentRatings }) => { + + useEffect( () => { getCommentRatings(subjects.commentsList) }, []) + + const [updateFormDiv, setUpdateFormDiv] = useState( { isActive: false, comment_id: -1 } ) + const [formDiv, setFormDiv] = useState(false) + + const addCommentTextArea = React.createRef() + const updateCommentTextArea = React.createRef() + + const addNewComment = (event) => { + event.preventDefault() + if ( addCommentTextArea.current.value !== '' ) { + let newComment = { + text: addCommentTextArea.current.value, + subject_id: subjects.actualSubjectID, + user_id: user.id, + token: user.token + } + addCommentTextArea.current.value = '' + addComment(newComment) + setFormDiv( !formDiv ) + let actualSubject = { + id: subjects.actualSubjectID + } + refreshSubjectComments(actualSubject) + } + } + + const deleteOldComment = (commentID) => { + let delComment = { + id: commentID, + token: user.token + } + deleteComment(delComment) + let actualSubject = { + id: subjects.actualSubjectID + } + refreshSubjectComments(actualSubject) + } + + const [commentText, setCommentText] = useState(0) + + return ( +
+
+

Subject:

+

{subjects.actualSubjectName}

+ +

author {subjects.actualSubjectAuthor}

+
+
+ { subjects.commentsList.map( comment => +
+
+
+ +

{comment.author}

+ { ( user.id === comment.user_id || user.privilige > 1 ) ? ( +
+ + { subjects.commentsList[0].id === comment.id ? + ( +
+ ) : ( + + ) } +
+ ) : ( +
+ ) } +
+
+

{comment.text}

+
+
+ +
+
+ +
+ ) } +
+
+
+ +

{commentText}/1000

+ +
+
+
+ +
+
+ ) +} + +const mapStateToProps = state => ({ + user: state.user, + subjects: state.subjects, + comments: state.comments +}) + +const mapDispatchToProps = dispatch => ({ + addComment: comments => dispatch( addComment(comments) ), + deleteComment: comments => dispatch( deleteComment(comments) ), + getCommentRatings: comments => dispatch( getCommentRatings(comments) ), + refreshSubjectComments: subjects => dispatch( refreshSubjectComments(subjects) ), + + deactivate: () => dispatch( actions.deactivate() ) +}) + +export default connect(mapStateToProps, mapDispatchToProps)(ForumComments) diff --git a/src/components/forum/forumRatings.js b/src/components/forum/forumRatings.js new file mode 100644 index 0000000..53a3859 --- /dev/null +++ b/src/components/forum/forumRatings.js @@ -0,0 +1,186 @@ +import React, { useEffect, useState } from 'react' +import { connect } from 'react-redux' + +import { getCommentRatings, addRatingComment, updateRatingComment } from '../../stores/comments/duck/operations' +import actions from '../../stores/subjects/duck/actions' + +import '../../styles/forumRatings.scss' + +const ForumRatings = ({ + user, subjects, deactivate, + comments, getCommentRatings, + addRatingComment, updateRatingComment, + comment }) => { + + useEffect( () => { getCommentRatings(subjects.commentsList) }, []) + + let commentRatingsAvg = (commentID) => { + for (let comment in Object.entries(subjects.commentsList)) { + if (commentID === subjects.commentsList[comment].id) + return parseInt(subjects.commentsList[comment].ratings_avg.value__avg) + } + } + + let getUserRating = (commentID) => { + let userRating = 0 + for (let comment = 0; comment < comments.ratingsCommentList.length; comment++) + for (let rating = 0; rating < comments.ratingsCommentList[comment].length; rating++) { + if ((+comments.ratingsCommentList[comment][rating].user_id) === (+user.id)) { + if ((+comments.ratingsCommentList[comment][rating].comment_id) === (+commentID)) { + userRating = comments.ratingsCommentList[comment][rating].value + return userRating + } + } + } + return 0 + } + + let getRatingID = (commentID) => { + let userRatingID = 0 + for (let comment = 0; comment < comments.ratingsCommentList.length; comment++) + for (let rating = 0; rating < comments.ratingsCommentList[comment].length; rating++) { + if ((+comments.ratingsCommentList[comment][rating].user_id) === (+user.id)) { + if ((+comments.ratingsCommentList[comment][rating].comment_id) === (+commentID)) { + userRatingID = comments.ratingsCommentList[comment][rating].id + return userRatingID + } + } + } + return -1 + } + + const [newRatingValue, setValue] = useState(0) + + const changeRatingValue = (event, commentID) => { + + let ratingDiv = document.getElementById('rate' + commentID) + let divYPositionOnPage = ratingDiv.getBoundingClientRect().top + 72 + let yPosition = event.screenY - divYPositionOnPage + + if ( yPosition > 200 ) { + setValue(5) + } + else if ( yPosition > 150 && yPosition < 200 ) { + setValue(4) + } + else if ( yPosition > 100 && yPosition < 150 ) { + setValue(3) + } + else if ( yPosition > 50 && yPosition < 150 ) { + setValue(2) + } + else if ( yPosition > 0 && yPosition < 50 ) { + setValue(1) + } + } + + const [updateRating, setUpdate] = useState(false) + + const updateUserRating = () => { + const data = { + 'id': getRatingID(comment.id), + 'value': newRatingValue, + 'token': user.token + } + updateRatingComment(data) + setUpdate(false) + getCommentRatings(subjects.commentsList) + } + + const addUserRating = () => { + const data = { + 'user_id': user.id, + 'comment_id': comment.id, + 'value': newRatingValue, + 'token': user.token + } + addRatingComment(data) + getCommentRatings(subjects.commentsList) + } + + if ( getUserRating(comment.id) === 0 ) { + return ( +
+
addUserRating() } + onMouseOver={ event => changeRatingValue(event, comment.id) } + className='rating'> +

{ getUserRating(comment.id) === 0 ? newRatingValue : getUserRating(comment.id) }

+
+
+
+
+
+

{ commentRatingsAvg(comment.id) }

+
+
+
+
+
+ ) + } + else if ( updateRating === false && getUserRating(comment.id) > 0 ) { + return ( +
+
setUpdate( !updateRating ) } + onMouseOver={ event => changeRatingValue(event, comment.id) } + className='rating'> +

{ getUserRating(comment.id) === 0 ? newRatingValue : getUserRating(comment.id) }

+
+
+
+
+
+

{ commentRatingsAvg(comment.id) }

+
+
+
+
+
+ ) + } + else if ( updateRating === true ) { + return ( +
+
updateUserRating() } + onMouseOver={ event => changeRatingValue(event, comment.id) } + className='rating'> +

{ newRatingValue }

+
+
+
+
+
+

{ commentRatingsAvg(comment.id) }

+
+
+
+
+
+ ) + } +} + +const mapStateToProps = state => ({ + user: state.user, + subjects: state.subjects, + comments: state.comments +}) + +const mapDispatchToProps = dispatch => ({ + getCommentRatings: comments => dispatch( getCommentRatings(comments) ), + addRatingComment: comments => dispatch( addRatingComment(comments) ), + updateRatingComment: comments => dispatch( updateRatingComment(comments) ), + + deactivate: () => dispatch( actions.deactivate() ) +}) + +export default connect(mapStateToProps, mapDispatchToProps)(ForumRatings) diff --git a/src/components/forum/forumSubjects.js b/src/components/forum/forumSubjects.js new file mode 100644 index 0000000..cf7f61e --- /dev/null +++ b/src/components/forum/forumSubjects.js @@ -0,0 +1,148 @@ +import React, { useState } from 'react' +import { connect } from 'react-redux' + +import { refreshThreadSubjects } from '../../stores/threads/duck/operations' +import { getSubjectComments, addSubject } from '../../stores/subjects/duck/operations' +import { addComment } from '../../stores/comments/duck/operations' +import actions from '../../stores/threads/duck/actions' + +import '../../styles/indexForum.scss' + +import ForumComments from './forumComments' + +const ForumSubjects = ({ + user, + threads, deactivate, + subjects, addSubject, getSubjectComments, + comments, addComment }) => { + + const [formDiv, setFormDiv] = useState(false) + + const addSubjectTitle = React.createRef() + const addSubjectComment = React.createRef() + + const addNewSubject = (event) => { + event.preventDefault() + if ( addSubjectTitle.current.value !== '' && addSubjectComment.current.value !== '' ) { + let newSubject = { + name: addSubjectTitle.current.value, + user_id: user.id, + thread_id: threads.actualThreadID, + comment: { + text: addSubjectComment.current.value, + user_id: user.id, + token: user.token + }, + token: user.token + } + addSubject(newSubject) + addSubjectComment.current.value = '' + addSubjectTitle.current.value = '' + } + } + + const [commentText, setCommentText] = useState(0) + const [titleText, setTitleText] = useState(0) + + if (threads.isActive === true && subjects.isActive === false) { + return ( +
+
+

Subjects in thread:

+

{threads.actualThreadName}

+ +

moderator {threads.actualThreadModerator}

+
+
+ { threads.subjectsList.map( subject => +
+

getSubjectComments(subject) }> + {subject.name} +

+
+ { (user.id === subject.user_id || + user.id === threads.actualThreadModeratorID || + user.privilige === 3) ? ( +
+ + + +

{subject.author}

+
+ ) : ( +
+ +

{subject.author}

+
+ ) + } +
+ ) } +
+
+
+ setTitleText(e.target.value.length) }> + + +

Title: {titleText}/30

+

Comment: {commentText}/1000

+ +
+
+
+ +
+
+ ) + } + else if (threads.isActive === true && subjects.isActive === true) { + return ( +
+ +
+ ) + } +} + +const mapStateToProps = state => ({ + user: state.user, + threads: state.threads, + subjects: state.subjects, + comments: state.comments +}) + +const mapDispatchToProps = dispatch => ({ + refreshThreadSubjects: threads => dispatch( refreshThreadSubjects(threads) ), + getSubjectComments: subjects => dispatch( getSubjectComments(subjects) ), + addSubject: subjects => dispatch( addSubject(subjects) ), + addComment: comments => dispatch( addComment(comments) ), + + deactivate: () => dispatch( actions.deactivate() ) +}) + +export default connect(mapStateToProps, mapDispatchToProps)(ForumSubjects) diff --git a/src/components/forum/indexForum.js b/src/components/forum/indexForum.js new file mode 100644 index 0000000..a37bf3e --- /dev/null +++ b/src/components/forum/indexForum.js @@ -0,0 +1,71 @@ +import React, { useEffect } from 'react' +import { connect } from 'react-redux' + +import { getAllThreads, getThreadSubjects } from '../../stores/threads/duck/operations' + +import '../../styles/indexForum.scss' + +import ForumSubjects from './forumSubjects' + +const IndexForum = ({ user, threads, getAllThreads, getThreadSubjects }) => { + + useEffect( () => { getAllThreads() }, [] ) + + if (threads.isActive === false) { + return ( +
+
+
+
+
+

Forum:

+

Threads

+

Forum about BTC exchange

+
+
+ { threads.threadsList.map( thread => +
getThreadSubjects(thread) }> +

{thread.name}

+

moderator: {thread.moderator}

+
+ ) } +
+
+ Foot +
+
+
+
+
+ ) + } + else if (threads.isActive === true) { + return ( +
+
+
+
+ +
+
+
+
+ ) + } +} + +const mapStateToProps = state => ({ + user: state.user, + threads: state.threads +}) + +const mapDispatchToProps = dispatch => ({ + getAllThreads: () => dispatch( getAllThreads() ), + getThreadSubjects: thread => dispatch( getThreadSubjects(thread) ) +}) + +export default connect(mapStateToProps, mapDispatchToProps)(IndexForum) diff --git a/src/components/index.js b/src/components/index.js new file mode 100644 index 0000000..ab85c78 --- /dev/null +++ b/src/components/index.js @@ -0,0 +1,28 @@ +import React, { useEffect } from 'react'; +import { connect } from 'react-redux'; +import { getSubjectsThread } from '../stores/subjects/duck/operations' + +import '../styles/index.scss' + +const Index = ({subjects, getSubjectsThread}) =>{ + + useEffect( () => { getSubjectsThread() }, []) + + return +} + + // do odczytu globalnego state'a + +const mapStateToProps = state => ({ + subjects: state.subjects +}) + + // do modyfikacji globalnego state'a + +const mapDispatchToProps = dispatch => ({ + getSubjectsThread: () => dispatch( getSubjectsThread() ) +}) + +export default connect(mapStateToProps, mapDispatchToProps)(Index) diff --git a/src/components/indexForm.js b/src/components/indexForm.js new file mode 100644 index 0000000..ac43755 --- /dev/null +++ b/src/components/indexForm.js @@ -0,0 +1,28 @@ +import React from 'react' +import { connect } from 'react-redux' +import actions from '../stores/subjects/duck/actions' + +const IndexForm = (props) => { + + const subjectInput = React.createRef() + + const addSubject = (event) => { + event.preventDefault() + props.add(subjectInput.current.value) + + subjectInput.current.value = '' + } + + return ( +
+ + +
+ ) +} + +const mapDispatchToProps = dispatch => ({ + add: subject => dispatch(actions.add(subject)) +}) + +export default connect(null, mapDispatchToProps)(IndexForm) diff --git a/src/components/indexInterface.js b/src/components/indexInterface.js new file mode 100644 index 0000000..75f120f --- /dev/null +++ b/src/components/indexInterface.js @@ -0,0 +1,324 @@ +import React from 'react' +import { connect } from 'react-redux' + +// Operations Redux + +import { createSession, deleteSession, updateSession, registerUser } from '../stores/user/duck/operations' + +// Actions Redux + +import actions from '../stores/movements/duck/actions' + +// Styles + +import '../styles/index.scss' + +// Components + +import MenuBar from './menuBar/menuBar' + +import Exchange from './exchange/indexExchange' +import Forum from './forum/indexForum' +import AdminPanel from './admin/adminPanel' + +// Images / Videos + +import VideoEx from '../images/stockExchange.mp4' +import BtcLogo from '../images/BtcLogo.png' +import ForumLogo from '../images/ForumLogo.png' + +const IndexInterface = ({ + user, movements, + createSession, deleteSession, updateSession, registerUser, + setRegister, setEdit, setForum, setExchange, setAdminPanel, resetMovements}) => { + + const loginInput = React.createRef() + const passwordInput = React.createRef() + + const userLogin = (event) => { + event.preventDefault() + let userInput = { + login: loginInput.current.value, + password: passwordInput.current.value + } + loginInput.current.value = '' + passwordInput.current.value = '' + createSession(userInput) + } + + const userLogout = (event) => { + event.preventDefault() + let userToken = { + token: user.token + } + deleteSession(userToken) + } + + const loginRegister = React.createRef() + const passOneRegister = React.createRef() + const passTwoRegister = React.createRef() + const emailRegister = React.createRef() + + const userRegister = (event) => { + event.preventDefault() + if (passOneRegister.current.value === passTwoRegister.current.value) { + let userRegister = { + login: loginRegister.current.value, + password: passOneRegister.current.value, + email: emailRegister.current.value + } + registerUser(userRegister) + } + loginRegister.current.value = '' + passOneRegister.current.value = '' + passTwoRegister.current.value = '' + emailRegister.current.value = '' + } + + const loginUpdate = React.createRef() + const passOldOneUpdate = React.createRef() + const passOldTwoUpdate = React.createRef() + const passNewUpdate = React.createRef() + const emailUpdate = React.createRef() + const avatarUpdate = React.createRef() + + const userUpdate = (event) => { + event.preventDefault() + if ( passOldOneUpdate.current.value === passOldTwoUpdate.current.value ) { + let userUpdate = { + id: user.id, + login: loginUpdate.current.value === '' ? user.login : loginUpdate.current.value, + passwordOld: passOldOneUpdate.current.value, + passwordNew: passNewUpdate.current.value === '' ? passOldOneUpdate.current.value : passNewUpdate.current.value, + email: emailUpdate.current.value === '' ? user.email : emailUpdate.current.value, + avatar: avatarUpdate.current.value === '' ? user.avatar : avatarUpdate.current.value, + token: user.token + } + updateSession(userUpdate) + } + loginUpdate.current.value = '' + passOldOneUpdate.current.value = '' + passOldTwoUpdate.current.value = '' + passNewUpdate.current.value = '' + emailUpdate.current.value = '' + avatarUpdate.current.value = '' + } + + if (user.isActive === false && movements.register === false && movements.exchange === false){ + return ( +
+ +
+
setExchange() }> + +
+
+
+
+
+ + +

+ +
+
+ +
+
+
+
+ ) + } + else if (movements.register === true) { + return ( +
+ +
+
+
+ + + + +

+ +
+ +
+
+
+ ) + } + else if (movements.edit === true) { + return ( +
+ +
+
+
+ Login: + + Old Password + + + New Password + + E-mail: + + Avatar URL: + +

+ +
+ +
+
+
+ ) + } + else if (movements.exchange === true) { + return ( +
+ +
+ + +
+
+ ) + } + else if (movements.forum === true) { + return ( +
+ +
+ + +
+
+ ) + } + else if (movements.adminPanel === true) { + return ( +
+ +
+ + +
+
+ ) + } + else if (user.privilige === 3) { + return ( +
+ +
+
setExchange() }> + +
+
setForum() }> + +
+
+
+

Welcome

+

{user.login}

+
+
+ + +
+ +
+
+
+
+ ) + } + else { + return ( +
+ +
+
setExchange() }> + +
+
setForum() }> + +
+
+
+

Welcome

+

{user.login}

+
+
+ +
+ +
+
+
+
+ ) + } +} + +const mapStateToProps = state => ({ + user: state.user, + movements: state.movements +}) + +const mapDispatchToProps = dispatch => ({ + createSession: user => dispatch( createSession(user) ), + deleteSession: user => dispatch( deleteSession(user) ), + updateSession: user => dispatch( updateSession(user) ), + registerUser: user => dispatch( registerUser(user) ), + + setRegister: movements => dispatch( actions.register() ), + setEdit: movements => dispatch( actions.editAccount() ), + setExchange: movements => dispatch( actions.exchange() ), + setForum: movements => dispatch( actions.forum() ), + setAdminPanel: movements => dispatch( actions.adminPanel() ), + resetMovements: movements => dispatch( actions.reset() ) +}) + +export default connect(mapStateToProps, mapDispatchToProps)(IndexInterface) diff --git a/src/components/menuBar/menuBar.js b/src/components/menuBar/menuBar.js new file mode 100644 index 0000000..de2a90d --- /dev/null +++ b/src/components/menuBar/menuBar.js @@ -0,0 +1,69 @@ +import React, { useState } from 'react' +import { connect } from 'react-redux' + +import { deleteSession } from '../../stores/user/duck/operations' + +import actions from '../../stores/movements/duck/actions' + +import '../../styles/menuBar.scss' + +import BtcLogo from '../../images/BtcLogo.png' + +const MenuBar = ({ user, movements, resetMovements, deleteSession }) => { + + const [menuActive, setActivity] = useState(false) + + const userLogout = (event) => { + event.preventDefault() + let userToken = { + token: user.token + } + resetMovements() + deleteSession(userToken) + } + + if (user.isActive === true) { + return ( +
+ setActivity( !menuActive ) } /> +
+ +
+ +
+

{user.login}

+

{user.email}

+
+
+ ) + } + else { + return ( +
+ setActivity( !menuActive ) } /> +
+ +

Welcome Guest!

+
+
+ ) + } +} + +const mapStateToProps = state => ({ + user: state.user, + movements: state.movements +}) + +const mapDispatchToProps = dispatch => ({ + deleteSession: user => dispatch( deleteSession(user) ), + resetMovements: movements => dispatch( actions.reset() ) +}) + +export default connect(mapStateToProps, mapDispatchToProps)(MenuBar) diff --git a/src/pages/index.js b/src/pages/index.js new file mode 100644 index 0000000..dcb7e73 --- /dev/null +++ b/src/pages/index.js @@ -0,0 +1,16 @@ +import React from "react"; + +import IndexInterface from "../components/indexInterface" + +import store from "../stores/store"; +import { Provider } from "react-redux"; + +import '../styles/general.scss' + +const IndexPage = () => ( + + + +) + +export default IndexPage diff --git a/src/stores/comments/duck/actions.js b/src/stores/comments/duck/actions.js new file mode 100644 index 0000000..7de1f42 --- /dev/null +++ b/src/stores/comments/duck/actions.js @@ -0,0 +1,9 @@ +import types from './types' + +const getRatingsComment = item => ({ + type: types.GET_COMMENTS_RATINGS, item +}) + +export default { + getRatingsComment +} diff --git a/src/stores/comments/duck/index.js b/src/stores/comments/duck/index.js new file mode 100644 index 0000000..76ddf13 --- /dev/null +++ b/src/stores/comments/duck/index.js @@ -0,0 +1,5 @@ +import commentReducer from './reducers' +export { default as commentTypes } from './types' +export { default as commentActions } from './actions' + +export default commentReducer diff --git a/src/stores/comments/duck/operations.js b/src/stores/comments/duck/operations.js new file mode 100644 index 0000000..0bbb4c7 --- /dev/null +++ b/src/stores/comments/duck/operations.js @@ -0,0 +1,87 @@ +import actions from './actions' + +const fetchRatingsComment = async (comment) => { + const response = await + fetch ('http://localhost:8001/index/comment/' + comment.id + '/rating', { + method: 'GET', + credentials: 'same-origin' + }); + return response.json() +} + +const fetchAddRating = async (data) => { + fetch ('http://localhost:8001/index/comment/' + data.comment_id + '/rating', { + method: 'POST', + credentials: 'same-origin', + body: JSON.stringify(data) + }) +} + +const fetchUpdateRating = async (rating) => { + fetch ('http://localhost:8001/index/rating/' + rating.id, { + method: 'PUT', + credentials: 'same-origin', + body: JSON.stringify(rating) + }) +} + +export const getCommentRatings = (data) => + async (dispatch) => { + let ratings = [] + for(let x = 0; x < data.length; x++) { + const rating = await fetchRatingsComment(data[x]) + for(let y = 0; y < rating.length; y++) + rating[y].userRating = 0 + ratings[x] = rating + } + dispatch( actions.getRatingsComment(ratings) ) + } + +export const addRatingComment = (data) => + async (dispatch) => { + await fetchAddRating(data) + } + +export const updateRatingComment = (data) => + async (dispatch) => { + await fetchUpdateRating(data) + } + +const fetchAddComment = async (data) => { + fetch ('http://localhost:8001/index/subject/' + data.subject_id + '/comment', { + method: 'POST', + credentials: 'same-origin', + body: JSON.stringify(data) + }) +} + +const fetchUpdateComment = async (data) => { + fetch ('http://localhost:8001/index/comment/' + data.id, { + method: 'PUT', + credentials: 'same-origin', + body: JSON.stringify(data) + }) +} + +const fetchDeleteComment = async (data) => { + fetch ('http://localhost:8001/index/comment/' + data.id, { + method: 'Delete', + credentials: 'same-origin', + body: JSON.stringify(data) + }) +} + +export const addComment = (data) => + async (dispatch) => { + await fetchAddComment(data) + } + +export const updateComment = (data) => + async (dispatch) => { + await fetchUpdateComment(data) + } + +export const deleteComment = (data) => + async (dispatch) => { + await fetchDeleteComment(data) + } diff --git a/src/stores/comments/duck/reducers.js b/src/stores/comments/duck/reducers.js new file mode 100644 index 0000000..97009a0 --- /dev/null +++ b/src/stores/comments/duck/reducers.js @@ -0,0 +1,19 @@ +import types from './types' + +const INITIAL_STATE = { + ratingsCommentList: [], +} + +function commentReducer(state = INITIAL_STATE, action) { + switch(action.type) { + case types.GET_COMMENTS_RATINGS: + return { + ...state, + ratingsCommentList: action.item + } + default: + return state; + } +} + +export default commentReducer diff --git a/src/stores/comments/duck/types.js b/src/stores/comments/duck/types.js new file mode 100644 index 0000000..66e1543 --- /dev/null +++ b/src/stores/comments/duck/types.js @@ -0,0 +1,5 @@ +const GET_COMMENTS_RATINGS = 'GET_COMMENTS_RATINGS' + +export default { + GET_COMMENTS_RATINGS +} diff --git a/src/stores/movements/duck/actions.js b/src/stores/movements/duck/actions.js new file mode 100644 index 0000000..ffe6a5c --- /dev/null +++ b/src/stores/movements/duck/actions.js @@ -0,0 +1,34 @@ +import types from './types' + +const register = item => ({ + type: types.REGISTER, item +}) + +const editAccount = item => ({ + type: types.EDIT_ACCOUNT, item +}) + +const adminPanel = item => ({ + type: types.ADMIN_PANEL, item +}) + +const exchange = item => ({ + type: types.EXCHANGE, item +}) + +const forum = item => ({ + type: types.FORUM, item +}) + +const reset = item => ({ + type: types.RESET, item +}) + +export default { + register, + editAccount, + adminPanel, + exchange, + forum, + reset, +} diff --git a/src/stores/movements/duck/index.js b/src/stores/movements/duck/index.js new file mode 100644 index 0000000..9321901 --- /dev/null +++ b/src/stores/movements/duck/index.js @@ -0,0 +1,5 @@ +import movementsReducer from './reducers' +export { default as movemetsTypes } from './types' +export { default as movementsActions } from './actions' + +export default movementsReducer diff --git a/src/stores/movements/duck/reducers.js b/src/stores/movements/duck/reducers.js new file mode 100644 index 0000000..6dd74ff --- /dev/null +++ b/src/stores/movements/duck/reducers.js @@ -0,0 +1,66 @@ +import types from './types' + +const INITIAL_STATE = { + forum: false, + exchange: false, + edit: false, + register: false, + adminPanel: false, +} + +const movementsReducer = (state = INITIAL_STATE, action) => { + switch(action.type) { + case types.EXCHANGE: + return { + exchange: true, + forum: false, + edit: false, + register: false, + adminPanel: false + } + case types.FORUM: + return { + forum: true, + exchange: false, + edit: false, + register: false, + adminPanel: false + } + case types.REGISTER: + return { + register: true, + forum: false, + exchange: false, + edit: false, + adminPanel: false + } + case types.EDIT_ACCOUNT: + return { + edit: true, + forum: false, + exchange: false, + register: false, + adminPanel: false + } + case types.ADMIN_PANEL: + return { + adminPanel: true, + edit: false, + forum: false, + exchange: false, + register: false + } + case types.RESET: + return { + edit: false, + forum: false, + exchange: false, + register: false, + adminPanel: false + } + default: + return state; + } +} + +export default movementsReducer diff --git a/src/stores/movements/duck/types.js b/src/stores/movements/duck/types.js new file mode 100644 index 0000000..7826340 --- /dev/null +++ b/src/stores/movements/duck/types.js @@ -0,0 +1,15 @@ +const REGISTER = 'REGISTER' +const EDIT_ACCOUNT = 'EDIT_ACCOUNT' +const FORUM = 'FORUM' +const EXCHANGE = 'EXCHANGE' +const RESET = 'RESET' +const ADMIN_PANEL = 'ADMIN_PANEL' + +export default { + REGISTER, + EDIT_ACCOUNT, + FORUM, + EXCHANGE, + RESET, + ADMIN_PANEL +} diff --git a/src/stores/reducers.js b/src/stores/reducers.js new file mode 100644 index 0000000..b510d9b --- /dev/null +++ b/src/stores/reducers.js @@ -0,0 +1,16 @@ +import { combineReducers } from 'redux' +import movementsReducer from './movements/duck' +import commentReducer from './comments/duck' +import subjectReducer from './subjects/duck' +import threadReducer from './threads/duck' +import userReducer from './user/duck' + +const rootReducer = combineReducers({ + user: userReducer, + threads: threadReducer, + subjects: subjectReducer, + comments: commentReducer, + movements: movementsReducer +}) + +export default rootReducer diff --git a/src/stores/store.js b/src/stores/store.js new file mode 100644 index 0000000..12cc1d7 --- /dev/null +++ b/src/stores/store.js @@ -0,0 +1,10 @@ +import { createStore, applyMiddleware } from 'redux' +import { composeWithDevTools } from 'redux-devtools-extension' +import rootReducer from './reducers' +import thunk from 'redux-thunk' + +const store = createStore(rootReducer, composeWithDevTools(applyMiddleware(thunk))) + +window.store = store + +export default store diff --git a/src/stores/subjects/duck/actions.js b/src/stores/subjects/duck/actions.js new file mode 100644 index 0000000..43b9dc7 --- /dev/null +++ b/src/stores/subjects/duck/actions.js @@ -0,0 +1,19 @@ +import types from './types' + +const getSubjectComments = item => ({ + type: types.GET_SUBJECT_COMMENTS, item +}) + +const activate = item => ({ + type: types.ACTIVATE, item +}) + +const deactivate = item => ({ + type: types.DEACTIVATE, item +}) + +export default { + getSubjectComments, + activate, + deactivate +} diff --git a/src/stores/subjects/duck/index.js b/src/stores/subjects/duck/index.js new file mode 100644 index 0000000..db324cb --- /dev/null +++ b/src/stores/subjects/duck/index.js @@ -0,0 +1,5 @@ +import subjectReducer from './reducers' +export { default as subjectTypes } from './types' +export { default as subjectActions } from './actions' + +export default subjectReducer diff --git a/src/stores/subjects/duck/operations.js b/src/stores/subjects/duck/operations.js new file mode 100644 index 0000000..fa1da0a --- /dev/null +++ b/src/stores/subjects/duck/operations.js @@ -0,0 +1,68 @@ +import actions from './actions' + +const fetchSubjectComments = async (subject) => { + const response = await + fetch('http://localhost:8001/index/subject/' + subject.id + '/comment', { + method: 'GET', + credentials: 'same-origin' + }); + return response.json() +} + +export const getSubjectComments = (data) => + async (dispatch) => { + const comments = await fetchSubjectComments(data) + dispatch( actions.activate(data) ) + dispatch( actions.getSubjectComments(comments) ) + } + + export const refreshSubjectComments = (data) => + async (dispatch) => { + const comments = await fetchSubjectComments(data) + dispatch( actions.getSubjectComments(comments) ) + } + +const fetchAddSubject = async (data) => { + const response = await + fetch('http://localhost:8001/index/thread/' + data.thread_id + '/subject', { + method: 'POST', + credentials: 'same-origin', + body: JSON.stringify(data) + }); + return response.json() + } + + export const addSubject = (data) => + async (dispatch) => { + const comments = await fetchAddSubject(data) + } + +const fetchPutSubject = async (data) => { + const response = await + fetch('http://localhost:8001/index/subject/' + data.id, { + method: 'PUT', + credentials: 'same-origin', + body: JSON.stringify(data) + }); + return response.json() + } + + export const putSubject = (data) => + async (dispatch) => { + const comments = await fetchPutSubject(data) + } + +const fetchDeleteSubject = async (data) => { + const response = await + fetch('http://localhost:8001/index/subject/' + data.id, { + method: 'DELETE', + credentials: 'same-origin', + body: JSON.stringify(data) + }); + return response.json() + } + + export const deleteSubject = (data) => + async (dispatch) => { + const comments = await fetchDeleteSubject(data) + } diff --git a/src/stores/subjects/duck/reducers.js b/src/stores/subjects/duck/reducers.js new file mode 100644 index 0000000..f58292e --- /dev/null +++ b/src/stores/subjects/duck/reducers.js @@ -0,0 +1,42 @@ +import types from './types' + +const INITIAL_STATE = { + commentsList: [], + actualSubjectID: -1, + actualSubjectName: '', + actualSubjectAuthor: '', + actualSubjectAuthorID: -1, + isActive: false +} + +const subjectReducer = (state = INITIAL_STATE, action) => { + switch(action.type) { + case types.GET_SUBJECT_COMMENTS: + return { + ...state, + commentsList: action.item + } + case types.ACTIVATE: + return { + ...state, + actualSubjectID: action.item.id, + actualSubjectName: action.item.name, + actualSubjectAuthor: action.item.author, + actualSubjectAuthorID: action.item.user_id, + isActive: true + } + case types.DEACTIVATE: + return { + ...state, + actualSubjectID: -1, + actualSubjectName: '', + actualSubjectAuthor: '', + actualSubjectAuthorID: -1, + isActive: false + } + default: + return state; + } +} + +export default subjectReducer diff --git a/src/stores/subjects/duck/types.js b/src/stores/subjects/duck/types.js new file mode 100644 index 0000000..d6ce16d --- /dev/null +++ b/src/stores/subjects/duck/types.js @@ -0,0 +1,9 @@ +const GET_SUBJECT_COMMENTS = 'GET_SUBJECT_COMMENTS' +const ACTIVATE = 'ACTIVATE' +const DEACTIVATE = 'DEACTIVATE' + +export default{ + GET_SUBJECT_COMMENTS, + ACTIVATE, + DEACTIVATE +} diff --git a/src/stores/threads/duck/actions.js b/src/stores/threads/duck/actions.js new file mode 100644 index 0000000..802ba68 --- /dev/null +++ b/src/stores/threads/duck/actions.js @@ -0,0 +1,24 @@ +import types from './types' + +const getAll = item => ({ + type: types.GET_ALL_THREADS, item +}) + +const getThreadSubjects = item => ({ + type: types.GET_THREAD_SUBJECTS, item +}) + +const activate = item => ({ + type: types.ACTIVATE_THREAD, item +}) + +const deactivate = item => ({ + type: types.DEACTIVATE_THREAD, item +}) + +export default { + getAll, + getThreadSubjects, + activate, + deactivate +} diff --git a/src/stores/threads/duck/index.js b/src/stores/threads/duck/index.js new file mode 100644 index 0000000..e04d459 --- /dev/null +++ b/src/stores/threads/duck/index.js @@ -0,0 +1,5 @@ +import threadReducer from './reducers' +export { default as threadTypes } from './types' +export { default as threadActions } from './actions' + +export default threadReducer diff --git a/src/stores/threads/duck/operations.js b/src/stores/threads/duck/operations.js new file mode 100644 index 0000000..cd882a5 --- /dev/null +++ b/src/stores/threads/duck/operations.js @@ -0,0 +1,43 @@ +import actions from './actions' + +const fetchGetAll = async () => { + const response = await + fetch ( + 'http://localhost:8001/index/thread', { + method: 'GET', + credential: 'same-origin' + } + ) + return response.json() +} + +const fetchGetSubjects = async (threadID) => { + const response = await + fetch( + 'http://localhost:8001/index/thread/' + threadID + '/subject', { + method: 'GET', + credential: 'same-origin' + } + ) + return response.json() +} + +export const getAllThreads = () => + async (dispatch) => { + const allThreads = await fetchGetAll() + + dispatch( actions.getAll(allThreads) ) + } + +export const refreshThreadSubjects = (threadID) => + async (dispatch) => { + const subjects = await fetchGetSubjects(threadID) + dispatch( actions.getThreadSubjects(subjects) ) + } + +export const getThreadSubjects = (data) => + async (dispatch) => { + const subjects = await fetchGetSubjects(data.id) + dispatch( actions.activate(data) ) + dispatch( actions.getThreadSubjects(subjects) ) + } diff --git a/src/stores/threads/duck/reducers.js b/src/stores/threads/duck/reducers.js new file mode 100644 index 0000000..e6c4af1 --- /dev/null +++ b/src/stores/threads/duck/reducers.js @@ -0,0 +1,46 @@ +import types from './types' + +const INITIAL_STATE = { + threadsList: [], + actualThreadID: -1, + actualThreadName: '', + actualThreadModeratorID: -1, + actualThreadModerator: '', + subjectsList: [], + isActive: false +} + +const threadReducer = (state = INITIAL_STATE, action) => { + switch(action.type) { + case types.GET_ALL_THREADS: + return { + ...state, threadsList: action.item + } + case types.GET_THREAD_SUBJECTS: + return { + ...state, subjectsList: action.item + } + case types.ACTIVATE_THREAD: + return { + ...state, + actualThreadID: action.item.id, + actualThreadName: action.item.name, + actualThreadModeratorID: action.item.user_id, + actualThreadModerator: action.item.moderator, + isActive: true + } + case types.DEACTIVATE_THREAD: + return { + ...state, + actualThreadID: -1, + actualThreadName: '', + actualThreadModeratorID: -1, + actualThreadModerator: '', + isActive: false + } + default: + return state; + } +} + +export default threadReducer diff --git a/src/stores/threads/duck/types.js b/src/stores/threads/duck/types.js new file mode 100644 index 0000000..78fd133 --- /dev/null +++ b/src/stores/threads/duck/types.js @@ -0,0 +1,11 @@ +const GET_ALL_THREADS = 'GET_ALL_THREADS' +const GET_THREAD_SUBJECTS = 'GET_THREAD_SUBJECTS' +const ACTIVATE_THREAD = 'ACTIVATE_THREAD' +const DEACTIVATE_THREAD = '.DEACTIVATE_THREAD' + +export default { + GET_ALL_THREADS, + GET_THREAD_SUBJECTS, + ACTIVATE_THREAD, + DEACTIVATE_THREAD, +} diff --git a/src/stores/user/duck/actions.js b/src/stores/user/duck/actions.js new file mode 100644 index 0000000..70e9ef9 --- /dev/null +++ b/src/stores/user/duck/actions.js @@ -0,0 +1,14 @@ +import types from './types' + +const login = item => ({ + type: types.LOGIN_USER, item +}) + +const logout = item => ({ + type: types.LOGOUT_USER, item +}) + +export default { + login, + logout +} diff --git a/src/stores/user/duck/index.js b/src/stores/user/duck/index.js new file mode 100644 index 0000000..163784e --- /dev/null +++ b/src/stores/user/duck/index.js @@ -0,0 +1,5 @@ +import userReducer from './reducers' +export { default as userTypes } from './types' +export { default as userActions } from './actions' + +export default userReducer diff --git a/src/stores/user/duck/operations.js b/src/stores/user/duck/operations.js new file mode 100644 index 0000000..5d78bf2 --- /dev/null +++ b/src/stores/user/duck/operations.js @@ -0,0 +1,77 @@ +import actions from './actions' + +var jwtDecode = require('jwt-decode') + +const fetchLogin = async (user) => { + const response = await + fetch ( + 'http://localhost:8001/index/authUser', { + method: 'POST', + credential: 'same-origin', + body: JSON.stringify(user), + }) + const json = await response.json() + return json +} + +const fetchLogout = async (userToken) => { + fetch ( + 'http://localhost:8001/index/authUser', { + method: 'DELETE', + credential: 'same-origin', + body: JSON.stringify(userToken), + } + ) +} + +const fetchUpdate = async (user) => { + fetch ( + 'http://localhost:8001/index/user/' + user.id, { + method: 'PUT', + credential: 'same-origin', + body: JSON.stringify(user), + }) +} + +const fetchRegister = async (user) => { + fetch ( + 'http://localhost:8001/index/user', { + method: 'POST', + credential: 'same-origin', + body: JSON.stringify(user), + } + ) +} + +export const createSession = (data) => + async (dispatch) => { + const token = await fetchLogin(data) + let user = jwtDecode(token.token) + + let userFull = { + 'token': token.token, + 'id': user.payload.id, + 'login': user.payload.login, + 'privilige': user.payload.privilige, + 'avatar': user.payload.avatar, + 'email': user.payload.email + } + + dispatch(actions.login(userFull)) + } + +export const updateSession = (data) => + async (dispatch) => { + await fetchUpdate(data) + } + +export const deleteSession = (data) => + async (dispatch) => { + await fetchLogout(data) + dispatch(actions.logout()) + } + +export const registerUser = (data) => + async (dispatch) => { + await fetchRegister(data) + } diff --git a/src/stores/user/duck/reducers.js b/src/stores/user/duck/reducers.js new file mode 100644 index 0000000..f5775f0 --- /dev/null +++ b/src/stores/user/duck/reducers.js @@ -0,0 +1,34 @@ +import types from './types' + +const INITIAL_STATE = { + id: -1, + login: '', + email: '', + privilige: '', + avatar: '', + token: '', + isActive: false +} + +const userReducer = (state = INITIAL_STATE, action) => { + switch(action.type) { + case types.LOGIN_USER: + return { ...state, + id: action.item.id, + login: action.item.login, + privilige: action.item.privilige, + email: action.item.email, + avatar: action.item.avatar, + token: action.item.token, + isActive: true + } + case types.LOGOUT_USER: + return { + isActive: false + } + default: + return state; + } +} + +export default userReducer diff --git a/src/stores/user/duck/types.js b/src/stores/user/duck/types.js new file mode 100644 index 0000000..29dae3d --- /dev/null +++ b/src/stores/user/duck/types.js @@ -0,0 +1,9 @@ +const LOGIN_USER = 'LOGIN_USER' +const LOGOUT_USER = 'LOGOUT_USER' +const GET_TOKEN = 'GET_TOKEN' + +export default { + LOGIN_USER, + LOGOUT_USER, + GET_TOKEN +} diff --git a/src/styles/elements.scss b/src/styles/elements.scss new file mode 100644 index 0000000..1798473 --- /dev/null +++ b/src/styles/elements.scss @@ -0,0 +1,91 @@ + +@mixin center { + top: 50%; + transform: translate(0, 110%); + margin: auto; +} + +@mixin inputStyle { + width: 200px; + height: 35px; + margin-top: 5px; + margin-bottom: 5px; + border: 0px; + border-radius: 10px; + font-size: 12pt; + text-align: center; + color: rgba(111,108,106,1); + background-color: rgba(22,28,29,0.6); +} + +@mixin buttonStyle { + width: 200px; + height: 35px; + margin-top: 5px; + margin-bottom: 5px; + border: 0px; + border-radius: 10px; + font-size: 12pt; + color: rgba(117,82,29,1); + background-color: rgba(22,28,29,1); + transition-duration: 0.5s; + + &:hover { + color: rgba(22,28,29,1); + background-color: rgba(117,82,29,0.7); + transition-duration: 0.1s; + } + + &:active { + background-color: rgba(117,82,29,1); + } +} + +@mixin fontStyle { + color: rgba(117,82,29,1); + font-size: 20px; + margin-top: 0; + margin-bottom: 10px; +} + +@mixin backgroundDivMenubarStyle{ + background-color: rgba(22,28,29,0.2); + border-bottom: 1px solid; + border-color: rgba(117,82,29,0.7); + transition-duration: 0.5s; +} + +@mixin backgroundDefaultDivStyle { + background-color: rgba(22,28,29,0.4); + border: 1px solid; + border-color: rgba(117,82,29,0.7); + border-radius: 25px; + transition-duration: 0.5s; +} + +@mixin backgroundDivButtonStyle { + background-color: rgba(22,28,29,0.2); + border: 1px solid; + border-color: rgba(117,82,29,0.7); + border-radius: 25px; + transition-duration: 0.5s; + + &:hover { + background-color: rgba(22,28,29,0.5); + border-radius: 15px; + } +} + +.adminDivColor { + background: rgb(36,0,0); + background: linear-gradient(180deg, + rgba(121,9,9,0.1) 10%, + rgba(0,212,255,0) 50%); +} + +.moderDivColor { + background: rgb(0,12,36); + background: linear-gradient(180deg, + rgba(9,17,121,0.1) 10%, + rgba(0,212,255,0) 50%); +} diff --git a/src/styles/forumRatings.scss b/src/styles/forumRatings.scss new file mode 100644 index 0000000..7ef130d --- /dev/null +++ b/src/styles/forumRatings.scss @@ -0,0 +1,59 @@ +@import 'elements'; +@import 'indexForum'; + +$widthRT: 40px; + +.rating { + width: $widthRT; + height: 250px; + margin-left: 40px; + float:left; +} + + .ratingStick { + width: 1px; + height: 250px; + + background-color: rgba(117,82,29,1); + margin: auto; + } + + .ratingValue { + transition-duration: 0.5s; + } + + .ratingValue5 { + width: $widthRT; + height: 250px; + background-color: rgba(117,82,29,1); + } + + .ratingValue4 { + width: $widthRT; + height: 200px; + background-color: rgba(117,82,29,1); + } + + .ratingValue3 { + width: $widthRT; + height: 150px; + background-color: rgba(117,82,29,1); + } + + .ratingValue2 { + width: $widthRT; + height: 100px; + background-color: rgba(117,82,29,1); + } + + .ratingValue1 { + width: $widthRT; + height: 50px; + background-color: rgba(117,82,29,1); + } + + .ratingValue0 { + width: $widthRT; + height: 1px; + background-color: rgba(117,82,29,1); + } diff --git a/src/styles/general.scss b/src/styles/general.scss new file mode 100644 index 0000000..6360a06 --- /dev/null +++ b/src/styles/general.scss @@ -0,0 +1,22 @@ +@import 'elements'; + +body { + margin: 0 auto; + + input { + @include inputStyle + } + + textarea { + @include inputStyle + text-align: left; + } + + button { + @include buttonStyle + } + + p { + @include fontStyle + } +} diff --git a/src/styles/index.scss b/src/styles/index.scss new file mode 100644 index 0000000..9ec59e0 --- /dev/null +++ b/src/styles/index.scss @@ -0,0 +1,102 @@ +@import 'elements'; + +.indexView { + width: 100vw; + height: 100vh; + background-color: rgba(31,34,35,1); + overflow-x: hidden; +} + + #indexVideo { + opacity: 0.1; + position: fixed; + margin-bottom: -100vh; + filter: saturate(100%) sepia(100%); + } + + .interface { + width: 1030px; + height: 300px; + @include center; + } + + @mixin OneDiv { + width: 300px; + height: auto; + padding: 50px; + margin-top: -125px; + margin-right: auto; + margin-left: auto; + + @include BigButtonStyle + + input { + @include inputStyle + width: 100%; + } + + button { + @include buttonStyle + } + } + + @mixin DefaultDiv { + width: 200px; + height: 200px; + padding: 50px; + margin-right: 40px; + float: left; + } + + @mixin BigButtonStyle { + + @include backgroundDivButtonStyle + + color: rgba(117,82,29,1); + font-size: 20pt; + text-align: center; + + img { + width: 150px; + height: 200px; + opacity: 0.7; + } + &:hover{ + img { + opacity: 1; + } + } + } + + @mixin BttAndLogin { + @include DefaultDiv + @include BigButtonStyle + } + + .oneDivForm { + @include OneDiv + } + + .emptySpace { + @include DefaultDiv + } + + .exchangeBtt { + @include BttAndLogin; + } + + .forumBtt { + @include BttAndLogin; + } + + .loginForm { + @include BttAndLogin; + + input { + @include inputStyle; + } + + button { + @include buttonStyle; + } + } diff --git a/src/styles/indexForum.scss b/src/styles/indexForum.scss new file mode 100644 index 0000000..9cbb93c --- /dev/null +++ b/src/styles/indexForum.scss @@ -0,0 +1,242 @@ +@import 'elements'; + +.indexForumMarginTop { + width: 100%; + height: 300px; +} + +.indexForum { + @include backgroundDefaultDivStyle + + position: relative; + z-index: 0; + + width: 1400px; + height: auto; + + margin-left: auto; + margin-right: auto; +} + + @mixin forumDiv { + width: 91%; + height: 60px; + + padding-bottom: 3%; + padding-left: 4.5%; + padding-right: 4.5%; + + margin-top: 3%; + + margin-left: auto; + margin-right: auto; + } + + @mixin gapTopBetweenElements { + border-bottom: 2px dashed; + border-color: rgba(117,82,29,0.7); + } + + @mixin gapBetweenItems { + border-bottom: 1px dashed; + border-color: rgba(117,82,29,0.7); + } + + @mixin gapBetweenSections { + border-right: 1px dashed; + border-color: rgba(117,82,29,0.7); + } + + .forumTitle { + @include forumDiv + @include gapTopBetweenElements + p { + font-size: 50px; + float: left; + margin-right: 50px; + } + + button { + float: right; + margin-top: 15px; + } + + :last-child{ + float: right; + font-size: 20px; + margin-top: 20px; + } + + :first-child { + font-size: 20px; + margin-top: 20px; + } + + } + + .forumItemsList { + @include gapTopBetweenElements + + .forumListItem:last-child{ + border-bottom: 0px dashed; + } + } + .forumListItem { + width: 90%; + height: 50px; + padding-right: 5%; + padding-left: 5%; + padding-top: 15px; + + @include gapBetweenItems + + p:first-child { + font-size: 30px; + float: left; + } + + p:last-child { + float: right; + padding-top: 10px; + } + + + div { + float: right; + width: auto; + margin-top: -5px; + + img { + width: 30px; + height: 30px; + margin-top: 5px; + margin-right: 20px; + } + button { + float: left; + margin-right: 40px; + } + } + + &:last-child{ + border-bottom: 0px; + } + + &:hover { + background-color: rgba(22,28,29,0.5); + } + } + + .forumListComment { + width: 100%; + height: auto; + transition-duration: 0.5s; + display: flex; + + @include gapBetweenItems + + &:last-child{ + border-bottom: 1px; + } + } + + .commentAvatar { + width: 20%; + padding: 50px; + padding-bottom: 30px; + text-align: center; + @include gapBetweenSections + + img { + width: 200px; + height: 200px; + margin-bottom: 20px; + } + } + .commentText { + width: 47.5%; + height: auto; + + padding-top: 20px; + padding-bottom: 20px; + padding-left: 2.5%; + padding-right: 2.5%; + + word-wrap: break-word; + + @include gapBetweenSections + } + .commentRating { + width: 15%; + height: 100px; + + padding-top: 20px; + padding-bottom: 20px; + padding-left: 2.5%; + padding-right: 2.5%; + + text-align: center; + } + + .forumFormSubject { + @include forumDiv + + height: auto; + display: flex; + transition-duration: 0.5s; + + @include gapTopBetweenElements + input { + width: 100%; + float: left; + text-align: left; + } + textarea { + width: 100%; + height: 200px; + float: left; + } + button { + float: right; + } + p { + padding-top: 10px; + margin-right: 50px; + float: left; + } + } + + .forumFormComment { + @include forumDiv + + height: auto; + display: flex; + transition-duration: 0.5s; + + @include gapTopBetweenElements + textarea { + width: 100%; + height: 200px; + } + button { + float: right; + } + p { + padding-top: 10px; + margin-right: 50px; + float: left; + } + } + + .forumFoot { + @include forumDiv + button { + float: right; + } + } + +.forumHiddenDiv { + height: 0px; + display: none; + transition-duration: 0.5s; +} diff --git a/src/styles/menuBar.scss b/src/styles/menuBar.scss new file mode 100644 index 0000000..a98ed78 --- /dev/null +++ b/src/styles/menuBar.scss @@ -0,0 +1,58 @@ +@import 'elements'; + +.menuBarActive { + @include backgroundDivMenubarStyle + position: fixed; + width: 100%; + height: 75px; + z-index: 1; + padding-top: 25px; + margin-top: 0px; + + button, p { + float: right; + margin-right: 50px; + transition-duration: 0.5s; + } + + img { + margin-top: 34px; + margin-left: 150px; + width: 70px; + height: 90px; + position: fixed; + } + + p { + padding-top: 10px; + } +} + +.menuBar { + @include backgroundDivMenubarStyle + position: fixed; + width: 100%; + height: 75px; + z-index: 1; + padding-top: 25px; + margin-top: -25px; + + button, p { + float: right; + margin-right: 50px; + transition-duration: 0.5s; + margin-top: -50px; + } + + img { + margin-top: 34px; + margin-left: 150px; + width: 70px; + height: 90px; + position: fixed; + } + + p { + padding-top: 10px; + } +}