234 lines
11 KiB
TypeScript
234 lines
11 KiB
TypeScript
import { SeparatorWithAnchor } from '../../components';
|
|
import news from '../../datas/recent_news_event.json';
|
|
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 { getListRecentLocationsRatingsService } from '../../services';
|
|
import { useNavigate } from 'react-router-dom';
|
|
|
|
type NewPlaces = {
|
|
id: Number,
|
|
name: string,
|
|
thumbnail: NullValueRes<'String', string>,
|
|
regency_name: String,
|
|
province_name: String,
|
|
critic_score: Number,
|
|
critic_count: Number,
|
|
user_score: Number,
|
|
user_count: Number
|
|
}
|
|
|
|
type News = {
|
|
header: string,
|
|
thumbnail: string,
|
|
link: string,
|
|
comments_count: Number
|
|
likes_count: Number
|
|
}
|
|
|
|
function Home() {
|
|
const [recentLocations, setRecentLocations] = useState<Array<NewPlaces>>([])
|
|
// const [isLoading, setIsLoading] = useState<boolean>(true)
|
|
|
|
const navigate = useNavigate()
|
|
|
|
|
|
async function getRecentLocations() {
|
|
try {
|
|
const locations = await getListRecentLocationsRatingsService(12)
|
|
setRecentLocations(locations.data)
|
|
// setIsLoading(false)
|
|
} catch(error) {
|
|
console.log(error)
|
|
}
|
|
}
|
|
|
|
function onNavigateToDetail(
|
|
id: Number,
|
|
critic_count: Number,
|
|
critic_score: Number,
|
|
user_count: Number,
|
|
user_score: Number,
|
|
) {
|
|
|
|
navigate(`/location/${id}`, { state: { user_score: user_score, user_count: user_count, critic_score: critic_score, critic_count: critic_count } })
|
|
|
|
}
|
|
|
|
useEffect(() => {
|
|
getRecentLocations()
|
|
},[])
|
|
return (
|
|
<>
|
|
<div className="content main-content mt-3">
|
|
|
|
{/* RECENTLY ADDED SECTION */}
|
|
<section about={"Recently added places"} className={'mt-3'}>
|
|
<SeparatorWithAnchor pageLink='#' pageName='recently added' secondLink='#' />
|
|
{recentLocations.map((x) => (
|
|
<div className={"recently-added-section-card"}>
|
|
<a onClick={() => onNavigateToDetail(x.id, x.critic_count, x.critic_score, x.user_count, x.user_score)}>
|
|
<div className={'border-secondary recently-img-container'}>
|
|
<img alt={x.name} src={x.thumbnail.String.toString()} loading="lazy" style={{ width: '100%', height: '100%' }} />
|
|
</div>
|
|
</a>
|
|
<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.regency_name}, {x.province_name}</p>
|
|
</div>
|
|
{ x.critic_count !== 0 &&
|
|
<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}</p>
|
|
<div style={{ height: 4, width: 30, backgroundColor: "#72767d"}}>
|
|
<div style={{ height: 4, width: `${x.critic_score}%`, backgroundColor: 'green' }} />
|
|
</div>
|
|
</div>
|
|
<p className={"users-score"}>critic score ({x.critic_count})</p>
|
|
</div>
|
|
}
|
|
{ x.user_score !== 0 &&
|
|
<div className={"flex flex-row items-center"}>
|
|
<div className={'mr-3 users-score-bar'}>
|
|
<p className={'text-sm text-center'}>{x.user_score}</p>
|
|
<div style={{ height: 4, width: 30, backgroundColor: "#72767d" }}>
|
|
<div style={{ height: 4, width: ` ${x.user_score}%`, backgroundColor: 'green' }} />
|
|
</div>
|
|
</div>
|
|
<p className={'users-score'}>user score ({x.user_count})</p>
|
|
</div>
|
|
}
|
|
</div>
|
|
))}
|
|
</section>
|
|
{/* END RECENTLY ADDED SECTION */}
|
|
|
|
{/* START RECENT NEWS / EVENT SECTION */}
|
|
{/* USE OPEN GRAPH PARSER TO READ OG DATA FROM HTML */}
|
|
{/* https://github.com/dyatlov/go-opengraph */}
|
|
<section className={"mt-10"}>
|
|
<SeparatorWithAnchor pageLink='#' pageName='Recent News / Event' secondLink='#' />
|
|
<div className={"mt-5"}>
|
|
{news.data.map((x: News) => (
|
|
<div class={"text-sm news-card"}>
|
|
<div className={"image-news-container"}>
|
|
<img src={x.thumbnail} loading={'lazy'} className={"news-img"}/>
|
|
</div>
|
|
<a className={'news-link'} target="_blank" href={x.link}>{x.link.split("/")[2].replace(/www\./, '')}</a>
|
|
<p className={'mt-2 mb-2'}>{x.header}</p>
|
|
<div className={"flex flex-row user-engagement"}>
|
|
<svg xmlns="http://www.w3.org/2000/svg" fill={"gray"} height="18" viewBox="0 -960 960 960" width="18"><path d="m480-120-58-52q-101-91-167-157T150-447.5Q111-500 95.5-544T80-634q0-94 63-157t157-63q52 0 99 22t81 62q34-40 81-62t99-22q94 0 157 63t63 157q0 46-15.5 90T810-447.5Q771-395 705-329T538-172l-58 52Zm0-108q96-86 158-147.5t98-107q36-45.5 50-81t14-70.5q0-60-40-100t-100-40q-47 0-87 26.5T518-680h-76q-15-41-55-67.5T300-774q-60 0-100 40t-40 100q0 35 14 70.5t50 81q36 45.5 98 107T480-228Zm0-273Z" /></svg>
|
|
<p className={"mr-3 ml-1"}>{x.likes_count}</p>
|
|
<svg style={{ marginTop: 2}} stroke="currentColor" fill="white" stroke-width="0" viewBox="0 0 512 512" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M256 32C114.6 32 0 125.1 0 240c0 49.6 21.4 95 57 130.7C44.5 421.1 2.7 466 2.2 466.5c-2.2 2.3-2.8 5.7-1.5 8.7S4.8 480 8 480c66.3 0 116-31.8 140.6-51.4 32.7 12.3 69 19.4 107.4 19.4 141.4 0 256-93.1 256-208S397.4 32 256 32zM128 272c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32zm128 0c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32zm128 0c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32z"></path></svg>
|
|
<p className={"ml-1"}>{x.comments_count}</p>
|
|
</div>
|
|
</div>
|
|
))
|
|
}
|
|
</div>
|
|
</section>
|
|
{/* END RECENT NEWS / EVENT SECTION */}
|
|
|
|
{/* LOCATION CRITICS BEST AND USERS BEST SECTION */}
|
|
|
|
<section className={"mt-10"}>
|
|
<SeparatorWithAnchor pageLink='#' pageName={"Popular user reviews"} secondLink='#' />
|
|
<div>
|
|
{popular_user_review.data.map((x) => (
|
|
<div className={'text-sm reviews-container'}>
|
|
<div style={{ float: 'left', width: 120, margin: '0 12px 10px 0' }}>
|
|
<img src={x.thumbnail} loading={'lazy'} style={{ width: '100%' }} />
|
|
</div>
|
|
<p className={"text-sm location-titles"}>{x.place_name}</p>
|
|
<p className={'text-xs mb-2'}>{x.location}</p>
|
|
<p className={'text-sm'}>{x.username}</p>
|
|
<div style={{ display: 'inline-block', overflow: 'hidden', verticalAlign: 'middle' }}>
|
|
<p className={'text-xs ml-2 mt-1'}>{x.rating}</p>
|
|
<div style={{ height: 4, width: 30, backgroundColor: "#72767d" }}>
|
|
<div style={{ height: 4, width: `${x.rating}%`, backgroundColor: 'green' }} />
|
|
</div>
|
|
</div>
|
|
<div style={{ clear: 'both'}} className={'mb-3'}/>
|
|
<div className={'text-sm'}>
|
|
{x.message}
|
|
<a className={'text-tertiary ml-2'} style={{ cursor: 'pointer'}}>read more</a>
|
|
</div>
|
|
</div>
|
|
))
|
|
|
|
}
|
|
</div>
|
|
</section>
|
|
|
|
|
|
{/* START LOCATION CRITICS BEST AND USERS BEST SECTION */}
|
|
<section className={"mt-10 mb-10"}>
|
|
<div class={"grid grid-cols-4 lg:gap-12"}>
|
|
<div className={'col-span-4 lg:col-span-2 trending-section'}>
|
|
<SeparatorWithAnchor pageLink='#' pageName={"Trending Now"} secondLink='#' />
|
|
<div className={'grid grid-cols-4 md:grid-cols-3'}>
|
|
{popular.data.map((x) => (
|
|
<div className={"m-2 text-sm col-span-2 md:col-span-1"}>
|
|
<div className={"mb-2 trending-image-container"}>
|
|
<img src={x.thumbnail} loading={"lazy"} style={{ width: '100%', height: '100%' }} />
|
|
</div >
|
|
<p className={"location-title"}>{x.name}</p>
|
|
<p className={"text-xs location-title"}>{x.location}</p>
|
|
<div>
|
|
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
<div className={'col-span-2 lg:col-span-1'}>
|
|
<SeparatorWithAnchor pageLink='#' pageName={"Critic's Best"} />
|
|
{critics_users_pick.critics.map((x) => (
|
|
<div className={"pt-2 text-sm"}>
|
|
<div className={'mr-2 critics-users-image'}>
|
|
<img src={x.thumbnail} loading={'lazy'} style={{ height: '100%', width: '100%', borderRadius: 3}} />
|
|
</div>
|
|
<p className={'location-title'}>{x.name}</p>
|
|
<p className={'text-xs location-province location-title'}>{x.location}</p>
|
|
<div className={'critics-users-rating-container'} style={{ display: 'inline-block' }}>
|
|
<p className={'text-xs ml-2'}>{x.critic_rating}</p>
|
|
<div style={{ height: 4, width: 30, backgroundColor: "#72767d" }}>
|
|
<div style={{ height: 4, width: `${x.critic_rating}%`, backgroundColor: 'green' }} />
|
|
</div>
|
|
</div>
|
|
<div style={{ clear: 'both'}} />
|
|
</div>
|
|
))
|
|
}
|
|
</div>
|
|
<div className={'col-span-2 lg:col-span-1'}>
|
|
<SeparatorWithAnchor pageLink='#' pageName={"User's Best"} />
|
|
{critics_users_pick.users.map((x) => (
|
|
<div className={"pt-2 text-sm"}>
|
|
<div className={'mr-2 critics-users-image'}>
|
|
<img src={x.thumbnail} style={{ height: '100%', width: '100%', borderRadius: 3}} />
|
|
</div>
|
|
<p className={'location-title'}>{x.name}</p>
|
|
<p className={'text-xs location-province location-title'}>{x.location}</p>
|
|
<div className={'critics-users-rating-container'} style={{ display: 'inline-block' }}>
|
|
<p className={'text-xs ml-2'}>{x.user_rating}</p>
|
|
<div style={{ height: 4, width: 30, backgroundColor: "#72767d"}}>
|
|
<div style={{ height: 4, width: `${x.user_rating}%`, backgroundColor: 'green' }} />
|
|
</div>
|
|
</div>
|
|
<div style={{ clear: 'both'}} />
|
|
</div>
|
|
))
|
|
}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
</>
|
|
|
|
)
|
|
}
|
|
|
|
export default Home; |