diff --git a/src/assets/icons/loader.svg b/src/assets/icons/loader.svg new file mode 100644 index 0000000..6f610fc --- /dev/null +++ b/src/assets/icons/loader.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/assets/styles/_loader.scss b/src/assets/styles/_loader.scss new file mode 100644 index 0000000..0bee826 --- /dev/null +++ b/src/assets/styles/_loader.scss @@ -0,0 +1,23 @@ +.loader { + z-index: 20; + display: flex; + justify-content: center; + align-items: center; + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + background: rgba(255, 255, 255, 0.4); + + &.inner { + opacity: 1; + + img { + width: 100%; + height: 100%; + max-width: 10rem; + max-height: 10rem; + } + } +} diff --git a/src/assets/styles/_posts.scss b/src/assets/styles/_posts.scss index c518aaa..1d338ea 100644 --- a/src/assets/styles/_posts.scss +++ b/src/assets/styles/_posts.scss @@ -17,6 +17,7 @@ button { @include transition-std; cursor: pointer; + color: $base-gray; font-size: 1.6rem; width: 15%; padding: 1rem 2rem; @@ -35,6 +36,9 @@ gap: 0.8rem; label { + display: flex; + + gap: 0.8rem; font-size: 1.4rem; } @@ -67,6 +71,10 @@ } &__table { + &.disabled { + pointer-events: none; + } + &__head { min-height: unset !important; background: $light-black; @@ -96,6 +104,10 @@ background: $light-blue; td { color: $light-black; + + svg { + fill: $base-black; + } } } } @@ -133,8 +145,10 @@ } tbody { - max-height: 70vh; - overflow-y: auto; + min-height: 20rem; + position: relative; + // max-height: 70vh; + // overflow-y: auto; display: flex; flex-direction: column; } @@ -211,6 +225,80 @@ font-size: 1.6rem; } } + + &__table { + thead { + tr { + min-height: unset !important; + background: $light-black; + } + } + + th { + cursor: pointer; + width: 100%; + height: 100%; + text-align: center; + font-size: 1.6rem; + justify-self: center; + background: transparent; + color: $base-gray; + @include transition-std; + } + + tr { + background: $base-black; + &:nth-child(2n) { + background: $light-blue; + td { + color: $light-black; + + svg { + fill: $base-black; + } + } + } + } + + tr { + min-height: 7rem; + padding: 1rem; + display: grid; + grid-template-columns: 1fr repeat(4, 2fr); + gap: 1rem; + } + + td { + color: $base-gray; + 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 { + min-height: 20rem; + position: relative; + display: flex; + flex-direction: column; + } + } } } diff --git a/src/assets/styles/style.scss b/src/assets/styles/style.scss index 7336bd0..4f1ea79 100644 --- a/src/assets/styles/style.scss +++ b/src/assets/styles/style.scss @@ -9,3 +9,4 @@ @import "./details"; @import "./source"; @import "./edit-source"; +@import "./loader.scss"; diff --git a/src/components/Loader.tsx b/src/components/Loader.tsx new file mode 100644 index 0000000..cba865b --- /dev/null +++ b/src/components/Loader.tsx @@ -0,0 +1,14 @@ +// Icons +import loader from "../assets/icons/loader.svg"; + +const Loader = () => { + return ( +
+
+ +
+
+ ); +}; + +export default Loader; diff --git a/src/helpers/apiRequests.ts b/src/helpers/apiRequests.ts index 0dabcfa..d7a8a74 100644 --- a/src/helpers/apiRequests.ts +++ b/src/helpers/apiRequests.ts @@ -7,15 +7,18 @@ import { PostType } from "../types/posts"; import { LinksAll } from "../types/links"; export const getPosts = ( + setLoad: React.Dispatch, setPosts: React.Dispatch, params?: string ) => { + setLoad(true); axios .get("http://95.85.124.41:8080/posts" + (params ? params : "")) .then((res) => { setPosts(res.data.data); }) - .catch((err) => {}); + .catch((err) => {}) + .finally(() => setLoad(false)); }; export const deleteLink = (setSuccess: React.Dispatch, id: number) => { diff --git a/src/pages/Post.tsx b/src/pages/Post.tsx index 4e34512..ba624ce 100644 --- a/src/pages/Post.tsx +++ b/src/pages/Post.tsx @@ -1,8 +1,9 @@ // Modules +import { v4 as uuidv4 } from "uuid"; import { useContext, useState, useEffect } from "react"; import { useParams } from "react-router-dom"; import { PostContext } from "../context/PostContext"; -import { PostType } from "../types/posts"; +import { HistoryList, PostType } from "../types/posts"; import { IconContext } from "react-icons"; // Icons @@ -18,16 +19,7 @@ import { ContextType } from "../types/context"; const Post = () => { const date = new Date("0.0.0000"); - const [postData, setPostData] = useState({ - id: -1, - category: "", - title: "", - link: "", - publish_date: date, - summary: "", - createdAt: date, - updatedAt: date, - }); + const [postData, setPostData] = useState(); const { posts } = useContext(PostContext).postValue; const { id } = useParams(); @@ -48,18 +40,12 @@ const Post = () => { -

- {postData.id !== -1 ? postData.title : ""} -

+

{postData ? postData.title : ""}

ID

- +

Category

@@ -67,7 +53,7 @@ const Post = () => { type="text" readOnly value={ - postData.id !== -1 + postData ? capitalizeFirstLetter(postData.category.toLowerCase()) : "" } @@ -78,7 +64,7 @@ const Post = () => {
@@ -86,9 +72,7 @@ const Post = () => {
@@ -96,12 +80,12 @@ const Post = () => {
@@ -109,6 +93,49 @@ const Post = () => { Link + {postData ? ( + postData.HistoryList.length > 0 ? ( +
+

History List

+ + + + + + + + + + + + {postData + ? postData.HistoryList.length > 0 + ? postData.HistoryList.map((History: HistoryList) => { + return ( + + + + + + + + ); + }) + : "" + : ""} + +
Post IDOld publishedNew publishedCreatedUpdated
{History.PostID} + {parseDate(History.old_published_at)[0]} + + {parseDate(History.new_published_at)[0]} + {parseDate(History.createdAt)[0]}{parseDate(History.updatedAt)[0]}
+
+ ) : ( + "" + ) + ) : ( + "" + )}
diff --git a/src/pages/Posts.tsx b/src/pages/Posts.tsx index 463ac0f..c4a4ef2 100644 --- a/src/pages/Posts.tsx +++ b/src/pages/Posts.tsx @@ -17,24 +17,31 @@ import { parseDate } from "../helpers/parseDate"; // Types import { paramsType } from "../types/posts"; import { ContextType } from "../types/context"; + +// Components +import Loader from "../components/Loader"; + interface pageType { perPage: number; pageNumber: number; } const Posts = () => { - const [categories, setCategories] = useState(["All"]); + const [load, setLoad] = useState(false); const contextValue: ContextType = useContext(PostContext); const { posts, setPosts } = contextValue.postValue; + const { sources } = contextValue.sourceValue; + const [showAll, setShowAll] = useState(true); const [category, setCategory] = useState("All"); const [sort, setSort] = useState("id"); const [page, setPage] = useState({ perPage: 10, pageNumber: 1, }); + const [params, setParams] = useState({ id: "asc", - category: "asc", + source: "asc", title: "asc", link: "asc", date: "asc", @@ -47,29 +54,17 @@ const Posts = () => { useEffect(() => { const key = sort as keyof typeof params; getPosts( + setLoad, setPosts, `?sortBy=${sort}.${params[key]}&strLimit=${page.perPage}&strOffset=${page.pageNumber}&filter=${search}` ); - }, [params, sort, page, search, category]); + }, [params, sort, page, search]); useEffect(() => { - const categoriesTemp: string[] = categories; - if (posts[0]) { - if (posts[0].id !== -1) { - posts.map((post: PostType) => categoriesTemp.push(post.category)); - let categoriesTempUnique = categoriesTemp.filter((element, index) => { - return categoriesTemp.indexOf(element) === index; - }); - setCategories(categoriesTempUnique); - } + if (!showAll) { + setPage({ ...page, perPage: 60 }); } - }, [posts]); - - useEffect(() => { - if (category !== "All") { - setPage({ ...page, perPage: 100 }); - } - }, [category, page.perPage]); + }, [showAll, page.perPage]); return (
@@ -85,34 +80,40 @@ const Posts = () => {
+