diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/TODO b/TODO old mode 100644 new mode 100755 diff --git a/index.html b/index.html old mode 100644 new mode 100755 diff --git a/package.json b/package.json old mode 100644 new mode 100755 index 50fa9cd..37a79e7 --- a/package.json +++ b/package.json @@ -9,8 +9,8 @@ "preview": "vite preview" }, "dependencies": { + "@floating-ui/react": "^0.26.9", "@reduxjs/toolkit": "^1.9.5", - "@types/react-redux": "^7.1.26", "axios": "^1.5.0", "emojibase": "^15.0.0", "interweave": "^13.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml old mode 100644 new mode 100755 index a844d9d..f92a05f --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,12 +5,12 @@ settings: excludeLinksFromLockfile: false dependencies: + '@floating-ui/react': + specifier: ^0.26.9 + version: 0.26.9(react-dom@18.2.0)(react@18.2.0) '@reduxjs/toolkit': specifier: ^1.9.5 version: 1.9.7(react-redux@8.1.3)(react@18.2.0) - '@types/react-redux': - specifier: ^7.1.26 - version: 7.1.33 axios: specifier: ^1.5.0 version: 1.6.7 @@ -623,6 +623,37 @@ packages: '@floating-ui/utils': 0.2.1 dev: false + /@floating-ui/dom@1.6.3: + resolution: {integrity: sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==} + dependencies: + '@floating-ui/core': 1.6.0 + '@floating-ui/utils': 0.2.1 + dev: false + + /@floating-ui/react-dom@2.0.8(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-HOdqOt3R3OGeTKidaLvJKcgg75S6tibQ3Tif4eyd91QnIJWr0NLvoXFpJA/j8HqkFSL68GDca9AuyWEHlhyClw==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + dependencies: + '@floating-ui/dom': 1.6.3 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@floating-ui/react@0.26.9(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-p86wynZJVEkEq2BBjY/8p2g3biQ6TlgT4o/3KgFKyTWoJLU1GZ8wpctwRqtkEl2tseYA+kw7dBAIDFcednfI5w==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + dependencies: + '@floating-ui/react-dom': 2.0.8(react-dom@18.2.0)(react@18.2.0) + '@floating-ui/utils': 0.2.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + tabbable: 6.2.0 + dev: false + /@floating-ui/utils@0.2.1: resolution: {integrity: sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==} dev: false @@ -800,15 +831,6 @@ packages: resolution: {integrity: sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==} dev: false - /@types/react-redux@7.1.33: - resolution: {integrity: sha512-NF8m5AjWCkert+fosDsN3hAlHzpjSiXlVy9EgQEmLoBhaNXbmyeGs/aj5dQzKuF+/q+S7JQagorGDW8pJ28Hmg==} - dependencies: - '@types/hoist-non-react-statics': 3.3.5 - '@types/react': 18.2.48 - hoist-non-react-statics: 3.3.2 - redux: 4.2.1 - dev: false - /@types/react-transition-group@4.4.10: resolution: {integrity: sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==} dependencies: @@ -2065,6 +2087,10 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + /tabbable@6.2.0: + resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} + dev: false + /tailwindcss@3.4.1: resolution: {integrity: sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==} engines: {node: '>=14.0.0'} diff --git a/postcss.config.js b/postcss.config.js old mode 100644 new mode 100755 diff --git a/public/vite.svg b/public/vite.svg old mode 100644 new mode 100755 diff --git a/src/actions/LogoutAction.ts b/src/actions/LogoutAction.ts old mode 100644 new mode 100755 diff --git a/src/actions/index.ts b/src/actions/index.ts old mode 100644 new mode 100755 diff --git a/src/app.css b/src/app.css old mode 100644 new mode 100755 index 9020a53..81f0dd6 --- a/src/app.css +++ b/src/app.css @@ -60,6 +60,10 @@ line-height: 1.25rem; } +.input-checkbox:hover { + cursor: pointer; +} + @media screen and(max-width: 425px) { .users-score { font-size: .75rem; diff --git a/src/app.tsx b/src/app.tsx old mode 100644 new mode 100755 index 9299c18..c05cba2 --- a/src/app.tsx +++ b/src/app.tsx @@ -14,64 +14,54 @@ import { getRoutes } from './routes'; export function App() { const { routes } = getRoutes(); return ( - <> - - - - - } /> - }> - {routes.map(({ path, name, element, protectedRoute }) => { - let Element = element as any - if (protectedRoute === "user") { - return ( - <> - - - - } - /> - - ) - } - - if (protectedRoute === "admin") { - return ( - <> - <> - - - - } - /> - - - ) - } + + + + + } /> + }> + {routes.map(({ path, name, element, protectedRoute }) => { + let Element = element as any + if (protectedRoute === "user") { return ( - <> - - + + + + } + /> ) - })} - } /> - - - - - - + } + + if (protectedRoute === "admin") { + return ( + + + + } + /> + ) + } + return ( + + ) + })} + } /> + + + + + ) } diff --git a/src/assets/preact.svg b/src/assets/preact.svg old mode 100644 new mode 100755 diff --git a/src/components/Button/DefaultButton/index.tsx b/src/components/Button/DefaultButton/index.tsx old mode 100644 new mode 100755 diff --git a/src/components/Button/DefaultButton/style.css b/src/components/Button/DefaultButton/style.css old mode 100644 new mode 100755 diff --git a/src/components/Button/FilterButton/index.tsx b/src/components/Button/FilterButton/index.tsx new file mode 100755 index 0000000..db850c6 --- /dev/null +++ b/src/components/Button/FilterButton/index.tsx @@ -0,0 +1,14 @@ +import "./style.css"; + +interface ComponentProps { + label: string + onClick: () => void; +} + +const FilterButton = (props: ComponentProps) => ( + +) + +export default FilterButton; \ No newline at end of file diff --git a/src/components/Button/FilterButton/style.css b/src/components/Button/FilterButton/style.css new file mode 100755 index 0000000..a336aed --- /dev/null +++ b/src/components/Button/FilterButton/style.css @@ -0,0 +1,20 @@ +.button-label { + text-align: center; + /* color: #85CE73; */ +} + +.button-container { + align-self: stretch; + padding-left: 12px; + padding-right: 12px; + padding-top: 10px; + padding-bottom: 10px; + border-radius: 6px; + border: 1px #58874d solid; + color: #85CE73; +} + +.button-container:hover { + background-color: #58874d; + color: #FFF; +} \ No newline at end of file diff --git a/src/components/Button/WarningButton/index.tsx b/src/components/Button/WarningButton/index.tsx old mode 100644 new mode 100755 diff --git a/src/components/Button/WarningButton/style.css b/src/components/Button/WarningButton/style.css old mode 100644 new mode 100755 diff --git a/src/components/Card/LocationCard/index.tsx b/src/components/Card/LocationCard/index.tsx new file mode 100755 index 0000000..f287e36 --- /dev/null +++ b/src/components/Card/LocationCard/index.tsx @@ -0,0 +1,47 @@ +import { JSXInternal } from "node_modules/preact/src/jsx"; +import { LocationInfo } from "../../../domains"; + +interface ComponentProps { + onCardClick: (id: Number) => void, + data: LocationInfo, + containerClass?: string, + containerStyle?: JSXInternal.CSSProperties +} + +const LocationCard = (props: ComponentProps) => ( +
+ props.onCardClick(props.data.id)}> +
+ {props.data.name} +
+
+
+

