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": {
"axios": "^1.5.0",
"preact": "^10.16.0"
"preact": "^10.16.0",
"react-router-dom": "^6.16.0"
},
"devDependencies": {
"@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 { Home } from './pages'
import { DefaultLayout } from './layouts'
import routes from './routes'
export function App() {
return (
<>
<Home />
<Router>
<Routes>
<Route element={<DefaultLayout />}>
{routes.map(({ path, name, element}) => (
<>
<Route
path={path}
id={name}
element={element}
/>
</>
))}
</Route>
</Routes>
</Router>
</>
)
}

View File

@ -114,9 +114,4 @@ label:before {
/* display: 'inline-block';
max-width: '100%';
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 { Footer, Header } from "../../components";
import { Outlet } from "react-router-dom";
type ChildrenProps = {
children: ComponentChildren
}
function DefaultLayout({ children }: ChildrenProps) {
function DefaultLayout() {
return (
<>
<Header />
<main style={{ overflow: 'hidden' }}>
{children}
<Outlet />
</main>
<Footer />
</>

View File

@ -1,4 +1,3 @@
import { DefaultLayout } from '../../layouts/';
import { SeparatorWithAnchor } from '../../components';
import data from '../../datas/home.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 popular_user_review from '../../datas/popular_user_reviews.json';
import './style.css';
import { useEffect, useState } from 'preact/hooks';
import { getListLocations, getListRecentLocationsRatings } from '../../services';
type NewPlaces = {
id: Number,
name: string,
thumbnail: string,
location: string,
critic_rating: Number,
critic_voters: Number,
user_rating: Number,
user_voters: Number
thumbnail: NullValueRes<'String', string>,
regency_name: NullValueRes<'String', string>,
critic_score: Number,
critic_count: Number,
user_score: Number,
user_count: Number
}
type News = {
@ -27,40 +28,58 @@ type News = {
}
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 (
<DefaultLayout>
<>
<div className="content main-content mt-3">
{/* RECENTLY ADDED SECTION */}
<section about={"Recently added places"} className={'mt-3'}>
<SeparatorWithAnchor pageLink='#' pageName='recently added' secondLink='#' />
{data.new_places.map((x: NewPlaces) => (
{recentLocations.map((x: NewPlaces) => (
<div className={"recently-added-section-card"}>
<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 className={"border-primary pb-2 location-container text-sm mb-2 mt-2"}>
<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 className={"flex flex-row items-center mb-3"}>
<div className={'mr-3 users-score-bar'}>
<p className={'text-sm text-center'}>{x.critic_rating}</p>
<div style={{ height: 4, width: 30, backgroundColor: "#72767d"}}>
<div style={{ height: 4, width: `${x.critic_rating}%`, backgroundColor: 'green' }} />
{ x.critic_score !== -1 &&
<div className={"flex flex-row items-center mb-3"}>
<div className={'mr-3 users-score-bar'}>
<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: `${x.critic_score === -1 ? 0 : x.critic_score}%`, backgroundColor: 'green' }} />
</div>
</div>
<p className={"users-score"}>critic score ({x.critic_count})</p>
</div>
<p className={"users-score"}>critic score ({x.critic_voters})</p>
</div>
<div className={"flex flex-row items-center"}>
<div className={'mr-3 users-score-bar'}>
<p className={'text-sm text-center'}>{x.user_rating}</p>
<div style={{ height: 4, width: 30, backgroundColor: "#72767d" }}>
<div style={{ height: 4, width: ` ${x.user_rating}%`, backgroundColor: 'green' }} />
}
{ x.user_score !== -1 &&
<div className={"flex flex-row items-center"}>
<div className={'mr-3 users-score-bar'}>
<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: ` ${x.user_score === -1 ? 0 : x.user_score}%`, backgroundColor: 'green' }} />
</div>
</div>
<p className={'users-score'}>user score ({x.user_count})</p>
</div>
<p className={'users-score'}>user score ({x.user_voters})</p>
</div>
}
</div>
))}
</section>
@ -187,7 +206,7 @@ function Home() {
</div>
</section>
</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"
"@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":
version "4.2.1"
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"
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:
version "1.0.0"
resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774"