diff --git a/components/Group/GroupList/GroupCard.jsx b/components/Group/GroupList/GroupCard.jsx index 4c0c6876..57501760 100644 --- a/components/Group/GroupList/GroupCard.jsx +++ b/components/Group/GroupList/GroupCard.jsx @@ -1,7 +1,7 @@ import LocationOnOutlinedIcon from '@mui/icons-material/LocationOnOutlined'; import Image from '@/shared/components/Image'; -import emptyCoverImg from '@/public/assets/empty-cover.png'; import { timeDuration } from '@/utils/date'; +import emptyCoverWithBackgroundImg from '@/public/assets/empty-cover-with-background.png'; import { StyledAreas, StyledContainer, @@ -31,7 +31,10 @@ function GroupCard({ return ( - {photoAlt + {photoAlt {title} diff --git a/components/Group/GroupList/index.jsx b/components/Group/GroupList/index.jsx index 3aa27d00..59352d3b 100644 --- a/components/Group/GroupList/index.jsx +++ b/components/Group/GroupList/index.jsx @@ -1,10 +1,13 @@ import { useEffect, Fragment } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import styled from '@emotion/styled'; +import Button from '@mui/material/Button'; import useMediaQuery from '@mui/material/useMediaQuery'; -import { Box } from '@mui/material'; import useSearchParamsManager from '@/hooks/useSearchParamsManager'; import { setQuery } from '@/redux/actions/group'; +import Image from '@/shared/components/Image'; +import emptyCoverImg from '@/public/assets/empty-cover.png'; +import errorCoverImg from '@/public/assets/contacterror.png'; import GroupCard from './GroupCard'; import SkeletonGroupCard from './SkeletonGroupCard'; @@ -41,10 +44,93 @@ const StyledGroupList = styled.ul` flex-wrap: wrap; `; +const StyledFullItem = styled.li` + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + width: 100%; + height: 412px; + + .color-gray { + color: #536166; + } + + .color-gray-light { + color: #92989a; + } + + p { + margin-top: 20px; + } + + span { + margin-top: 6px; + font-size: 14px; + } +`; + +function shouldRenderDivider( + index, + isLast, + isMobileScreen, + isPadScreen, + isDeskTopScreen, +) { + return ( + (isMobileScreen && !isLast) || + (isPadScreen && !isLast && index % 2 === 1) || + (isDeskTopScreen && !isLast && index % 3 === 2) + ); +} + +function GroupItems({ items, isMobileScreen, isPadScreen, isDeskTopScreen }) { + return ( + Array.isArray(items) && + items.map((data, index) => { + const isLast = index === items.length - 1; + return ( + + + + + {shouldRenderDivider( + index, + isLast, + isMobileScreen, + isPadScreen, + isDeskTopScreen, + ) && } + + ); + }) + ); +} + +function SkeletonItems({ isMobileScreen, isPadScreen, isDeskTopScreen }) { + return Array.from({ length: isMobileScreen ? 3 : 6 }, (_, index) => { + const isLast = index === (isMobileScreen ? 2 : 5); + return ( + + + + + {shouldRenderDivider( + index, + isLast, + isMobileScreen, + isPadScreen, + isDeskTopScreen, + ) && } + + ); + }); +} + function GroupList() { const dispatch = useDispatch(); const [getSearchParams] = useSearchParamsManager(); - const { items, isLoading } = useSelector((state) => state.group); + const { items, isLoading, isError } = useSelector((state) => state.group); const isMobileScreen = useMediaQuery('(max-width: 560px)'); const isPadScreen = useMediaQuery('(max-width: 767px)') && !isMobileScreen; @@ -55,54 +141,62 @@ function GroupList() { }, [getSearchParams]); return ( - <> - - {isLoading ? ( - // always show 3 || 6 skeleton cards in mobile || desktop screen - Array.from({ length: isMobileScreen ? 3 : 6 }, (_, index) => { - const isLast = index === (isMobileScreen ? 2 : 5); - const shouldRenderDivider = - (isMobileScreen && !isLast) || - (isPadScreen && !isLast && index % 2 === 1) || - (isDeskTopScreen && !isLast && index % 3 === 2); - - return ( - - - - - {shouldRenderDivider && } - - ); - }) - ) : items?.length ? ( - items.map((data, index) => { - const isLast = index === items.length - 1; - const shouldRenderDivider = - (isMobileScreen && !isLast) || - (isPadScreen && !isLast && index % 2 === 1) || - (isDeskTopScreen && !isLast && index % 3 === 2); - - return ( - - - - - {shouldRenderDivider && } - - ); - }) - ) : ( -
  • - 哎呀!這裡好像沒有符合你條件的揪團,別失望!讓我們試試其他選項。 -
  • - )} -
    - + + {isLoading && ( - 搜尋揪團中~ + + )} + {isError ? ( + + 異常錯誤 +

    哎呀!有不明錯誤

    + +
    + ) : ( + !isLoading && + items.length === 0 && ( + + 查無資料 +

    哎呀!這裡沒有符合條件的揪團

    + + 試著更改條件或搜尋其他關鍵字吧 + +
    + ) )} - +
    ); } diff --git a/components/Group/More.jsx b/components/Group/More.jsx index 342f68e9..63362427 100644 --- a/components/Group/More.jsx +++ b/components/Group/More.jsx @@ -11,7 +11,7 @@ export default function More() { - {isMore ? ( + {isMore && ( - ) : ( - '已經到底囉~' )} ); diff --git a/public/assets/empty-cover-with-background.png b/public/assets/empty-cover-with-background.png new file mode 100644 index 00000000..d0da2dd1 Binary files /dev/null and b/public/assets/empty-cover-with-background.png differ diff --git a/public/assets/empty-cover.png b/public/assets/empty-cover.png index 785b7dd0..5ff707cd 100644 Binary files a/public/assets/empty-cover.png and b/public/assets/empty-cover.png differ diff --git a/redux/reducers/group.js b/redux/reducers/group.js index 106a277c..5d3aa93b 100644 --- a/redux/reducers/group.js +++ b/redux/reducers/group.js @@ -12,6 +12,7 @@ const initialState = { items: [], total: 0, isLoading: true, + isError: false, }; const reducer = (state = initialState, action) => { @@ -39,6 +40,7 @@ const reducer = (state = initialState, action) => { ...state, ...(action.payload ?? {}), isLoading: false, + isError: false, }; } case GET_GROUP_ITEMS_FAILURE: { @@ -46,6 +48,7 @@ const reducer = (state = initialState, action) => { ...state, total: 0, isLoading: false, + isError: true, }; } default: { diff --git a/shared/components/Image/index.jsx b/shared/components/Image/index.jsx index 2fcc4752..13fa374a 100644 --- a/shared/components/Image/index.jsx +++ b/shared/components/Image/index.jsx @@ -1,6 +1,6 @@ import Skeleton from '@mui/material/Skeleton'; import { LazyLoadImage } from 'react-lazy-load-image-component'; -import emptyCoverImg from '@/public/assets/empty-cover.png'; +import emptyCoverWithBackgroundImg from '@/public/assets/empty-cover-with-background.png'; import { useState } from 'react'; const Loading = ({ height }) => ( @@ -17,13 +17,13 @@ const Image = ({ alt, width = '100%', height = '122px', - background = 'rgba(240, 240, 240, .8)', + background = 'transparent', borderRadius = '8px', }) => { const [isError, setIsError] = useState(false); return (