fixed filtering and moved refersh button into header, added css modules for components
This commit is contained in:
parent
d3f26083de
commit
12e5665a1c
50
src/App.css
50
src/App.css
@ -5,61 +5,11 @@
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.block{
|
||||
border-radius: 10px;
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #000000;
|
||||
width: 100%;
|
||||
padding: 15px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.refresh-btn{
|
||||
padding: 5px;
|
||||
background-color: #0000ff;
|
||||
color: #ffffff;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.refresh-btn:hover{
|
||||
opacity: 0.7;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.post{
|
||||
display: flex;
|
||||
border-bottom: 1px solid #b3b3b3;
|
||||
border-radius: 10px;
|
||||
margin-bottom: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.post-id{
|
||||
padding: 5px;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.post-body{
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.post:hover{
|
||||
background-color: #b3b3b3;
|
||||
}
|
||||
|
||||
.post-title{
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.refresh-and-search{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.refresh-and-search input{
|
||||
border-radius: 10px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
|
||||
44
src/App.tsx
44
src/App.tsx
@ -1,4 +1,4 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import './App.css'
|
||||
import Header from './components/Header'
|
||||
import PostList from './components/PostList'
|
||||
@ -7,7 +7,7 @@ import axios from 'axios'
|
||||
|
||||
function App() {
|
||||
|
||||
const [allPosts, setAllPosts] = useState<Post[]>([]);
|
||||
|
||||
const [posts, setPosts] = useState<Post[]>([]);
|
||||
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
@ -16,7 +16,7 @@ function App() {
|
||||
const fetchPosts = async () => {
|
||||
const response = await axios.get<Post[]>("https://jsonplaceholder.typicode.com/posts");
|
||||
|
||||
setAllPosts(response.data);
|
||||
|
||||
setPosts(response.data);
|
||||
|
||||
console.log("Posts fetched:", response.data);
|
||||
@ -29,20 +29,34 @@ function App() {
|
||||
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
const normalize = (str: string) => str.replace(/\s+/g, " ").toLowerCase();
|
||||
|
||||
|
||||
if (searchTerm) {
|
||||
const filteredPosts = allPosts.filter(post =>
|
||||
normalize(post.body).includes(searchTerm.toLowerCase()) || post.title.toLowerCase().includes(searchTerm.toLowerCase())
|
||||
);
|
||||
setPosts(filteredPosts);
|
||||
} else {
|
||||
setPosts(allPosts);
|
||||
const normalize = (str: string) => str.replace(/\s+/g, " ").toLowerCase();
|
||||
|
||||
|
||||
const filteredPosts = useMemo(() => {
|
||||
return posts.filter(post => {
|
||||
if (searchTerm == "") {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (normalize(post.body).includes(searchTerm.toLowerCase()) || post.title.toLowerCase().includes(searchTerm.toLowerCase())) {
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}, [searchTerm, allPosts]);
|
||||
|
||||
);
|
||||
},[posts, searchTerm]);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -51,7 +65,7 @@ function App() {
|
||||
|
||||
<Header setRefresh={fetchPosts} searchTerm={searchTerm} setSearchTerm={setSearchTerm} />
|
||||
|
||||
<PostList posts={posts} />
|
||||
<PostList posts={filteredPosts} />
|
||||
|
||||
</>
|
||||
|
||||
|
||||
8
src/components/Block.module.css
Normal file
8
src/components/Block.module.css
Normal file
@ -0,0 +1,8 @@
|
||||
.block {
|
||||
border-radius: 10px;
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #000000;
|
||||
width: 100%;
|
||||
padding: 15px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
@ -1,10 +1,11 @@
|
||||
import type { BlockProps } from "./types";
|
||||
import styles from "./Block.module.css";
|
||||
|
||||
function Block({title, children}:BlockProps) {
|
||||
return (
|
||||
<div className="block">
|
||||
<h1 className="title">{title}</h1>
|
||||
<div className="block-children">
|
||||
<div className={styles.block}>
|
||||
<h1>{title}</h1>
|
||||
<div>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
22
src/components/Header.module.css
Normal file
22
src/components/Header.module.css
Normal file
@ -0,0 +1,22 @@
|
||||
.refreshBtn {
|
||||
padding: 5px;
|
||||
background-color: #0000ff;
|
||||
color: #ffffff;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.refreshBtn:hover {
|
||||
opacity: 0.7;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.refreshAndSearch {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.refreshAndSearch input {
|
||||
border-radius: 10px;
|
||||
padding: 5px;
|
||||
}
|
||||
@ -1,15 +1,15 @@
|
||||
import Block from "./Block";
|
||||
import RefreshButton from "./RefreshButton";
|
||||
import type { HeaderProps } from "./types";
|
||||
import styles from "./Header.module.css";
|
||||
|
||||
function Header({setRefresh, searchTerm, setSearchTerm}:HeaderProps) {
|
||||
|
||||
|
||||
return (
|
||||
<Block title='Header'>
|
||||
<Block title="Header">
|
||||
<hr></hr>
|
||||
<div className="refresh-and-search">
|
||||
<RefreshButton setRefresh={setRefresh}/>
|
||||
<div className={styles.refreshAndSearch}>
|
||||
<button className={styles.refreshBtn} onClick={() => setRefresh()}>Refresh</button>
|
||||
<input type="text" name="search" id="search" value={searchTerm} onChange={(e) => setSearchTerm(e.target.value)} placeholder="search..."/>
|
||||
</div>
|
||||
|
||||
|
||||
25
src/components/PostItem.module.css
Normal file
25
src/components/PostItem.module.css
Normal file
@ -0,0 +1,25 @@
|
||||
.post {
|
||||
display: flex;
|
||||
border-bottom: 1px solid #b3b3b3;
|
||||
border-radius: 10px;
|
||||
margin-bottom: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.postId {
|
||||
padding: 5px;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.postBody {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.post:hover {
|
||||
background-color: #b3b3b3;
|
||||
}
|
||||
|
||||
.postTitle {
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
}
|
||||
@ -1,10 +1,11 @@
|
||||
|
||||
import type { postItemProps } from "./types";
|
||||
import styles from "./PostItem.module.css";
|
||||
|
||||
function PostItem({post}:postItemProps){
|
||||
return (
|
||||
<div className="post">
|
||||
<div className="post-id">{post.id}</div> <div className="post-body" onClick={() => alert("clicked on post: " + post.title)}> <span className="post-title">{post.title}</span> <br /> <br />{post.body} </div>
|
||||
<div className={styles.post}>
|
||||
<div className={styles.postId}>{post.id}</div> <div className={styles.postBody} onClick={() => alert("clicked on post: " + post.title)}> <span className={styles.postTitle}>{post.title}</span> <br /> <br />{post.body} </div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
import type { RefreshButtonProps } from "./types";
|
||||
|
||||
function RefreshButton({setRefresh}: RefreshButtonProps) {
|
||||
return (
|
||||
<button className="refresh-btn" onClick={() => setRefresh()}>Refresh</button>
|
||||
)
|
||||
}
|
||||
|
||||
export default RefreshButton;
|
||||
@ -18,3 +18,5 @@ body {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user