summaryrefslogtreecommitdiffhomepage
path: root/frontend
diff options
context:
space:
mode:
authorrealtradam <[email protected]>2024-07-27 16:44:01 -0400
committerrealtradam <[email protected]>2024-07-27 16:44:01 -0400
commitf75c5d9264d71298711321d83a9c6b23327b3f56 (patch)
treeb7f964a1e37cdead6a198e1138cc1f06331b0eb5 /frontend
parentb1112afc5162bb299d528974594dcf7c2ec46266 (diff)
downloadspring-blog-f75c5d9264d71298711321d83a9c6b23327b3f56.tar.gz
spring-blog-f75c5d9264d71298711321d83a9c6b23327b3f56.zip
fix linting
Diffstat (limited to 'frontend')
-rw-r--r--frontend/.eslintrc.cjs18
-rw-r--r--frontend/.vite/deps/_metadata.json2
-rw-r--r--frontend/README.md8
-rw-r--r--frontend/index.html2
-rw-r--r--frontend/postcss.config.js2
-rw-r--r--frontend/src/App.tsx4
-rw-r--r--frontend/src/components/Layout.tsx471
-rw-r--r--frontend/src/main.tsx12
-rw-r--r--frontend/src/pages/Home.tsx368
-rw-r--r--frontend/src/pages/articles/Article.tsx46
-rw-r--r--frontend/src/pages/articles/New.tsx161
-rw-r--r--frontend/src/pages/auth/Login.tsx181
-rw-r--r--frontend/src/pages/auth/Register.tsx161
-rw-r--r--frontend/src/routes/index.tsx55
-rw-r--r--frontend/tailwind.config.js8
-rw-r--r--frontend/vite.config.ts6
16 files changed, 794 insertions, 711 deletions
diff --git a/frontend/.eslintrc.cjs b/frontend/.eslintrc.cjs
index d6c9537..6e8698b 100644
--- a/frontend/.eslintrc.cjs
+++ b/frontend/.eslintrc.cjs
@@ -2,17 +2,17 @@ module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
- 'eslint:recommended',
- 'plugin:@typescript-eslint/recommended',
- 'plugin:react-hooks/recommended',
+ "eslint:recommended",
+ "plugin:@typescript-eslint/recommended",
+ "plugin:react-hooks/recommended",
],
- ignorePatterns: ['dist', '.eslintrc.cjs'],
- parser: '@typescript-eslint/parser',
- plugins: ['react-refresh'],
+ ignorePatterns: ["dist", ".eslintrc.cjs"],
+ parser: "@typescript-eslint/parser",
+ plugins: ["react-refresh"],
rules: {
- 'react-refresh/only-export-components': [
- 'warn',
+ "react-refresh/only-export-components": [
+ "warn",
{ allowConstantExport: true },
],
},
-}
+};
diff --git a/frontend/.vite/deps/_metadata.json b/frontend/.vite/deps/_metadata.json
index 905310f..9304faf 100644
--- a/frontend/.vite/deps/_metadata.json
+++ b/frontend/.vite/deps/_metadata.json
@@ -5,4 +5,4 @@
"browserHash": "f33efd09",
"optimized": {},
"chunks": {}
-} \ No newline at end of file
+}
diff --git a/frontend/README.md b/frontend/README.md
index e1cdc89..85a6989 100644
--- a/frontend/README.md
+++ b/frontend/README.md
@@ -17,12 +17,12 @@ If you are developing a production application, we recommend updating the config
export default {
// other rules...
parserOptions: {
- ecmaVersion: 'latest',
- sourceType: 'module',
- project: ['./tsconfig.json', './tsconfig.node.json', './tsconfig.app.json'],
+ ecmaVersion: "latest",
+ sourceType: "module",
+ project: ["./tsconfig.json", "./tsconfig.node.json", "./tsconfig.app.json"],
tsconfigRootDir: __dirname,
},
-}
+};
```
- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
diff --git a/frontend/index.html b/frontend/index.html
index 82a3d13..821eeac 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -10,4 +10,4 @@
<div id="root" class="w-full"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
-</div>
+</html>
diff --git a/frontend/postcss.config.js b/frontend/postcss.config.js
index 2e7af2b..2aa7205 100644
--- a/frontend/postcss.config.js
+++ b/frontend/postcss.config.js
@@ -3,4 +3,4 @@ export default {
tailwindcss: {},
autoprefixer: {},
},
-}
+};
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index 92de410..e66807e 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -1,5 +1,5 @@
-import Routes from "./routes"
+import Routes from "./routes";
export default function App() {
- return (<Routes />);
+ return <Routes />;
}
diff --git a/frontend/src/components/Layout.tsx b/frontend/src/components/Layout.tsx
index 2ebaa79..d8613d5 100644
--- a/frontend/src/components/Layout.tsx
+++ b/frontend/src/components/Layout.tsx
@@ -1,246 +1,269 @@
import { Outlet, useNavigate } from "react-router-dom";
-import { useState, useEffect, FormEvent } from "react";
+import { useEffect, FormEvent } from "react";
type user = {
- set: React.Dispatch<React.SetStateAction<string | null>>;
- value: string | null;
+ set: React.Dispatch<React.SetStateAction<string | null>>;
+ value: string | null;
};
type articleSearch = user;
export default function Layout({
- user,
- articleSearch,
+ user,
+ articleSearch,
}: {
- user: user;
- articleSearch: articleSearch;
+ user: user;
+ articleSearch: articleSearch;
}) {
- const navigate = useNavigate();
+ const navigate = useNavigate();
- useEffect(() => {
- 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(response.username);
- });
- }, [user]);
+ useEffect(() => {
+ 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(response.username);
+ });
+ }, [user]);
- const logout = () => {
- fetch(`${import.meta.env.VITE_API_TITLE}/api/v1/logout`, {
- credentials: "include",
- method: "get",
- }).then(() => {
- user.set(null);
- });
- };
+ const logout = () => {
+ fetch(`${import.meta.env.VITE_API_TITLE}/api/v1/logout`, {
+ credentials: "include",
+ method: "get",
+ }).then(() => {
+ user.set(null);
+ });
+ };
- const search = (e: FormEvent<HTMLFormElement>) => {
- e.preventDefault();
+ const search = (e: FormEvent<HTMLFormElement>) => {
+ e.preventDefault();
- const target = e.target as typeof e.target & {
- search: { value: string };
- };
+ const target = e.target as typeof e.target & {
+ search: { value: string };
+ };
- articleSearch.set(target.search.value);
+ articleSearch.set(target.search.value);
- navigate("/");
- };
+ navigate("/");
+ };
- return (
- <>
- <div className="w-full bg-gray-200 min-h-screen font-sans leading-normal tracking-normal">
- <nav className="bg-gray-900 p-4 mt-0 w-full">
- <div className="container mx-auto flex items-center">
- <div className="flex text-white font-extrabold">
- {/*th:if="${(user == null || user.username == null)}"*/}
- <a
- className="flex text-white text-base no-underline whitespace-nowrap hover:text-white hover:no-underline"
- href="#">
- ☕ {user.value === null ? "Spring!" : user.value}
- <span className="hidden w-0 md:w-auto md:block pl-1"></span>
- </a>
- </div>
- <div className="flex pl-4 text-sm place-content-between w-full">
- <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" href="/">
- HOME
- </a>
- </li>
- <li className="mr-2">
- <a
- className="inline-block text-indigo-200 no-underline hover:text-gray-100 hover:text-underline py-2 px-2"
- href="/article/new">
- NEW
- </a>
- </li>
- <li className="mr-2">
- <a
- className="inline-block text-indigo-200 no-underline hover:text-indigo-100 hover:text-underline py-2 px-2"
- href="/register">
- REGISTER
- </a>
- </li>
- <li className="mr-2">
- {user.value === null ? (
- <a
- className="inline-block text-indigo-200 no-underline hover:text-indigo-100 hover:text-underline py-2 px-2"
- href="/login">
- LOGIN
- </a>
- ) : (
- <button
- className="inline-block text-indigo-200 no-underline hover:text-indigo-100 hover:text-underline py-2 px-2"
- onClick={logout}>
- LOGOUT
- </button>
- )}
- </li>
- </ul>
- <form onSubmit={search} className="w-full max-w-md">
- <div className="flex flex-wrap -mx-3">
- <div className="w-full px-3">
- <input
- className="appearance-none block w-full bg-gray-200 text-gray-700 border rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white"
- id="search"
- type="search"
- name="search"
- placeholder="Search"
- />
- </div>
- </div>
- </form>
- </div>
- </div>
- </nav>
+ return (
+ <>
+ <div className="w-full bg-gray-200 min-h-screen font-sans leading-normal tracking-normal">
+ <nav className="bg-gray-900 p-4 mt-0 w-full">
+ <div className="container mx-auto flex items-center">
+ <div className="flex text-white font-extrabold">
+ {/*th:if="${(user == null || user.username == null)}"*/}
+ <a
+ className="flex text-white text-base no-underline whitespace-nowrap hover:text-white hover:no-underline"
+ href="#"
+ >
+ ☕ {user.value === null ? "Spring!" : user.value}
+ <span className="hidden w-0 md:w-auto md:block pl-1"></span>
+ </a>
+ </div>
+ <div className="flex pl-4 text-sm place-content-between w-full">
+ <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"
+ href="/"
+ >
+ HOME
+ </a>
+ </li>
+ <li className="mr-2">
+ <a
+ className="inline-block text-indigo-200 no-underline hover:text-gray-100 hover:text-underline py-2 px-2"
+ href="/article/new"
+ >
+ NEW
+ </a>
+ </li>
+ <li className="mr-2">
+ <a
+ className="inline-block text-indigo-200 no-underline hover:text-indigo-100 hover:text-underline py-2 px-2"
+ href="/register"
+ >
+ REGISTER
+ </a>
+ </li>
+ <li className="mr-2">
+ {user.value === null ? (
+ <a
+ className="inline-block text-indigo-200 no-underline hover:text-indigo-100 hover:text-underline py-2 px-2"
+ href="/login"
+ >
+ LOGIN
+ </a>
+ ) : (
+ <button
+ className="inline-block text-indigo-200 no-underline hover:text-indigo-100 hover:text-underline py-2 px-2"
+ onClick={logout}
+ >
+ LOGOUT
+ </button>
+ )}
+ </li>
+ </ul>
+ <form onSubmit={search} className="w-full max-w-md">
+ <div className="flex flex-wrap -mx-3">
+ <div className="w-full px-3">
+ <input
+ className="appearance-none block w-full bg-gray-200 text-gray-700 border rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white"
+ id="search"
+ type="search"
+ name="search"
+ placeholder="Search"
+ />
+ </div>
+ </div>
+ </form>
+ </div>
+ </div>
+ </nav>
- {/*slide in nav*/}
- <div
- id="header"
- className="bg-white fixed w-full z-10 top-0 hidden animated"
- style={{ opacity: ".95" }}>
- <div className="bg-white">
- <div className="flex flex-wrap items-center content-center">
- <div className="flex w-1/2 justify-start text-white font-extrabold">
- <a
- className="flex text-gray-100 no-underline hover:text-gray-900 hover:no-underline pl-2"
- href="#">
- 👻{" "}
- <span className="hidden w-0 md:w-auto md:block pl-1">
- Ghostwind CSS
- </span>
- </a>
- </div>
- <div className="flex w-1/2 justify-end content-center">
- <p className="hidden sm:block mr-3 text-center h-14 p-4 text-xs">
- <span className="pr-2">Share this</span> 👉
- </p>
- <a
- className="inline-block text-white no-underline hover:text-white hover:text-underline text-center h-10 w-10 p-2 md:h-auto md:w-16 md:p-4"
- href="https://twitter.com/intent/tweet?url=#"
- style={{ backgroundColor: "#33b1ff" }}>
- <svg
- className="fill-current text-white 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-white no-underline hover:text-white hover:text-underline text-center h-10 w-10 p-2 md:h-auto md:w-16 md:p-4"
- href="https://www.facebook.com/sharer/sharer.php?u=#"
- style={{ backgroundColor: "#005e99" }}>
- <svg
- className="fill-current text-white 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>
- </div>
- {/*Progress bar*/}
- <div
- id="progress"
- className="h-1 bg-white shadow"
- style={{
- background:
- "linear-gradient(to right, #4dc0b5 var(--scroll), transparent 0)",
- }}></div>
- </div>
+ {/*slide in nav*/}
+ <div
+ id="header"
+ className="bg-white fixed w-full z-10 top-0 hidden animated"
+ style={{ opacity: ".95" }}
+ >
+ <div className="bg-white">
+ <div className="flex flex-wrap items-center content-center">
+ <div className="flex w-1/2 justify-start text-white font-extrabold">
+ <a
+ className="flex text-gray-100 no-underline hover:text-gray-900 hover:no-underline pl-2"
+ href="#"
+ >
+ 👻{" "}
+ <span className="hidden w-0 md:w-auto md:block pl-1">
+ Ghostwind CSS
+ </span>
+ </a>
+ </div>
+ <div className="flex w-1/2 justify-end content-center">
+ <p className="hidden sm:block mr-3 text-center h-14 p-4 text-xs">
+ <span className="pr-2">Share this</span> 👉
+ </p>
+ <a
+ className="inline-block text-white no-underline hover:text-white hover:text-underline text-center h-10 w-10 p-2 md:h-auto md:w-16 md:p-4"
+ href="https://twitter.com/intent/tweet?url=#"
+ style={{ backgroundColor: "#33b1ff" }}
+ >
+ <svg
+ className="fill-current text-white 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-white no-underline hover:text-white hover:text-underline text-center h-10 w-10 p-2 md:h-auto md:w-16 md:p-4"
+ href="https://www.facebook.com/sharer/sharer.php?u=#"
+ style={{ backgroundColor: "#005e99" }}
+ >
+ <svg
+ className="fill-current text-white 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>
+ </div>
+ {/*Progress bar*/}
+ <div
+ id="progress"
+ className="h-1 bg-white shadow"
+ style={{
+ background:
+ "linear-gradient(to right, #4dc0b5 var(--scroll), transparent 0)",
+ }}
+ ></div>
+ </div>
- {/*Header*/}
- <div
- className="w-full m-0 p-0 bg-cover bg-bottom"
- style={{
- backgroundImage:
- "url('https://upload.wikimedia.org/wikipedia/commons/6/65/Toronto_Skyline_Summer_2020.jpg')",
- height: "60vh",
- maxHeight: "460px",
- }}>
- <div className="container max-w-4xl bg-black bg-opacity-50 pb-16 rounded-b-xl mx-auto pt-16 md:pt-32 text-center break-normal">
- {/*Title*/}
- <p className="text-white font-extrabold text-3xl md:text-5xl">
- ☕ Spring!
- </p>
- <p className="text-xl md:text-2xl text-gray-200">Welcome to my Blog</p>
- </div>
- </div>
+ {/*Header*/}
+ <div
+ className="w-full m-0 p-0 bg-cover bg-bottom"
+ style={{
+ backgroundImage:
+ "url('https://upload.wikimedia.org/wikipedia/commons/6/65/Toronto_Skyline_Summer_2020.jpg')",
+ height: "60vh",
+ maxHeight: "460px",
+ }}
+ >
+ <div className="container max-w-4xl bg-black bg-opacity-50 pb-16 rounded-b-xl mx-auto pt-16 md:pt-32 text-center break-normal">
+ {/*Title*/}
+ <p className="text-white font-extrabold text-3xl md:text-5xl">
+ ☕ Spring!
+ </p>
+ <p className="text-xl md:text-2xl text-gray-200">
+ Welcome to my Blog
+ </p>
+ </div>
+ </div>
- <Outlet />
+ <Outlet />
- <footer className="bg-gray-900">
- <div className="container max-w-6xl mx-auto flex items-center px-2 py-8">
- <div className="w-full mx-auto flex flex-wrap items-center">
- <div className="flex w-full md:w-1/2 justify-center md:justify-start text-white font-extrabold">
- <a
- className="text-gray-900 no-underline hover:text-gray-900 hover:no-underline"
- href="#">
- <span className="text-base text-gray-200"></span>
- </a>
- </div>
- <div className="flex w-full pt-2 content-center justify-between md:w-1/2 md:justify-end">
- <ul className="list-reset flex justify-center flex-1 md:flex-none items-center">
- <li>
- <a
- className="inline-block py-2 px-3 text-white no-underline"
- href="#"></a>
- </li>
- <li>
- <a
- className="inline-block text-gray-600 no-underline hover:text-gray-200 hover:underline py-2 px-3"
- href="#"></a>
- </li>
- <li>
- <a
- className="inline-block text-gray-600 no-underline hover:text-gray-200 hover:underline py-2 px-3"
- href="#"></a>
- </li>
- <li>
- <a
- className="inline-block text-gray-600 no-underline hover:text-gray-200 hover:underline py-2 px-3"
- href="#"></a>
- </li>
- </ul>
- </div>
- </div>
- </div>
- </footer>
+ <footer className="bg-gray-900">
+ <div className="container max-w-6xl mx-auto flex items-center px-2 py-8">
+ <div className="w-full mx-auto flex flex-wrap items-center">
+ <div className="flex w-full md:w-1/2 justify-center md:justify-start text-white font-extrabold">
+ <a
+ className="text-gray-900 no-underline hover:text-gray-900 hover:no-underline"
+ href="#"
+ >
+ <span className="text-base text-gray-200"></span>
+ </a>
+ </div>
+ <div className="flex w-full pt-2 content-center justify-between md:w-1/2 md:justify-end">
+ <ul className="list-reset flex justify-center flex-1 md:flex-none items-center">
+ <li>
+ <a
+ className="inline-block py-2 px-3 text-white no-underline"
+ href="#"
+ ></a>
+ </li>
+ <li>
+ <a
+ className="inline-block text-gray-600 no-underline hover:text-gray-200 hover:underline py-2 px-3"
+ href="#"
+ ></a>
+ </li>
+ <li>
+ <a
+ className="inline-block text-gray-600 no-underline hover:text-gray-200 hover:underline py-2 px-3"
+ href="#"
+ ></a>
+ </li>
+ <li>
+ <a
+ className="inline-block text-gray-600 no-underline hover:text-gray-200 hover:underline py-2 px-3"
+ href="#"
+ ></a>
+ </li>
+ </ul>
+ </div>
+ </div>
+ </div>
+ </footer>
- <script src="https://unpkg.com/@popperjs/core@2"></script>
- <script src="https://unpkg.com/tippy.js@6"></script>
- <script>//Init tooltips tippy('.avatar')</script>
- </div>
- </>
- );
+ <script src="https://unpkg.com/@popperjs/core@2"></script>
+ <script src="https://unpkg.com/tippy.js@6"></script>
+ <script>//Init tooltips tippy('.avatar')</script>
+ </div>
+ </>
+ );
}
diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx
index 3d7150d..f25366e 100644
--- a/frontend/src/main.tsx
+++ b/frontend/src/main.tsx
@@ -1,10 +1,10 @@
-import React from 'react'
-import ReactDOM from 'react-dom/client'
-import App from './App.tsx'
-import './index.css'
+import React from "react";
+import ReactDOM from "react-dom/client";
+import App from "./App.tsx";
+import "./index.css";
-ReactDOM.createRoot(document.getElementById('root')!).render(
+ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
<App />
</React.StrictMode>,
-)
+);
diff --git a/frontend/src/pages/Home.tsx b/frontend/src/pages/Home.tsx
index 682f794..e0866a4 100644
--- a/frontend/src/pages/Home.tsx
+++ b/frontend/src/pages/Home.tsx
@@ -1,194 +1,210 @@
import { useState, useEffect } from "react";
type article = {
- id: number;
- title: string;
- photoUrl: string;
- content: string;
- createdOn: string;
- updateOn: string;
+ id: number;
+ title: string;
+ photoUrl: string;
+ content: string;
+ createdOn: string;
+ updateOn: string;
};
+// if null then code will know to not search and just return all articles
type articleSearch = {
- set: React.Dispatch<React.SetStateAction<string | null>>;
- value: string | null;
+ set: React.Dispatch<React.SetStateAction<string | null>>;
+ value: string | null;
};
export default function Home({
- articleSearch,
+ articleSearch,
}: {
- articleSearch: articleSearch;
+ articleSearch: articleSearch;
}) {
- const [articles, setArticles] = useState<article[]>([]);
- const [allArticles, setAllArticles] = useState<any>(null);
+ const [articles, setArticles] = useState<article[]>([]);
+ const [allArticles, setAllArticles] = useState<JSX.Element[]>([]);
- // pull data when new search is given
- useEffect(() => {
- 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]);
+ // pull data when new search is given
+ useEffect(() => {
+ 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>
- {/*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>
- )),
- );
- }, [articles]);
+ // 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>
+ {/*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>
+ )),
+ );
+ }, [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>
+ 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="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="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="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 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>
+ </>
+ );
}
diff --git a/frontend/src/pages/articles/Article.tsx b/frontend/src/pages/articles/Article.tsx
index b367811..1a96ada 100644
--- a/frontend/src/pages/articles/Article.tsx
+++ b/frontend/src/pages/articles/Article.tsx
@@ -1,25 +1,35 @@
import { useState, useEffect } from "react";
import { useParams } from "react-router-dom";
-export default function Article () {
- const { id } = useParams();
- const [articleData, setArticleData] = useState<any>();
+type article = {
+ id: number;
+ title: string;
+ photoUrl: string;
+ content: string;
+ createdOn: string;
+ updateOn: string;
+};
- useEffect(() => {
- const url = `${import.meta.env.VITE_API_TITLE}/api/v1/article/${id}`;
- fetch(url).then((response) => {
- if (response.ok) {
- return response.json();
- }
- throw new Error("Network response was not ok.");
- }).then((response) => setArticleData(response)); //.catch(() => navigate("/"));
- }, [id]);
+export default function Article() {
+ const { id } = useParams();
+ const [articleData, setArticleData] = useState<article>();
- return(
- <>
- <h1>{articleData?.title}</h1>
- <div>{articleData?.content}</div>
- </>
- );
+ useEffect(() => {
+ const url = `${import.meta.env.VITE_API_TITLE}/api/v1/article/${id}`;
+ fetch(url)
+ .then((response) => {
+ if (response.ok) {
+ return response.json();
+ }
+ throw new Error("Network response was not ok.");
+ })
+ .then((response) => setArticleData(response)); //.catch(() => navigate("/"));
+ }, [id]);
+ return (
+ <>
+ <h1>{articleData?.title}</h1>
+ <div>{articleData?.content}</div>
+ </>
+ );
}
diff --git a/frontend/src/pages/articles/New.tsx b/frontend/src/pages/articles/New.tsx
index 3402f22..f98c19a 100644
--- a/frontend/src/pages/articles/New.tsx
+++ b/frontend/src/pages/articles/New.tsx
@@ -1,83 +1,100 @@
import { FormEvent } from "react";
import { useNavigate } from "react-router-dom";
-export default function NewArticle () {
- const navigate = useNavigate();
+export default function NewArticle() {
+ const navigate = useNavigate();
- const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
- e.preventDefault(); //stops submit from happening
+ const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
+ e.preventDefault(); //stops submit from happening
- const target = e.target as typeof e.target & {
- title: { value: string };
- photoUrl: { value: string };
- content: { value: string };
- };
+ const target = e.target as typeof e.target & {
+ title: { value: string };
+ photoUrl: { value: string };
+ content: { value: string };
+ };
- const formData = new FormData();
- formData.append('title', target.title.value);
- formData.append('photoUrl', target.photoUrl.value);
- formData.append('content', target.content.value);
+ const formData = new FormData();
+ formData.append("title", target.title.value);
+ formData.append("photoUrl", target.photoUrl.value);
+ formData.append("content", target.content.value);
- const response = await fetch(`${import.meta.env.VITE_API_TITLE}/api/v1/article/new`, {
- credentials: 'include',
- method: 'post',
- body: formData,
- });
- if(response.ok) {
- navigate("/");
- }
- else {
- console.log(response);
- alert("check console for error");
- }
- };
- return(
- <>
-<div className="flex 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">
+ const response = await fetch(
+ `${import.meta.env.VITE_API_TITLE}/api/v1/article/new`,
+ {
+ credentials: "include",
+ method: "post",
+ body: formData,
+ },
+ );
+ if (response.ok) {
+ navigate("/");
+ } else {
+ console.log(response);
+ alert("check console for error");
+ }
+ };
+ return (
+ <>
+ <div className="flex 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 border-red-500 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white"
- id="title"
- type="text"
- name="title"
- placeholder="Yep"/>
- <p className="text-red-500 text-xs italic">Please fill out this field.</p>
- </div>
- <div className="w-full md:w-1/2 px-3">
- <label className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2">
+ </label>
+ <input
+ className="appearance-none block w-full bg-gray-200 text-gray-700 border border-red-500 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white"
+ id="title"
+ type="text"
+ name="title"
+ placeholder="Yep"
+ />
+ <p className="text-red-500 text-xs italic">
+ Please fill out this field.
+ </p>
+ </div>
+ <div className="w-full md:w-1/2 px-3">
+ <label className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2">
Photo URL
- </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="photoUrl"
- type="text"
- name="photoUrl"
- placeholder="Doe"/>
- <p className="text-red-500 text-xs italic">Please fill out this field.</p>
- </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">
+ </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="photoUrl"
+ type="text"
+ name="photoUrl"
+ placeholder="Doe"
+ />
+ <p className="text-red-500 text-xs italic">
+ Please fill out this field.
+ </p>
+ </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">
Content
- </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="content"
- type="text"
- name="content"
- placeholder="Doe"/>
- <p className="text-red-500 text-xs italic">Please fill out this field.</p>
- </div>
- </div>
- <div className="flex flex-wrap mb-2">
- </div>
- <button type="submit" className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Create</button>
-
-</form>
-</div>
- </>
- );
+ </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="content"
+ type="text"
+ name="content"
+ placeholder="Doe"
+ />
+ <p className="text-red-500 text-xs italic">
+ Please fill out this field.
+ </p>
+ </div>
+ </div>
+ <div className="flex flex-wrap mb-2"></div>
+ <button
+ type="submit"
+ className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
+ >
+ Create
+ </button>
+ </form>
+ </div>
+ </>
+ );
}
diff --git a/frontend/src/pages/auth/Login.tsx b/frontend/src/pages/auth/Login.tsx
index d064acf..33529a8 100644
--- a/frontend/src/pages/auth/Login.tsx
+++ b/frontend/src/pages/auth/Login.tsx
@@ -3,102 +3,103 @@ 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;
+ set: React.Dispatch<React.SetStateAction<string | null>>;
+ value: string | null;
};
export default function Login({ user }: { user: user }) {
- const navigate = useNavigate();
+ const navigate = useNavigate();
- const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
- e.preventDefault(); //stops submit from happening
+ const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
+ e.preventDefault(); //stops submit from happening
- const target = e.target as typeof e.target & {
- username: { value: string };
- email: { value: string };
- password: { value: string };
- };
+ const target = e.target as typeof e.target & {
+ username: { value: string };
+ email: { value: string };
+ password: { value: string };
+ };
- const formData = new FormData();
- formData.append("username", target.username.value);
- formData.append("password", target.password.value);
+ const formData = new FormData();
+ 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 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 {
- console.log(response);
- alert("check console for error");
- }
- });
- };
+ 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 {
+ console.log(response);
+ alert("check console for error");
+ }
+ });
+ };
- 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>
- </>
- );
+ 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>
+ </>
+ );
}
diff --git a/frontend/src/pages/auth/Register.tsx b/frontend/src/pages/auth/Register.tsx
index 14ceea4..cf1972a 100644
--- a/frontend/src/pages/auth/Register.tsx
+++ b/frontend/src/pages/auth/Register.tsx
@@ -1,86 +1,103 @@
import { FormEvent } from "react";
-import { useNavigate } from 'react-router-dom';
+import { useNavigate } from "react-router-dom";
-export default function Register () {
- const navigate = useNavigate();
+export default function Register() {
+ const navigate = useNavigate();
-const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
- e.preventDefault(); //stops submit from happening
+ const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
+ e.preventDefault(); //stops submit from happening
- const target = e.target as typeof e.target & {
- username: { value: string };
- email: { value: string };
- password: { value: string };
- };
+ const target = e.target as typeof e.target & {
+ username: { value: string };
+ email: { value: string };
+ password: { value: string };
+ };
- const formData = new FormData();
- formData.append('username', target.username.value);
- formData.append('email', target.email.value);
- formData.append('password', target.password.value);
+ const formData = new FormData();
+ formData.append("username", target.username.value);
+ formData.append("email", target.email.value);
+ formData.append("password", target.password.value);
- const response = await fetch(`${import.meta.env.VITE_API_TITLE}/api/v1/register`, {
- credentials: 'include',
- method: 'post',
- body: formData,
- });
- if(response.ok) {
- navigate("/login");
- }
- else {
- alert("error");
- }
- };
+ const response = await fetch(
+ `${import.meta.env.VITE_API_TITLE}/api/v1/register`,
+ {
+ credentials: "include",
+ method: "post",
+ body: formData,
+ },
+ );
+ if (response.ok) {
+ navigate("/login");
+ } else {
+ alert("error");
+ }
+ };
- return(
- <>
-<div className="flex flex-col items-center justify-center bg-white p-12">
- <div className="text-xl w-full text-center mb-8 p-4 bg-black text-red-500">Username or Email already exists</div>
- <form onSubmit={handleSubmit} method="post" className="w-full max-w-lg">
- <div className="flex flex-wrap -mx-3 mb-6">
+ return (
+ <>
+ <div className="flex flex-col items-center justify-center bg-white p-12">
+ <div className="text-xl w-full text-center mb-8 p-4 bg-black text-red-500">
+ Username or Email already exists
+ </div>
+ <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"/>
- <p className="text-red-500 text-xs italic">Please fill out this field.</p>
+ <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"
+ />
+ <p className="text-red-500 text-xs italic">
+ Please fill out this field.
+ </p>
</div>
<div className="w-full md:w-1/2 px-3">
- <label className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2">
- Email
- </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="email"
- type="text"
- name="email"
- placeholder="[email protected]"/>
- <p className="text-red-500 text-xs italic">Please fill out this field.</p>
+ <label className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2">
+ Email
+ </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="email"
+ type="text"
+ name="email"
+ placeholder="[email protected]"
+ />
+ <p className="text-red-500 text-xs italic">
+ Please fill out this field.
+ </p>
</div>
- </div>
- <div className="flex flex-wrap -mx-3 mb-6">
+ </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"/>
- <p className="text-red-500 text-xs italic">Please fill out this field.</p>
+ <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"
+ />
+ <p className="text-red-500 text-xs italic">
+ Please fill out this field.
+ </p>
</div>
- </div>
- <div className="flex flex-wrap mb-2">
- </div>
- <button type="submit" className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Register</button>
-
- </form>
-</div>
- </>
- );
-
+ </div>
+ <div className="flex flex-wrap mb-2"></div>
+ <button
+ type="submit"
+ className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
+ >
+ Register
+ </button>
+ </form>
+ </div>
+ </>
+ );
}
diff --git a/frontend/src/routes/index.tsx b/frontend/src/routes/index.tsx
index b46315b..cee3529 100644
--- a/frontend/src/routes/index.tsx
+++ b/frontend/src/routes/index.tsx
@@ -8,36 +8,39 @@ import Register from "../pages/auth/Register";
import Login from "../pages/auth/Login";
type user = {
- set: React.Dispatch<React.SetStateAction<string | null>>;
- value: string | null;
+ set: React.Dispatch<React.SetStateAction<string | null>>;
+ value: string | null;
};
type articleSearch = user;
export default function Index() {
- const [user, setUser] = useState<string | null>(null);
- const [articleSearch, setArticleSearch] = useState<string | null>(null);
+ const [user, setUser] = useState<string | null>(null);
+ const [articleSearch, setArticleSearch] = useState<string | null>(null);
- const userProp: user = { set: setUser, value: user };
- const articleSearchProp: articleSearch = {
- set: setArticleSearch,
- value: articleSearch,
- };
+ const userProp: user = { set: setUser, value: user };
+ const articleSearchProp: articleSearch = {
+ set: setArticleSearch,
+ value: articleSearch,
+ };
- return (
- <>
- <Router>
- <Routes>
- <Route
- path="/"
- element={<Layout user={userProp} articleSearch={articleSearchProp} />}>
- <Route index element={<Home articleSearch={articleSearchProp} />} />
- <Route path="/article/:id" element={<Article />} />
- <Route path="/article/new" element={<NewArticle />} />
- <Route path="register" element={<Register />} />
- <Route path="login" element={<Login user={userProp} />} />
- </Route>
- </Routes>
- </Router>
- </>
- );
+ return (
+ <>
+ <Router>
+ <Routes>
+ <Route
+ path="/"
+ element={
+ <Layout user={userProp} articleSearch={articleSearchProp} />
+ }
+ >
+ <Route index element={<Home articleSearch={articleSearchProp} />} />
+ <Route path="/article/:id" element={<Article />} />
+ <Route path="/article/new" element={<NewArticle />} />
+ <Route path="register" element={<Register />} />
+ <Route path="login" element={<Login user={userProp} />} />
+ </Route>
+ </Routes>
+ </Router>
+ </>
+ );
}
diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js
index d37737f..614c86b 100644
--- a/frontend/tailwind.config.js
+++ b/frontend/tailwind.config.js
@@ -1,12 +1,8 @@
/** @type {import('tailwindcss').Config} */
export default {
- content: [
- "./index.html",
- "./src/**/*.{js,ts,jsx,tsx}",
- ],
+ content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
theme: {
extend: {},
},
plugins: [],
-}
-
+};
diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts
index 861b04b..d366e8c 100644
--- a/frontend/vite.config.ts
+++ b/frontend/vite.config.ts
@@ -1,7 +1,7 @@
-import { defineConfig } from 'vite'
-import react from '@vitejs/plugin-react-swc'
+import { defineConfig } from "vite";
+import react from "@vitejs/plugin-react-swc";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
-})
+});