Commit 51adc624 authored by Болатов Ален's avatar Болатов Ален

Merge branch 'master' into 'dev'

# Conflicts:
#   backend/src/controllers/comments.ts
#   backend/src/repository/mongoose.ts
#   frontend/src/containers/DetailsPost/DetailsPost.css
#   frontend/src/containers/DetailsPost/DetailsPost.tsx
parents e5f6ca58 fc57e0b5
......@@ -179,6 +179,10 @@ export class Mongo implements IDataBase {
return response
}
}
<<<<<<< backend/src/repository/mongoose.ts
=======
>>>>>>> backend/src/repository/mongoose.ts
public addComment = async (commentDto: ICommentDto): Promise<IResponse<IComment | undefined>> => {
try {
const comment = new Comment(commentDto)
......
......@@ -4,6 +4,7 @@ import Layout from './components/Layout';
import HomePage from './containers/HomePage';
import Login from './containers/Login';
import CreatePost from './components/CreatePost/CreatePost';
import DetailsPost from './containers/DetailsPost/DetailsPost';
const App: React.FunctionComponent = (): React.ReactElement => {
return (
......@@ -12,6 +13,7 @@ const App: React.FunctionComponent = (): React.ReactElement => {
<Route path="/" element={<Layout />}>
<Route index element={<HomePage />} />
<Route path="register" element={<Login />} />
<Route path="/posts/:id" element={<DetailsPost />} />
<Route path="create" element={<CreatePost />} />
</Route>
</Routes>
......
import { FunctionComponent, ReactElement, useState, ChangeEvent, FormEvent } from 'react';
import { AppDispatch, AppState } from '../../store/store';
import { shallowEqual, useDispatch } from 'react-redux';
import {
FunctionComponent,
ReactElement,
useState,
ChangeEvent,
FormEvent,
} from 'react';
import {AppDispatch, AppState} from '../../store/store';
import {shallowEqual, useDispatch} from 'react-redux';
import IPostDto from '../../interfaces/IPostDto';
import { createPost } from '../../store/posts/posts.slice';
import { useSelector } from 'react-redux';
import {createPost} from '../../store/posts/posts.slice';
import {useSelector} from 'react-redux';
const CreatePost: FunctionComponent = (): ReactElement => {
const { user } = useSelector((state: AppState) => state.user,shallowEqual);
const dispatch: AppDispatch = useDispatch()
const {user} = useSelector((state: AppState) => state.user, shallowEqual);
const dispatch: AppDispatch = useDispatch();
const [post, setPost] = useState<IPostDto>({
title: '',
description: '',
image: undefined
})
image: undefined,
});
const [fileName, setFileName] = useState<string>('')
const [fileName, setFileName] = useState<string>('');
const inputHandler = (e: ChangeEvent<HTMLInputElement>): void => {
setPost(prevState => {
return { ...prevState, [e.target.name]: e.target.value }
})
}
setPost((prevState) => {
return {...prevState, [e.target.name]: e.target.value};
});
};
const inputFileHandler = (e: ChangeEvent<HTMLInputElement>): void => {
setPost(prevState => {
setPost((prevState) => {
return {
...prevState,
image: e.target.files ? e.target.files[0] : undefined
}
})
setFileName(e.target.files && e.target.files[0] ? e.target.files[0].name : '')
}
image: e.target.files ? e.target.files[0] : undefined,
};
});
setFileName(
e.target.files && e.target.files[0] ? e.target.files[0].name : ''
);
};
const submitHandler = (e: FormEvent) => {
e.preventDefault()
e.preventDefault();
const formData = new FormData();
Object.keys(post).forEach((key: any) => {
//@ts-ignore
formData.append(key, post[key])
})
formData.append("user", user._id)
dispatch(createPost(formData))
setPost(post)
}
formData.append('title', post.title);
formData.append('description', post.description);
formData.append('user', user._id);
dispatch(createPost(formData));
setPost(post);
};
return (
<div className="bg-gray-100 p-4">
<form onSubmit={submitHandler} className="flex gap-4 flex-col items-center">
<form
onSubmit={submitHandler}
className="flex gap-4 flex-col items-center"
>
<input
name="title"
type="text"
placeholder="Title"
......@@ -83,7 +89,7 @@ const CreatePost: FunctionComponent = (): ReactElement => {
</button>
</form>
</div>
)
}
);
};
export default CreatePost
export default CreatePost;
import React, { FunctionComponent, MutableRefObject, ReactElement, useRef } from "react";
import IPost from "../../interfaces/IPost";
import defaultImage from '../../assets/default-image.jpg'
import { useNavigate } from "react-router-dom";
interface IPostProps {
post: IPost;
......
......@@ -6,10 +6,17 @@ import { useSelector } from "react-redux";
import { RootState } from "../../store/store";
import { createComment, getCommentsByPost } from "../../store/comments/comments.slice";
import Comment from "../../components/Comment/Comment";
<<<<<<< frontend/src/containers/DetailsPost/DetailsPost.tsx
import Post from "../../components/Post/Post";
import ICommentDto from "../../interfaces/ICommentDto";
import './DetailsPost.css'
=======
import ICommentDto from "../../interfaces/ICommentDto";
import Post from "../../components/Post/Post";
>>>>>>> frontend/src/containers/DetailsPost/DetailsPost.tsx
const DetailsPost: FunctionComponent = (): ReactElement => {
const params: any = useParams();
const dispatch = useDispatch();
......@@ -21,6 +28,10 @@ const DetailsPost: FunctionComponent = (): ReactElement => {
post: params.id,
comment: ''
})
<<<<<<< frontend/src/containers/DetailsPost/DetailsPost.tsx
=======
>>>>>>> frontend/src/containers/DetailsPost/DetailsPost.tsx
useEffect(() => {
//@ts-ignore
dispatch(getPostById(params.id))
......@@ -52,13 +63,17 @@ const DetailsPost: FunctionComponent = (): ReactElement => {
<div className="container">
<Post post={post} />
{comments ? <h1>Comments</h1> : ''}
{comments.map(c => {
{comments ? comments.map(c => {
return <Comment
key={c._id}
params_id={params.id}
comments={c}
/>
<<<<<<< frontend/src/containers/DetailsPost/DetailsPost.tsx
})}
=======
}): ''}
>>>>>>> frontend/src/containers/DetailsPost/DetailsPost.tsx
<h2>Add comment</h2>
<div className="addcomment_block">
<div className="addComment">
......@@ -72,6 +87,10 @@ const DetailsPost: FunctionComponent = (): ReactElement => {
<button className="addcomment_btn" onClick={sendComment}>Send</button>
</div>
<<<<<<< frontend/src/containers/DetailsPost/DetailsPost.tsx
=======
>>>>>>> frontend/src/containers/DetailsPost/DetailsPost.tsx
</div>
</div>
)
......
import {createAsyncThunk, createSlice} from '@reduxjs/toolkit';
import IPost from '../../interfaces/IPost'
import { postApi } from '../../api/postApi'
import IResponse from '../../interfaces/IResponse'
import IPost from '../../interfaces/IPost';
import {postApi} from '../../api/postApi';
import IResponse from '../../interfaces/IResponse';
interface IPostState {
posts: IPost[]
post: IPost
loadingPosts: boolean
messagePosts: string
posts: IPost[];
post: IPost;
loadingPosts: boolean;
messagePosts: string;
}
const initialState:IPostState = {
const initialState: IPostState = {
posts: [] as IPost[],
post: {} as IPost,
loadingPosts: false,
messagePosts: ''
}
const namespace = 'posts'
messagePosts: '',
};
const namespace = 'posts';
export const getPosts = createAsyncThunk(
`${namespace}/getPosts`,
async (): Promise<IResponse<IPost[] | undefined>> => {
return postApi.getPosts()
return await postApi.getPosts();
}
)
);
export const getPostById = createAsyncThunk(
`${namespace}/getPostById`,
async (id: string): Promise<IResponse<IPost | undefined>> => {
return postApi.getPostById(id)
return await postApi.getPostById(id);
}
)
);
export const createPost = createAsyncThunk(
`${namespace}/createPost`,
async (post: FormData) => {
return postApi.createPost(post)
return await postApi.createPost(post);
}
)
);
export const deletePostById = createAsyncThunk(
`${namespace}/deletePostById`,
async (id: string) => {
return postApi.deletePostById(id)
return await postApi.deletePostById(id);
}
)
);
export const postsSlice = createSlice({
name: namespace,
......@@ -54,48 +53,49 @@ export const postsSlice = createSlice({
extraReducers: (builder) => {
builder
.addCase(getPosts.rejected, (state) => {
state.loadingPosts = false
state.loadingPosts = false;
})
.addCase(getPosts.pending, (state) => {
state.loadingPosts = true
state.loadingPosts = true;
})
.addCase(getPosts.fulfilled, (state, action) => {
state.loadingPosts = false
state.posts = action.payload.result as IPost[]
state.messagePosts = action.payload.message
state.loadingPosts = false;
state.posts = action.payload.result as IPost[];
state.messagePosts = action.payload.message;
})
.addCase(getPostById.rejected, (state) => {
state.loadingPosts = false
state.loadingPosts = false;
})
.addCase(getPostById.pending, (state) => {
state.loadingPosts = true
state.loadingPosts = true;
})
.addCase(getPostById.fulfilled, (state, action) => {
state.loadingPosts = false
state.post = action.payload.result as IPost
state.messagePosts = action.payload.message
state.loadingPosts = false;
state.post = action.payload.result as IPost;
state.messagePosts = action.payload.message;
})
.addCase(createPost.rejected, (state) => {
state.loadingPosts = false
state.loadingPosts = false;
})
.addCase(createPost.pending, (state) => {
state.loadingPosts = true
state.loadingPosts = true;
})
.addCase(createPost.fulfilled, (state, action) => {
state.loadingPosts = false
state.messagePosts = action.payload.message
state.loadingPosts = false;
state.messagePosts = action.payload.message;
console.log(action.payload);
})
.addCase(deletePostById.rejected, (state) => {
state.loadingPosts = false
state.loadingPosts = false;
})
.addCase(deletePostById.pending, (state) => {
state.loadingPosts = true
state.loadingPosts = true;
})
.addCase(deletePostById.fulfilled, (state, action) => {
state.loadingPosts = false
state.messagePosts = action.payload.message
})
}
})
state.loadingPosts = false;
state.messagePosts = action.payload.message;
});
},
});
export default postsSlice.reducer;
......@@ -104,6 +104,7 @@ export const userSlice = createSlice({
state.user.username = action.payload[0].username;
state.loading = false;
state.userLoggedIn = true;
state.user._id = action.payload[0]._id;
});
},
});
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment