summaryrefslogtreecommitdiffhomepage
path: root/frontend/src/pages
diff options
context:
space:
mode:
authorrealtradam <[email protected]>2024-07-27 04:17:50 -0400
committerrealtradam <[email protected]>2024-07-27 04:17:50 -0400
commitcc04a47f4e1597b4fe3d92235929d553205dac4a (patch)
tree6732b2ce0e604910a656d5ac441272b80506b1d4 /frontend/src/pages
parentde3d80ce3ea20a869d700c3238020d44059de099 (diff)
downloadspring-blog-cc04a47f4e1597b4fe3d92235929d553205dac4a.tar.gz
spring-blog-cc04a47f4e1597b4fe3d92235929d553205dac4a.zip
implement search and better UX
Diffstat (limited to 'frontend/src/pages')
-rw-r--r--frontend/src/pages/Home.tsx297
-rw-r--r--frontend/src/pages/auth/Login.tsx137
2 files changed, 259 insertions, 175 deletions
diff --git a/frontend/src/pages/Home.tsx b/frontend/src/pages/Home.tsx
index eed745b..682f794 100644
--- a/frontend/src/pages/Home.tsx
+++ b/frontend/src/pages/Home.tsx
@@ -1,123 +1,194 @@
import { useState, useEffect } from "react";
-export default function Home() {
- const [articles, setArticles] = useState<any>([]);
-
+type article = {
+ id: number;
+ title: string;
+ photoUrl: string;
+ content: string;
+ createdOn: string;
+ updateOn: string;
+};
+type articleSearch = {
+ set: React.Dispatch<React.SetStateAction<string | null>>;
+ value: string | null;
+};
+
+export default function Home({
+ articleSearch,
+}: {
+ articleSearch: articleSearch;
+}) {
+ const [articles, setArticles] = useState<article[]>([]);
+ const [allArticles, setAllArticles] = useState<any>(null);
+
+ // pull data when new search is given
useEffect(() => {
- const url = `${import.meta.env.VITE_API_TITLE}/api/v1/articles`;
- fetch(url).then((response) => {
- if (response.ok) {
- return response.json();
- }
- throw new Error("Network response was not ok.");
- }).then((response) => setArticles(response));
- }, []);
-
- const allArticles = articles.map((article) => (
- <div className="w-full md:w-1/2 p-6 flex flex-col flex-grow flex-shrink">
- <div className="flex-1 bg-white rounded-t rounded-b-none overflow-hidden shadow-lg">
- {/*th:href="@{/articles/{articleId}(articleId=${article.id})}"*/}
- <a className="flex flex-wrap no-underline hover:no-underline">
- {/*th:src="${article.photoUrl}"*/}
- <img src={article.photoUrl} className="h-full w-full rounded-t pb-6"/>
- {/*th:text="${article.title}"*/}
- <div className="w-full font-bold text-xl text-gray-900 px-6">{article.title}</div>
- <p className="text-gray-800 font-serif text-base px-6 mb-5"></p>
- </a>
+ let url;
+ if (articleSearch.value === null) {
+ //alert("not searched");
+ url = `${import.meta.env.VITE_API_TITLE}/api/v1/articles`;
+ } else {
+ //alert("searched");
+ url = `${import.meta.env.VITE_API_TITLE}/api/v1/articles?search=${
+ articleSearch.value
+ }`;
+ }
+ fetch(url)
+ .then((response) => {
+ if (response.ok) {
+ return response.json();
+ }
+ throw new Error("Network response was not ok.");
+ })
+ .then((response) => setArticles(response));
+ }, [articleSearch.value]);
+
+ // when new data is pulled update the articles shown
+ useEffect(() => {
+ setAllArticles(
+ articles.map((article) => (
+ <div
+ key={article.id}
+ className="w-full md:w-1/2 p-6 flex flex-col flex-grow flex-shrink">
+ <div className="flex-1 bg-white rounded-t rounded-b-none overflow-hidden shadow-lg">
+ {/*th:href="@{/articles/{articleId}(articleId=${article.id})}"*/}
+ <a className="flex flex-wrap no-underline hover:no-underline">
+ <img src={article.photoUrl} className="h-full w-full rounded-t pb-6" />
+ <div className="w-full font-bold text-xl text-gray-900 px-6">
+ {article.title}
+ </div>
+ <p className="text-gray-800 font-serif text-base px-6 mb-5"></p>
+ </a>
{/*th:if="${user.id} == ${article.createdBy.id}"*/}
- <div ></div>
+ <div></div>
{/*th:href="@{/articles/edit/{articleId}(articleId=${article.id})}"*/}
- <a className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-2 ml-4 text-sm rounded">Edit</a>
- {/*th:href="@{/articles/delete/{articleId}(articleId=${article.id})}"*/}
- <a className="bg-red-500 hover:bg-red-700 text-white font-bold py-1 px-2 ml-4 text-sm rounded">Delete</a>
-
- </div>
- <div className="flex-none mt-auto bg-white rounded-b rounded-t-none overflow-hidden shadow-lg p-6">
- <div className="flex items-center justify-between">
- <p className="text-gray-600 text-xs md:text-sm"></p>
- </div>
- </div>
- </div>
- ));
- return(
+ <a className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-2 ml-4 text-sm rounded">
+ Edit
+ </a>
+ {/*th:href="@{/articles/delete/{articleId}(articleId=${article.id})}"*/}
+ <a className="bg-red-500 hover:bg-red-700 text-white font-bold py-1 px-2 ml-4 text-sm rounded">
+ Delete
+ </a>
+ </div>
+ <div className="flex-none mt-auto bg-white rounded-b rounded-t-none overflow-hidden shadow-lg p-6">
+ <div className="flex items-center justify-between">
+ <p className="text-gray-600 text-xs md:text-sm"></p>
+ </div>
+ </div>
+ </div>
+ )),
+ );
+ }, [articles]);
+
+ return (
<>
- {/*Container*/}
-<div className="container px-4 md:px-0 max-w-6xl mx-auto -mt-32">
-
- <div className="mx-0 sm:mx-6">
-
- {/*<!--Nav-->*/}
- <nav className="mt-0 w-full">
- <div className="container mx-auto flex items-center">
-
- <div className="flex w-1/2 pl-4 text-sm">
- <ul className="list-reset flex justify-between flex-1 md:flex-none items-center">
- <li className="mr-2">
- <a className="inline-block py-2 px-2 text-white no-underline hover:underline" href="post.html">POST</a>
- </li>
- <li className="mr-2">
- <a className="inline-block text-gray-600 no-underline hover:text-gray-200 hover:underline py-2 px-2" href="multimenu post.html">MULTIMENU POST</a>
- </li>
- <li className="mr-2">
- <a className="inline-block text-gray-600 no-underline hover:text-gray-200 hover:underline py-2 px-2" href="#">LINK</a>
- </li>
- <li className="mr-2">
- <a className="inline-block text-gray-600 no-underline hover:text-gray-200 hover:underline py-2 px-2" href="post_vue.html">POST_VUE</a>
- </li>
- </ul>
- </div>
-
-
- <div className="flex w-1/2 justify-end content-center">
- <a className="inline-block text-gray-500 no-underline hover:text-white hover:text-underline text-center h-10 p-2 md:h-auto md:p-4 avatar" data-tippy-content="@twitter_handle" href="https://twitter.com/intent/tweet?url=#">
- <svg className="fill-current h-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M30.063 7.313c-.813 1.125-1.75 2.125-2.875 2.938v.75c0 1.563-.188 3.125-.688 4.625a15.088 15.088 0 0 1-2.063 4.438c-.875 1.438-2 2.688-3.25 3.813a15.015 15.015 0 0 1-4.625 2.563c-1.813.688-3.75 1-5.75 1-3.25 0-6.188-.875-8.875-2.625.438.063.875.125 1.375.125 2.688 0 5.063-.875 7.188-2.5-1.25 0-2.375-.375-3.375-1.125s-1.688-1.688-2.063-2.875c.438.063.813.125 1.125.125.5 0 1-.063 1.5-.25-1.313-.25-2.438-.938-3.313-1.938a5.673 5.673 0 0 1-1.313-3.688v-.063c.813.438 1.688.688 2.625.688a5.228 5.228 0 0 1-1.875-2c-.5-.875-.688-1.813-.688-2.75 0-1.063.25-2.063.75-2.938 1.438 1.75 3.188 3.188 5.25 4.25s4.313 1.688 6.688 1.813a5.579 5.579 0 0 1 1.5-5.438c1.125-1.125 2.5-1.688 4.125-1.688s3.063.625 4.188 1.813a11.48 11.48 0 0 0 3.688-1.375c-.438 1.375-1.313 2.438-2.563 3.188 1.125-.125 2.188-.438 3.313-.875z"></path></svg>
- </a>
- <a className="inline-block text-gray-500 no-underline hover:text-white hover:text-underline text-center h-10 p-2 md:h-auto md:p-4 avatar" data-tippy-content="#facebook_id" href="https://www.facebook.com/sharer/sharer.php?u=#">
- <svg className="fill-current h-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M19 6h5V0h-5c-3.86 0-7 3.14-7 7v3H8v6h4v16h6V16h5l1-6h-6V7c0-.542.458-1 1-1z"></path></svg>
- </a>
- </div>
-
- </div>
- </nav>
-
- <div className="bg-gray-200 w-full text-xl md:text-2xl text-gray-800 leading-normal rounded-t">
-
- {/*<!--Lead Card-->*/}
- <div className="flex h-full bg-contain rounded overflow-hidden shadow-lg" style={{backgroundImage: "url('/public/abstract-polygonal-banner-background-vector.jpg')"}}>
- <a href="post.html" className="flex flex-wrap no-underline hover:no-underline">
- <div className="w-full md:w-2/3 rounded-t">
- </div>
-
- <div className="w-full md:w-1/3 flex flex-col flex-grow flex-shrink">
- <div className="flex-1 bg-white rounded-t rounded-b-none overflow-hidden shadow-lg">
- <p className="w-full text-gray-600 text-xs md:text-sm pt-6 px-6">Spring Blog</p>
- <div className="w-full font-bold text-xl text-gray-900 px-6">👋 Welcome to my Java Spring Blog!</div>
- <p className="text-gray-800 font-serif text-base px-6 mb-5">
- This is a blog project I have created with the goal of learning and understand the ins and outs of the Java Spring framework.
- </p>
- </div>
-
- <div className="flex-none mt-auto bg-white rounded-b rounded-t-none overflow-hidden shadow-lg p-6">
- <div className="flex items-center justify-between">
- <p className="text-gray-600 text-xs md:text-sm"></p>
- </div>
- </div>
- </div>
-
- </a>
- </div>
- {/*<!--/Lead Card-->*/}
-{/*th:if="${param.success}"*/}
- <div className="text-xl p-4 bg-black text-red-500">Successful Registration!</div>
-
-
- {/*<!--Posts Container-->*/}
- <div className="flex flex-wrap justify-between pt-12 -mx-6">
- { allArticles }
+ {/*Container*/}
+ <div className="container px-4 md:px-0 max-w-6xl mx-auto -mt-32">
+ <div className="mx-0 sm:mx-6">
+ {/*<!--Nav-->*/}
+ <nav className="mt-0 w-full">
+ <div className="container mx-auto flex items-center">
+ <div className="flex w-1/2 pl-4 text-sm">
+ <ul className="list-reset flex justify-between flex-1 md:flex-none items-center">
+ <li className="mr-2">
+ <a
+ className="inline-block py-2 px-2 text-white no-underline hover:underline"
+ href="post.html">
+ POST
+ </a>
+ </li>
+ <li className="mr-2">
+ <a
+ className="inline-block text-gray-600 no-underline hover:text-gray-200 hover:underline py-2 px-2"
+ href="multimenu post.html">
+ MULTIMENU POST
+ </a>
+ </li>
+ <li className="mr-2">
+ <a
+ className="inline-block text-gray-600 no-underline hover:text-gray-200 hover:underline py-2 px-2"
+ href="#">
+ LINK
+ </a>
+ </li>
+ <li className="mr-2">
+ <a
+ className="inline-block text-gray-600 no-underline hover:text-gray-200 hover:underline py-2 px-2"
+ href="post_vue.html">
+ POST_VUE
+ </a>
+ </li>
+ </ul>
+ </div>
+
+ <div className="flex w-1/2 justify-end content-center">
+ <a
+ className="inline-block text-gray-500 no-underline hover:text-white hover:text-underline text-center h-10 p-2 md:h-auto md:p-4 avatar"
+ data-tippy-content="@twitter_handle"
+ href="https://twitter.com/intent/tweet?url=#">
+ <svg
+ className="fill-current h-4"
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 32 32">
+ <path d="M30.063 7.313c-.813 1.125-1.75 2.125-2.875 2.938v.75c0 1.563-.188 3.125-.688 4.625a15.088 15.088 0 0 1-2.063 4.438c-.875 1.438-2 2.688-3.25 3.813a15.015 15.015 0 0 1-4.625 2.563c-1.813.688-3.75 1-5.75 1-3.25 0-6.188-.875-8.875-2.625.438.063.875.125 1.375.125 2.688 0 5.063-.875 7.188-2.5-1.25 0-2.375-.375-3.375-1.125s-1.688-1.688-2.063-2.875c.438.063.813.125 1.125.125.5 0 1-.063 1.5-.25-1.313-.25-2.438-.938-3.313-1.938a5.673 5.673 0 0 1-1.313-3.688v-.063c.813.438 1.688.688 2.625.688a5.228 5.228 0 0 1-1.875-2c-.5-.875-.688-1.813-.688-2.75 0-1.063.25-2.063.75-2.938 1.438 1.75 3.188 3.188 5.25 4.25s4.313 1.688 6.688 1.813a5.579 5.579 0 0 1 1.5-5.438c1.125-1.125 2.5-1.688 4.125-1.688s3.063.625 4.188 1.813a11.48 11.48 0 0 0 3.688-1.375c-.438 1.375-1.313 2.438-2.563 3.188 1.125-.125 2.188-.438 3.313-.875z"></path>
+ </svg>
+ </a>
+ <a
+ className="inline-block text-gray-500 no-underline hover:text-white hover:text-underline text-center h-10 p-2 md:h-auto md:p-4 avatar"
+ data-tippy-content="#facebook_id"
+ href="https://www.facebook.com/sharer/sharer.php?u=#">
+ <svg
+ className="fill-current h-4"
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 32 32">
+ <path d="M19 6h5V0h-5c-3.86 0-7 3.14-7 7v3H8v6h4v16h6V16h5l1-6h-6V7c0-.542.458-1 1-1z"></path>
+ </svg>
+ </a>
+ </div>
+ </div>
+ </nav>
+
+ <div className="bg-gray-200 w-full text-xl md:text-2xl text-gray-800 leading-normal rounded-t">
+ {/*<!--Lead Card-->*/}
+ <div
+ className="flex h-full bg-contain rounded overflow-hidden shadow-lg"
+ style={{
+ backgroundImage:
+ "url('/public/abstract-polygonal-banner-background-vector.jpg')",
+ }}>
+ <a
+ href="post.html"
+ className="flex flex-wrap no-underline hover:no-underline">
+ <div className="w-full md:w-2/3 rounded-t"></div>
+
+ <div className="w-full md:w-1/3 flex flex-col flex-grow flex-shrink">
+ <div className="flex-1 bg-white rounded-t rounded-b-none overflow-hidden shadow-lg">
+ <p className="w-full text-gray-600 text-xs md:text-sm pt-6 px-6">
+ Spring Blog
+ </p>
+ <div className="w-full font-bold text-xl text-gray-900 px-6">
+ 👋 Welcome to my Java Spring Blog!
+ </div>
+ <p className="text-gray-800 font-serif text-base px-6 mb-5">
+ This is a blog project I have created with the goal of learning and
+ understand the ins and outs of the Java Spring framework.
+ </p>
+ </div>
+
+ <div className="flex-none mt-auto bg-white rounded-b rounded-t-none overflow-hidden shadow-lg p-6">
+ <div className="flex items-center justify-between">
+ <p className="text-gray-600 text-xs md:text-sm"></p>
+ </div>
+ </div>
+ </div>
+ </a>
+ </div>
+ <div className="flex flex-wrap justify-between pt-12 -mx-6">
+ {allArticles}
+ </div>
+ </div>
+ </div>
</div>
- </div>
- </div>
-</div>
</>
);
}
diff --git a/frontend/src/pages/auth/Login.tsx b/frontend/src/pages/auth/Login.tsx
index 5a1e858..d064acf 100644
--- a/frontend/src/pages/auth/Login.tsx
+++ b/frontend/src/pages/auth/Login.tsx
@@ -2,12 +2,15 @@ import { FormEvent } from "react";
import { useNavigate } from "react-router-dom";
//type setUser = { setUser: { func: React.Dispatch<React.SetStateAction<string | null>> } };
-type user = { set: React.Dispatch<React.SetStateAction<string | null>>, value: string | null };
+type user = {
+ set: React.Dispatch<React.SetStateAction<string | null>>;
+ value: string | null;
+};
-export default function Login ({user}: {user: user}) {
+export default function Login({ user }: { user: user }) {
const navigate = useNavigate();
-const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
+ const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault(); //stops submit from happening
const target = e.target as typeof e.target & {
@@ -17,75 +20,85 @@ const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
};
const formData = new FormData();
- formData.append('username', target.username.value);
- formData.append('password', target.password.value);
+ formData.append("username", target.username.value);
+ formData.append("password", target.password.value);
- const response = await fetch(`${import.meta.env.VITE_API_TITLE}/api/v1/login`, {
- credentials: 'include',
- method: 'post',
- body: formData,
- }).then((res) => {
- if(res.ok) {
+ const response = await fetch(
+ `${import.meta.env.VITE_API_TITLE}/api/v1/login`,
+ {
+ credentials: "include",
+ method: "post",
+ body: formData,
+ },
+ ).then((res) => {
+ if (res.ok) {
const url = `${import.meta.env.VITE_API_TITLE}/api/v1/profile`;
fetch(url, {
- credentials: 'include',
- method: 'get',
- }).then((response) => {
- if (response.ok) {
- return response.json();
- }
- throw new Error("Network response was not ok.");
- }).then((response) => {
- user.set(response.username);
- console.log("USER:");
- console.log(user);
- console.log(user.value);
- console.log(response.username);
- navigate("/");
- });
- }
- else {
+ credentials: "include",
+ method: "get",
+ })
+ .then((response) => {
+ if (response.ok) {
+ return response.json();
+ }
+ throw new Error("Network response was not ok.");
+ })
+ .then((response) => {
+ user.set(response.username);
+ console.log("USER:");
+ console.log(user);
+ console.log(user.value);
+ console.log(response.username);
+ navigate("/");
+ });
+ } else {
console.log(response);
alert("check console for error");
}
});
};
- return(
+ return (
<>
-<div className="flex h-full justify-center bg-white p-12">
- <form onSubmit={handleSubmit} method="post" className="w-full max-w-lg">
- <div className="flex flex-wrap -mx-3 mb-6">
- <div className="w-full md:w-1/2 px-3 mb-6 md:mb-0">
- <label className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2">
- Title
- </label>
- <input className="appearance-none block w-full bg-gray-200 text-gray-700 border rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white"
- id="username"
- type="text"
- name="username"
- placeholder="Ted"/>
- </div>
- </div>
- <div className="flex flex-wrap -mx-3 mb-6">
- <div className="w-full px-3">
- <label className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2">
- Password
- </label>
- <input className="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
- id="password"
- type="password"
- name="password"
- placeholder="Doe"/>
- </div>
- </div>
- <div className="flex flex-wrap mb-2">
- </div>
- <button type="submit" value="Log in" className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Log In</button>
-
- </form>
-</div>
+ <div className="flex h-full justify-center bg-white p-12">
+ <form onSubmit={handleSubmit} method="post" className="w-full max-w-lg">
+ <div className="flex flex-wrap -mx-3 mb-6">
+ <div className="w-full md:w-1/2 px-3 mb-6 md:mb-0">
+ <label className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2">
+ Title
+ </label>
+ <input
+ className="appearance-none block w-full bg-gray-200 text-gray-700 border rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white"
+ id="username"
+ type="text"
+ name="username"
+ placeholder="Ted"
+ />
+ </div>
+ </div>
+ <div className="flex flex-wrap -mx-3 mb-6">
+ <div className="w-full px-3">
+ <label className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2">
+ Password
+ </label>
+ <input
+ className="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
+ id="password"
+ type="password"
+ name="password"
+ placeholder="Doe"
+ />
+ </div>
+ </div>
+ <div className="flex flex-wrap mb-2"></div>
+ <button
+ type="submit"
+ value="Log in"
+ className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
+ Log In
+ </button>
+ </form>
+ </div>
</>
);
-
}