diff --git a/web/.prettierrc b/web/.prettierrc new file mode 100644 index 0000000..dda75ab --- /dev/null +++ b/web/.prettierrc @@ -0,0 +1,8 @@ +{ + "singleQuote": true, + "trailingComma": "all", + "printWidth": 80, + "tabWidth": 2, + "useTabs": false, + "semi": false +} \ No newline at end of file diff --git a/web/src/views/App.jsx b/web/src/views/App.jsx index 7a6c801..797b8d8 100644 --- a/web/src/views/App.jsx +++ b/web/src/views/App.jsx @@ -1,61 +1,74 @@ -import { Outlet, Link, NavLink } from 'react-router-dom'; -import { Layout, Menu, ConfigProvider, theme, Row, Col, Typography, Flex, App as AntApp } from 'antd'; -import 'antd/dist/reset.css'; -import AppLogo from '@/assets/logo-gh.png'; -import 'dayjs/locale/zh-cn'; -import ErrorBoundary from '@/components/ErrorBoundary'; -import { BUILD_VERSION, } from '@/config'; -import { useThemeContext } from '@/stores/ThemeContext'; +import { Outlet, Link, NavLink } from 'react-router-dom' +import { + Layout, + Menu, + ConfigProvider, + theme, + Row, + Col, App as AntApp +} from 'antd' +import 'antd/dist/reset.css' +import AppLogo from '@/assets/logo-gh.png' +import 'dayjs/locale/zh-cn' +import ErrorBoundary from '@/components/ErrorBoundary' +import { BUILD_VERSION } from '@/config' +import { useThemeContext } from '@/stores/ThemeContext' - -const { Header, Content, Footer } = Layout; -const { Title } = Typography; +const { Header, Content, Footer } = Layout function App() { - const { colorPrimary } = useThemeContext() - console.info('theme: ', theme) - - return ( - - - - -
- - - - App logo - - 喜玩酒店 } - ]} - /> - - -
- -
- + return ( + + + + +
+ + + + App logo + + 喜玩酒店, + }, + ]} + /> + + +
+ +
+
-
-
China Highlights International Travel Service Co., LTD, Version: {BUILD_VERSION}
-
+ +
+ China Highlights International Travel Service Co., LTD, Version:{' '} + {BUILD_VERSION} +
+
-
-
- ) + + + ) } export default App diff --git a/web/src/views/hotel/Detail.jsx b/web/src/views/hotel/Detail.jsx index bcd1c83..44bc99a 100644 --- a/web/src/views/hotel/Detail.jsx +++ b/web/src/views/hotel/Detail.jsx @@ -2,29 +2,27 @@ import { useState, useEffect } from 'react' import { useParams, useNavigate } from 'react-router-dom' import { Modal, InputNumber, Form, Typography, DatePicker, Button } from 'antd' import useHotelStore from '@/stores/Hotel' -import { RoomList } from "./HotelComponents" +import { RoomList } from './HotelComponents' import dayjs from 'dayjs' import { isEmpty } from '@/utils/commons' function Detail() { - const { hotelId, checkin, checkout } = useParams() const [loading, setLoading] = useState(true) const [hotelQuotation, setHotelQuotation] = useState({ hotelName: '', roomName: '', - price: '' + price: '', }) const navigate = useNavigate() const [searchForm] = Form.useForm() - const [selectedHotel, getRoomListByHotel, roomList] = - useHotelStore(state => - [state.selectedHotel, state.getRoomListByHotel, state.roomList]) - - useEffect (() => { + const [selectedHotel, getRoomListByHotel, roomList] = useHotelStore( + (state) => [state.selectedHotel, state.getRoomListByHotel, state.roomList], + ) + useEffect(() => { // http://localhost:5175/hotel/416980/2024-09-10/2024-09-11 if (isEmpty(hotelId) || isEmpty(checkin) || isEmpty(checkout)) { console.info('criteria is null') @@ -33,13 +31,13 @@ function Detail() { searchForm.setFieldsValue({ dataRange: [dayjs(checkin), dayjs(checkout)], adultCount: 2, - roomCount: 1 + roomCount: 1, }) setLoading(true) - getRoomListByHotel(hotelId, checkin, checkout) - .finally(() => setLoading(false)) + getRoomListByHotel(hotelId, checkin, checkout).finally(() => + setLoading(false), + ) } - }, []) const handelFormFinish = () => { @@ -51,18 +49,20 @@ function Detail() { // }) setLoading(true) - getRoomListByHotel(hotelId, + getRoomListByHotel( + hotelId, formValue.dataRange[0].format('YYYY-MM-DD'), formValue.dataRange[1].format('YYYY-MM-DD'), - formValue.adultCount, formValue.roomCount) - .finally(() => setLoading(false)) + formValue.adultCount, + formValue.roomCount, + ).finally(() => setLoading(false)) } const handleRoomChange = (room, plan) => { const forHtJson = { hotelName: selectedHotel.hotel_name, roomName: room.RoomName, - price: plan.Price + price: plan.Price, } setHotelQuotation(forHtJson) showModal() @@ -82,58 +82,64 @@ function Detail() { return (
- - + +

酒店:{hotelQuotation.hotelName}

房型:{hotelQuotation.roomName}

价格:{hotelQuotation.price}

- - {selectedHotel.hotel_name} - -
-
- - - - - - - - - - - - - - - -
-
- {handleRoomChange(room, plan)}} dataSource={roomList}> + {selectedHotel.hotel_name} +
+
+ + + + + + + + + + + + + + + +
+
+ { + handleRoomChange(room, plan) + }} + dataSource={roomList} + >
) } diff --git a/web/src/views/hotel/HotelComponents.jsx b/web/src/views/hotel/HotelComponents.jsx index d4abebf..46c138a 100644 --- a/web/src/views/hotel/HotelComponents.jsx +++ b/web/src/views/hotel/HotelComponents.jsx @@ -1,102 +1,56 @@ -import { createContext, useContext, useState } from 'react' -import { Flex, Button, Image, Divider, Typography, Empty, Skeleton, Row, Col, InputNumber, Form, DatePicker, Input } from 'antd' +import { createContext, useContext } from 'react' +import { + Flex, + Button, + Image, + Divider, + Typography, + Empty, + Skeleton, + Row, + Col, +} from 'antd' const HotelContext = createContext() -export function SearchForm({ onSearch, onInit }) { - const [searchForm] = Form.useForm() - - onInit(searchForm) - - const handelFormFinish = () => { - const formValue = searchForm.getFieldValue() - // setSearchParams({ - // hotel: formValue.hotelName, - // checkin: formValue.dataRange[0].format('YYYY-MM-DD'), - // checkout: formValue.dataRange[1].format('YYYY-MM-DD') - // }) - - onSearch(formValue) - - // setLoading(true) - // searchByCriteria(formValue) - // .finally(() => setLoading(false)) - } - - return ( -
console.info('onFinishFailed')} - autoComplete='off' - > - - - - - - - - - -
- ) -} - export function HotelList({ dataSource, loading, onChange }) { - if (dataSource && dataSource.length > 0) { const itemList = dataSource.map((data, index) => { return ( - <> - + - - {data.hotel_name} - - {data.address} - {data.base_price.Price??0} 起 - - - + ) }) return ( - + {itemList} @@ -107,51 +61,46 @@ export function HotelList({ dataSource, loading, onChange }) { } export function RoomList({ dataSource, loading, onChange }) { - const triggerChange = (changedValue) => { - onChange?.( - changedValue - ) + onChange?.(changedValue) } if (dataSource && dataSource.length > 0) { const itemList = dataSource.map((room, index) => { - let roomImage = + let roomImage = if (room?.Images && room?.Images.length > 0) { roomImage = } return ( -
- - {room.RoomName}, {room.BedTypeDesc} - - - - - {roomImage} - 大小: {room.Area??0}m² - - - - { - room.RatePlans.map((plan, index) => { +
+ + {room.RoomName}, {room.BedTypeDesc} + + + + + {roomImage} + 大小: {room.Area ?? 0}m² + + + + {room.RatePlans.map((plan, index) => { return ( ) - }) - } - - -
+ })} + +
+
) }) return ( - + {itemList} @@ -164,7 +113,8 @@ export function RoomList({ dataSource, loading, onChange }) { const getMealDesc = (plan) => { const type = plan.MealType let desc = '未知' - if (type === 1) desc = '早' + plan.Breakfast + '中' + plan.Lunch + '晚' + plan.Dinner + if (type === 1) + desc = '早' + plan.Breakfast + '中' + plan.Lunch + '晚' + plan.Dinner else if (type === 2) desc = '半包' else if (type === 3) desc = '全包' else if (type === 4) desc = '午/晚二选一' @@ -173,20 +123,30 @@ const getMealDesc = (plan) => { return desc } -const PlanItem = ({room, plan}) => { +const PlanItem = ({ room, plan }) => { const { triggerChange } = useContext(HotelContext) return ( <> - - 餐: {getMealDesc(plan)} - {plan.Cancelable ? plan.CancelRulesText.join(';') : plan.CancelableText} + + + 餐: {getMealDesc(plan)} + + + + {plan.Cancelable + ? plan.CancelRulesText.join(';') + : plan.CancelableText} + + {plan.PriceUnit} {plan.Currency} - + + + diff --git a/web/src/views/hotel/List.jsx b/web/src/views/hotel/List.jsx index e79c6b4..cd69884 100644 --- a/web/src/views/hotel/List.jsx +++ b/web/src/views/hotel/List.jsx @@ -1,19 +1,20 @@ import { useState, useEffect } from 'react' import { useNavigate, useSearchParams } from 'react-router-dom' -import { Space, Typography } from 'antd' +import { Space, Typography, Form, Button, Input, DatePicker } from 'antd' import useHotelStore from '@/stores/Hotel' import dayjs from 'dayjs' -import { HotelList, SearchForm } from './HotelComponents' +import { HotelList } from './HotelComponents' import { isEmpty } from '@/utils/commons' const { Title } = Typography const List = () => { - const [loading, setLoading] = useState(false) - let searchForm = null - const [searchByCriteria, hotelList, selectHotel] = - useHotelStore(state => - [state.searchByCriteria, state.hotelList, state.selectHotel]) + const [searchForm] = Form.useForm() + const [searchByCriteria, hotelList, selectHotel] = useHotelStore((state) => [ + state.searchByCriteria, + state.hotelList, + state.selectHotel, + ]) const navigate = useNavigate() const [searchParams, setSearchParams] = useSearchParams() @@ -25,46 +26,101 @@ const List = () => { useEffect(() => { // 测试酒店:Hotel Skypark Kingstown Dongdaemun // http://localhost:5175/hotel/list?hotel=s&checkin=2024-8-20&checkout=2024-8-21 - if (isEmpty(hotelName) || isEmpty(checkinDateString) || isEmpty(checkoutDateString)) { - console.info('criteria is null') + if ( + isEmpty(hotelName) || + isEmpty(checkinDateString) || + isEmpty(checkoutDateString) + ) { + console.error('criteria is null') } else { searchForm.setFieldsValue({ dataRange: [dayjs(checkinDateString), dayjs(checkoutDateString)], - hotelName: hotelName + hotelName: hotelName, }) setLoading(true) - searchByCriteria(searchForm.getFieldValue()) - .finally(() => setLoading(false)) + searchByCriteria(searchForm.getFieldValue()).finally(() => + setLoading(false), + ) } }, []) - const handelSearch = (formValue) => { + const handelFormFinish = () => { + const formValue = searchForm.getFieldValue() setSearchParams({ hotel: formValue.hotelName, checkin: formValue.dataRange[0].format('YYYY-MM-DD'), - checkout: formValue.dataRange[1].format('YYYY-MM-DD') + checkout: formValue.dataRange[1].format('YYYY-MM-DD'), }) setLoading(true) - searchByCriteria(formValue) - .finally(() => setLoading(false)) + searchByCriteria(formValue).finally(() => setLoading(false)) } const handleHotelChange = (hotel) => { selectHotel(hotel) - navigate(`/hotel/${hotel.hotel_id}/${searchForm.getFieldValue().dataRange[0].format('YYYY-MM-DD')}/${searchForm.getFieldValue().dataRange[1].format('YYYY-MM-DD')}`) + navigate( + `/hotel/${hotel.hotel_id}/${searchForm + .getFieldValue() + .dataRange[0].format('YYYY-MM-DD')}/${searchForm + .getFieldValue() + .dataRange[1].format('YYYY-MM-DD')}`, + ) + } + + const SearchForm = () => { + return ( +
console.info('onFinishFailed')} + autoComplete="off" + > + + + + + + + + + +
+ ) } return ( <> - + 酒店列表 - searchForm = form} - > - - handleHotelChange(h)}> + + handleHotelChange(h)} + > )