Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
B
blog-app
Overview
Overview
Details
Activity
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
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Manivasagam S
blog-app
Commits
98808fe0
Commit
98808fe0
authored
Jul 23, 2025
by
Manivasagam S
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactor the code
parent
e802915f
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
269 additions
and
213 deletions
+269
-213
Card.jsx
Component/Base/Card/Card.jsx
+24
-1
Card.module.css
Component/Base/Card/Card.module.css
+7
-7
Header.jsx
Component/Base/Header/Header.jsx
+15
-12
Header.module.css
Component/Base/Header/Header.module.css
+50
-34
Header.stories.jsx
Component/Base/Header/Header.stories.jsx
+11
-12
Icons.module.css
Component/Base/Icons/Icons.module.css
+8
-11
Input.jsx
Component/Base/Input/Input.jsx
+39
-12
Search.jsx
Component/Base/Search/Search.jsx
+3
-3
Search.module.css
Component/Base/Search/Search.module.css
+9
-5
Search.stories.jsx
Component/Base/Search/Search.stories.jsx
+17
-18
CardList.jsx
Component/Top-level/CardList/CardList.jsx
+21
-36
CardList.module.css
Component/Top-level/CardList/CardList.module.css
+16
-2
CardList.stories.jsx
Component/Top-level/CardList/CardList.stories.jsx
+5
-8
Pagination.jsx
Component/Top-level/Pagination/Pagination.jsx
+0
-1
Pagination.stories.jsx
Component/Top-level/Pagination/Pagination.stories.jsx
+6
-8
Singleblog.module.css
Component/Top-level/Singleblog/Singleblog.module.css
+2
-2
Home.js
app/components/Home.js
+33
-5
globals.css
app/globals.css
+2
-36
page.js
app/page.js
+1
-0
No files found.
Component/Base/Card/Card.jsx
View file @
98808fe0
import
React
from
"react"
;
import
PropTypes
from
"prop-types"
;
import
styles
from
"@/Component/Base/Card/Card.module.css"
;
import
Link
from
"next/link"
;
import
Image
from
"next/image"
;
import
{
Icons
}
from
"@/Component/Base/Icons/Icons.jsx"
;
export
const
Card
=
({
id
,
title
,
...
...
@@ -39,7 +41,7 @@ export const Card = ({
height=
{
author
.
image
.
height
}
width=
{
author
.
image
.
width
}
loading=
"eager"
alt=
{
author
}
alt=
{
author
.
name
}
/>
</
div
>
<
div
className=
{
styles
.
authordescription
}
>
...
...
@@ -58,3 +60,24 @@ export const Card = ({
</
div
>
);
};
Card
.
propTypes
=
{
id
:
PropTypes
.
oneOfType
([
PropTypes
.
string
,
PropTypes
.
number
]).
isRequired
,
title
:
PropTypes
.
string
,
description
:
PropTypes
.
string
,
image
:
PropTypes
.
shape
({
url
:
PropTypes
.
string
,
height
:
PropTypes
.
number
,
width
:
PropTypes
.
number
,
}),
publishedDate
:
PropTypes
.
string
,
author
:
PropTypes
.
shape
({
name
:
PropTypes
.
string
,
image
:
PropTypes
.
shape
({
url
:
PropTypes
.
string
,
height
:
PropTypes
.
number
,
width
:
PropTypes
.
number
,
}),
}),
readingTime
:
PropTypes
.
string
,
};
Component/Base/Card/Card.module.css
View file @
98808fe0
.container
{
background-color
:
var
(
--card-bg
);
border-radius
:
12px
;
border-radius
:
0.8rem
;
overflow
:
hidden
;
box-shadow
:
0
2px
8px
rgba
(
0
,
0
,
0
,
0.05
);
transition
:
transform
0.2s
ease
;
...
...
@@ -29,9 +29,9 @@
.card-img
{
width
:
100%
;
max-width
:
27rem
;
height
:
300px
;
border-top-left-radius
:
12px
;
border-top-right-radius
:
12px
;
height
:
18.75rem
;
border-top-left-radius
:
0.75rem
;
border-top-right-radius
:
0.75rem
;
object-fit
:
cover
;
}
...
...
@@ -65,8 +65,8 @@
.img
{
border-radius
:
50%
;
object-fit
:
cover
;
width
:
50px
;
height
:
50px
;
width
:
3.125rem
;
height
:
3.125rem
;
margin-top
:
5px
;
}
...
...
@@ -78,7 +78,7 @@
.authorName
{
font-weight
:
600
;
font-size
:
1.1rem
;
color
:
var
(
--
text-color
);
color
:
var
(
--
light-text
);
}
.author-desc
{
...
...
Component/Base/Header/Header.jsx
View file @
98808fe0
"use client"
;
import
React
,
{
useContext
}
from
"react"
;
import
styles
from
"@/Component/Base/Header/Header.module.css"
;
import
React
,
{
useContext
,
useState
}
from
"react"
;
import
Link
from
"next/link"
;
import
{
Icons
}
from
"@/Component/Base/Icons/Icons.jsx"
;
import
PropTypes
from
"prop-types"
;
import
{
Search
}
from
"@/Component/Base/Search/Search.jsx"
;
import
{
ThemeContext
}
from
"@/Context/ThemeContext"
;
export
const
Header
=
({
name
,
onchange
})
=>
{
import
{
Icons
}
from
"@/Component/Base/Icons/Icons.jsx"
;
import
{
Search
}
from
"@/Component/Base/Search/Search.jsx"
;
import
styles
from
"@/Component/Base/Header/Header.module.css"
;
export
const
Header
=
({
name
,
onSearch
})
=>
{
const
{
theme
,
toggleTheme
}
=
useContext
(
ThemeContext
);
return
(
<
header
className=
{
styles
.
header
}
>
...
...
@@ -20,19 +21,21 @@ export const Header = ({ name, onchange }) => {
/>
<
h3
className=
{
styles
[
"nav-text"
]
}
>
{
name
}
</
h3
>
</
Link
>
<
div
className=
{
`${styles.searchWrapper}`
}
>
<
Search
onChange=
{
onchange
}
/>
<
div
className=
{
styles
.
searchWrapper
}
>
<
Search
onSearch=
{
onSearch
}
/>
</
div
>
<
div
className=
{
styles
.
headerIcons
}
>
<
div
className=
{
styles
.
themelight
}
onClick=
{
toggleTheme
}
>
<
Icons
name=
{
theme
===
"light"
?
"sun"
:
"moon"
}
size=
"medium"
/>
</
div
>
<
div
className=
{
styles
.
themelight
}
onClick=
{
toggleTheme
}
>
<
Icons
name=
{
theme
===
"light"
?
"sun"
:
"moon"
}
size=
"medium"
/>
</
div
>
</
nav
>
</
div
>
</
header
>
);
};
Header
.
propTypes
=
{
name
:
PropTypes
.
string
,
name
:
PropTypes
.
string
.
isRequired
,
onSearch
:
PropTypes
.
func
.
isRequired
,
};
Component/Base/Header/Header.module.css
View file @
98808fe0
...
...
@@ -5,13 +5,17 @@
}
.container
{
max-width
:
1200px
;
/* width: 100%; */
max-width
:
84rem
;
margin
:
0
auto
;
}
.navbar
{
display
:
flex
;
flex-wrap
:
wrap
;
align-items
:
center
;
justify-content
:
space-between
;
gap
:
1rem
;
}
.nav-brand
{
...
...
@@ -19,65 +23,77 @@
align-items
:
center
;
gap
:
0.5rem
;
text-decoration
:
none
;
position
:
relative
;
right
:
5rem
;
order
:
1
;
}
.nav-text
{
margin
:
0
;
color
:
var
(
--text-color
);
font-weight
:
600
;
margin-bottom
:
5px
;
font-size
:
1.25rem
;
}
.searchWrapper
{
flex
:
1
;
order
:
3
;
flex
:
1
1
100%
;
display
:
flex
;
justify-content
:
center
;
display
:
none
;
width
:
100%
;
max-width
:
25rem
;
margin
:
0
auto
;
}
.themelight
{
display
:
flex
;
align-items
:
center
;
}
.header-ul
{
display
:
flex
;
gap
:
2rem
;
position
:
relative
;
right
:
0.8rem
;
display
:
none
;
}
.header-ul
li
{
list-style-type
:
none
;
}
.headerIcons
{
display
:
flex
;
gap
:
1rem
;
cursor
:
pointer
;
position
:
relative
;
left
:
5rem
;
order
:
2
;
}
@media
(
min-width
:
640px
)
{
.navbar
{
gap
:
3rem
;
flex-wrap
:
nowrap
;
}
.nav-text
{
font-size
:
1.5rem
;
.nav-brand
{
order
:
1
;
}
.searchWrapper
{
order
:
2
;
}
.themelight
{
order
:
3
;
}
}
@media
(
min-width
:
768px
)
{
.nav-brand
{
order
:
1
;
}
.themelight
{
order
:
3
;
}
.searchWrapper
{
order
:
2
;
}
}
@media
(
min-width
:
1024px
)
{
/* .mobileMenu{
display: none;
} */
.header-ul
{
display
:
inline-flex
;
.navbar
{
flex-wrap
:
nowrap
;
}
.nav-brand
{
order
:
1
;
}
.searchWrapper
{
display
:
inline-flex
;
order
:
2
;
flex
:
1
1
auto
;
margin
:
0
auto
;
}
.themelight
{
order
:
3
;
}
.menuIcon
{
display
:
none
;
.nav-text
{
font-size
:
1.5rem
;
}
}
Component/Base/Header/Header.stories.jsx
View file @
98808fe0
import
{
Header
}
from
"@/Component/Base/Header/Header.jsx"
;
import
{
action
}
from
'storybook/actions'
;
export
default
{
title
:
'Base/Header'
,
component
:
Header
}
export
const
Heading
=
(
args
)
=>
<
Header
{
...
args
}
/>
Heading
.
args
=
{
name
:
"NewsBlog"
,
onchange
:
action
(
"Header Search Changed"
),
}
\ No newline at end of file
import
{
Header
}
from
"@/Component/Base/Header/Header.jsx"
;
import
{
action
}
from
"storybook/actions"
;
export
default
{
title
:
"Layout/Header"
,
component
:
Header
,
};
export
const
Heading
=
(
args
)
=>
<
Header
{
...
args
}
/>;
Heading
.
args
=
{
name
:
"NewsBlog"
,
onchange
:
action
(
"Header Search Changed"
),
};
Component/Base/Icons/Icons.module.css
View file @
98808fe0
/* Icon size styles */
.small
svg
{
height
:
1
8
px
;
width
:
1
8
px
;
height
:
1
6
px
;
width
:
1
6
px
;
color
:
var
(
--font-color-300
);
}
...
...
@@ -10,8 +10,8 @@
width
:
25
x
;
color
:
var
(
--font-color-300
);
}
.large
svg
{
height
:
35px
;
.large
svg
{
height
:
35px
;
width
:
35px
;
color
:
var
(
--font-color-300
);
}
...
...
@@ -50,15 +50,13 @@
font-size
:
0.75rem
;
gap
:
0.5rem
;
}
@media
(
min-width
:
640px
)
{
.medium
svg
{
@media
(
min-width
:
640px
)
{
.medium
svg
{
width
:
38px
;
height
:
38px
;
}
.large
svg
{
.large
svg
{
width
:
42px
;
height
:
42px
;
}
}
\ No newline at end of file
}
Component/Base/Input/Input.jsx
View file @
98808fe0
import
React
from
'react'
import
clsx
from
'clsx'
;
import
React
from
"react"
;
import
clsx
from
"clsx"
;
import
PropTypes
from
"prop-types"
;
import
styles
from
"@/Component/Base/Input/Input.module.css"
;
export
const
Input
=
({
type
=
'text'
,
placeholder
=
''
,
isInvalid
=
false
,
onChange
,
value
=
''
,
autoFocus
,
errorMessage
=
""
,...
props
})
=>
{
export
const
Input
=
({
type
=
"text"
,
placeholder
=
""
,
isInvalid
=
false
,
onChange
,
value
=
""
,
autoFocus
,
errorMessage
=
""
,
...
props
})
=>
{
return
(
<
div
>
<
input
className=
{
clsx
(
styles
.
inputbox
,
isInvalid
&&
styles
.
invalid
)
}
type=
{
type
}
placeholder=
{
placeholder
}
onChange=
{
onChange
}
autoFocus=
{
autoFocus
}
{
...
props
}
/>
{
errorMessage
&&
<
p
className=
{
styles
.
error
}
style=
{
{
color
:
'red'
}
}
>
{
errorMessage
}
</
p
>
}
<
div
>
<
input
className=
{
clsx
(
styles
.
inputbox
,
isInvalid
&&
styles
.
invalid
)
}
type=
{
type
}
placeholder=
{
placeholder
}
onChange=
{
onChange
}
autoFocus=
{
autoFocus
}
{
...
props
}
/>
{
errorMessage
&&
(
<
p
className=
{
styles
.
error
}
style=
{
{
color
:
"red"
,
}
}
>
{
errorMessage
}
</
p
>
)
}
</
div
>
)
}
);
};
Input
.
prototype
=
{
type
:
PropTypes
.
string
,
isInvalid
:
PropTypes
.
bool
,
placeholder
:
PropTypes
.
string
,
};
Component/Base/Search/Search.jsx
View file @
98808fe0
...
...
@@ -6,20 +6,20 @@ import { Icons } from "@/Component/Base/Icons/Icons.jsx";
export
const
Search
=
({
placeholder
=
"Discover news, articles and more"
,
onSearch
,
posts
,
})
=>
{
const
[
text
,
setText
]
=
useState
(
""
);
const
handleInputChange
=
(
value
)
=>
{
setText
(
value
);
on
Change
?.(
value
);
on
Search
?.(
value
);
};
const
handleClear
=
(
e
)
=>
{
e
.
preventDefault
();
setText
(
""
);
onSearch
?.(
""
);
};
console
.
log
(
text
);
return
(
<
div
className=
{
styles
.
searchContainer
}
>
<
span
className=
{
styles
.
searchIcon
}
>
...
...
Component/Base/Search/Search.module.css
View file @
98808fe0
...
...
@@ -2,9 +2,8 @@
display
:
flex
;
align-items
:
center
;
background-color
:
var
(
--search-color
);
border-radius
:
8px
;
border-radius
:
0.5rem
;
padding
:
0.5rem
0.5rem
;
max-width
:
25rem
;
width
:
100%
;
/* gap: 0.75rem; */
position
:
relative
;
...
...
@@ -25,11 +24,11 @@
align-items
:
center
;
}
.input-box
{
width
:
20
rem
;
min-width
:
15
rem
;
border
:
none
;
outline
:
none
;
background
:
transparent
;
font-size
:
1
rem
;
font-size
:
0.8
rem
;
color
:
var
(
--text-color
);
padding
:
0.25rem
0
;
margin-left
:
1rem
;
...
...
@@ -43,5 +42,10 @@
justify-content
:
center
;
cursor
:
pointer
;
color
:
#2b6cb0
;
margin-top
:
7px
;
margin-top
:
0.5rem
;
}
@media
(
min-width
:
640px
)
{
.input-box
{
font-size
:
1rem
;
}
}
Component/Base/Search/Search.stories.jsx
View file @
98808fe0
import
{
Search
,
search
}
from
"@/Component/Base/Search/Search.jsx"
;
import
{
action
}
from
'storybook/actions'
;
export
default
{
title
:
"Shared/Search"
,
component
:
Search
,
argsTypes
:{
onchange
:{
action
:
"changed"
}
}
}
export
const
Searchbar
=
(
args
)
=>
<
Search
{
...
args
}
/>
Searchbar
.
args
=
{
placeholder
:
"Discover news, articles and more"
,
onChange
:
action
(
"Input Changed"
),
}
import
{
Search
,
search
}
from
"@/Component/Base/Search/Search.jsx"
;
import
{
action
}
from
"storybook/actions"
;
import
{
background
}
from
"storybook/internal/theming"
;
export
default
{
title
:
"Shared/Search"
,
component
:
Search
,
argsTypes
:
{
onchange
:
{
action
:
"changed"
,
},
},
};
export
const
Searchbar
=
(
args
)
=>
<
Search
{
...
args
}
/>;
Searchbar
.
args
=
{
placeholder
:
"Discover news, articles and more"
,
onChange
:
action
(
"Input Changed"
),
};
Component/Top-level/CardList/CardList.jsx
View file @
98808fe0
"use client"
;
import
React
,
{
useState
,
useEffect
}
from
"react"
;
import
React
from
"react"
;
import
PropTypes
from
"prop-types"
;
import
styles
from
"@/Component/Top-level/CardList/CardList.module.css"
;
import
{
Pagination
}
from
"@/Component/Top-level/Pagination/Pagination"
;
import
{
Card
}
from
"@/Component/Base/Card/Card"
;
import
styles
from
"@/Component/Top-level/CardList/CardList.module.css"
;
export
const
CardList
=
({
title
,
description
,
blogs
})
=>
{
const
itemsPerPage
=
6
;
const
[
currentPage
,
setCurrentPage
]
=
useState
(
1
);
const
handlePageChange
=
(
pageNumber
)
=>
{
setCurrentPage
(
pageNumber
);
window
.
scrollTo
({
top
:
0
,
behavior
:
"smooth"
});
};
const
startIndex
=
(
currentPage
-
1
)
*
itemsPerPage
;
const
endIndex
=
startIndex
+
itemsPerPage
;
const
slicedData
=
blogs
.
slice
(
startIndex
,
endIndex
);
const
totalPages
=
Math
.
ceil
(
blogs
.
length
/
itemsPerPage
);
export
const
CardList
=
({
title
,
description
,
blogs
=
[],
slicedData
})
=>
{
const
displayData
=
slicedData
&&
slicedData
.
length
>
0
?
slicedData
:
blogs
;
return
(
<
div
className=
{
styles
.
cardListContainer
}
>
{
title
&&
<
h1
className=
{
styles
.
title
}
>
{
title
}
</
h1
>
}
{
description
&&
<
p
className=
{
styles
.
description
}
>
{
description
}
</
p
>
}
<
div
className=
{
styles
.
blogRow
}
>
{
slicedData
.
map
((
blogdata
,
i
)
=>
(
<
div
key=
{
i
}
className=
{
styles
.
blogCard
}
>
<
Card
{
...
blogdata
}
/>
{
blogs
.
length
===
0
?
(
<
p
className=
{
styles
.
resultFound
}
>
No result found
</
p
>
)
:
(
<
>
<
div
className=
{
styles
.
heading
}
>
{
title
&&
<
h1
className=
{
styles
.
title
}
>
{
title
}
</
h1
>
}
{
description
&&
<
p
className=
{
styles
.
description
}
>
{
description
}
</
p
>
}
</
div
>
))
}
</
div
>
{
totalPages
>
1
&&
(
<
div
className=
{
styles
.
pagination
}
>
<
Pagination
size=
{
totalPages
}
currentPage=
{
currentPage
}
onChange=
{
handlePageChange
}
/>
</
div
>
<
div
className=
{
styles
.
blogRow
}
>
{
displayData
.
map
((
blogdata
,
i
)
=>
(
<
div
key=
{
i
}
className=
{
styles
.
blogCard
}
>
<
Card
{
...
blogdata
}
/>
</
div
>
))
}
</
div
>
</>
)
}
</
div
>
);
};
CardList
.
propTypes
=
{
title
:
PropTypes
.
string
,
description
:
PropTypes
.
string
,
blogs
:
PropTypes
.
arrayOf
(
PropTypes
.
object
).
isRequired
,
blogs
:
PropTypes
.
arrayOf
(
PropTypes
.
object
),
slicedData
:
PropTypes
.
arrayOf
(
PropTypes
.
object
),
};
Component/Top-level/CardList/CardList.module.css
View file @
98808fe0
.cardListContainer
{
padding-left
:
2rem
;
padding-right
:
2rem
;
padding
:
1rem
2rem
;
}
.description
{
padding-left
:
2rem
;
...
...
@@ -12,6 +11,11 @@
padding-top
:
2rem
;
color
:
var
(
--light-text
);
}
.heading
{
display
:
flex
;
flex-direction
:
column
;
justify-content
:
center
;
}
.blogRow
{
display
:
grid
;
grid-template-columns
:
1
fr
;
...
...
@@ -19,7 +23,17 @@
place-self
:
center
;
margin-top
:
2rem
;
}
.resultFound
{
display
:
flex
;
justify-content
:
center
;
margin-top
:
20rem
;
font-size
:
1.5rem
;
text-transform
:
uppercase
;
}
@media
(
min-width
:
640px
)
{
.resultFound
{
font-size
:
2rem
;
}
.blogRow
{
display
:
grid
;
grid-template-columns
:
1
fr
;
...
...
Component/Top-level/CardList/CardList.stories.jsx
View file @
98808fe0
import
{
CardList
}
from
"@/Component/Top-level/CardList/CardList.jsx"
;
export
default
{
title
:
"Toplevel/CardList"
,
component
:
CardList
}
export
default
{
title
:
"Toplevel/CardList"
,
component
:
CardList
,
}
;
export
const
blogLists
=
{
args
:
{
title
:
"Lifestyle"
,
description
:
"Lorem ipsum dolor sit amet elit. Id quaerat amet ipsum sunt et quos dolorum"
,
blogs
:
[
{
id
:
1
,
...
...
@@ -203,7 +200,7 @@ export const blogLists = {
},
readingTime
:
"1min"
,
},
{
{
id
:
1
,
title
:
"How to get perfect start for beginning runners"
,
description
:
...
...
Component/Top-level/Pagination/Pagination.jsx
View file @
98808fe0
import
React
,
{
useState
,
useContext
}
from
"react"
;
import
{
Button
}
from
"@/Component/Base/Button/Button"
;
import
styles
from
"./Pagination.module.css"
;
import
{
ThemeContext
}
from
"@/Context/ThemeContext"
;
export
const
Pagination
=
({
size
,
currentPage
,
onChange
})
=>
{
const
[
isShow
,
setIsShow
]
=
useState
(
false
);
...
...
Component/Top-level/Pagination/Pagination.stories.jsx
View file @
98808fe0
...
...
@@ -4,13 +4,12 @@ export default {
title
:
"Toplevel/Pagination"
,
component
:
Pagination
,
argTypes
:
{
onChange
:
{
action
:
"page changed"
},
onChange
:
{
action
:
"page changed"
},
},
};
export
const
Default
=
(
args
)
=>
<
Pagination
{
...
args
}
/>
Default
.
args
=
{
size
:
7
,
currentPage
:
3
,
}
\ No newline at end of file
export
const
Default
=
(
args
)
=>
<
Pagination
{
...
args
}
/>;
Default
.
args
=
{
size
:
7
,
currentPage
:
3
,
};
Component/Top-level/Singleblog/Singleblog.module.css
View file @
98808fe0
...
...
@@ -75,8 +75,8 @@
}
.tagItems
{
border
:
1px
solid
black
;
padding
:
0.
3
rem
;
border-radius
:
0.5
rem
;
padding
:
0.
2
rem
;
border-radius
:
1
rem
;
background-color
:
rgb
(
91
,
90
,
90
);
color
:
white
;
border-color
:
transparent
;
...
...
app/components/Home.js
View file @
98808fe0
...
...
@@ -3,6 +3,7 @@ import React, { useState, useMemo } from "react";
import
{
CardList
}
from
"@/Component/Top-level/CardList/CardList"
;
import
{
Header
}
from
"@/Component/Base/Header/Header"
;
import
{
useThemeContext
}
from
"@/Context/ThemeContext"
;
import
{
Pagination
}
from
"@/Component/Top-level/Pagination/Pagination"
;
import
"../globals.css"
;
export
default
function
Home
({
blogs
})
{
...
...
@@ -12,14 +13,30 @@ export default function Home({ blogs }) {
const
handleSearch
=
(
value
)
=>
{
setSearchQuery
(
value
.
toLowerCase
());
};
const
filteredPosts
=
useMemo
(()
=>
{
return
blogs
.
filter
(
(
post
)
=>
post
.
title
.
toLowerCase
().
includes
(
searchQuery
)
||
post
.
author
.
toLowerCase
().
includes
(
searchQuery
)
);
return
blogs
.
filter
((
post
)
=>
{
const
title
=
typeof
post
.
title
===
"string"
?
post
.
title
.
toLowerCase
()
:
""
;
const
author
=
typeof
post
.
author
===
"string"
?
post
.
author
.
toLowerCase
()
:
""
;
return
title
.
includes
(
searchQuery
)
||
author
.
includes
(
searchQuery
);
});
},
[
searchQuery
,
blogs
]);
const
itemsPerPage
=
6
;
const
[
currentPage
,
setCurrentPage
]
=
useState
(
1
);
const
handlePageChange
=
(
pageNumber
)
=>
{
setCurrentPage
(
pageNumber
);
window
.
scrollTo
({
top
:
0
,
behavior
:
"smooth"
});
};
const
startIndex
=
(
currentPage
-
1
)
*
itemsPerPage
;
const
endIndex
=
startIndex
+
itemsPerPage
;
const
slicedData
=
filteredPosts
.
slice
(
startIndex
,
endIndex
);
const
totalPages
=
Math
.
ceil
(
filteredPosts
.
length
/
itemsPerPage
);
return
(
<>
<
Header
...
...
@@ -33,7 +50,18 @@ export default function Home({ blogs }) {
title
=
"Lifestyle"
description
=
"Lorem ipsum dolor sit amet elit. Id quaerat amet ipsum sunt et quos dolorum"
blogs
=
{
filteredPosts
}
slicedData
=
{
slicedData
}
/
>
{
totalPages
>
1
&&
(
<
div
>
<
Pagination
size
=
{
totalPages
}
currentPage
=
{
currentPage
}
onChange
=
{
handlePageChange
}
/
>
<
/div
>
)}
<
/
>
);
}
app/globals.css
View file @
98808fe0
@import
url("https://fonts.googleapis.com/css2?family=Hind:wght@300;400;500;600;700&family=Libre+Baskerville:ital,wght@0,400;0,700;1,400&display=swap")
;
@import
url("https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100..900;1,100..900&display=swap")
;
body
,
html
{
font-family
:
"Hind"
,
sans-serif
;
...
...
@@ -20,42 +22,6 @@ h6 {
margin
:
0
;
padding
:
0
;
}
/* .light {
--primary-bgcolor: #5a67d8;
--secondary-bgcolor: #fff;
--primary-color: #fff;
--secondary-color: #718096;
--font-color-900: #2d3748;
--font-color-300: #718096;
--title-color: #2d3748;
--bg-color: #f8f9fa;
--input-bg: #f4f4f4;
--card-bg: #fff;
--heading-color: #2d3748;
--border-radius: 6px;
--border-radius-full: 15px;
--border-color: transparent;
--bg-grey: #f4f4f4;
--bg-lightgrey: #f8f9fa;
--btn-bg: #e2e8f0;
--font-color-700: black;
--placeholder-color: #9f9f9f;
}
.dark {
--bg-color: black;
--input-bg: black;
--card-bg: #131617;
--font-color-300: #b7b7b7;
--placeholder-color: #b7b7b7;
--font-color-900: #fff;
--title-color: #fff;
--font-color-700: #fff;
--border-color: rgba(255, 255, 255, 0.2);
--primary-bgcolor: #5a67d8;
--secondary-bgcolor: #131617;
--primary-color: #fff;
--secondary-color: #fff;
} */
:root
{
/* --primary-bg:black; */
--primary-bgcolor
:
#5a67d8
;
...
...
app/page.js
View file @
98808fe0
"use server"
;
import
{
getAllPosts
}
from
"@/lib/post"
;
import
Home
from
"@/app/components/Home"
;
...
...
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