118 lines
4.5 KiB
JavaScript
118 lines
4.5 KiB
JavaScript
import React, {useEffect, useState} from 'react';
|
|
import NewPostForm from './components/NewPostForm';
|
|
import './App.scss';
|
|
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
|
import {faPenToSquare, faRotate, faTimes} from "@fortawesome/free-solid-svg-icons";
|
|
import {postApi} from "./api/posts.api";
|
|
import {locationUtils} from "./utils/location";
|
|
import Post from "./components/Post";
|
|
import keycloak from "./Authentification/Keycloak";
|
|
|
|
const App = () => {
|
|
const [posts, setPosts] = useState([]);
|
|
const [selectedPost, selectPost] = useState(null);
|
|
const [comment, setComment] = useState('');
|
|
|
|
useEffect(() => {
|
|
if(posts.length === 0) {
|
|
reload().then(null);
|
|
}
|
|
});
|
|
|
|
useEffect(() => {
|
|
if(selectedPost) {
|
|
selectPost(posts.find(post => post.id === selectedPost.id));
|
|
}
|
|
}, [posts]);
|
|
|
|
|
|
const reload = async () => {
|
|
await loadPosts().then(posts => {
|
|
posts = recursiveSort(posts);
|
|
setPosts(posts);
|
|
});
|
|
}
|
|
|
|
const recursiveSort = (posts) => {
|
|
posts.forEach((post, index) => {posts[index].comments = recursiveSort(post.comments)});
|
|
posts.sort((a, b) => a.date < b.date ? 1 : -1);
|
|
return posts;
|
|
}
|
|
|
|
const loadPosts = async () => {
|
|
const location = await locationUtils.getCurrentLocation();
|
|
return await postApi.getPostsByCoords(location.lat, location.lon);
|
|
}
|
|
|
|
const addPost = async (title, text) => {
|
|
await postApi.createNewPost(title, text);
|
|
await reload();
|
|
};
|
|
|
|
const addComment = async (postId, commentText) => {
|
|
await postApi.createNewPost("", commentText, postId).then(await reload);
|
|
};
|
|
|
|
const handleCommentSubmit = async (e) => {
|
|
e.preventDefault();
|
|
if (comment.trim() && selectedPost) {
|
|
await addComment(selectedPost.id, comment);
|
|
setComment('');
|
|
await reload();
|
|
selectPost(selectedPost);
|
|
}
|
|
};
|
|
|
|
const closePost = () => {
|
|
selectPost(null);
|
|
};
|
|
|
|
return (
|
|
<div className="app">
|
|
<div className="nav-bar">
|
|
<button className="nav-button" onClick={() => reload()}>
|
|
<FontAwesomeIcon className={"close-button"} icon={faRotate}/>
|
|
</button>
|
|
<button className="nav-button nav-space" onClick={() => keycloak.accountManagement()}>
|
|
<FontAwesomeIcon className={"close-button"} icon={faPenToSquare}/>
|
|
</button>
|
|
<button className="logout" onClick={() => keycloak.logout()}>Logout</button>
|
|
</div>
|
|
<h1>SWA - Jodel</h1>
|
|
<div style={{height: selectedPost ? 0 : "auto", overflowY: "hidden"}}>
|
|
<NewPostForm addPost={addPost}/>
|
|
{posts.map(post => <Post key={post.id} post={post} recursionDepth={5} selectPost={selectPost} reload={reload} />)}
|
|
</div>
|
|
{selectedPost && (
|
|
<div className="single-post-view">
|
|
<div className="close-post">
|
|
<FontAwesomeIcon className={"close-button"} onClick={closePost} icon={faTimes}/>
|
|
</div>
|
|
<Post key={selectedPost.id} post={selectedPost} recursionDepth={0} selectPost={null} reload={reload}/>
|
|
<form className="comment-form" onSubmit={handleCommentSubmit}>
|
|
<div className="textarea-container">
|
|
<textarea
|
|
rows={15}
|
|
value={comment}
|
|
onChange={(e) => setComment(e.target.value)}
|
|
placeholder="Kommentieren..."
|
|
maxLength={500}
|
|
/>
|
|
<div className="char-count-container">
|
|
<span className={comment.length === 500 ? "char-count max-char-count" : "char-count"}>
|
|
{comment.length} / 500
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<button type="submit">Kommentieren</button>
|
|
</form>
|
|
<div className="comments">
|
|
{selectedPost.comments.map(post => <Post key={post.id} post={post} recursionDepth={0} selectPost={null} reload={reload} />)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default App; |