{props.data.name}

+

{props.data.regency_name}, {props.data.province_name}

+
+ {props.data.critic_count !== 0 && +
+
+

{props.data.critic_score}

+
+
+
+
+

critic score ({props.data.critic_count})

+
+ } + {props.data.user_score !== 0 && +
+
+

{props.data.user_score}

+
+
+
+
+

user score ({props.data.user_count})

+
+ } +
+) + +export default LocationCard; \ No newline at end of file diff --git a/src/components/CustomInterweave/index.tsx b/src/components/CustomInterweave/index.tsx old mode 100644 new mode 100755 diff --git a/src/components/DropdownInput/index.tsx b/src/components/DropdownInput/index.tsx old mode 100644 new mode 100755 diff --git a/src/components/DropdownInput/style.css b/src/components/DropdownInput/style.css old mode 100644 new mode 100755 diff --git a/src/components/Footer/index.tsx b/src/components/Footer/index.tsx old mode 100644 new mode 100755 diff --git a/src/components/Footer/style.css b/src/components/Footer/style.css old mode 100644 new mode 100755 diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx old mode 100644 new mode 100755 index 85112ab..8cf918e --- a/src/components/Header/index.tsx +++ b/src/components/Header/index.tsx @@ -8,6 +8,7 @@ import './style.css'; import { logoutService } from "../../services"; import { getSearchLocationService } from "../../services/locations"; import { useNavigate } from "react-router-dom"; +import { ReactSelectData } from "src/types/common"; function Header() { @@ -40,7 +41,8 @@ function Header() { e.preventDefault(); } - const onSelectedSearchOption = (val: any) => { + const onSelectedSearchOption = (v: ReactSelectData | unknown) => { + const val = v as ReactSelectData navigate(`/location/${val.value}`) } @@ -88,19 +90,19 @@ function Header() { /> {user.username && -
-
Profile
-
Feed
-
Add location
-
Settings
-
Logout
- {/*
Halo
*/} - {/*
Halo
*/} -
- } -
-
- +
Profile
+
Feed
+
Add location
+
Settings
+
Logout
+ {/*
Halo
*/} + {/*
Halo
*/} +
+ } + + + ({ + option: (base, { isFocused }) => ({ ...base, backgroundColor: isFocused ? '#202225' : 'none', }), @@ -149,7 +151,7 @@ function Header() { // color: "white" // }) }} - onChange={onSelectedSearchOption} + onChange={(v: ReactSelectData | unknown, _) => onSelectedSearchOption(v)} /> + + + + ) + + return null +} + + function Discovery() { - return( - <> -

Discovery

- + + interface DiscoveryState { + filterQ: string, + regencies: any[], + searchRegencies: any[], + locations: LocationInfo[], + locationType: Array<{value: string, isSelected?: boolean}> + } + + const [data, setData] = useState({ + filterQ: '', + regencies: [], + searchRegencies: [], + locations: [], + locationType: [] + }); + const [isFloatFilterOpen, setFloatFilterOpen] = useState(false) + + useEffect(() => { + getLocationType() + getRecentLocations() + getRegion() + }, []) + + async function getRegion() { + try { + const res = await getRegenciesService(); + setData((prevState) => ({ ...prevState, regencies: res.data, searchRegencies: res.data })) + } catch (err) { + alert(err) + } + } + + async function getRecentLocations() { + try { + const locations = await getListRecentLocationsRatingsService(20) + setData((prevState) => ({ ...prevState, locations: locations.data })) + } catch (error) { + console.log(error) + } + } + + function onCheckedRegencyFilter(_val: any, id: number) { + // const value = val as HTMLInputElement; + const dataRegencies = data.searchRegencies as (Regency & { isSelected?: boolean })[]; + const regencyIdx = dataRegencies.findIndex(x => x.id == id); + dataRegencies[regencyIdx].isSelected = !dataRegencies[regencyIdx].isSelected + setData({ + ...data, + regencies: dataRegencies, + searchRegencies: dataRegencies + }) + } + + function onClearFilter() { + const dataRegencies = data.searchRegencies as (Regency & { isSelected?: boolean })[]; + const regencies = dataRegencies.map(x => ({ ...x, isSelected: false })) + + setData({ + ...data, + regencies: regencies, + searchRegencies: regencies + }) + } + + + function onInputChange(search: string) { + const dataRegencies = data.regencies as (Regency & { isSelected?: boolean })[]; + // console.log(dataRegencies.filter(x => x.regency_name.toLowerCase().includes(search))) + setData({ + ...data, + searchRegencies: dataRegencies.filter(x => x.regency_name.toLowerCase().includes(search)) + }) + } + + + function onClickedTypeLocations(idx: number) { + const locType = data.locationType + locType[idx].isSelected = !locType[idx].isSelected + setData({ + ...data, + locationType: locType + }) + } + + function onApplyFilter() { + const dataRegencies = data.regencies as (Regency & { isSelected?: boolean})[]; + const selectedRegencies = dataRegencies.filter(x => x.isSelected) + const selectedLocType = data.locationType.filter(x => x.isSelected) + let regenciesQ = ""; + let locTypeQ = "" + + if(selectedRegencies.length > 0) { + regenciesQ = selectedRegencies.map(x => x.id).join(" OR ").replace(/\s+/g, '%20') + + } + if(selectedLocType.length > 0) { + const onJoin = selectedRegencies.length > 0 ? " AND " : " OR " + locTypeQ = selectedLocType.map(x => x.value).join(onJoin).replace(/\s+/g, '%20') + + if(selectedRegencies.length > 0) locTypeQ = `%20AND%20${locTypeQ}` + } + + const searchQ = `${regenciesQ}${locTypeQ}` + + + + + } + + function getLocationType() { + const type: Array<{value: string, isSelected?: boolean}> = [] + for (const lt of enumKeys(LocationType)) { + type.push({value: LocationType[lt]}); + } + + setData((prevState) => ({ ...prevState, locationType: type })) + + } + + return ( +
+
+

Discovery

+ +
+
+
+ {/* FILTER */} +
+
+
+
Filter
+
+
+
Kota / Kabupaten
+
+ {data.regencies.filter(x => x.isSelected).map(x => ( +
+
{x.regency_name}
+
+ ))} +
+
+ + setFloatFilterOpen(false)} + onClearFilter={onClearFilter} + onChecked={onCheckedRegencyFilter} + onInputChange={onInputChange} + /> +
+
+
+
+
Tipe
+
+ {data.locationType.map((x, i) => ( + onClickedTypeLocations(i)} + value={x.value} + isSelected={x.isSelected} + /> + ))} +
+
+
+ +
+
+ {/* FILTER END */} +
+ {data.locations.map(x => ( + console.log(id)} + data={x} + /> + ))} +
+
+
+
) } diff --git a/src/pages/Discovery/style.css b/src/pages/Discovery/style.css new file mode 100755 index 0000000..9b50515 --- /dev/null +++ b/src/pages/Discovery/style.css @@ -0,0 +1,112 @@ +.float-filter-scroll::-webkit-scrollbar-track { + background: #e0e0e0; +} + +/* Customizing the scrollbar handle */ +.float-filter-scroll::-webkit-scrollbar-thumb { + background: #888; +} + +.float-filter-scroll::-webkit-scrollbar-thumb:hover { + background: #555; +} + +/* Customizing the scrollbar width */ +.float-filter-scroll::-webkit-scrollbar { + width: 12px; +} + +/* For Firefox */ +.float-filter-scroll { + scrollbar-width: thin; + scrollbar-color: #a8adb3 #2f3136; +} + +.card-list-container { + padding: 10px 1% 15px; + display: inline-block; + margin: 0 0 15px; + vertical-align: top; + width: 20%; +} + +.filter-container { + width: 195px; + flex-direction: column; + justify-content: + flex-start; + align-items: flex-start; + gap: 24px; + display: inline-flex; + margin-right: 20px; +} + +@media screen and (max-width: 1300px) { + .card-list-container { + width: 24.3%; + } +} + +@media screen and (max-width: 1135px) { + .card-list-container { + width: 25%; + } +} + +@media screen and (max-width: 1100px) { + .card-list-container { + width: 33%; + } +} + +@media screen and (max-width: 920px) { + .card-list-container { + width: 33%; + } + .filter-container { + display: none; + } +} + +@media screen and (max-width: 625px) { + .card-list-container { + width: 50%; + } + +} + +/* +@media screen and (max-width: 425px) { + .news-card { + width: 100%; + } + .news-link { + font-size: 0.75rem; + line-height: 1rem; + } + + .recently-img-container { + height: 120px; + width: 100%; + } + + .critics-users-image { + height: 60px; + width: 60px; + } + + .location-province { + font-size: 10px !important; + } + + .trending-image-container { + overflow: hidden; + border-radius: 7px; + height: 100px; + } + + .top-location-container .location-title { + font-size: 0.685rem; + } + +} */ \ No newline at end of file diff --git a/src/pages/Home/index.tsx b/src/pages/Home/index.tsx old mode 100644 new mode 100755 index 6b9ed4b..93385a7 --- a/src/pages/Home/index.tsx +++ b/src/pages/Home/index.tsx @@ -1,4 +1,4 @@ -import { SeparatorWithAnchor } from '../../components'; +import { LocationCard, SeparatorWithAnchor } from '../../components'; import news from '../../datas/recent_news_event.json'; import popular from '../../datas/popular.json'; import popular_user_review from '../../datas/popular_user_reviews.json'; @@ -23,32 +23,32 @@ function Home() { // const [isLoading, setIsLoading] = useState(true) const navigate = useNavigate() - + async function getRecentLocations() { try { const locations = await getListRecentLocationsRatingsService(12) setRecentLocations(locations.data) // setIsLoading(false) - } catch(error) { + } catch (error) { console.log(error) } } async function getCrititsBestLocations() { try { - const res = await getListTopLocationsService({ page: 1, page_size: 6, order_by: 2, region_type: 0}) + const res = await getListTopLocationsService({ page: 1, page_size: 6, order_by: 2, region_type: 0 }) setTopCriticsLocations(res.data) - }catch(err) { + } catch (err) { console.log(err) } } async function getUsersBestLocations() { - try { - const res = await getListTopLocationsService({ page: 1, page_size: 6, order_by: 3, region_type: 0}) + try { + const res = await getListTopLocationsService({ page: 1, page_size: 6, order_by: 3, region_type: 0 }) setTopUsersLocations(res.data) - }catch(err) { + } catch (err) { console.log(err) } } @@ -61,181 +61,184 @@ function Home() { getRecentLocations() getCrititsBestLocations() getUsersBestLocations() - },[]) + }, []) return ( - <> -
+
- {/* RECENTLY ADDED SECTION */} -
- - {recentLocations.map((x) => ( -
- onNavigateToDetail(x.id)}> -
- {x.name} + {/* RECENTLY ADDED SECTION */} +
+ + {recentLocations.map((x) => ( + + //
+ // onNavigateToDetail(x.id)}> + //
+ // {x.name} + //
+ //
+ //
+ //

{x.name}

+ //

{x.regency_name}, {x.province_name}

+ //
+ // {x.critic_count !== 0 && + //
+ //
+ //

{x.critic_score}

+ //
+ //
+ //
+ //
+ //

critic score ({x.critic_count})

+ //
+ // } + // {x.user_score !== 0 && + //
+ //
+ //

{x.user_score}

+ //
+ //
+ //
+ //
+ //

user score ({x.user_count})

+ //
+ // } + //
+ ))} +
+ {/* 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 */} +
+ +
+ {news.data.map((x: News) => ( +
+
+ +
+ {x.link.split("/")[2].replace(/www\./, '')} +

{x.header}

+
+ +

{x.likes_count}

+ +

{x.comments_count}

+
+
+ )) + } +
+
+ {/* END RECENT NEWS / EVENT SECTION */} + + {/* LOCATION CRITICS BEST AND USERS BEST SECTION */} + +
+ +
+ {popular_user_review.data.map((x) => ( +
+
+ +
+

{x.place_name}

+

{x.location}

+

{x.username}

+
+

{x.rating}

+
+
+
+
+
+
+ {x.message} + read more +
+
+ )) + + } +
+
+ + + {/* START LOCATION CRITICS BEST AND USERS BEST SECTION */} +
+
+
+ +
+ {popular.data.map((x) => ( +
+
+ +
+

{x.name}

+

{x.location}

+
+ +
+
+ ))} +
+
+
+ + {topCriticsLocations.map((x) => ( +
+
+
- -

{x.name}

-

{x.regency_name}, {x.province_name}

-
- { x.critic_count !== 0 && -
-
-

{x.critic_score}

-
-
-
-
-

critic score ({x.critic_count})

-
- } - { x.user_score !== 0 && -
-
-

{x.user_score}

-
-
-
-
-

user score ({x.user_count})

-
- } -
- ))} -
- {/* 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 */} -
- -
- {news.data.map((x: News) => ( -
-
- -
- {x.link.split("/")[2].replace(/www\./, '')} -

{x.header}

-
- -

{x.likes_count}

- -

{x.comments_count}

-
-
- )) - } -
-
- {/* END RECENT NEWS / EVENT SECTION */} - - {/* LOCATION CRITICS BEST AND USERS BEST SECTION */} - -
- -
- {popular_user_review.data.map((x) => ( -
-
- -
-

{x.place_name}

-

{x.location}

-

{x.username}

-
-

{x.rating}

+

{x.regency_name}

+
+

{x.critic_score} ({x.critic_count})

-
+
-
-
- {x.message} - read more -
+
)) - }
-
- - - {/* START LOCATION CRITICS BEST AND USERS BEST SECTION */} -
-
-
- -
- {popular.data.map((x) => ( -
-
- -
-

{x.name}

-

{x.location}

-
- -
+
+ + {topUsersLocations.map((x) => ( +
+
+ +
+

{x.name}

+

{x.regency_name}

+
+

{x.user_score} ({x.user_count})

+
+
- ))} +
+
-
-
- - {topCriticsLocations.map((x) => ( -
-
- -
-

{x.name}

-

{x.regency_name}

-
-

{x.critic_score} ({x.critic_count})

-
-
-
-
-
-
- )) - } -
-
- - {topUsersLocations.map((x) => ( -
-
- -
-

{x.name}

-

{x.regency_name}

-
-

{x.user_score} ({x.user_count})

-
-
-
-
-
-
- )) - } -
+ )) + }
-
-
- +
+
+
) } diff --git a/src/pages/Home/style.css b/src/pages/Home/style.css old mode 100644 new mode 100755 diff --git a/src/pages/LocationDetail/index.css b/src/pages/LocationDetail/index.css old mode 100644 new mode 100755 diff --git a/src/pages/LocationDetail/index.tsx b/src/pages/LocationDetail/index.tsx old mode 100644 new mode 100755 index 498767b..eafd49b --- a/src/pages/LocationDetail/index.tsx +++ b/src/pages/LocationDetail/index.tsx @@ -3,10 +3,10 @@ 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, +import { + EmptyLocationDetailResponse, + LocationDetailResponse, + LocationResponse, emptyLocationResponse, CurrentUserLocationReviews, } from './types'; @@ -33,7 +33,7 @@ function LocationDetail() { const [locationImages, setLocationImages] = useState(emptyLocationResponse()) const [currentUserReview, setCurrentUserReview] = useState() const [lightboxOpen, setLightboxOpen] = useState(false) - const[updatePage, setUpdatePage] = useState(true) + const [updatePage, setUpdatePage] = useState(true) const [pageState, setPageState] = useState({ critic_filter_name: 'highest rated', critic_filter_type: 0, @@ -61,7 +61,7 @@ function LocationDetail() { try { const res = await getLocationService(Number(id)) setLocationDetail(res.data, (val) => { - if(val.detail.thumbnail) { + if (val.detail.thumbnail) { getImage(val.detail.thumbnail) } }) @@ -87,17 +87,17 @@ function LocationDetail() { } 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 + 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) } - alert(err.error.response.data.message) - } } function handleTextAreaChange(e: ChangeEvent): void { @@ -176,7 +176,7 @@ function LocationDetail() { console.log(err) const str = handleAxiosError(err) alert(str) - setPageState({ ...pageState, on_submit_loading: false }) + setPageState({ ...pageState, on_submit_loading: false }) } } @@ -191,476 +191,372 @@ function LocationDetail() { useEffect(() => { getCurrentUserLocationReview() }, []) - + useEffect(() => { - if(updatePage) { + if (updatePage || id) { getLocationDetail() } }, [updatePage, id]) return ( - <> -
-
- -
+
+
+ +
-
-
-
-

{locationDetail?.detail.name}

+
+
+
+

{locationDetail?.detail.name}

+
+ {isLoading ? +
+ : + - {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 +
+ } +
+
+
+
+

DETAILS

+ +
+
+ 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
: -
- setLightboxOpen(true)} - className={'mt-3'} - style={{ display: 'grid', position: 'relative', gridTemplateColumns: 'repeat(12,1fr)', cursor: 'zoom-in' }} - >{Number(locationImages?.total_image) > 0 && -
- - {locationImages?.images.length > 1 && -
- Total images ({locationImages?.images.length}) +
+
+ + + + + +
+ {currentUserReview ? +
+

{currentUserReview.score}

+
+
+
+ : + <> + +
/ score
+ {pageState.is_score_rating_panic_msg && +
{pageState.is_score_rating_panic_msg}
+ } + + + } +
+
+ +
+ {currentUserReview ? + + : + }
- } - {locationImages?.images.length > 1 && -
- + +
+ - } -
1 ? {} : { gridColumn: '13/1' }}> - 1 ? locationImages?.images[1].src.toString() : locationDetail.detail.thumbnail!} alt="" style={{ aspectRatio: '1/1' }} /> + {pageState.on_submit_loading ? + + : + + + POST + + + }
- +
+ } -
-
-
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 -
- } -
-
-
-
-

DETAILS

- -
-
- 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}

-
-
-
+ {locationDetail.critics_review.map(x => ( +
+
+
+ {x.score}
- : - <> - +
+
+
+ -
- - } -
- - {locationDetail.critics_review.length > 0 ? - <> - -
- - {locationDetail.critics_review.map(x => ( -
-
-
- {x.score} -
-
-
-
-
-
- - + + ))} : + No Critics review to display + } +
+ +
+ 0 ? '#' : ''} /> + {locationDetail.users_review.length > 0 ? <> - No Critics review to display - - - } -
- -
- 0 ? '#' : ''} /> - { locationDetail.users_review.length > 0 ? - <> - {locationDetail.users_review.map(x => ( -
-
- - + {locationDetail.users_review.map(x => ( +
+ +
+ - -
-
{x.score}
-
-
-
-
-
- -
- +
+
{x.score}
+
+
+
+
+
+ +
+ - ))} - - - - : - <> - 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 -
+ + : + <> + No users review to display + + }
- {/* {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 +
+ CONTRUBITION + + anoeantoeh aoenthaoe aoenth aot +
-
- setLightboxOpen(false)} - slides={locationImages?.images} - /> -
- +
+
+
+ +
+
+ Added on: 28 May 1988 +
+
+ setLightboxOpen(false)} + slides={locationImages?.images} + /> +
) } diff --git a/src/pages/LocationDetail/types.ts b/src/pages/LocationDetail/types.ts old mode 100644 new mode 100755 diff --git a/src/pages/Login/index.css b/src/pages/Login/index.css old mode 100644 new mode 100755 diff --git a/src/pages/Login/index.tsx b/src/pages/Login/index.tsx old mode 100644 new mode 100755 diff --git a/src/pages/NewsEvent/index.tsx b/src/pages/NewsEvent/index.tsx old mode 100644 new mode 100755 diff --git a/src/pages/NewsEvent/style.css b/src/pages/NewsEvent/style.css old mode 100644 new mode 100755 diff --git a/src/pages/NotFound/index.tsx b/src/pages/NotFound/index.tsx old mode 100644 new mode 100755 diff --git a/src/pages/Stories/index.tsx b/src/pages/Stories/index.tsx old mode 100644 new mode 100755 index 9c6ec40..89dc45c --- a/src/pages/Stories/index.tsx +++ b/src/pages/Stories/index.tsx @@ -1,8 +1,6 @@ function Story() { return( - <>

Best PLaces

- ) } diff --git a/src/pages/Submissions/index.tsx b/src/pages/Submissions/index.tsx old mode 100644 new mode 100755 diff --git a/src/pages/UserFeed/index.tsx b/src/pages/UserFeed/index.tsx old mode 100644 new mode 100755 diff --git a/src/pages/UserProfile/index.tsx b/src/pages/UserProfile/index.tsx old mode 100644 new mode 100755 index 679b113..ef35364 --- a/src/pages/UserProfile/index.tsx +++ b/src/pages/UserProfile/index.tsx @@ -188,9 +188,7 @@ function UserProfile() { ))} : - <> - No users review to display - + No users review to display }
diff --git a/src/pages/UserProfile/style.css b/src/pages/UserProfile/style.css old mode 100644 new mode 100755 diff --git a/src/pages/UserSettings/index.tsx b/src/pages/UserSettings/index.tsx old mode 100644 new mode 100755 diff --git a/src/pages/UserSettings/styles.css b/src/pages/UserSettings/styles.css old mode 100644 new mode 100755 diff --git a/src/pages/index.tsx b/src/pages/index.tsx old mode 100644 new mode 100755 diff --git a/src/reducers/index.ts b/src/reducers/index.ts old mode 100644 new mode 100755 diff --git a/src/routes/ProtectedRoute.tsx b/src/routes/ProtectedRoute.tsx old mode 100644 new mode 100755 diff --git a/src/routes/index.tsx b/src/routes/index.tsx old mode 100644 new mode 100755 diff --git a/src/services/auth.ts b/src/services/auth.ts old mode 100644 new mode 100755 diff --git a/src/services/config.ts b/src/services/config.ts old mode 100644 new mode 100755 diff --git a/src/services/images.ts b/src/services/images.ts old mode 100644 new mode 100755 diff --git a/src/services/index.ts b/src/services/index.ts old mode 100644 new mode 100755 diff --git a/src/services/locations.ts b/src/services/locations.ts old mode 100644 new mode 100755 index 6c00fac..de373ce --- a/src/services/locations.ts +++ b/src/services/locations.ts @@ -24,6 +24,7 @@ interface GetListLocationsArg extends GetRequestPagination { interface GetSearchLocations extends GetRequestPagination { name: string + filter?: string } async function getListLocationsService({ page, page_size }: GetListLocationsArg) { @@ -135,9 +136,12 @@ async function getSearchLocationService(arg: GetSearchLocations): Promise = BaseNullValueRes & Record +export const capitalize = (s: T) => (s[0].toUpperCase() + s.slice(1)) as Capitalize; +export const enumKeys = (obj: O): K[] => { + return Object.keys(obj).filter(k => !Number.isNaN(k)) as K[] +} export interface GetRequestPagination { - page: number, - page_size: number, + page?: number, + page_size?: number, +} + +export type ReactSelectData = { + value: number, + label: string } export interface IHttpResponse { diff --git a/src/types/state-callback.ts b/src/types/state-callback.ts old mode 100644 new mode 100755 diff --git a/src/utils/common.ts b/src/utils/common.ts old mode 100644 new mode 100755 diff --git a/src/utils/index.ts b/src/utils/index.ts old mode 100644 new mode 100755 diff --git a/src/utils/useAutosizeTextArea.ts b/src/utils/useAutosizeTextArea.ts old mode 100644 new mode 100755 diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts old mode 100644 new mode 100755 diff --git a/tailwind.config.js b/tailwind.config.js old mode 100644 new mode 100755 index 5563d0c..0445e23 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -8,6 +8,8 @@ export default { primary: '#202225', secondary: '#2f3136', tertiary: '#a8adb3', + quartenary: '#4D4E51', + green: '#85CE73', error: '#ff5454', gray: '#797979', yellow: '#e5c453' diff --git a/tsconfig.json b/tsconfig.json old mode 100644 new mode 100755 diff --git a/tsconfig.node.json b/tsconfig.node.json old mode 100644 new mode 100755 diff --git a/vite.config.ts b/vite.config.ts old mode 100644 new mode 100755 diff --git a/yarn.lock b/yarn.lock old mode 100644 new mode 100755