farheen_blog_app 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createContext,
|
|
3
|
+
useContext,
|
|
4
|
+
useEffect,
|
|
5
|
+
useState
|
|
6
|
+
} from "react";
|
|
7
|
+
|
|
8
|
+
const UserContext = createContext();
|
|
9
|
+
|
|
10
|
+
export const UserProvider = ({ children }) => {
|
|
11
|
+
const [user, setUser] = useState(null);
|
|
12
|
+
const [token, setToken] = useState(null);
|
|
13
|
+
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
|
|
16
|
+
const storedUser =
|
|
17
|
+
localStorage.getItem(
|
|
18
|
+
"user"
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
const storedToken =
|
|
22
|
+
localStorage.getItem(
|
|
23
|
+
"token"
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
if (
|
|
27
|
+
storedUser &&
|
|
28
|
+
storedToken
|
|
29
|
+
) {
|
|
30
|
+
|
|
31
|
+
setUser(JSON.parse(storedUser));
|
|
32
|
+
setToken(storedToken);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
}, []);
|
|
36
|
+
|
|
37
|
+
const login = (userData, jwtToken) => {
|
|
38
|
+
setUser(userData);
|
|
39
|
+
setToken(jwtToken);
|
|
40
|
+
|
|
41
|
+
localStorage.setItem(
|
|
42
|
+
"user",
|
|
43
|
+
JSON.stringify(
|
|
44
|
+
userData
|
|
45
|
+
)
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
localStorage.setItem(
|
|
49
|
+
"token",
|
|
50
|
+
jwtToken
|
|
51
|
+
);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const logout = () => {
|
|
55
|
+
|
|
56
|
+
setUser(null);
|
|
57
|
+
|
|
58
|
+
setToken(null);
|
|
59
|
+
|
|
60
|
+
localStorage.removeItem(
|
|
61
|
+
"user"
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
localStorage.removeItem(
|
|
65
|
+
"token"
|
|
66
|
+
);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<UserContext.Provider
|
|
71
|
+
value={{
|
|
72
|
+
user,
|
|
73
|
+
token,
|
|
74
|
+
login,
|
|
75
|
+
logout
|
|
76
|
+
}}
|
|
77
|
+
>
|
|
78
|
+
{children}
|
|
79
|
+
</UserContext.Provider>
|
|
80
|
+
);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export const useUser = () => {
|
|
84
|
+
return useContext(UserContext);
|
|
85
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useState,
|
|
3
|
+
useEffect
|
|
4
|
+
} from "react";
|
|
5
|
+
|
|
6
|
+
const useDebounce = (
|
|
7
|
+
value,
|
|
8
|
+
delay
|
|
9
|
+
) => {
|
|
10
|
+
|
|
11
|
+
const [
|
|
12
|
+
debouncedValue,
|
|
13
|
+
setDebouncedValue
|
|
14
|
+
] = useState(value);
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
|
|
18
|
+
const timer =
|
|
19
|
+
setTimeout(() => {
|
|
20
|
+
|
|
21
|
+
setDebouncedValue(
|
|
22
|
+
value
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
}, delay);
|
|
26
|
+
|
|
27
|
+
return () =>
|
|
28
|
+
clearTimeout(timer);
|
|
29
|
+
|
|
30
|
+
}, [value, delay]);
|
|
31
|
+
|
|
32
|
+
return debouncedValue;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export default useDebounce;
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
Navigate,
|
|
3
|
+
Outlet
|
|
4
|
+
}
|
|
5
|
+
from "react-router-dom";
|
|
4
6
|
|
|
5
|
-
export
|
|
6
|
-
const token = localStorage.getItem("token");
|
|
7
|
+
export function ProtectedRoute(){
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
const token =
|
|
10
|
+
localStorage.getItem(
|
|
11
|
+
"token"
|
|
12
|
+
);
|
|
11
13
|
|
|
12
|
-
|
|
14
|
+
return token
|
|
15
|
+
? <Outlet />
|
|
16
|
+
: <Navigate to="/login"/>
|
|
13
17
|
}
|
|
@@ -1,33 +1,43 @@
|
|
|
1
1
|
import { useEffect, useState } from "react";
|
|
2
2
|
import api from "../../services/api";
|
|
3
|
+
import useDebounce from "../../hooks/useDebounce";
|
|
3
4
|
|
|
4
5
|
const ManageBlogs = () => {
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
// for pagination and debounce search
|
|
8
|
+
const [page, setPage] = useState(1);
|
|
9
|
+
const [totalPage, setTotalPage] = useState(1);
|
|
10
|
+
const [search, setSearch] = useState("");
|
|
11
|
+
|
|
12
|
+
const debouncedSearch = useDebounce(search, 500);
|
|
13
|
+
|
|
14
|
+
const [blogs, setBlogs] = useState([]);
|
|
7
15
|
|
|
8
16
|
const getBlogs = async () => {
|
|
9
|
-
try{
|
|
17
|
+
try {
|
|
10
18
|
|
|
11
|
-
const res = await api.get(
|
|
19
|
+
const res = await api.get(`/admin/blogs/posts?page=${page}&search=${debouncedSearch}`);
|
|
12
20
|
|
|
13
21
|
setBlogs(res.data);
|
|
22
|
+
setTotalPage(res.data.totalPges);
|
|
14
23
|
|
|
15
|
-
}catch(error){
|
|
24
|
+
} catch (error) {
|
|
16
25
|
console.log(error);
|
|
17
26
|
}
|
|
18
27
|
};
|
|
19
28
|
|
|
20
|
-
useEffect(()=>{
|
|
29
|
+
useEffect(() => {
|
|
21
30
|
getBlogs();
|
|
22
|
-
},[]);
|
|
31
|
+
}, [page, debouncedSearch]);
|
|
23
32
|
|
|
24
33
|
return (
|
|
25
34
|
<div>
|
|
35
|
+
<input type="text" value={search} placeholder="search" onChange={(e) => setSearch(e.target.value)} />
|
|
26
36
|
|
|
27
37
|
<h1>Manage Blogs</h1>
|
|
28
38
|
|
|
29
39
|
{
|
|
30
|
-
blogs.map((blog)=>(
|
|
40
|
+
blogs.map((blog) => (
|
|
31
41
|
<div key={blog._id}>
|
|
32
42
|
|
|
33
43
|
<h3>{blog.title}</h3>
|
|
@@ -40,6 +50,43 @@ const ManageBlogs = () => {
|
|
|
40
50
|
))
|
|
41
51
|
}
|
|
42
52
|
|
|
53
|
+
{/* pagination */}
|
|
54
|
+
<div>
|
|
55
|
+
<button
|
|
56
|
+
disabled={
|
|
57
|
+
page === 1
|
|
58
|
+
}
|
|
59
|
+
onClick={() =>
|
|
60
|
+
setPage(
|
|
61
|
+
page - 1
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
>
|
|
65
|
+
Prev
|
|
66
|
+
</button>
|
|
67
|
+
|
|
68
|
+
<span>
|
|
69
|
+
{" "}
|
|
70
|
+
{page} / {
|
|
71
|
+
totalPages
|
|
72
|
+
}{" "}
|
|
73
|
+
</span>
|
|
74
|
+
|
|
75
|
+
<button
|
|
76
|
+
disabled={
|
|
77
|
+
page ===
|
|
78
|
+
totalPages
|
|
79
|
+
}
|
|
80
|
+
onClick={() =>
|
|
81
|
+
setPage(
|
|
82
|
+
page + 1
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
>
|
|
86
|
+
Next
|
|
87
|
+
</button>
|
|
88
|
+
</div>
|
|
89
|
+
|
|
43
90
|
</div>
|
|
44
91
|
);
|
|
45
92
|
};
|
package/src/routes/AppRoutes.jsx
CHANGED
|
@@ -13,8 +13,9 @@ import ManageBlogs from "../pages/admin/ManageBlogs";
|
|
|
13
13
|
import AdminDashboard from "../pages/admin/AdminDashboard";
|
|
14
14
|
import AdminLayout from "../layout/AdminLayout";
|
|
15
15
|
import Register from "../pages/Register";
|
|
16
|
+
import { ProtectedRoute } from "../middleware/ProtectedRoute";
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
function AppRoutes() {
|
|
18
19
|
return (
|
|
19
20
|
<BrowserRouter>
|
|
20
21
|
{/* <Navbar /> */}
|
|
@@ -25,7 +26,7 @@ const AppRoutes = () => {
|
|
|
25
26
|
element={<Home />}
|
|
26
27
|
/>
|
|
27
28
|
|
|
28
|
-
|
|
29
|
+
<Route
|
|
29
30
|
path="/register"
|
|
30
31
|
element={<Register />}
|
|
31
32
|
/>
|
|
@@ -40,22 +41,28 @@ const AppRoutes = () => {
|
|
|
40
41
|
element={<CreatePost />}
|
|
41
42
|
/>
|
|
42
43
|
|
|
43
|
-
<Route
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
44
|
+
<Route
|
|
45
|
+
element={<ProtectedRoute />}
|
|
46
|
+
>
|
|
47
|
+
|
|
48
|
+
<Route path="/admin" element={<AdminLayout />}>
|
|
49
|
+
<Route index element={<AdminDashboard />} />
|
|
50
|
+
<Route
|
|
51
|
+
path="users"
|
|
52
|
+
element={<ManageUsers />}
|
|
53
|
+
/>
|
|
54
|
+
<Route
|
|
55
|
+
path="blogs"
|
|
56
|
+
element={<ManageBlogs />}
|
|
57
|
+
/>
|
|
58
|
+
{/* <Route
|
|
54
59
|
path="settings"
|
|
55
60
|
element={<Settings />}
|
|
56
61
|
/> */}
|
|
62
|
+
</Route>
|
|
63
|
+
|
|
57
64
|
</Route>
|
|
58
|
-
|
|
65
|
+
|
|
59
66
|
</Routes>
|
|
60
67
|
</BrowserRouter>
|
|
61
68
|
);
|