refactor & redesign

This commit is contained in:
VividTruthKeeper 2022-09-20 00:27:20 +05:00
parent e565f450b8
commit d9f9c8c013
17 changed files with 305 additions and 75 deletions

View File

@ -9,6 +9,8 @@ import "./assets/styles/style.scss";
// Types
import { PostType } from "./types/posts";
import { SourceType } from "./types/sources";
import { LinksAll } from "./types/links";
// Pages
import Login from "./pages/Login";
@ -18,6 +20,10 @@ import Posts from "./pages/Posts";
import Details from "./pages/Details";
import Post from "./pages/Post";
import Source from "./pages/Source";
import EditSource from "./pages/EditSource";
// Helpers
import { getLinks } from "./helpers/apiRequests";
const App = () => {
const navigate = useNavigate();
@ -35,6 +41,8 @@ const App = () => {
},
]);
const [sources, setSources] = useState<SourceType[]>();
const [user, setUser] = useState({
username: "",
accessLevel: "",
@ -49,6 +57,10 @@ const App = () => {
const userValue = useMemo(() => ({ user, setUser }), [user, setUser]);
const postValue = useMemo(() => ({ posts, setPosts }), [posts, setPosts]);
const sourceValue = useMemo(
() => ({ sources, setSources }),
[sources, setSources]
);
useEffect(() => {
if (!user.username) {
@ -59,8 +71,12 @@ const App = () => {
}
}, [user]);
useEffect(() => {
getLinks(setSources);
}, []);
return (
<PostContext.Provider value={postValue}>
<PostContext.Provider value={{ postValue, sourceValue }}>
<UserContext.Provider value={userValue}>
<div className="App">
<Routes>
@ -68,7 +84,12 @@ const App = () => {
<Route path="/dashboard" element={<Main child={<Dashboard />} />} />
<Route path="/posts" element={<Main child={<Posts />} />} />
<Route path="/source" element={<Main child={<Source />} />} />
<Route
path="/source/edit/:id"
element={<Main child={<EditSource />} />}
/>
<Route path="/posts/:id" element={<Main child={<Post />} />} />
<Route
path="/user_details"
element={<Main child={<Details />} />}

View File

@ -38,7 +38,7 @@
display: flex;
align-items: center;
justify-content: flex-start;
gap: 1rem;
gap: 2rem;
width: 100%;
padding: 0.8rem 0.4rem 0.8rem 1.2rem;
}

View File

@ -0,0 +1,58 @@
.source-edit {
&.inner {
display: flex;
flex-direction: column;
gap: 4rem;
}
&__content {
form {
display: flex;
flex-direction: column;
gap: 4rem;
}
}
&__info,
&__content {
display: flex;
flex-direction: column;
gap: 3rem;
padding: 1rem;
h2 {
font-weight: normal;
font-size: 3rem;
}
}
&__input {
color: $base-gray;
display: flex;
flex-direction: column;
gap: 0.8rem;
font-size: 1.6rem;
input {
font-size: 1.6rem;
background: $light-black;
padding: 0.6rem 1.2rem;
border-radius: 0.5rem;
}
}
&__submit {
font-size: 1.6rem;
cursor: pointer;
color: $base-gray;
border-radius: 0.5rem;
background: $base-blue;
@include transition-std;
padding: 1.6rem 1.2rem;
&:hover {
@include transition-std;
background: $hover-blue;
}
}
}

View File

@ -73,7 +73,7 @@
input {
font-size: 1.6rem;
padding: 0.6rem 1.2rem;
border-radius: 0.2rem;
border-radius: 0.5rem;
}
&--check {

View File

@ -58,7 +58,7 @@
padding: 1rem;
display: flex;
align-items: center;
gap: 0.5rem;
gap: 1.6rem;
@include transition-std;
&:hover {

View File

@ -22,7 +22,6 @@
padding: 1rem 2rem;
border-radius: 0.5rem;
background: $base-blue;
color: white;
&:hover {
@include transition-std;
@ -46,6 +45,7 @@
padding: 1rem 1.2rem;
border-radius: 0.2rem;
cursor: default;
border-radius: 0.5rem;
}
&__wrapper {
@ -57,6 +57,7 @@
padding: 1rem 1.2rem;
color: $base-gray;
background: $light-black;
border-radius: 0.5rem;
}
&.inner {
@ -168,42 +169,37 @@
display: flex;
align-items: center;
gap: 1rem;
max-width: 30rem;
border-radius: 0.2rem;
cursor: pointer;
width: 100%;
padding: 0.6rem 1.2rem;
color: #fff;
padding: 1rem 1.2rem;
color: $base-gray;
font-size: 1.6rem;
background-color: #7c69ef;
border: 0.1rem solid #7c69ef;
background-color: $base-blue;
@include transition-std;
&:hover {
@include transition-std;
background-color: #705ed6;
border: 0.1rem solid #705ed6;
background-color: $hover-blue;
}
}
input {
font-size: 1.6rem;
padding: 1rem 1.2rem;
border: 1px solid #b8b9bb;
border-radius: 0.2rem;
padding: 0.6rem 1.2rem;
border-radius: 0.5rem;
cursor: default;
background: #ebedef;
background: $light-black;
}
textarea {
background: #ebedef;
background: $light-black;
cursor: default;
padding: 1rem 1.2rem;
padding: 0.6rem 1.2rem;
resize: none;
outline: none;
font-size: 1.6rem;
border: 1px solid #b8b9bb;
border-radius: 0.2rem;
border-radius: 0.5rem;
}
&__block {

View File

@ -3,7 +3,6 @@
display: flex;
flex-direction: column;
gap: 4rem;
padding-bottom: 3rem;
}
&__head {
svg {
@ -95,10 +94,18 @@
gap: 1rem;
color: $base-gray;
background: $base-black;
&:nth-child(2n) {
background: $light-blue;
td {
color: $light-black;
svg {
fill: $base-black;
}
span {
color: $base-black;
font-weight: bold;
}
}
}
}
@ -139,8 +146,8 @@
}
svg {
width: 1.2rem;
height: 1.2rem;
width: 1.5rem;
height: 1.5rem;
}
span {

View File

@ -8,3 +8,4 @@
@import "./posts";
@import "./details";
@import "./source";
@import "./edit-source";

View File

@ -7,7 +7,7 @@ import { IconContext } from "react-icons";
// Icons
import { FaMeteor } from "react-icons/fa";
import { GiHamburgerMenu } from "react-icons/gi";
import { FaUserCog } from "react-icons/fa";
import { FaUserAlt } from "react-icons/fa";
// Types
import { userContextType } from "../types/user";
@ -52,7 +52,7 @@ const Nav = ({ aside, setAside }: Props) => {
}}
>
<IconContext.Provider value={{ color: "#8DD77F" }}>
<FaUserCog className="nav__right__user__img" />
<FaUserAlt className="nav__right__user__img" />
</IconContext.Provider>
<span>Profile</span>

View File

@ -1,4 +1,5 @@
// Modules
// Tyoes
import { createContext } from "react";
import { ContextType } from "../types/context";
export const PostContext: any = createContext(null);
export const PostContext: any = createContext<ContextType | null>(null);

View File

@ -61,7 +61,7 @@ export const updateLink = (
data: { name: string; source: string }
) => {
axios
.put(`http://95.85.124.41:8080/link/update/${id}`, { source: data.source })
.put(`http://95.85.124.41:8080/link/update/${id}`, data)
.then((res) => {
setSuccess(res.data.message);
})

132
src/pages/EditSource.tsx Normal file
View File

@ -0,0 +1,132 @@
// Modules
import React, { useState, useEffect, useContext } from "react";
import { useParams } from "react-router-dom";
import { IconContext } from "react-icons/lib";
import { PostContext } from "../context/PostContext";
import { useNavigate } from "react-router-dom";
// Icons
import { FaRegEdit } from "react-icons/fa";
// Types
import { SourceType, SourceEditDataType } from "../types/sources";
import { ContextType } from "../types/context";
// Helpers
import { getLinks, updateLink } from "../helpers/apiRequests";
const EditSource = () => {
const navigate = useNavigate();
const { sources, setSources } =
useContext<ContextType>(PostContext).sourceValue;
const [source, setSource] = useState<SourceType>();
useEffect(() => {
if (sources) {
sources.map((post: SourceType) => {
if (post.id.toString() === id) {
setSource(post);
}
});
}
}, [sources]);
const { id } = useParams();
const [data, setData] = useState<SourceEditDataType>({
name: "",
source: "",
});
return (
<main className="source-edit">
<div className="container">
<div className="source-edit inner">
<div className="dashboard__head source-edit__head">
<IconContext.Provider value={{ color: "#8DD77F" }}>
<FaRegEdit className="dashboard__img" />
</IconContext.Provider>
<h1>Edit source</h1>
</div>
<div className="source-edit__content">
<form
onSubmit={(e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
}}
>
<div className="source-edit__info">
<h2>Information</h2>
<div className="source-edit__input">
<label htmlFor="id">Source ID</label>
<input
readOnly
type="text"
id="id"
value={source ? source.name : ""}
/>
</div>
<div className="source-edit__input">
<label htmlFor="name">Source old name</label>
<input
readOnly
type="text"
id="name"
value={source ? source.name : ""}
/>
</div>
<div className="source-edit__input">
<label htmlFor="source">Source old link</label>
<input
readOnly
type="text"
id="source"
value={source ? source.source : ""}
/>
</div>
</div>
<div className="source-edit__content">
<h2>Edit</h2>
<div className="source-edit__input">
<label htmlFor="new_name">Source new name</label>
<input
placeholder="Enter new name"
type="text"
id="new_name"
value={data.name}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setData({ ...data, name: e.target.value });
}}
/>
</div>
<div className="source-edit__input">
<label htmlFor="new_source">Source new link</label>
<input
placeholder="Enter new link"
type="text"
id="new_source"
value={data.source}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setData({ ...data, source: e.target.value });
}}
/>
</div>
</div>
<button
className="source-edit__submit"
onClick={() => {
updateLink(() => {}, id ? parseInt(id) : 0, data);
setTimeout(() => {
navigate("/source");
getLinks(setSources);
}, 2000);
}}
>
Update source
</button>
</form>
</div>
</div>
</div>
</main>
);
};
export default EditSource;

View File

@ -3,15 +3,19 @@ import { useContext, useState, useEffect } from "react";
import { useParams } from "react-router-dom";
import { PostContext } from "../context/PostContext";
import { PostType } from "../types/posts";
import { IconContext } from "react-icons";
// Icons
import { ImNewspaper } from "react-icons/im";
import { FaBoxOpen } from "react-icons/fa";
import { BiLinkExternal } from "react-icons/bi";
// Helpers
import { parseDate } from "../helpers/parseDate";
import { capitalizeFirstLetter } from "../helpers/stringMethods";
// Types
import { ContextType } from "../types/context";
const Post = () => {
const date = new Date("0.0.0000");
const [postData, setPostData] = useState<PostType>({
@ -24,7 +28,7 @@ const Post = () => {
createdAt: date,
updatedAt: date,
});
const { posts } = useContext<any>(PostContext);
const { posts } = useContext<ContextType>(PostContext).postValue;
const { id } = useParams();
useEffect(() => {
@ -41,7 +45,9 @@ const Post = () => {
<div className="container">
<div className="post inner">
<div className="dashboard__head post__head">
<ImNewspaper />
<IconContext.Provider value={{ color: "#8DD77F" }}>
<FaBoxOpen className="dashboard__img" />
</IconContext.Provider>
<h1 className="post__head">
{postData.id !== -1 ? postData.title : ""}
</h1>
@ -97,7 +103,10 @@ const Post = () => {
className="post__content__btn"
href={postData.id !== -1 ? postData.link : ""}
>
<BiLinkExternal />
<IconContext.Provider value={{ color: "#FFFFFF" }}>
<BiLinkExternal />
</IconContext.Provider>
<span>Link</span>
</a>
</div>

View File

@ -16,7 +16,7 @@ import { parseDate } from "../helpers/parseDate";
// Types
import { paramsType } from "../types/posts";
import { ContextType } from "../types/context";
interface pageType {
perPage: number;
pageNumber: number;
@ -24,7 +24,8 @@ interface pageType {
const Posts = () => {
const [categories, setCategories] = useState<string[]>(["All"]);
const { posts, setPosts } = useContext<any>(PostContext);
const contextValue: ContextType = useContext<ContextType>(PostContext);
const { posts, setPosts } = contextValue.postValue;
const [category, setCategory] = useState<string>("All");
const [sort, setSort] = useState<string>("id");
const [page, setPage] = useState<pageType>({
@ -309,7 +310,7 @@ const Posts = () => {
</button>
<input type="text" value={page.pageNumber} readOnly />
<button
disabled={posts[0] ? false : true}
disabled={posts ? false : true}
type="button"
onClick={() =>
setPage({ ...page, pageNumber: page.pageNumber + 1 })

View File

@ -1,61 +1,34 @@
// Modules
import { v4 as uuidv4 } from "uuid";
import { useState, useEffect } from "react";
import { useState, useEffect, useContext } from "react";
import { IconContext } from "react-icons";
import { Link } from "react-router-dom";
// Context
import { PostContext } from "../context/PostContext";
// Icons
import { FaSourcetree } from "react-icons/fa";
import { FaRegEdit } from "react-icons/fa";
import { FaTrash } from "react-icons/fa";
import { getLinks } from "../helpers/apiRequests";
// Helpers
import { deleteLink } from "../helpers/apiRequests";
import { deleteLink, getLinks } from "../helpers/apiRequests";
// Types
import { LinksAll } from "../types/links";
// interface dataType {
// createName: string;
// createLink: string;
// delete: number;
// updateId: number;
// updateName: string;
// updateLink: string;
// }
// interface successType {
// create: string;
// delete: string;
// update: string;
// hasCreateUpdated: boolean;
// hasDeleteUpdated: boolean;
// hasUpdateUpdated: boolean;
// }
import { ContextType } from "../types/context";
const Source = () => {
const defaultDate = new Date("00-00-00");
const { sources, setSources } =
useContext<ContextType>(PostContext).sourceValue;
const [deleted, setDeleted] = useState<boolean>(false);
const [all, setAll] = useState<LinksAll[]>([
{
id: -1,
name: "",
source: "",
createdAt: defaultDate,
updatedAt: defaultDate,
},
]);
useEffect(() => {
getLinks(setAll);
}, []);
useEffect(() => {
if (deleted) {
setTimeout(() => {
setDeleted(false);
getLinks(setAll);
getLinks(setSources);
}, 2000);
}
}, [deleted, setDeleted]);
@ -82,8 +55,8 @@ const Source = () => {
</tr>
</thead>
<tbody>
{all[0].id !== -1 ? (
all.map((source: LinksAll) => {
{sources ? (
sources.map((source: LinksAll) => {
return (
<tr key={uuidv4()}>
<td>{source.id}</td>

19
src/types/context.ts Normal file
View File

@ -0,0 +1,19 @@
// Modules
import React, { SetStateAction } from "react";
// Types
import { PostType } from "../types/posts";
import { SourceType } from "../types/sources";
// Context type
export interface ContextType {
postValue: {
posts: PostType[];
setPosts: React.Dispatch<SetStateAction<PostType[]>>;
};
sourceValue: {
sources: SourceType[];
setSources: React.Dispatch<SetStateAction<SourceType[]>>;
};
}

12
src/types/sources.ts Normal file
View File

@ -0,0 +1,12 @@
export interface SourceType {
id: number;
name: string;
source: string;
createdAt: Date;
updatedAt: Date;
}
export interface SourceEditDataType {
name: string;
source: string;
}