Add Front-End for Comments/Ratings and half Subjects
commit
21c6bffdeb
|
|
@ -0,0 +1,18 @@
|
|||
import React from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
|
||||
import '../../styles/index.scss'
|
||||
|
||||
const AdminPanel = ({ user }) => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
user: state.user,
|
||||
})
|
||||
|
||||
export default connect(mapStateToProps, null)(AdminPanel)
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
import React from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
|
||||
import '../../styles/index.scss'
|
||||
|
||||
const IndexExchange = ({ user }) => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
user: state.user,
|
||||
})
|
||||
|
||||
|
||||
export default connect(mapStateToProps,null)(IndexExchange)
|
||||
|
|
@ -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 (
|
||||
<div className='forumFormComment'>
|
||||
<form onSubmit={ updateOldComment }>
|
||||
<textarea
|
||||
name='addCommentText'
|
||||
placeholder={ comment.text }
|
||||
ref={ updateCommentTextArea }
|
||||
cols='150'
|
||||
maxLength='1000'
|
||||
onChange={ e => setCommentText( e.target.value.length ) }>
|
||||
</textarea>
|
||||
<p>{commentText}/1000</p>
|
||||
<button>
|
||||
Update Comment
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<div className='forumHiddenDiv'>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
@ -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 (
|
||||
<div>
|
||||
<div className='forumTitle'>
|
||||
<p>Subject:</p>
|
||||
<p>{subjects.actualSubjectName}</p>
|
||||
<button onClick={ () => deactivate() }>
|
||||
Back to subjects
|
||||
</button>
|
||||
<p>author {subjects.actualSubjectAuthor}</p>
|
||||
</div>
|
||||
<div className='forumItemsList'>
|
||||
{ subjects.commentsList.map( comment =>
|
||||
<div>
|
||||
<div
|
||||
className={comment.author_privilige === 3 ? 'forumListComment adminDivColor' :
|
||||
(comment.author_privilige === 2 ? 'forumListComment moderDivColor' : 'forumListComment') }
|
||||
key={comment.id}>
|
||||
<div className='commentAvatar'>
|
||||
<img src={comment.author_avatar} />
|
||||
<p>{comment.author}</p>
|
||||
{ ( user.id === comment.user_id || user.privilige > 1 ) ? (
|
||||
<div>
|
||||
<button onClick={ () => setUpdateFormDiv( { isActive: !updateFormDiv.isActive, comment_id: comment.id } ) }>
|
||||
{ updateFormDiv.isActive ? 'Close Edit' : 'Edit Comment'}
|
||||
</button>
|
||||
{ subjects.commentsList[0].id === comment.id ?
|
||||
(
|
||||
<div></div>
|
||||
) : (
|
||||
<button onClick={ () => deleteOldComment(comment.id) }>
|
||||
Delete Comment
|
||||
</button>
|
||||
) }
|
||||
</div>
|
||||
) : (
|
||||
<div></div>
|
||||
) }
|
||||
</div>
|
||||
<div className='commentText'>
|
||||
<p>{comment.text}</p>
|
||||
</div>
|
||||
<div className='commentRating'>
|
||||
<ForumRatings comment={comment} />
|
||||
</div>
|
||||
</div>
|
||||
<ForumCommentUpdate comment={comment} thisComment={updateFormDiv} />
|
||||
</div>
|
||||
) }
|
||||
</div>
|
||||
<div className={ formDiv === true ? 'forumFormComment' : 'forumHiddenDiv' }>
|
||||
<form onSubmit={ addNewComment }>
|
||||
<textarea
|
||||
name='addCommentText'
|
||||
placeholder='Write a comment'
|
||||
ref={addCommentTextArea}
|
||||
cols='150'
|
||||
maxLength='1000'
|
||||
onChange={ e => setCommentText( e.target.value.length )}>
|
||||
</textarea>
|
||||
<p>{commentText}/1000</p>
|
||||
<button>
|
||||
Add Comment
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<div className='forumFoot'>
|
||||
<button onClick={ () => setFormDiv( !formDiv ) }>
|
||||
{ formDiv === true ? 'Close Add Comment' : 'Add Comment' }
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
@ -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 (
|
||||
<div>
|
||||
<div
|
||||
onClick={ () => addUserRating() }
|
||||
onMouseOver={ event => changeRatingValue(event, comment.id) }
|
||||
className='rating'>
|
||||
<p>{ getUserRating(comment.id) === 0 ? newRatingValue : getUserRating(comment.id) }</p>
|
||||
<div
|
||||
id={'rate' + comment.id}
|
||||
className={'ratingValue ratingValue' + ( getUserRating(comment.id) === 0 ? newRatingValue : getUserRating(comment.id))}>
|
||||
<div className='ratingStick'></div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='rating'>
|
||||
<p>{ commentRatingsAvg(comment.id) }</p>
|
||||
<div className={'ratingValue ratingValue' + commentRatingsAvg(comment.id) }>
|
||||
<div className='ratingStick'></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
else if ( updateRating === false && getUserRating(comment.id) > 0 ) {
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
onClick={ () => setUpdate( !updateRating ) }
|
||||
onMouseOver={ event => changeRatingValue(event, comment.id) }
|
||||
className='rating'>
|
||||
<p>{ getUserRating(comment.id) === 0 ? newRatingValue : getUserRating(comment.id) }</p>
|
||||
<div
|
||||
id={'rate' + comment.id}
|
||||
className={'ratingValue ratingValue' + ( getUserRating(comment.id) === 0 ? newRatingValue : getUserRating(comment.id))}>
|
||||
<div className='ratingStick'></div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='rating'>
|
||||
<p>{ commentRatingsAvg(comment.id) }</p>
|
||||
<div className={'ratingValue ratingValue' + commentRatingsAvg(comment.id) }>
|
||||
<div className='ratingStick'></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
else if ( updateRating === true ) {
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
onClick={ () => updateUserRating() }
|
||||
onMouseOver={ event => changeRatingValue(event, comment.id) }
|
||||
className='rating'>
|
||||
<p>{ newRatingValue }</p>
|
||||
<div
|
||||
id={'rate' + comment.id}
|
||||
className={'ratingValue ratingValue' + newRatingValue }>
|
||||
<div className='ratingStick'></div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='rating'>
|
||||
<p>{ commentRatingsAvg(comment.id) }</p>
|
||||
<div className={'ratingValue ratingValue' + commentRatingsAvg(comment.id) }>
|
||||
<div className='ratingStick'></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
@ -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 (
|
||||
<div>
|
||||
<div className='forumTitle'>
|
||||
<p>Subjects in thread:</p>
|
||||
<p>{threads.actualThreadName} </p>
|
||||
<button onClick={ () => deactivate() }>
|
||||
Back to Threads
|
||||
</button>
|
||||
<p>moderator {threads.actualThreadModerator}</p>
|
||||
</div>
|
||||
<div className='forumItemsList'>
|
||||
{ threads.subjectsList.map( subject =>
|
||||
<div
|
||||
className={subject.author_privilige === 3 ? 'forumListItem adminDivColor' :
|
||||
(subject.author_privilige === 2 ? 'forumListItem moderDivColor' : 'forumListItem') }
|
||||
key={subject.id}>
|
||||
<p onClick={ () => getSubjectComments(subject) }>
|
||||
{subject.name}
|
||||
</p>
|
||||
<div></div>
|
||||
{ (user.id === subject.user_id ||
|
||||
user.id === threads.actualThreadModeratorID ||
|
||||
user.privilige === 3) ? (
|
||||
<div>
|
||||
<button>
|
||||
Edit Title
|
||||
</button>
|
||||
<button>
|
||||
Delete Subject
|
||||
</button>
|
||||
<img src={subject.author_avatar} />
|
||||
<p>{subject.author}</p>
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<img src={subject.author_avatar} />
|
||||
<p>{subject.author}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
) }
|
||||
</div>
|
||||
<div className={ formDiv === true ? 'forumFormSubject' : 'forumHiddenDiv' }>
|
||||
<form onSubmit={addNewSubject}>
|
||||
<input
|
||||
name='addSubjectTitle'
|
||||
placeholder='Write a subject title'
|
||||
ref={addSubjectTitle}
|
||||
maxLength='30'
|
||||
onChange={ e => setTitleText(e.target.value.length) }>
|
||||
</input>
|
||||
<textarea
|
||||
name='addCommentText'
|
||||
placeholder='Write a first comment'
|
||||
cols='150'
|
||||
ref={addSubjectComment}
|
||||
maxLength='1000'
|
||||
onChange={ e => setCommentText(e.target.value.length) }>
|
||||
</textarea>
|
||||
<p>Title: {titleText}/30</p>
|
||||
<p>Comment: {commentText}/1000</p>
|
||||
<button>
|
||||
Add Subject
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<div className='forumFoot'>
|
||||
<button onClick={ () => setFormDiv( !formDiv ) }>
|
||||
{ formDiv === true ? 'Close Add Subject' : 'Add Subject' }
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
else if (threads.isActive === true && subjects.isActive === true) {
|
||||
return (
|
||||
<div>
|
||||
<ForumComments />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
@ -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 (
|
||||
<div>
|
||||
<div className='indexForumMarginTop'>
|
||||
</div>
|
||||
<div className='indexForum'>
|
||||
<div className='forumTitle'>
|
||||
<p>Forum:</p>
|
||||
<p>Threads</p>
|
||||
<p>Forum about BTC exchange</p>
|
||||
</div>
|
||||
<div className='forumItemsList'>
|
||||
{ threads.threadsList.map( thread =>
|
||||
<div
|
||||
className={thread.moderator_privilige === 3 ? 'forumListItem adminDivColor' :
|
||||
(thread.moderator_privilige === 2 ? 'forumListItem moderDivColor' : 'forumListItem') }
|
||||
key={thread.id}
|
||||
onClick={ () => getThreadSubjects(thread) }>
|
||||
<p>{thread.name}</p>
|
||||
<p>moderator: {thread.moderator}</p>
|
||||
</div>
|
||||
) }
|
||||
</div>
|
||||
<div className='forumFoot'>
|
||||
Foot
|
||||
</div>
|
||||
</div>
|
||||
<div className='indexForumMarginTop'>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
else if (threads.isActive === true) {
|
||||
return (
|
||||
<div>
|
||||
<div className='indexForumMarginTop'>
|
||||
</div>
|
||||
<div className='indexForum'>
|
||||
<ForumSubjects />
|
||||
</div>
|
||||
<div className='indexForumMarginTop'>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
@ -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 <ul>
|
||||
{subjects.list.map(subject => <li>{subject}</li>)}
|
||||
</ul>
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
|
@ -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 (
|
||||
<form onSubmit={addSubject}>
|
||||
<input ref={subjectInput} />
|
||||
<button type='submit'>Add Subject</button>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
add: subject => dispatch(actions.add(subject))
|
||||
})
|
||||
|
||||
export default connect(null, mapDispatchToProps)(IndexForm)
|
||||
|
|
@ -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 (
|
||||
<div className='indexView'>
|
||||
<video id='indexVideo' autoPlay muted loop>
|
||||
<source src={VideoEx} type="video/mp4" />
|
||||
</video>
|
||||
<div className="interface">
|
||||
<div className='exchangeBtt' onClick={ () => setExchange() }>
|
||||
<img src={BtcLogo} />
|
||||
</div>
|
||||
<div className='emptySpace'>
|
||||
</div>
|
||||
<div className='loginForm'>
|
||||
<form onSubmit={userLogin}>
|
||||
<input type='text' placeholder='Account' ref={loginInput}/>
|
||||
<input type='password' placeholder='Password' ref={passwordInput}/>
|
||||
<br /><br />
|
||||
<button>
|
||||
Log in
|
||||
</button>
|
||||
</form>
|
||||
<form>
|
||||
<button onClick={ () => setRegister() }>
|
||||
Register
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
else if (movements.register === true) {
|
||||
return (
|
||||
<div className='indexView'>
|
||||
<video id='indexVideo' autoPlay muted loop>
|
||||
<source src={VideoEx} type="video/mp4" />
|
||||
</video>
|
||||
<div className="interface">
|
||||
<div className='oneDivForm'>
|
||||
<form onSubmit={userRegister}>
|
||||
<input type='text' placeholder='Login' ref={loginRegister} />
|
||||
<input type='password' placeholder='Password' ref={passOneRegister}/>
|
||||
<input type='password' placeholder='Replace Password' ref={passTwoRegister}/>
|
||||
<input type='text' placeholder='E-mail' ref={emailRegister}/>
|
||||
<br /><br />
|
||||
<button>
|
||||
Register
|
||||
</button>
|
||||
</form>
|
||||
<button onClick={ () => resetMovements() }>
|
||||
Back
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
else if (movements.edit === true) {
|
||||
return (
|
||||
<div className='indexView'>
|
||||
<video id='indexVideo' autoPlay muted loop>
|
||||
<source src={VideoEx} type="video/mp4" />
|
||||
</video>
|
||||
<div className="interface">
|
||||
<div className='oneDivForm'>
|
||||
<form onSubmit={userUpdate}>
|
||||
Login:
|
||||
<input type='text' placeholder={user.login} ref={loginUpdate}/>
|
||||
Old Password
|
||||
<input type='password' placeholder='Password' ref={passOldOneUpdate}/>
|
||||
<input type='password' placeholder='Replace Password' ref={passOldTwoUpdate}/>
|
||||
New Password
|
||||
<input type='password' placeholder='New Password' ref={passNewUpdate}/>
|
||||
E-mail:
|
||||
<input type='text' placeholder={user.email} ref={emailUpdate}/>
|
||||
Avatar URL:
|
||||
<input type='text' placeholder={user.avatar} ref={avatarUpdate}/>
|
||||
<br /><br />
|
||||
<button>
|
||||
Update
|
||||
</button>
|
||||
</form>
|
||||
<button onClick={ () => resetMovements() }>
|
||||
Back
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
else if (movements.exchange === true) {
|
||||
return (
|
||||
<div className='indexView'>
|
||||
<video id='indexVideo' autoPlay muted loop>
|
||||
<source src={VideoEx} type="video/mp4" />
|
||||
</video>
|
||||
<div>
|
||||
<MenuBar />
|
||||
<Exchange />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
else if (movements.forum === true) {
|
||||
return (
|
||||
<div className='indexView'>
|
||||
<video id='indexVideo' autoPlay muted loop>
|
||||
<source src={VideoEx} type="video/mp4" />
|
||||
</video>
|
||||
<div>
|
||||
<MenuBar />
|
||||
<Forum />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
else if (movements.adminPanel === true) {
|
||||
return (
|
||||
<div className='indexView'>
|
||||
<video id='indexVideo' autoPlay muted loop>
|
||||
<source src={VideoEx} type="video/mp4" />
|
||||
</video >
|
||||
<div>
|
||||
<MenuBar />
|
||||
<AdminPanel />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
else if (user.privilige === 3) {
|
||||
return (
|
||||
<div className='indexView'>
|
||||
<video id='indexVideo' autoPlay muted loop>
|
||||
<source src={VideoEx} type="video/mp4" />
|
||||
</video>
|
||||
<div className="interface">
|
||||
<div className='exchangeBtt' onClick={ () => setExchange() }>
|
||||
<img src={BtcLogo} />
|
||||
</div>
|
||||
<div className='forumBtt' onClick={ () => setForum() }>
|
||||
<img src={ForumLogo} />
|
||||
</div>
|
||||
<div className='loginForm'>
|
||||
<form>
|
||||
<p>Welcome</p>
|
||||
<p>{user.login}</p>
|
||||
<br />
|
||||
</form>
|
||||
<button onClick={ () => setAdminPanel() }>
|
||||
Admin Panel
|
||||
</button>
|
||||
<button onClick={ () => setEdit() }>
|
||||
Edit Account
|
||||
</button>
|
||||
<form onSubmit={userLogout}>
|
||||
<button>
|
||||
Log out
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
else {
|
||||
return (
|
||||
<div className='indexView'>
|
||||
<video id='indexVideo' autoPlay muted loop>
|
||||
<source src={VideoEx} type="video/mp4" />
|
||||
</video>
|
||||
<div className="interface">
|
||||
<div className='exchangeBtt' onClick={ () => setExchange() }>
|
||||
<img src={BtcLogo} />
|
||||
</div>
|
||||
<div className='forumBtt' onClick={ () => setForum() }>
|
||||
<img src={ForumLogo} />
|
||||
</div>
|
||||
<div className='loginForm'>
|
||||
<form>
|
||||
<p>Welcome</p>
|
||||
<p>{user.login}</p>
|
||||
<br />
|
||||
</form>
|
||||
<button onClick={ () => setEdit()}>
|
||||
Edit Account
|
||||
</button>
|
||||
<form onSubmit={userLogout}>
|
||||
<button>
|
||||
Log out
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
@ -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 (
|
||||
<div className={ menuActive === true ? 'menuBarActive' : 'menuBar' }>
|
||||
<img src={BtcLogo} onClick={ () => setActivity( !menuActive ) } />
|
||||
<div>
|
||||
<button onClick={ () => resetMovements() }>
|
||||
Back to Home
|
||||
</button>
|
||||
<form onSubmit={userLogout}>
|
||||
<button>
|
||||
Log out
|
||||
</button>
|
||||
</form>
|
||||
<p>{user.login}</p>
|
||||
<p>{user.email}</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
else {
|
||||
return (
|
||||
<div className={ menuActive === true ? 'menuBarActive' : 'menuBar' }>
|
||||
<img src={BtcLogo} onClick={ () => setActivity( !menuActive ) } />
|
||||
<div>
|
||||
<button onClick={ () => resetMovements() }>
|
||||
Back to Home
|
||||
</button>
|
||||
<p>Welcome Guest!</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
@ -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 = () => (
|
||||
<Provider store={store}>
|
||||
<IndexInterface />
|
||||
</Provider>
|
||||
)
|
||||
|
||||
export default IndexPage
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import types from './types'
|
||||
|
||||
const getRatingsComment = item => ({
|
||||
type: types.GET_COMMENTS_RATINGS, item
|
||||
})
|
||||
|
||||
export default {
|
||||
getRatingsComment
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
import commentReducer from './reducers'
|
||||
export { default as commentTypes } from './types'
|
||||
export { default as commentActions } from './actions'
|
||||
|
||||
export default commentReducer
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
const GET_COMMENTS_RATINGS = 'GET_COMMENTS_RATINGS'
|
||||
|
||||
export default {
|
||||
GET_COMMENTS_RATINGS
|
||||
}
|
||||
|
|
@ -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,
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
import movementsReducer from './reducers'
|
||||
export { default as movemetsTypes } from './types'
|
||||
export { default as movementsActions } from './actions'
|
||||
|
||||
export default movementsReducer
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
import subjectReducer from './reducers'
|
||||
export { default as subjectTypes } from './types'
|
||||
export { default as subjectActions } from './actions'
|
||||
|
||||
export default subjectReducer
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
const GET_SUBJECT_COMMENTS = 'GET_SUBJECT_COMMENTS'
|
||||
const ACTIVATE = 'ACTIVATE'
|
||||
const DEACTIVATE = 'DEACTIVATE'
|
||||
|
||||
export default{
|
||||
GET_SUBJECT_COMMENTS,
|
||||
ACTIVATE,
|
||||
DEACTIVATE
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
import threadReducer from './reducers'
|
||||
export { default as threadTypes } from './types'
|
||||
export { default as threadActions } from './actions'
|
||||
|
||||
export default threadReducer
|
||||
|
|
@ -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) )
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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,
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
import userReducer from './reducers'
|
||||
export { default as userTypes } from './types'
|
||||
export { default as userActions } from './actions'
|
||||
|
||||
export default userReducer
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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%);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue