diff --git a/part5/bloglist-frontend/src/App.js b/part5/bloglist-frontend/src/App.js
index 49ae691..de682e6 100644
--- a/part5/bloglist-frontend/src/App.js
+++ b/part5/bloglist-frontend/src/App.js
@@ -1,26 +1,22 @@
-import { useState, useEffect } from "react";
+import { useState, useEffect, useRef } from "react";
import Blog from "./components/Blog";
+import { BlogForm } from "./components/BlogForm";
import Notification from "./components/Notification";
import blogService from "./services/blogs";
import loginService from "./services/login";
+import Togglable from "./components/Togglable";
const App = () => {
const [blogs, setBlogs] = useState([]);
const [user, setUser] = useState(null);
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
- const [title, setTitle] = useState("");
- const [author, setAuthor] = useState("");
- const [urlAddress, setUrlAddress] = useState("");
const [errorMessage, setErrorMessage] = useState(null);
const [successMessage, setSuccessMessage] = useState(null);
const resetInputFields = () => {
setUsername("");
setPassword("");
- setTitle("");
- setAuthor("");
- setUrlAddress("");
};
const setNotification = (message, type) => {
@@ -75,22 +71,16 @@ const App = () => {
setNotification("Logout failed", "error");
}
};
-
- const handleNewBlog = async (event) => {
- event.preventDefault();
- const newBlog = {
- title: title,
- author: author,
- url: urlAddress,
- };
-
+ const newBlogRef = useRef();
+ const handleNewBlog = async (newBlog) => {
+ newBlogRef.current.toggleVisibility();
blogService
.create(newBlog)
.then((returnedBlog) => {
setBlogs(blogs.concat(returnedBlog));
resetInputFields();
setNotification(
- `A new blog ${title} by ${author} at ${urlAddress} added`,
+ `A new blog ${returnedBlog.title} by ${returnedBlog.author} at ${returnedBlog.url} added`,
"success"
);
})
@@ -123,52 +113,21 @@ const App = () => {
);
- const blogForm = () => (
-
-
Create new blog
-
-
All blogs
-
-
- | Title |
- Author |
- URL |
-
+ const blogForm = () => {
+ return (
+
+
{user.name} logged in
+
+
+
+
+
All blogs
{blogs.map((blog) => (
))}
-
-
- );
+
+ );
+ };
return (
@@ -183,11 +142,7 @@ const App = () => {
{loginForm()}
) : (
-
-
{user.name} logged in
-
- {blogForm()}
-
+ {blogForm()}
)}
);
diff --git a/part5/bloglist-frontend/src/components/Blog.js b/part5/bloglist-frontend/src/components/Blog.js
index 1b61a44..a539016 100644
--- a/part5/bloglist-frontend/src/components/Blog.js
+++ b/part5/bloglist-frontend/src/components/Blog.js
@@ -1,9 +1,26 @@
-const Blog = ({ blog }) => (
-
- | {blog.title} |
- {blog.author} |
- {blog.url} |
-
-);
+import Togglable from "./Togglable";
+
+const Blog = ({ blog }) => {
+ const blogStyle = {
+ paddingTop: 10,
+ paddingLeft: 2,
+ border: "solid",
+ borderWidth: 1,
+ marginBottom: 5,
+ };
+ return (
+
+
+ {blog.title}
+
+
+ - {blog.author}
+ - {blog.url}
+
+
+
+
+ );
+};
export default Blog;
diff --git a/part5/bloglist-frontend/src/components/BlogForm.js b/part5/bloglist-frontend/src/components/BlogForm.js
new file mode 100644
index 0000000..7cb6621
--- /dev/null
+++ b/part5/bloglist-frontend/src/components/BlogForm.js
@@ -0,0 +1,59 @@
+import { useState } from "react";
+
+export const BlogForm = ({ createBlog }) => {
+ const [title, setTitle] = useState("");
+ const [author, setAuthor] = useState("");
+ const [urlAddress, setUrlAddress] = useState("");
+
+ const resetInputFields = () => {
+ setTitle("");
+ setAuthor("");
+ setUrlAddress("");
+ };
+
+ const addBlog = async (event) => {
+ event.preventDefault();
+ createBlog({
+ title: title,
+ author: author,
+ url: urlAddress,
+ });
+ resetInputFields();
+ };
+
+ return (
+
+ );
+};
diff --git a/part5/bloglist-frontend/src/components/Togglable.js b/part5/bloglist-frontend/src/components/Togglable.js
new file mode 100644
index 0000000..84c0e0a
--- /dev/null
+++ b/part5/bloglist-frontend/src/components/Togglable.js
@@ -0,0 +1,30 @@
+import { useState, forwardRef, useImperativeHandle } from "react";
+
+const Togglable = forwardRef((props, refs) => {
+ const [visible, setVisible] = useState(false);
+
+ const hideWhenVisible = { display: visible ? "none" : "" };
+ const showWhenVisible = { display: visible ? "" : "none" };
+
+ const toggleVisibility = () => {
+ setVisible(!visible);
+ };
+
+ useImperativeHandle(refs, () => {
+ return { toggleVisibility };
+ });
+
+ return (
+
+
+
+
+
+ {props.children}
+
+
+
+ );
+});
+
+export default Togglable;