import { useNavigate, useParams } from 'react-router-dom'; import { ChangeEvent, TargetedEvent } from 'preact/compat'; import { useEffect, useRef, useState } from 'preact/hooks'; import Lightbox from 'yet-another-react-lightbox'; import useCallbackState from '../../types/state-callback'; import { EmptyLocationDetailResponse, LocationDetailResponse, LocationResponse, emptyLocationResponse, CurrentUserLocationReviews, } from './types'; import { AxiosError } from 'axios'; import { handleAxiosError, useAutosizeTextArea } from '../../utils'; import { getCurrentUserLocationReviewService, getImagesByLocationService, getLocationService, postReviewLocation } from "../../services"; import { DefaultSeparator, SeparatorWithAnchor, CustomInterweave, SpinnerLoading } from '../../components'; import { useSelector } from 'react-redux'; import { UserRootState } from '../../store/type'; import { DEFAULT_AVATAR_IMG } from '../../constants/default'; import './index.css'; import { IHttpResponse } from '../../types/common'; import ReactTextareaAutosize from 'react-textarea-autosize'; const SORT_TYPE = [ 'highest rated', 'lowest rated', 'newest', 'oldest' ] function LocationDetail() { const [locationDetail, setLocationDetail] = useCallbackState(EmptyLocationDetailResponse) const [locationImages, setLocationImages] = useState(emptyLocationResponse()) const [currentUserReview, setCurrentUserReview] = useState() const [lightboxOpen, setLightboxOpen] = useState(false) const[updatePage, setUpdatePage] = useState(true) const [pageState, setPageState] = useState({ critic_filter_name: 'highest rated', critic_filter_type: 0, show_sort: false, enable_post: true, on_submit_loading: false, is_score_rating_panic_msg: '', }) const [reviewValue, setReviewValue] = useState({ review_textArea: '', score_input: '', }) const [isLoading, setIsLoading] = useState(true) const navigate = useNavigate(); const user = useSelector((state: UserRootState) => state.auth) const textAreaRef = useRef(null); useAutosizeTextArea(textAreaRef.current, reviewValue.review_textArea); const { id } = useParams() async function getLocationDetail(): Promise { try { const res = await getLocationService(Number(id)) setLocationDetail(res.data, (val) => { getImage(val.detail.thumbnail.String.toString()) }) } catch (error) { let err = error as AxiosError; if (err.response?.status == 404) { navigate("/") } alert(error) } } async function getImage(thumbnail?: String): Promise { try { const res = await getImagesByLocationService({ page: 1, page_size: 15, location_id: Number(id) }) res.data.images.push({ src: thumbnail }) setLocationImages(res.data) setUpdatePage(false) } catch (error) { console.log(error) } setIsLoading(false) } async function getCurrentUserLocationReview(): Promise { try { const res = await getCurrentUserLocationReviewService(Number(id)) setCurrentUserReview(res.data) setPageState({ ...pageState, enable_post: false}) } catch (error) { let err = error as IHttpResponse; if(err.status == 404 || err.status == 401 ) { return } alert(err.error.response.data.message) } } function handleTextAreaChange(e: ChangeEvent): void { const val = e.target as HTMLTextAreaElement; setReviewValue({ ...reviewValue, review_textArea: val.value }) } function handleScoreInputChange(e: ChangeEvent): void { const val = e.target as HTMLInputElement; setReviewValue({ ...reviewValue, score_input: val.value }) setPageState({ ...pageState, is_score_rating_panic_msg: '' }) } function onChangeCriticsSort(e: TargetedEvent, sort_name: string, sort_type: number): void { e.preventDefault() setPageState({ ...pageState, show_sort: false, critic_filter_name: sort_name, critic_filter_type: sort_type }) } async function handleSubmitReview(e: TargetedEvent) { e.preventDefault(); setPageState({ ...pageState, on_submit_loading: true }) if (isNaN(Number(reviewValue.score_input))) { setPageState({ ...pageState, is_score_rating_panic_msg: "SCORE MUST BE A NUMBER" }) return } if (Number(reviewValue.score_input) > 100) { setPageState({ ...pageState, is_score_rating_panic_msg: "SCORE MUST BE LESS OR EQUAL THAN 100" }) return } if (reviewValue.score_input === '') { setPageState({ ...pageState, is_score_rating_panic_msg: "SCORE MUSTN'T BE EMPTY" }) return } try { const { data } = await postReviewLocation({ is_hided: false, location_id: Number(id), score: Number(reviewValue.score_input), submitted_by: Number(user.id), is_from_critic: user.is_critics, comments: reviewValue.review_textArea, }) setPageState({ ...pageState, enable_post: false, on_submit_loading: false }) setReviewValue({ review_textArea: '', score_input: '' }) setCurrentUserReview({ id: data.id, comments: data.comments, is_from_critic: data.is_from_critic, is_hided: data.is_hided, location_id: data.location_id, score: data.score, submitted_by: data.submitted_by, created_at: data.created_at, updated_at: data.updated_at }) setUpdatePage(true) } catch (error) { let err = error as AxiosError; console.log(err) const str = handleAxiosError(err) alert(str) setPageState({ ...pageState, on_submit_loading: false }) } } function handleSignInNavigation(e: TargetedEvent) { e.preventDefault(); navigate('/login', { state: { from: `/location/${id}` } }) } useEffect(() => { getCurrentUserLocationReview() }, []) useEffect(() => { if(updatePage) { getLocationDetail() } }, [updatePage]) return ( <>

{locationDetail?.detail.name}

{isLoading ?
: }
CRITICS SCORE
{locationDetail.detail.critic_count !== 0 ? Math.floor(Number(locationDetail.detail.critic_score) / Number(locationDetail.detail.critic_count)) : "NR"}
{locationDetail.detail.critic_count !== 0 &&
Based on {locationDetail.detail.critic_count} reviews
}
USERS SCORE
{locationDetail.detail.user_count !== 0 ? Math.floor(Number(locationDetail.detail.user_score) / Number(locationDetail.detail.user_count)) : "NR"}
{locationDetail.detail.user_count !== 0 &&
Based on {locationDetail.detail.user_count} reviews
}
address: {locationDetail.detail.address} {locationDetail.detail.regency_name}
average cost: IDR 25.0000
Tags:
{locationDetail.tags.map(x => (
{x}
)) }
{!user.username ?
SIGN IN TO REVIEW
:
{currentUserReview ?

{currentUserReview.score}

: <>
/ score
{pageState.is_score_rating_panic_msg &&
{pageState.is_score_rating_panic_msg}
} }
{currentUserReview ? : }
{pageState.on_submit_loading ? : POST }
}
{locationDetail.critics_review.length > 0 ? <>
{locationDetail.critics_review.map(x => (
))} : <> No Critics review to display }
0 ? '#' : ''} /> { locationDetail.users_review.length > 0 ? <> {locationDetail.users_review.map(x => (
))} : <> No users review to display }
{/*
80

Lorem ipsum dolor sit amet consectetur adipisicing elit. Porro nihil dolor delectus ex minima aliquid quidem veniam officiis temporibus ipsum ea incidunt voluptatum a, repellat illum, cumque consequatur saepe assumenda.

80

Lorem ipsum dolor sit amet consectetur adipisicing elit. Porro nihil dolor delectus ex minima aliquid quidem veniam officiis temporibus ipsum ea incidunt voluptatum a, repellat illum, cumque consequatur saepe assumenda.

*/}
CONTRUBITION anoeantoeh aoenthaoe aoenth aot
{/* {screen.width >= 1024 &&
// ADD USER DISTRIBUTION SOMETHING LIKE THIS // https://www.w3schools.com/howto/tryit.asp?filename=tryhow_css_user_rating Lorem ipsum dolor sit amet consectetur adipisicing elit. Reprehenderit cumque aliquam doloribus in reiciendis? Laborum, ea assumenda, tempora dolore placeat aspernatur, cumque totam sequi debitis dolor nam eligendi suscipit aliquid?
} */}
Added on: 28 May 1988
setLightboxOpen(false)} slides={locationImages?.images} />
) } export default LocationDetail;