mirror of
https://github.com/astuto/astuto.git
synced 2025-12-15 19:27:52 +01:00
Add new post form
This commit is contained in:
29
app/javascript/components/Board/Board.tsx
Normal file
29
app/javascript/components/Board/Board.tsx
Normal 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;
|
||||
170
app/javascript/components/Board/NewPost.tsx
Normal file
170
app/javascript/components/Board/NewPost.tsx
Normal 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;
|
||||
55
app/javascript/components/Board/NewPostForm.tsx
Normal file
55
app/javascript/components/Board/NewPostForm.tsx
Normal 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;
|
||||
11
app/javascript/components/Board/PostList.tsx
Normal file
11
app/javascript/components/Board/PostList.tsx
Normal 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;
|
||||
Reference in New Issue
Block a user