Add new post form

This commit is contained in:
riggraz
2019-09-02 14:32:57 +02:00
parent 4cb60cf2ed
commit edacfb1a4f
16 changed files with 397 additions and 2 deletions

View File

@@ -0,0 +1,29 @@
import * as React from 'react';
import NewPost from './NewPost';
import PostList from './PostList';
import IBoard from '../../interfaces/IBoard';
import '../../stylesheets/components/Board/Board.scss';
interface Props {
board: IBoard;
isLoggedIn: boolean;
authenticityToken: string;
}
class Board extends React.Component<Props> {
render() {
const { board, isLoggedIn, authenticityToken } = this.props;
return (
<div className="boardContainer">
<NewPost board={board} isLoggedIn={isLoggedIn} authenticityToken={authenticityToken} />
<PostList />
</div>
);
}
}
export default Board;

View File

@@ -0,0 +1,170 @@
import * as React from 'react';
import NewPostForm from './NewPostForm';
import Spinner from '../Shared/Spinner';
import IBoard from '../../interfaces/IBoard';
import '../../stylesheets/components/Board/NewPost.scss';
interface Props {
board: IBoard;
isLoggedIn: boolean;
authenticityToken: string;
}
interface State {
showForm: boolean;
error: string;
success: string;
isLoading: boolean;
title: string;
description: string;
}
class NewPost extends React.Component<Props, State> {
constructor(props) {
super(props);
this.state = {
showForm: false,
error: '',
success: '',
isLoading: false,
title: '',
description: '',
};
this.toggleForm = this.toggleForm.bind(this);
this.onTitleChange = this.onTitleChange.bind(this);
this.onDescriptionChange = this.onDescriptionChange.bind(this);
this.submitForm = this.submitForm.bind(this);
}
toggleForm() {
this.setState({
showForm: !this.state.showForm,
error: '',
success: '',
isLoading: false,
});
}
onTitleChange(title) {
this.setState({
title,
error: '',
});
}
onDescriptionChange(description) {
this.setState({
description,
});
}
async submitForm(e) {
e.preventDefault();
this.setState({
error: '',
success: '',
isLoading: true,
});
const boardId = this.props.board.id;
const { authenticityToken } = this.props;
const { title, description } = this.state;
if (title === '') {
this.setState({
error: 'You forgot to enter a title!',
isLoading: false,
});
return;
}
try {
let res = await fetch('http://localhost:3000/posts', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'X-CSRF-Token': authenticityToken,
},
body: JSON.stringify({
post: {
title,
description,
board_id: boardId,
},
}),
});
this.setState({isLoading: false});
let data = await res.json();
if (data.status === 'success') this.setState({success: 'Your post has been published!'});
else this.setState({error: data.message});
} catch (e) {
this.setState({
error: 'An unknown error occurred, try again.'
});
}
}
render() {
const { board, isLoggedIn } = this.props;
const {
showForm,
error,
success,
isLoading,
title,
description
} = this.state;
return (
<div className="newBoardContainer">
<span className="boardName">{board.name}</span>
<span className="boardDescription">{board.description}</span>
{/* <span>{this.props.authenticityToken}</span> */}
{
isLoggedIn ?
<button
onClick={this.toggleForm}
className="submitBtn btn btn-dark">
{ showForm ? 'Cancel' : 'Submit feedback' }
</button>
:
<a href="http://localhost:3000/users/sign_in" className="btn btn-dark">
Log in / Sign up
</a>
}
{
showForm ?
<NewPostForm
title={title}
description={description}
handleTitleChange={this.onTitleChange}
handleDescriptionChange={this.onDescriptionChange}
handleSubmit={this.submitForm}
/>
:
null
}
{ isLoading ? <Spinner /> : null }
{ error ? <span className="error">{error}</span> : null }
{ success ? <span className="success">{success}</span> : null }
</div>
);
}
}
export default NewPost;

View File

@@ -0,0 +1,55 @@
import * as React from 'react';
import '../../stylesheets/components/Board/NewPostForm.scss';
interface Props {
title: string;
description: string;
handleTitleChange(title: string): void;
handleDescriptionChange(description: string): void;
handleSubmit(e: object): void;
}
const NewPostForm = ({
title,
description,
handleTitleChange,
handleDescriptionChange,
handleSubmit,
}: Props) => (
<div className="newPostForm">
<form>
<div className="form-group">
<label htmlFor="postTitle">Title</label>
<input
type="text"
value={title}
onChange={e => handleTitleChange(e.target.value)}
id="postTitle"
className="form-control"
autoFocus
/>
</div>
<div className="form-group">
<label htmlFor="postDescription">Description (optional)</label>
<textarea
value={description}
onChange={e => handleDescriptionChange(e.target.value)}
rows={3}
className="form-control"
id="postDescription"
></textarea>
</div>
<button
onClick={e => handleSubmit(e)}
className="submitBtn btn btn-dark d-block mx-auto">
Submit feedback
</button>
</form>
</div>
);
export default NewPostForm;

View File

@@ -0,0 +1,11 @@
import * as React from 'react';
import '../../stylesheets/components/Board/PostList.scss';
const PostList = () => (
<div className="postListContainer">
Posts will be show here.
</div>
);
export default PostList;

View File

@@ -0,0 +1,9 @@
import * as React from 'react';
const Spinner = () => (
<div className="spinner-border" role="status">
<span className="sr-only">Loading...</span>
</div>
);
export default Spinner;

View File

@@ -0,0 +1,7 @@
.boardContainer {
display: flex;
flex: 1 1 auto;
justify-content: space-between;
align-items: flex-start;
flex-wrap: nowrap;
}

View File

@@ -0,0 +1,47 @@
.newBoardContainer {
flex: 0 0 auto;
width: 250px;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
border: 1px solid black;
border-radius: 4px;
padding: 8px;
margin: 8px;
}
.boardName {
font-size: 24px;
font-weight: 600;
text-align: center;
}
.boardDescription {
color: grey;
font-size: 17px;
font-weight: 200;
text-align: center;
margin-bottom: 8px;
}
.submitBtn {
margin-bottom: 8px;
}
.success {
color: green;
text-align: center;
}
.error {
color: red;
text-align: center;
}

View File

@@ -0,0 +1,3 @@
.submitBtn {
margin-bottom: 8px;
}

View File

@@ -0,0 +1,9 @@
.postListContainer {
flex: 1 1 auto;
border: 1px solid black;
border-radius: 4px;
padding: 8px;
margin: 8px;
}