posts page done
This commit is contained in:
parent
ddd794e115
commit
2049b8fff3
|
|
@ -12,7 +12,8 @@
|
|||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-icons": "^4.4.0",
|
||||
"react-router-dom": "^6.3.0"
|
||||
"react-router-dom": "^6.3.0",
|
||||
"uuidv4": "^6.2.13"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.0.17",
|
||||
|
|
@ -544,6 +545,11 @@
|
|||
"integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/uuid": {
|
||||
"version": "8.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
|
||||
"integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw=="
|
||||
},
|
||||
"node_modules/@vitejs/plugin-react": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-2.0.1.tgz",
|
||||
|
|
@ -1743,6 +1749,23 @@
|
|||
"browserslist": ">= 4.21.0"
|
||||
}
|
||||
},
|
||||
"node_modules/uuid": {
|
||||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/uuidv4": {
|
||||
"version": "6.2.13",
|
||||
"resolved": "https://registry.npmjs.org/uuidv4/-/uuidv4-6.2.13.tgz",
|
||||
"integrity": "sha512-AXyzMjazYB3ovL3q051VLH06Ixj//Knx7QnUSi1T//Ie3io6CpsPu9nVMOx5MoLWh6xV0B9J0hIaxungxXUbPQ==",
|
||||
"dependencies": {
|
||||
"@types/uuid": "8.3.4",
|
||||
"uuid": "8.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "3.0.9",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-3.0.9.tgz",
|
||||
|
|
@ -2173,6 +2196,11 @@
|
|||
"integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/uuid": {
|
||||
"version": "8.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
|
||||
"integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw=="
|
||||
},
|
||||
"@vitejs/plugin-react": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-2.0.1.tgz",
|
||||
|
|
@ -2917,6 +2945,20 @@
|
|||
"picocolors": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"uuid": {
|
||||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
|
||||
},
|
||||
"uuidv4": {
|
||||
"version": "6.2.13",
|
||||
"resolved": "https://registry.npmjs.org/uuidv4/-/uuidv4-6.2.13.tgz",
|
||||
"integrity": "sha512-AXyzMjazYB3ovL3q051VLH06Ixj//Knx7QnUSi1T//Ie3io6CpsPu9nVMOx5MoLWh6xV0B9J0hIaxungxXUbPQ==",
|
||||
"requires": {
|
||||
"@types/uuid": "8.3.4",
|
||||
"uuid": "8.3.2"
|
||||
}
|
||||
},
|
||||
"vite": {
|
||||
"version": "3.0.9",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-3.0.9.tgz",
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@
|
|||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-icons": "^4.4.0",
|
||||
"react-router-dom": "^6.3.0"
|
||||
"react-router-dom": "^6.3.0",
|
||||
"uuidv4": "^6.2.13"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.0.17",
|
||||
|
|
|
|||
46
src/App.tsx
46
src/App.tsx
|
|
@ -2,10 +2,14 @@
|
|||
import { useMemo, useState, useEffect } from "react";
|
||||
import { Routes, Route } from "react-router-dom";
|
||||
import { UserContext } from "./context/UserContext";
|
||||
import { PostContext } from "./context/PostContext";
|
||||
|
||||
// Style
|
||||
import "./assets/styles/style.scss";
|
||||
|
||||
// Types
|
||||
import { PostType } from "./types/posts";
|
||||
|
||||
// Pages
|
||||
import Login from "./pages/Login";
|
||||
import Main from "./pages/Main";
|
||||
|
|
@ -14,6 +18,20 @@ import Posts from "./pages/Posts";
|
|||
import Details from "./pages/Details";
|
||||
|
||||
const App = () => {
|
||||
const date = new Date("0.0.0000");
|
||||
const [posts, setPosts] = useState<PostType[]>([
|
||||
{
|
||||
id: -1,
|
||||
category: "",
|
||||
title: "",
|
||||
link: "",
|
||||
date: date,
|
||||
summary: "",
|
||||
createdAt: date,
|
||||
updatedAt: date,
|
||||
},
|
||||
]);
|
||||
|
||||
const [user, setUser] = useState({
|
||||
username: "",
|
||||
accessLevel: "",
|
||||
|
|
@ -28,19 +46,25 @@ const App = () => {
|
|||
}, []);
|
||||
|
||||
const userValue = useMemo(() => ({ user, setUser }), [user, setUser]);
|
||||
const postValue = useMemo(() => ({ posts, setPosts }), [posts, setPosts]);
|
||||
|
||||
return (
|
||||
<UserContext.Provider value={userValue}>
|
||||
<div className="App">
|
||||
<Routes>
|
||||
<Route path="/" element={<Main />} />
|
||||
<Route path="/dashboard" element={<Main child={<Dashboard />} />} />
|
||||
<Route path="/posts" element={<Main child={<Posts />} />} />
|
||||
<Route path="/user_details" element={<Main child={<Details />} />} />
|
||||
<Route path="/login" element={<Login />} />
|
||||
</Routes>
|
||||
</div>
|
||||
</UserContext.Provider>
|
||||
<PostContext.Provider value={postValue}>
|
||||
<UserContext.Provider value={userValue}>
|
||||
<div className="App">
|
||||
<Routes>
|
||||
<Route path="/" element={<Main />} />
|
||||
<Route path="/dashboard" element={<Main child={<Dashboard />} />} />
|
||||
<Route path="/posts" element={<Main child={<Posts />} />} />
|
||||
<Route
|
||||
path="/user_details"
|
||||
element={<Main child={<Details />} />}
|
||||
/>
|
||||
<Route path="/login" element={<Login />} />
|
||||
</Routes>
|
||||
</div>
|
||||
</UserContext.Provider>
|
||||
</PostContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
<svg width="47" height="24" viewBox="0 0 47 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="47" height="24" fill="white"/>
|
||||
<path d="M13.4229 12.5379L14.8061 23.9928H14.1174C12.6332 23.9928 11.3827 22.8715 11.2024 21.3799L10.2835 13.7759H9.1968V10.4708H9.88431L9.88394 10.4678L9.88659 10.4708H10.3245C11.0309 10.4708 11.6054 9.88914 11.6054 9.17398V4.72051C11.6054 4.00522 11.0309 3.42365 10.3245 3.42365H9.11734C8.94731 2.30419 8.4253 1.27604 7.60516 0.468812C7.47884 0.344802 7.34766 0.227592 7.21204 0.118454H10.3245C12.8307 0.118454 14.8694 2.18282 14.8694 4.72053V9.174C14.8694 10.5003 14.3123 11.697 13.4229 12.5379Z" fill="#00822C"/>
|
||||
<path d="M16.1693 0.139488H15.8031V23.9928H19.195V3.2032C19.195 1.51112 17.8404 0.139488 16.1693 0.139488Z" fill="#00822C"/>
|
||||
<path d="M5.10361 19.7123C5.10361 20.7759 4.66069 20.9226 4.1819 20.9226C3.70312 20.9226 3.26007 20.7759 3.26007 19.7123V4.43076C3.26007 3.36729 3.70312 3.22065 4.1819 3.22065C4.66069 3.22065 5.10361 3.36731 5.10361 4.43076V19.7123ZM7.28147 1.33161C6.55249 0.547738 5.50961 0.150425 4.1819 0.150425C2.85418 0.150425 1.81119 0.547738 1.08236 1.33161C0.364251 2.10373 0.000167847 3.20084 0.000167847 4.5923V19.5508C0.000167847 20.9423 0.364233 22.0394 1.08236 22.8115C1.81119 23.5954 2.85418 23.9928 4.1819 23.9928C5.50961 23.9928 6.55249 23.5954 7.28147 22.8115C7.99956 22.0394 8.36364 20.9423 8.36364 19.5508V4.5923C8.36364 3.20084 7.99958 2.10374 7.28147 1.33161Z" fill="#00822C"/>
|
||||
<path d="M46.154 0.150517V3.58545H43.6588V23.9997C43.2094 23.9997 42.7806 23.911 42.3881 23.7508C41.528 23.3986 40.8428 22.6997 40.502 21.8254C40.502 21.825 40.5017 21.8247 40.5017 21.8247C40.4595 21.7162 40.4229 21.6055 40.3916 21.4922C40.3325 21.278 40.2933 21.0552 40.2763 20.8262C40.2699 20.7399 40.2665 20.6529 40.2665 20.5648V3.58549H36.1613C36.299 2.66223 36.6375 1.90691 37.1723 1.33174C37.9013 0.547905 38.9442 0.150554 40.2718 0.150554H46.154L46.154 0.150517Z" fill="#00822C"/>
|
||||
<path d="M36.1656 4.47772V13.8369L32.4801 -0.000217438H27.9792V19.7748H31.2084V6.37333L35.0097 20.6186C35.5409 22.6097 37.325 23.9928 39.3618 23.9928V4.4777H36.1656L36.1656 4.47772Z" fill="#00822C"/>
|
||||
<path d="M23.4546 20.8155V13.7549H25.842V10.4709H23.4546V3.33114H27.0983V0.165054H20.0627V20.5578C20.0627 22.3909 21.4807 23.8885 23.2665 23.9874C23.3287 23.9909 23.3914 23.9928 23.4546 23.9928H31.2083V20.8155H23.4546L23.4546 20.8155Z" fill="#EE4037"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.4 KiB |
|
|
@ -1,7 +1,7 @@
|
|||
@import url("https://fonts.googleapis.com/css2?family=Poppins&display=swap");
|
||||
@import url("https://fonts.googleapis.com/css2?family=Roboto&display=swap");
|
||||
|
||||
* {
|
||||
font-family: "Poppins", sans-serif;
|
||||
font-family: "Roboto", sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
|
|
|
|||
|
|
@ -118,12 +118,11 @@
|
|||
|
||||
&__img {
|
||||
width: 7rem;
|
||||
height: 3.4rem;
|
||||
height: 5rem;
|
||||
|
||||
img {
|
||||
svg {
|
||||
width: 7rem;
|
||||
height: 3.4rem;
|
||||
object-fit: contain;
|
||||
height: 5rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
.posts {
|
||||
&.inner {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4rem;
|
||||
}
|
||||
|
||||
&__table {
|
||||
padding: 3rem 0;
|
||||
|
||||
&__head {
|
||||
min-height: unset !important;
|
||||
background: #dbdbdb;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: center;
|
||||
font-size: 1.6rem;
|
||||
justify-self: center;
|
||||
}
|
||||
|
||||
.post-link {
|
||||
background: #f2f0fd;
|
||||
&:nth-child(2n) {
|
||||
background: #fafafa;
|
||||
}
|
||||
}
|
||||
|
||||
tr {
|
||||
min-height: 7rem;
|
||||
padding: 1rem;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 2.5fr 2fr 2fr 1.5fr 3fr 1.5fr 1.5fr;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
td {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
justify-self: center;
|
||||
font-size: 1.2rem;
|
||||
align-self: center;
|
||||
|
||||
a {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
tbody {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ import { UserContext } from "../context/UserContext";
|
|||
import { Link } from "react-router-dom";
|
||||
|
||||
// Icons
|
||||
import Orient from "../assets/icons/logo_orient.svg";
|
||||
import { ImStatsDots } from "react-icons/im";
|
||||
import { GiHamburgerMenu } from "react-icons/gi";
|
||||
import { AiOutlineUser } from "react-icons/ai";
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ const Nav = ({ aside, setAside }: Props) => {
|
|||
<div className="nav inner">
|
||||
<div className="nav__left">
|
||||
<Link to={"/dashboard"} className="nav__img">
|
||||
<img src={Orient} alt="orient" />
|
||||
<ImStatsDots />
|
||||
</Link>
|
||||
<GiHamburgerMenu
|
||||
type="button"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
// Modules
|
||||
import { createContext } from "react";
|
||||
|
||||
export const PostContext: any = createContext(null);
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
// Modules
|
||||
import axios from "axios";
|
||||
|
||||
// Types
|
||||
import { PostType } from "../types/posts";
|
||||
|
||||
export const getPosts = (setPosts: React.Dispatch<PostType[]>) => {
|
||||
axios
|
||||
.get("http://95.85.124.41:8080/posts")
|
||||
.then((res) => {
|
||||
setPosts(res.data);
|
||||
})
|
||||
.catch();
|
||||
};
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
export const parseDate = (date: Date) => {
|
||||
const split = date.toString().split("T");
|
||||
const yyyy_mm_dd = split[0];
|
||||
const time = split[1].split(".");
|
||||
const hh_mm_ss = time[0];
|
||||
|
||||
return [yyyy_mm_dd, hh_mm_ss];
|
||||
};
|
||||
|
|
@ -1,9 +1,6 @@
|
|||
// Modules
|
||||
import { useState, useContext, useEffect } from "react";
|
||||
import {
|
||||
useNavigate,
|
||||
// useLocation
|
||||
} from "react-router-dom";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { UserContext } from "../context/UserContext";
|
||||
|
||||
// Components
|
||||
|
|
@ -15,14 +12,9 @@ import { userContextType } from "../types/user";
|
|||
|
||||
const Main = ({ child }: any) => {
|
||||
const navigate = useNavigate();
|
||||
// const location = useLocation();
|
||||
const { user, setUser }: userContextType = useContext(UserContext);
|
||||
const [aside, setAside] = useState(true);
|
||||
|
||||
// useEffect(() => {
|
||||
// if(location.pathname.includes('dashboard'))
|
||||
// }, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (!user.username) {
|
||||
navigate("/login");
|
||||
|
|
|
|||
|
|
@ -1,12 +1,85 @@
|
|||
// Modules
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { useContext, useEffect } from "react";
|
||||
import { PostContext } from "../context/PostContext";
|
||||
|
||||
// Components
|
||||
// Icons
|
||||
import { BsFillFileEarmarkPostFill } from "react-icons/bs";
|
||||
import { BiLinkExternal } from "react-icons/bi";
|
||||
|
||||
// Helpers
|
||||
import { getPosts } from "../helpers/apiRequests";
|
||||
import { PostType } from "../types/posts";
|
||||
import { Link } from "react-router-dom";
|
||||
import { parseDate } from "../helpers/parseDate";
|
||||
|
||||
// Data
|
||||
const headers: string[] = [
|
||||
"ID",
|
||||
"Category",
|
||||
"Title",
|
||||
"Link",
|
||||
"Date",
|
||||
"Summary",
|
||||
"Created",
|
||||
"Updated",
|
||||
];
|
||||
|
||||
const Posts = () => {
|
||||
const { posts, setPosts } = useContext<any>(PostContext);
|
||||
|
||||
useEffect(() => {
|
||||
getPosts(setPosts);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<main className="posts">
|
||||
<div className="container">
|
||||
<div className="posts inner"></div>
|
||||
<div className="posts inner">
|
||||
<div className="dashboard__head">
|
||||
<BsFillFileEarmarkPostFill className="dashboard__img" />
|
||||
<h1>Posts</h1>
|
||||
</div>
|
||||
<table className="posts__table">
|
||||
<tbody>
|
||||
<tr className="posts__table__head">
|
||||
{headers.map((header: string) => {
|
||||
return <th key={uuidv4()}>{header}</th>;
|
||||
})}
|
||||
</tr>
|
||||
{posts[0].id !== -1
|
||||
? posts.map((post: PostType) => {
|
||||
return (
|
||||
<Link
|
||||
className="post-link"
|
||||
to={`/posts/${post.id}`}
|
||||
key={uuidv4()}
|
||||
>
|
||||
<tr>
|
||||
<td>{post.id}</td>
|
||||
<td>{post.category}</td>
|
||||
<td>{post.title}</td>
|
||||
<td>
|
||||
<a
|
||||
href={post.link}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<BiLinkExternal />
|
||||
</a>
|
||||
</td>
|
||||
<td>{parseDate(post.date)[0]}</td>
|
||||
<td>{post.summary}</td>
|
||||
<td>{parseDate(post.createdAt)[0]}</td>
|
||||
<td>{parseDate(post.updatedAt)[0]}</td>
|
||||
</tr>
|
||||
</Link>
|
||||
);
|
||||
})
|
||||
: ""}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
export interface PostType {
|
||||
id: number;
|
||||
category: string;
|
||||
title: string;
|
||||
link: string;
|
||||
date: Date;
|
||||
summary: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
Loading…
Reference in New Issue