Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
Newspaper Frontend
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lap nguyen
Newspaper Frontend
Commits
276daafc
Commit
276daafc
authored
2 years ago
by
Ken
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat:
add news filter by category and abort signal for api
parent
6cf25b38
Pipeline
#19395
canceled with stages
Changes
11
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
85 additions
and
26 deletions
+85
-26
model.ts
src/api/model.ts
+9
-0
newsApi.ts
src/api/newsApi.ts
+3
-3
index.tsx
src/components/Header/index.tsx
+2
-3
Newspaper.scss
src/components/Newspaper/Newspaper.scss
+4
-2
index.tsx
src/components/Newspaper/index.tsx
+8
-1
index.tsx
src/components/Sidenav/index.tsx
+9
-1
enum.ts
src/configuration/enum.ts
+4
-0
index.tsx
src/pages/NewsByCategoy/index.tsx
+7
-0
homePageSlice.ts
src/pages/home/homePageSlice.ts
+21
-10
index.tsx
src/pages/home/index.tsx
+14
-6
checkUrlLink.ts
src/utils/helpers/checkUrlLink.ts
+4
-0
No files found.
src/api/model.ts
0 → 100644
View file @
276daafc
import
{
IPagination
}
from
"pages/interface"
;
export
interface
BaseAPI
{
signal
?:
AbortSignal
;
}
export
interface
NewsAPI
extends
BaseAPI
{
params
:
IPagination
;
}
This diff is collapsed.
Click to expand it.
src/api/newsApi.ts
View file @
276daafc
import
{
IPagination
}
from
"pages/interface"
;
import
axiosClient
from
"./axiosClient"
;
import
{
NewsAPI
}
from
"./model"
;
const
newsApi
=
{
getNews
:
(
params
:
IPagination
)
=>
{
getNews
:
(
{
params
,
signal
}:
NewsAPI
)
=>
{
const
url
=
"/api/news"
;
return
axiosClient
.
get
(
url
,
{
params
});
return
axiosClient
.
get
(
url
,
{
params
,
signal
});
},
getNewsDetail
:
(
id
:
string
)
=>
{
const
url
=
`/api/news/
${
id
}
`
;
...
...
This diff is collapsed.
Click to expand it.
src/components/Header/index.tsx
View file @
276daafc
...
...
@@ -10,15 +10,14 @@ import { useAppDispatch, useAppSelector } from "app/hooks";
import
{
getCategories
}
from
"./headerSlice"
;
import
{
handleLoading
}
from
"app/globalSlice"
;
import
{
headerSelector
}
from
"app/selectors"
;
import
{
useNavigate
}
from
"react-router-dom"
;
import
HeaderLogo
from
"./HeaderLogo"
;
import
{
handleSetFilter
}
from
"pages/home/homePageSlice"
;
export
default
function
Header
()
{
const
dispatch
=
useAppDispatch
();
const
headerRef
=
useRef
<
HTMLElement
>
(
null
);
const
[
mobileOpen
,
setMobileOpen
]
=
useState
<
boolean
>
(
false
);
const
{
data
:
categoryData
}
=
useAppSelector
(
headerSelector
);
const
navigate
=
useNavigate
();
useEffect
(()
=>
{
dispatch
(
handleLoading
(
true
));
...
...
@@ -89,7 +88,7 @@ export default function Header() {
>
{
categoryData
.
map
((
item
)
=>
(
<
Box
onClick=
{
()
=>
navigate
(
item
.
link
)
}
onClick=
{
()
=>
dispatch
(
handleSetFilter
(
item
.
link
)
)
}
component=
"li"
key=
{
item
.
link
}
sx=
{
{
...
...
This diff is collapsed.
Click to expand it.
src/components/Newspaper/Newspaper.scss
View file @
276daafc
...
...
@@ -20,7 +20,8 @@
width
:
50%
;
min-height
:
288px
;
img
{
img
,
video
{
border
:
0
;
display
:
block
;
}
...
...
@@ -55,7 +56,8 @@
&
-img
{
width
:
100%
;
img
{
img
,
video
{
width
:
100%
;
height
:
100%
;
object-fit
:
cover
;
...
...
This diff is collapsed.
Click to expand it.
src/components/Newspaper/index.tsx
View file @
276daafc
...
...
@@ -4,6 +4,7 @@ import { INewspaper } from "pages/interface";
import
React
from
"react"
;
import
{
useNavigate
}
from
"react-router-dom"
;
import
{
useWindowSize
}
from
"usehooks-ts"
;
import
{
checkUrlLink
}
from
"utils/helpers/checkUrlLink"
;
type
Props
=
{
data
:
INewspaper
;
...
...
@@ -32,7 +33,13 @@ const Newspaper = (props: Props) => {
onClick=
{
()
=>
navigate
(
`${PageUrl.NEWS_ROOT}/${id}`
)
}
>
<
div
className=
"newspaper-img"
>
<
img
src=
{
image
}
alt=
{
title
}
/>
{
checkUrlLink
(
image
)
===
"image"
?
(
<
img
src=
{
image
}
alt=
{
title
}
/>
)
:
(
<
video
autoPlay
muted
loop
>
<
source
src=
{
image
}
type=
"video/mp4"
/>
</
video
>
)
}
</
div
>
<
div
className=
"newspaper-content"
>
...
...
This diff is collapsed.
Click to expand it.
src/components/Sidenav/index.tsx
View file @
276daafc
...
...
@@ -10,7 +10,10 @@ import {
Typography
,
}
from
"@mui/material"
;
import
{
ICategory
}
from
"components/interface"
;
import
{
handleSetFilter
}
from
"pages/home/homePageSlice"
;
import
{
useAppDispatch
}
from
"app/hooks"
;
import
{
useNavigate
}
from
"react-router-dom"
;
import
{
PageUrl
}
from
"configuration/enum"
;
type
Props
=
{
handleDrawerToggle
:
()
=>
void
;
...
...
@@ -20,8 +23,13 @@ type Props = {
const
drawerWidth
=
240
;
const
Sidenav
=
(
props
:
Props
)
=>
{
const
dispatch
=
useAppDispatch
();
const
navigate
=
useNavigate
();
const
{
navItems
,
handleDrawerToggle
,
mobileOpen
}
=
props
;
const
handleItemClick
=
(
link
:
string
)
=>
{
navigate
(
PageUrl
.
HOMEPAGE
);
dispatch
(
handleSetFilter
(
link
));
};
return
(
<
Box
component=
"nav"
>
...
...
@@ -49,7 +57,7 @@ const Sidenav = (props: Props) => {
<
ListItem
key=
{
item
.
link
}
disablePadding
onClick=
{
()
=>
navigate
(
item
.
link
)
}
onClick=
{
()
=>
handleItemClick
(
item
.
link
)
}
>
<
ListItemButton
sx=
{
{
textAlign
:
"center"
}
}
>
<
ListItemText
primary=
{
item
.
label
}
/>
...
...
This diff is collapsed.
Click to expand it.
src/configuration/enum.ts
View file @
276daafc
...
...
@@ -5,3 +5,7 @@ export const enum PageUrl {
NEWS_ROOT
=
"/newspaper"
,
ALL
=
"*"
,
}
export
const
enum
PageSearchParams
{
FILTER
=
"filterBy"
,
}
This diff is collapsed.
Click to expand it.
src/pages/NewsByCategoy/index.tsx
0 → 100644
View file @
276daafc
import
React
from
"react"
;
const
NewsByCategory
=
()
=>
{
return
<
div
>
NewsByCategory
</
div
>;
};
export
default
NewsByCategory
;
This diff is collapsed.
Click to expand it.
src/pages/home/homePageSlice.ts
View file @
276daafc
import
{
createAsyncThunk
,
createSlice
,
PayloadAction
}
from
"@reduxjs/toolkit"
;
import
{
NewsAPI
}
from
"api/model"
;
import
newsApi
from
"api/newsApi"
;
import
{
INewspaper
,
IPagination
}
from
"pages/interface"
;
import
{
INewspaper
}
from
"pages/interface"
;
const
initialState
:
{
newsData
:
INewspaper
[];
currentPage
:
number
;
isMaxPage
:
boolean
;
currentFilter
:
string
;
}
=
{
newsData
:
[],
currentPage
:
1
,
isMaxPage
:
false
,
currentFilter
:
""
,
};
export
const
getNews
=
createAsyncThunk
(
"home/news"
,
async
(
params
:
IPagination
)
=>
{
const
res
=
await
newsApi
.
getNews
(
params
);
return
res
;
}
);
export
const
getNews
=
createAsyncThunk
(
"home/news"
,
async
(
data
:
NewsAPI
)
=>
{
const
res
=
await
newsApi
.
getNews
(
data
);
return
res
;
});
const
home
=
createSlice
({
name
:
"home"
,
initialState
,
reducers
:
{
handleResetNews
:
(
state
)
=>
{
return
initialState
;
return
{
...
initialState
,
currentFilter
:
state
.
currentFilter
,
};
},
handlePage
:
(
state
,
action
)
=>
{
state
.
currentPage
+=
action
.
payload
;
...
...
@@ -33,6 +36,13 @@ const home = createSlice({
handleMaxPage
:
(
state
)
=>
{
state
.
isMaxPage
=
true
;
},
handleSetFilter
:
(
state
,
action
)
=>
{
const
filterValue
=
action
.
payload
;
if
(
filterValue
===
"/"
)
{
state
.
currentFilter
=
""
;
}
else
state
.
currentFilter
=
action
.
payload
;
},
},
extraReducers
:
(
builder
)
=>
{
builder
.
addCase
(
getNews
.
fulfilled
,
(
state
,
action
:
PayloadAction
<
any
>
)
=>
{
...
...
@@ -46,5 +56,6 @@ const home = createSlice({
});
const
{
reducer
,
actions
}
=
home
;
export
const
{
handleResetNews
,
handlePage
,
handleMaxPage
}
=
actions
;
export
const
{
handleResetNews
,
handlePage
,
handleMaxPage
,
handleSetFilter
}
=
actions
;
export
default
reducer
;
This diff is collapsed.
Click to expand it.
src/pages/home/index.tsx
View file @
276daafc
...
...
@@ -15,7 +15,8 @@ import { CircularProgress } from "@mui/material";
const
HomePage
=
()
=>
{
const
dispatch
=
useAppDispatch
();
const
{
newsData
,
currentPage
,
isMaxPage
}
=
useAppSelector
(
homeSelector
);
const
{
newsData
,
currentPage
,
isMaxPage
,
currentFilter
}
=
useAppSelector
(
homeSelector
);
const
{
ref
,
inView
}
=
useInView
({
threshold
:
0.7
,
initialInView
:
false
,
...
...
@@ -24,18 +25,23 @@ const HomePage = () => {
const
[
isLocalLoading
,
setIsLocalLoading
]
=
useState
<
boolean
>
(
false
);
useEffect
(()
=>
{
const
controller
=
new
AbortController
();
const
{
signal
}
=
controller
;
try
{
if
(
!
isMaxPage
)
{
setIsLocalLoading
(
true
);
setTimeout
(()
=>
{
const
newsParams
:
IPagination
=
{
Filters
:
""
,
Sorts
:
""
,
Filters
:
currentFilter
?
`categorylink==
${
currentFilter
}
`
:
""
,
Sorts
:
"
-CreatedAt
"
,
Page
:
currentPage
,
PageSize
:
10
,
};
const
fetchData
=
async
()
=>
{
const
res
:
any
=
await
dispatch
(
getNews
(
newsParams
)).
unwrap
();
const
res
:
any
=
await
dispatch
(
getNews
({
params
:
newsParams
,
signal
})
).
unwrap
();
if
(
res
.
data
.
collection
.
length
===
0
)
{
dispatch
(
handleMaxPage
());
...
...
@@ -51,8 +57,10 @@ const HomePage = () => {
setIsLocalLoading
(
false
);
}
return
()
=>
controller
.
abort
();
// eslint-disable-next-line react-hooks/exhaustive-deps
},
[
currentPage
]);
},
[
currentPage
,
currentFilter
]);
useEffect
(()
=>
{
if
(
inView
&&
!
isMaxPage
)
{
...
...
@@ -64,7 +72,7 @@ const HomePage = () => {
useEffect
(()
=>
{
dispatch
(
handleResetNews
());
// eslint-disable-next-line react-hooks/exhaustive-deps
},
[]);
},
[
currentFilter
]);
return
(
<
main
className=
"homePage"
>
...
...
This diff is collapsed.
Click to expand it.
src/utils/helpers/checkUrlLink.ts
0 → 100644
View file @
276daafc
export
const
checkUrlLink
=
(
url
:
string
)
=>
{
if
(
url
.
endsWith
(
"mp4"
))
return
"video"
;
return
"image"
;
};
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment