refactor: Post folder

This commit is contained in:
Ruidy Nemausat 2020-06-02 19:59:48 +02:00
parent 01a5c61e81
commit abf0ba5b0c
5 changed files with 162 additions and 115 deletions

View file

@ -1,115 +0,0 @@
import React, {FC} from 'react';
// Routing
import {useParams, Link} from 'react-router-dom';
import Routes from '../constants/routes';
// Redux
import {compose} from '@reduxjs/toolkit';
import {connect, useSelector} from 'react-redux';
import {firestoreConnect, WithFirestoreProps} from 'react-redux-firebase';
import {RootState} from '../store';
import {selectProfile} from '../store/firebase';
import Collections from '../constants/collections';
// Typing
import Post from '../models/Post';
import Comment from '../types/Comment';
// Form
import useForm from '../hooks';
interface IProps extends WithFirestoreProps {
post: Post;
}
/**
* Display a Post and the related comments. Shows a form to add a comment.
*/
const PostPage: FC<IProps> = ({post, firestore}) => {
const {avatarUrl, displayName} = useSelector(selectProfile);
const newComment: Comment = {
name: displayName ?? 'error',
avatarUrl: avatarUrl ?? 'error',
text: '',
};
const {formData, handleChange, resetForm} = useForm(newComment);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
firestore
.update(`${Collections.POSTS}/${post.id}`, {
comments: [...post.comments, formData],
})
.then(() => resetForm())
.catch(err => console.error(err));
};
return (
<section className="container">
<Link to={Routes.POSTS} className="btn btn-light">
Back To Posts
</Link>
<div className="post bg-white p-1 my-1">
<div>
<Link to={`${Routes.PROFILE}/${post.userID}`}>
<img className="round-img" src={post.avatarUrl} alt={post.name} />
<h4>{post.name}</h4>
</Link>
</div>
<div>
<p className="my-1">{post.text}</p>
</div>
</div>
<div className="post-form">
<div className="post-form-header bg-primary">
<h3>Leave A Comment</h3>
</div>
<form className="form my-1" onSubmit={handleSubmit}>
<textarea
name="text"
cols={30}
rows={5}
placeholder="Comment on this post"
value={formData.text}
onChange={handleChange}
></textarea>
<input type="submit" className="btn btn-dark my-1" value="Submit" />
</form>
</div>
<div className="posts">
{post.comments?.map((c: Comment, i: number) => (
<div className="post bg-white p-1 my-1" key={i}>
<div>
<a href="profile.html">
<img className="round-img" src={c.avatarUrl} alt={c.name} />
<h4>{c.name}</h4>
</a>
</div>
<div>
<p className="my-1">{c.text}</p>
</div>
</div>
))}
</div>
</section>
);
};
/**
* Container to fetch id params from thr URI and pass it to Profile page
*/
const PostPageContainer: FC = () => {
const {id} = useParams();
const Component = compose<FC>(
firestoreConnect(() => [`${Collections.POSTS}/${id}`]),
connect(({firestore: {data}}: RootState) => ({
post: data.posts && {...data.posts[id], id},
})),
)(PostPage);
return <Component />;
};
export default PostPageContainer;

View file

@ -0,0 +1,26 @@
import React, {FC} from 'react';
import Comment from '../../types/Comment';
interface IProps {
comments: Comment[];
}
const PostComments: FC<IProps> = ({comments}) => (
<div className="posts">
{comments?.map(({name, avatarUrl, text}: Comment, i: number) => (
<div className="post bg-white p-1 my-1" key={i}>
<div>
<a href="profile.html">
<img className="round-img" src={avatarUrl} alt={name} />
<h4>{name}</h4>
</a>
</div>
<div>
<p className="my-1">{text}</p>
</div>
</div>
))}
</div>
);
export default PostComments;

View file

@ -0,0 +1,24 @@
import React, {FC} from 'react';
// Routing
import {Link} from 'react-router-dom';
import Routes from '../../constants/routes';
import Post from '../../models/Post';
const PostDisplay: FC<{post: Post}> = ({
post: {name, userID, avatarUrl, text},
}) => (
<div className="post bg-white p-1 my-1">
<div>
<Link to={`${Routes.PROFILE}/${userID}`}>
<img className="round-img" src={avatarUrl} alt={name} />
<h4>{name}</h4>
</Link>
</div>
<div>
<p className="my-1">{text}</p>
</div>
</div>
);
export default PostDisplay;

28
src/pages/Post/Form.tsx Normal file
View file

@ -0,0 +1,28 @@
import React, {FC} from 'react';
interface IProps {
handleSubmit: (e: React.FormEvent<HTMLFormElement>) => void;
handleChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
text: string;
}
const PostForm: FC<IProps> = ({text, handleChange, handleSubmit}) => (
<div className="post-form">
<div className="post-form-header bg-primary">
<h3>Leave A Comment</h3>
</div>
<form className="form my-1" onSubmit={handleSubmit}>
<textarea
name="text"
cols={30}
rows={5}
placeholder="Comment on this post"
value={text}
onChange={handleChange}
></textarea>
<input type="submit" className="btn btn-dark my-1" value="Submit" />
</form>
</div>
);
export default PostForm;

84
src/pages/Post/index.tsx Normal file
View file

@ -0,0 +1,84 @@
import React, {FC} from 'react';
// Routing
import {useParams, Link} from 'react-router-dom';
import Routes from '../../constants/routes';
// Redux
import {compose} from '@reduxjs/toolkit';
import {connect, useSelector} from 'react-redux';
import {firestoreConnect, WithFirestoreProps} from 'react-redux-firebase';
import {RootState} from '../../store';
import {selectProfile} from '../../store/firebase';
import Collections from '../../constants/collections';
// Typing
import Post from '../../models/Post';
import Comment from '../../types/Comment';
// Form
import useForm from '../../hooks';
import PostForm from './Form';
import PostComments from './Comments';
import PostDisplay from './Display';
interface IProps extends WithFirestoreProps {
post: Post;
}
/**
* Display a Post and the related comments. Shows a form to add a comment.
*/
const PostComponent: FC<IProps> = ({post, firestore}) => {
const {avatarUrl, displayName} = useSelector(selectProfile);
const newComment: Comment = {
name: displayName ?? 'error',
avatarUrl: avatarUrl ?? 'error',
text: '',
};
const {formData, handleChange, resetForm} = useForm(newComment);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
firestore
.update(`${Collections.POSTS}/${post.id}`, {
comments: [...post.comments, formData],
})
.then(() => resetForm())
.catch(err => console.error(err));
};
return (
<section className="container">
<Link to={Routes.POSTS} className="btn btn-light">
Back To Posts
</Link>
<PostDisplay post={post} />
<PostForm
text={formData.text}
handleChange={handleChange}
handleSubmit={handleSubmit}
/>
<PostComments comments={post.comments} />
</section>
);
};
/**
* Container to fetch id params from thr URI and pass it to Profile page
*/
const PostPage: FC = () => {
const {id} = useParams();
const Component = compose<FC>(
firestoreConnect(() => [`${Collections.POSTS}/${id}`]),
connect(({firestore: {data}}: RootState) => ({
post: data.posts && {...data.posts[id], id},
})),
)(PostComponent);
return <Component />;
};
export default PostPage;