Commit 2a3688f8 authored by Ken's avatar Ken

refractor code

parent f10f185b
import axiosClient from "./axiosClient";
const homeApi = {
getNews: () => {
const url = "/api/news";
return axiosClient.get(url);
},
};
export default homeApi;
import { RootState } from "./store";
export const homeSelector = (state: RootState) => state.home;
export const globalSelector = (state: RootState) => state.global;
export const headerSelector = (state: RootState) => state.header;
import { configureStore } from "@reduxjs/toolkit"; import { configureStore } from "@reduxjs/toolkit";
import headerReducer from "components/Header/headerSlice"; import headerReducer from "components/Header/headerSlice";
import globalReducer from "./globalSlice"; import globalReducer from "./globalSlice";
import homeReducer from "pages/homePageSlice";
const rootReducer = { const rootReducer = {
header: headerReducer, header: headerReducer,
global: globalReducer, global: globalReducer,
home: homeReducer,
}; };
const store = configureStore({ reducer: rootReducer }); const store = configureStore({ reducer: rootReducer });
......
...@@ -11,12 +11,13 @@ import { Typography } from "@mui/material"; ...@@ -11,12 +11,13 @@ import { Typography } from "@mui/material";
import { useAppDispatch, useAppSelector } from "app/hooks"; import { useAppDispatch, useAppSelector } from "app/hooks";
import { getCategories } from "./headerSlice"; import { getCategories } from "./headerSlice";
import { handleLoading } from "app/globalSlice"; import { handleLoading } from "app/globalSlice";
import { headerSelector } from "app/selectors";
export default function Header() { export default function Header() {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const headerRef = useRef<HTMLElement>(null); const headerRef = useRef<HTMLElement>(null);
const [mobileOpen, setMobileOpen] = useState<boolean>(false); const [mobileOpen, setMobileOpen] = useState<boolean>(false);
const { data: categoryData } = useAppSelector((state) => state.header); const { data: categoryData } = useAppSelector(headerSelector);
useEffect(() => { useEffect(() => {
dispatch(handleLoading(true)); dispatch(handleLoading(true));
......
...@@ -27,6 +27,10 @@ ...@@ -27,6 +27,10 @@
margin-top: 20px; margin-top: 20px;
} }
small {
color: $gray;
}
h6 { h6 {
font-size: 2.5rem; font-size: 2.5rem;
padding-right: 50px; padding-right: 50px;
......
import { INewspaper } from "pages/interface";
import React from "react"; import React from "react";
import { INewspaper } from "../../utils/interface";
type Props = { type Props = {
data: INewspaper; data: INewspaper;
...@@ -7,18 +7,19 @@ type Props = { ...@@ -7,18 +7,19 @@ type Props = {
const Newspaper = (props: Props) => { const Newspaper = (props: Props) => {
const { data } = props; const { data } = props;
const { description, img, label } = data; const { description, image, title, createdAt } = data;
return ( return (
<div className="newspaper"> <div className="newspaper">
<div className="row flex-nowrap newspaper-article"> <div className="row flex-nowrap newspaper-article">
<div className="col-12 col-lg-7"> <div className="col-12 col-lg-7">
<img src={img} alt="poster" className="newspaper-article__img" /> <img src={image} alt="poster" className="newspaper-article__img" />
</div> </div>
<div className="col"> <div className="col">
<div className="newspaper-article__content"> <div className="newspaper-article__content">
<h6>{label}</h6> <small>{createdAt}</small>
<h6>{title}</h6>
<p>{description}</p> <p>{description}</p>
</div> </div>
</div> </div>
......
import { useAppSelector } from "app/hooks"; import { handleLoading } from "app/globalSlice";
import { useAppDispatch, useAppSelector } from "app/hooks";
import { globalSelector, homeSelector } from "app/selectors";
import Loading from "components/Loading"; import Loading from "components/Loading";
import React from "react"; import React, { useEffect } from "react";
import Newspaper from "../components/Newspaper"; import Newspaper from "../components/Newspaper";
import { INewspaper } from "../utils/interface"; import { getNews } from "./homePageSlice";
const newspapers: Array<INewspaper> = [
{
img: "https://cdn.tuoitre.vn/zoom/504_315/2022/10/24/nova-1-1666595567101786912310-crop-16665957294551455548631.jpeg",
label: "Novaland: Tin đồn và văn bản 'cầu cứu' trên mạng là bịa đặt",
description:
"TTO - Ngày 24-10, Novaland đã chính thức thông tin về các tin đồn những ngày qua liên quan đến các dự án của doanh nghiệp này. Phía Novaland khẳng...",
},
{
img: "https://cdn.tuoitre.vn/zoom/504_315/2022/10/24/nova-1-1666595567101786912310-crop-16665957294551455548631.jpeg",
label: "Novaland: Tin đồn và văn bản 'cầu cứu' trên mạng là bịa đặt",
description:
"TTO - Ngày 24-10, Novaland đã chính thức thông tin về các tin đồn những ngày qua liên quan đến các dự án của doanh nghiệp này. Phía Novaland khẳng...",
},
{
img: "https://cdn.tuoitre.vn/zoom/504_315/2022/10/24/nova-1-1666595567101786912310-crop-16665957294551455548631.jpeg",
label: "Novaland: Tin đồn và văn bản 'cầu cứu' trên mạng là bịa đặt",
description:
"TTO - Ngày 24-10, Novaland đã chính thức thông tin về các tin đồn những ngày qua liên quan đến các dự án của doanh nghiệp này. Phía Novaland khẳng...",
},
{
img: "https://cdn.tuoitre.vn/zoom/504_315/2022/10/24/nova-1-1666595567101786912310-crop-16665957294551455548631.jpeg",
label: "Novaland: Tin đồn và văn bản 'cầu cứu' trên mạng là bịa đặt",
description:
"TTO - Ngày 24-10, Novaland đã chính thức thông tin về các tin đồn những ngày qua liên quan đến các dự án của doanh nghiệp này. Phía Novaland khẳng...",
},
{
img: "https://cdn.tuoitre.vn/zoom/504_315/2022/10/24/nova-1-1666595567101786912310-crop-16665957294551455548631.jpeg",
label: "Novaland: Tin đồn và văn bản 'cầu cứu' trên mạng là bịa đặt",
description:
"TTO - Ngày 24-10, Novaland đã chính thức thông tin về các tin đồn những ngày qua liên quan đến các dự án của doanh nghiệp này. Phía Novaland khẳng...",
},
{
img: "https://cdn.tuoitre.vn/zoom/504_315/2022/10/24/nova-1-1666595567101786912310-crop-16665957294551455548631.jpeg",
label: "Novaland: Tin đồn và văn bản 'cầu cứu' trên mạng là bịa đặt",
description:
"TTO - Ngày 24-10, Novaland đã chính thức thông tin về các tin đồn những ngày qua liên quan đến các dự án của doanh nghiệp này. Phía Novaland khẳng...",
},
];
const MainPage = () => { const MainPage = () => {
const { isLoading } = useAppSelector((state) => state.global); const dispatch = useAppDispatch();
const { isLoading } = useAppSelector(globalSelector);
const { newsData } = useAppSelector(homeSelector);
useEffect(() => {
dispatch(handleLoading(true));
try {
const fetchData = async () => {
await dispatch(getNews());
};
fetchData();
} catch (err) {
console.error("ERROR: ", err);
} finally {
dispatch(handleLoading(false));
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return ( return (
<main className="container py-3"> <main className="container py-3">
<Loading isOpen={isLoading} /> <Loading isOpen={isLoading} />
{newspapers.map((newspaper, idx) => ( {newsData.map((newspaper) => (
<Newspaper key={`newspaper-${idx}`} data={newspaper} /> <Newspaper key={newspaper.id} data={newspaper} />
))} ))}
</main> </main>
); );
......
import { createAsyncThunk, createSlice, PayloadAction } from "@reduxjs/toolkit";
import homeApi from "api/homeApi";
import { INewspaper } from "./interface";
const initialState: { newsData: INewspaper[] } = {
newsData: [],
};
export const getNews = createAsyncThunk("home/news", async () => {
const res = await homeApi.getNews();
return res;
});
const home = createSlice({
name: "home",
initialState,
reducers: {},
extraReducers: (builder) => {
builder.addCase(getNews.fulfilled, (state, action: PayloadAction<any>) => {
state.newsData = action.payload.data;
});
},
});
const { reducer } = home;
export default reducer;
// Generated by https://quicktype.io
export interface INewspaper {
id: string;
categoryId: string;
title: string;
description: string;
image: string;
createdAt: string;
}
export interface INewspaper {
img: string;
label: string;
description: string;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment