Integrate with get recent locations ratings in home page

This commit is contained in:
NCanggoro 2023-09-14 22:49:29 +07:00
parent f01bf17fcf
commit 1ecefbf60a
13 changed files with 210 additions and 42 deletions

View File

@ -10,7 +10,8 @@
}, },
"dependencies": { "dependencies": {
"axios": "^1.5.0", "axios": "^1.5.0",
"preact": "^10.16.0" "preact": "^10.16.0",
"react-router-dom": "^6.16.0"
}, },
"devDependencies": { "devDependencies": {
"@preact/preset-vite": "^2.5.0", "@preact/preset-vite": "^2.5.0",

View File

@ -1,11 +1,26 @@
import { Route, Routes } from 'react-router-dom'
import { BrowserRouter as Router } from 'react-router-dom'
import './app.css' import './app.css'
import { Home } from './pages' import { DefaultLayout } from './layouts'
import routes from './routes'
export function App() { export function App() {
return ( return (
<> <>
<Home /> <Router>
<Routes>
<Route element={<DefaultLayout />}>
{routes.map(({ path, name, element}) => (
<>
<Route
path={path}
id={name}
element={element}
/>
</>
))}
</Route>
</Routes>
</Router>
</> </>
) )
} }

View File

@ -115,8 +115,3 @@ label:before {
max-width: '100%'; max-width: '100%';
text-align: 'center'; */ text-align: 'center'; */
} }
.navLink:hover{
border-bottom-width: 2px;
margin-bottom: -2px;
}

16
src/constants/api.ts Normal file
View File

@ -0,0 +1,16 @@
const BASE_URL = "http://localhost:8888"
const SIGNUP_URI = `${BASE_URL}/user/signup`
const GET_LIST_LOCATIONS_URI = `${BASE_URL}/locations`;
const GET_LIST_RECENT_LOCATIONS_RATING_URI = `${BASE_URL}/recent-locations/ratings`
const GET_LOCATION_URI = `${BASE_URL}/location`;
export {
BASE_URL,
GET_LIST_RECENT_LOCATIONS_RATING_URI,
GET_LIST_LOCATIONS_URI,
GET_LOCATION_URI,
SIGNUP_URI
}

View File

@ -1,16 +1,13 @@
import { ComponentChildren } from "preact"; import { ComponentChildren } from "preact";
import { Footer, Header } from "../../components"; import { Footer, Header } from "../../components";
import { Outlet } from "react-router-dom";
type ChildrenProps = { function DefaultLayout() {
children: ComponentChildren
}
function DefaultLayout({ children }: ChildrenProps) {
return ( return (
<> <>
<Header /> <Header />
<main style={{ overflow: 'hidden' }}> <main style={{ overflow: 'hidden' }}>
{children} <Outlet />
</main> </main>
<Footer /> <Footer />
</> </>

View File

@ -1,4 +1,3 @@
import { DefaultLayout } from '../../layouts/';
import { SeparatorWithAnchor } from '../../components'; import { SeparatorWithAnchor } from '../../components';
import data from '../../datas/home.json'; import data from '../../datas/home.json';
import news from '../../datas/recent_news_event.json'; import news from '../../datas/recent_news_event.json';
@ -6,16 +5,18 @@ import popular from '../../datas/popular.json';
import critics_users_pick from '../../datas/critics_users_best_pick.json'; import critics_users_pick from '../../datas/critics_users_best_pick.json';
import popular_user_review from '../../datas/popular_user_reviews.json'; import popular_user_review from '../../datas/popular_user_reviews.json';
import './style.css'; import './style.css';
import { useEffect, useState } from 'preact/hooks';
import { getListLocations, getListRecentLocationsRatings } from '../../services';
type NewPlaces = { type NewPlaces = {
id: Number, id: Number,
name: string, name: string,
thumbnail: string, thumbnail: NullValueRes<'String', string>,
location: string, regency_name: NullValueRes<'String', string>,
critic_rating: Number, critic_score: Number,
critic_voters: Number, critic_count: Number,
user_rating: Number, user_score: Number,
user_voters: Number user_count: Number
} }
type News = { type News = {
@ -27,40 +28,58 @@ type News = {
} }
function Home() { function Home() {
const [recentLocations, setRecentLocations] = useState([])
async function getRecentLocations() {
try {
const locations = await getListRecentLocationsRatings(12)
setRecentLocations(locations.data)
} catch(error) {
console.log(error)
}
}
useEffect(() => {
getRecentLocations()
},[])
return ( return (
<DefaultLayout> <>
<div className="content main-content mt-3"> <div className="content main-content mt-3">
{/* RECENTLY ADDED SECTION */} {/* RECENTLY ADDED SECTION */}
<section about={"Recently added places"} className={'mt-3'}> <section about={"Recently added places"} className={'mt-3'}>
<SeparatorWithAnchor pageLink='#' pageName='recently added' secondLink='#' /> <SeparatorWithAnchor pageLink='#' pageName='recently added' secondLink='#' />
{data.new_places.map((x: NewPlaces) => ( {recentLocations.map((x: NewPlaces) => (
<div className={"recently-added-section-card"}> <div className={"recently-added-section-card"}>
<div className={'border-secondary recently-img-container'}> <div className={'border-secondary recently-img-container'}>
<img alt={x.name} src={x.thumbnail} loading="eager" style={{ width: '100%', height: '100%' }} /> <img alt={x.name} src={x.thumbnail.String.toString()} loading="eager" style={{ width: '100%', height: '100%' }} />
</div> </div>
<div className={"border-primary pb-2 location-container text-sm mb-2 mt-2"}> <div className={"border-primary pb-2 location-container text-sm mb-2 mt-2"}>
<p className={'location-title'}>{x.name}</p> <p className={'location-title'}>{x.name}</p>
<p className={'text-xs mt-1'}>{x.location}</p> <p className={'text-xs mt-1'}>{x.regency_name.String}</p>
</div> </div>
{ x.critic_score !== -1 &&
<div className={"flex flex-row items-center mb-3"}> <div className={"flex flex-row items-center mb-3"}>
<div className={'mr-3 users-score-bar'}> <div className={'mr-3 users-score-bar'}>
<p className={'text-sm text-center'}>{x.critic_rating}</p> <p className={'text-sm text-center'}>{x.critic_score === -1 ? "NR" : x.critic_score}</p>
<div style={{ height: 4, width: 30, backgroundColor: "#72767d"}}> <div style={{ height: 4, width: 30, backgroundColor: "#72767d"}}>
<div style={{ height: 4, width: `${x.critic_rating}%`, backgroundColor: 'green' }} /> <div style={{ height: 4, width: `${x.critic_score === -1 ? 0 : x.critic_score}%`, backgroundColor: 'green' }} />
</div> </div>
</div> </div>
<p className={"users-score"}>critic score ({x.critic_voters})</p> <p className={"users-score"}>critic score ({x.critic_count})</p>
</div> </div>
}
{ x.user_score !== -1 &&
<div className={"flex flex-row items-center"}> <div className={"flex flex-row items-center"}>
<div className={'mr-3 users-score-bar'}> <div className={'mr-3 users-score-bar'}>
<p className={'text-sm text-center'}>{x.user_rating}</p> <p className={'text-sm text-center'}>{x.user_score === -1 ? "NR" : x.user_score}</p>
<div style={{ height: 4, width: 30, backgroundColor: "#72767d" }}> <div style={{ height: 4, width: 30, backgroundColor: "#72767d" }}>
<div style={{ height: 4, width: ` ${x.user_rating}%`, backgroundColor: 'green' }} /> <div style={{ height: 4, width: ` ${x.user_score === -1 ? 0 : x.user_score}%`, backgroundColor: 'green' }} />
</div> </div>
</div> </div>
<p className={'users-score'}>user score ({x.user_voters})</p> <p className={'users-score'}>user score ({x.user_count})</p>
</div> </div>
}
</div> </div>
))} ))}
</section> </section>
@ -187,7 +206,7 @@ function Home() {
</div> </div>
</section> </section>
</div> </div>
</DefaultLayout> </>
) )
} }

13
src/routes/index.tsx Normal file
View File

@ -0,0 +1,13 @@
import {
Home
} from '../pages';
const routes = [
{
path: "/",
name: "Home",
element: <Home />
}
]
export default routes;

19
src/services/config.ts Normal file
View File

@ -0,0 +1,19 @@
import axios, { AxiosPromise, AxiosRequestConfig } from "axios";
import {BASE_URL} from '../constants/api'
export const client = (props: AxiosRequestConfig): AxiosPromise => axios({
method: props.method,
baseURL: `${BASE_URL}`,
url: props.url,
headers: props.headers,
data: props.data
})
// export const authClient = (props: AxiosRequestConfig) => axios({
// method: props.method,
// baseURL: `${BASE_URL}`,
// url: props.url,
// headers: {
// 'Authorization':
// }
// })

6
src/services/index.ts Normal file
View File

@ -0,0 +1,6 @@
import { getListLocations, getListRecentLocationsRatings } from "./locations";
export {
getListLocations,
getListRecentLocationsRatings
}

54
src/services/locations.ts Normal file
View File

@ -0,0 +1,54 @@
import { GET_LIST_LOCATIONS_URI, GET_LIST_RECENT_LOCATIONS_RATING_URI } from "../constants/api";
import { client } from "./config";
import statusCode from "./status-code";
const initialState: any = {
data: null,
error: null
}
type getListLocationsArg = {
page: number,
page_size: number
}
async function getListLocations ({ page, page_size}: getListLocationsArg) {
const newState = {...initialState};
const url = `${GET_LIST_LOCATIONS_URI}?page=${page}&page_size=${page_size}`
try {
const response = await client({method: 'GET', url: url})
switch (response.request.status) {
case statusCode.OK:
newState.data = response.data;
return newState;
default:
newState.error = response.data;
return newState
}
} catch (error) {
console.log(error)
}
}
async function getListRecentLocationsRatings (page_size: Number) {
const newState = {...initialState};
const url = `${GET_LIST_RECENT_LOCATIONS_RATING_URI}?page_size=${page_size}`
try {
const response = await client({method: 'GET', url: url})
switch (response.request.status) {
case statusCode.OK:
newState.data = response.data;
return newState;
default:
newState.error = response.data;
return newState
}
} catch (error) {
console.log(error)
}
}
export {
getListLocations,
getListRecentLocationsRatings
}

View File

@ -0,0 +1,10 @@
export default {
OK: 200,
CREATED: 201,
ACCEPTED: 202,
BAD_REQUEST: 400,
UNAUTHORIZED: 401,
NOT_ALLOWED: 405,
NOT_FOUND: 404,
SERVER_ERROR: 500,
};

3
src/types/common.ts Normal file
View File

@ -0,0 +1,3 @@
type BaseNullValueRes = { valid: boolean };
type NullValueRes<Key extends string, Type> = BaseNullValueRes & Record<Key, string | number>

View File

@ -434,6 +434,11 @@
"@prefresh/utils" "^1.2.0" "@prefresh/utils" "^1.2.0"
"@rollup/pluginutils" "^4.2.1" "@rollup/pluginutils" "^4.2.1"
"@remix-run/router@1.9.0":
version "1.9.0"
resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.9.0.tgz#9033238b41c4cbe1e961eccb3f79e2c588328cf6"
integrity sha512-bV63itrKBC0zdT27qYm6SDZHlkXwFL1xMBuhkn+X7l0+IIhNaH5wuuvZKp6eKhCD4KFhujhfhCT1YxXW6esUIA==
"@rollup/pluginutils@^4.1.1", "@rollup/pluginutils@^4.2.1": "@rollup/pluginutils@^4.1.1", "@rollup/pluginutils@^4.2.1":
version "4.2.1" version "4.2.1"
resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.2.1.tgz#e6c6c3aba0744edce3fb2074922d3776c0af2a6d" resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.2.1.tgz#e6c6c3aba0744edce3fb2074922d3776c0af2a6d"
@ -1050,6 +1055,21 @@ queue-microtask@^1.2.2:
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
react-router-dom@^6.16.0:
version "6.16.0"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.16.0.tgz#86f24658da35eb66727e75ecbb1a029e33ee39d9"
integrity sha512-aTfBLv3mk/gaKLxgRDUPbPw+s4Y/O+ma3rEN1u8EgEpLpPe6gNjIsWt9rxushMHHMb7mSwxRGdGlGdvmFsyPIg==
dependencies:
"@remix-run/router" "1.9.0"
react-router "6.16.0"
react-router@6.16.0:
version "6.16.0"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.16.0.tgz#abbf3d5bdc9c108c9b822a18be10ee004096fb81"
integrity sha512-VT4Mmc4jj5YyjpOi5jOf0I+TYzGpvzERy4ckNSvSh2RArv8LLoCxlsZ2D+tc7zgjxcY34oTz2hZaeX5RVprKqA==
dependencies:
"@remix-run/router" "1.9.0"
read-cache@^1.0.0: read-cache@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774" resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774"