Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

♻️ Move mockData to the API directory and implement Redux integration with the API #20

Merged
merged 5 commits into from
Jan 17, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions components/Group/GroupList/GroupCard.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import LocationOnOutlinedIcon from '@mui/icons-material/LocationOnOutlined';
import Image from '@/shared/components/Image';
import emptyCoverImg from '@/public/assets/empty-cover.png';
import {
StyledAreas,
StyledContainer,
Expand All @@ -19,10 +20,11 @@ function GroupCard({
partnerEducationStep,
description,
area,
isGrouping,
}) {
return (
<StyledGroupCard>
<Image alt={photoAlt} src={photoURL} />
<Image alt={photoAlt || '未放封面'} src={photoURL || emptyCoverImg.src} />
<StyledContainer>
<StyledTitle>{title}</StyledTitle>
<StyledInfo>
Expand All @@ -44,7 +46,11 @@ function GroupCard({
</StyledAreas>
<StyledFooter>
<time>2天前更新</time>
<div>揪團中</div>
{isGrouping ? (
<div>揪團中</div>
) : (
<div className="finished">已結束</div>
)}
</StyledFooter>
</StyledContainer>
</StyledGroupCard>
Expand Down
6 changes: 5 additions & 1 deletion components/Group/GroupList/GroupCard.styled.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ export const StyledTitle = styled.h2`
font-size: 14px;
font-weight: bold;
line-height: 1.4;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
overflow: hidden;
`;

export const StyledInfo = styled.div`
Expand Down Expand Up @@ -66,7 +70,7 @@ export const StyledFooter = styled.footer`
border-radius: 50%;
}

&.end {
&.finished {
--bg-color: #f3f3f3;
--color: #92989a;
}
Expand Down
70 changes: 57 additions & 13 deletions components/Group/GroupList/index.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import styled from '@emotion/styled';
import { Box } from '@mui/material';
import { AREAS } from '@/constants/areas';
import { CATEGORIES } from '@/constants/category';
import { EDUCATION_STEP } from '@/constants/member';
import useSearchParamsManager from '@/hooks/useSearchParamsManager';
import { setQuery } from '@/redux/actions/group';
import GroupCard from './GroupCard';

export const StyledGroupItem = styled.li`
Expand Down Expand Up @@ -50,21 +58,57 @@ const StyledGroupList = styled.ul`
justify-content: space-between;
`;

function GroupList({ list, isLoading }) {
function GroupList() {
const dispatch = useDispatch();
const [getSearchParams] = useSearchParamsManager();
const { items, isLoading } = useSelector((state) => state.group);

useEffect(() => {
const filterOptions = {
area: AREAS,
category: CATEGORIES,
edu: EDUCATION_STEP,
grouping: true,
q: true,
};
const params = {};
const searchParams = getSearchParams();
Object.keys(filterOptions).forEach((key) => {
const searchParam = searchParams[key];
const options = filterOptions[key];

if (searchParam && options) {
params[key] = Array.isArray(options)
? searchParam
.split(',')
.filter((item) => options.some((option) => option.label === item))
.join(',')
: searchParam;
}
});
dispatch(setQuery(params));
}, [getSearchParams]);

return (
<StyledGroupList>
{list?.length || isLoading ? (
list.map((data) => (
<StyledGroupItem key={data.id}>
<GroupCard {...data} />
</StyledGroupItem>
))
) : (
<li style={{ textAlign: 'center', width: '100%' }}>
哎呀!這裡好像沒有符合你條件的揪團,別失望!讓我們試試其他選項。
</li>
<>
<StyledGroupList>
{items?.length || isLoading ? (
items.map((data) => (
<StyledGroupItem key={data.id}>
<GroupCard {...data} />
</StyledGroupItem>
))
) : (
<li style={{ textAlign: 'center', width: '100%' }}>
哎呀!這裡好像沒有符合你條件的揪團,別失望!讓我們試試其他選項。
</li>
)}
</StyledGroupList>

{isLoading && (
<Box sx={{ textAlign: 'center', paddingTop: '32px' }}>搜尋揪團中~</Box>
)}
</StyledGroupList>
</>
);
}

Expand Down
33 changes: 33 additions & 0 deletions components/Group/More.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { useDispatch, useSelector } from 'react-redux';
import { Box, Button } from '@mui/material';
import { setLimit } from '@/redux/actions/group';

export default function More() {
const dispatch = useDispatch();
const { limit, total, isLoading } = useSelector((state) => state.group);
const isMore = total > limit || isLoading;

return (
<Box
sx={{ textAlign: 'center', paddingTop: '80px', paddingBottom: '100px' }}
>
{isMore ? (
<Button
variant="outlined"
sx={{
fontSize: '16px',
color: '#536166',
borderColor: '#16B9B3',
borderRadius: '20px',
padding: '6px 48px',
}}
onClick={() => dispatch(setLimit(limit + 12))}
>
顯示更多
</Button>
) : (
'已經到底囉~'
)}
</Box>
);
}
63 changes: 4 additions & 59 deletions components/Group/index.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { useEffect, useState } from 'react';
import styled from '@emotion/styled';
import { Box, Button } from '@mui/material';
import { Box } from '@mui/material';
import AreaChips from './AreaChips';
import Banner from './Banner';
import SearchField from './SearchField';
import SelectedCategory from './SelectedCategory';
import GroupList from './GroupList';
import More from './More';

const StyledGroup = styled.div`
position: relative;
Expand All @@ -30,41 +30,7 @@ const ContainerWrapper = styled(Box)`
z-index: 2;
`;

const createTemplate = (_, id) => ({
id,
title: '颱風天不衝浪要幹嘛',
photoURL:
'https://images.unsplash.com/photo-1502680390469-be75c86b636f?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxzZWFyY2h8Mnx8c3VyZnxlbnwwfHwwfHw%3D&auto=format&fit=crop&w=800&q=60',
photoAlt: '封面圖',
category: ['語言與文學', '人文社會', '自然科學', '生活'],
partnerEducationStep: '高中',
description:
'希望能像朋友,一起讀有興趣的科目,每週1-2次見面練習這兩種,每次總時數2-3小時不限,希望你跟我一樣很想追求有效進步也不怕辛苦!一起讀日文也可以喔!',
area: '台北市',
});

const mockData = (length) =>
new Promise((res) =>
setTimeout(() => {
res(Array.from({ length }, createTemplate));
}, 600),
);

function Group() {
const [total, setTotal] = useState(12);
const [list, setList] = useState([]);
const [isLoading, setIsLoading] = useState(true);

useEffect(() => {
const setDataAndLoaded = (data) => {
setList(data);
setIsLoading(false);
};

setIsLoading(true);
mockData(total).then(setDataAndLoaded);
}, [total]);

return (
<Box sx={{ background: '#f3fcfc' }}>
<Banner />
Expand All @@ -75,31 +41,10 @@ function Group() {
</ContainerWrapper>
<ContainerWrapper as="main" sx={{ marginTop: '24px' }}>
<AreaChips />
<GroupList list={list} isLoading={isLoading} />
{isLoading && (
<Box sx={{ textAlign: 'center', paddingTop: '32px' }}>
搜尋揪團中~
</Box>
)}
<GroupList />
</ContainerWrapper>
</StyledGroup>
<Box
sx={{ textAlign: 'center', paddingTop: '80px', paddingBottom: '100px' }}
>
<Button
variant="outlined"
sx={{
fontSize: '16px',
color: '#536166',
borderColor: '#16B9B3',
borderRadius: '20px',
padding: '6px 48px',
}}
onClick={() => setTotal((pre) => pre + 12)}
>
顯示更多
</Button>
</Box>
<More />
</Box>
);
}
Expand Down
46 changes: 23 additions & 23 deletions constants/areas.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
export const AREAS = [
{ name: '線上' },
{ name: '臺北市' },
{ name: '新北市' },
{ name: '基隆市' },
{ name: '桃園市' },
{ name: '新竹市' },
{ name: '新竹縣' },
{ name: '苗栗縣' },
{ name: '臺中市' },
{ name: '南投縣' },
{ name: '彰化縣' },
{ name: '雲林縣' },
{ name: '嘉義市' },
{ name: '嘉義縣' },
{ name: '臺南市' },
{ name: '高雄市' },
{ name: '屏東縣' },
{ name: '臺東縣' },
{ name: '花蓮縣' },
{ name: '宜蘭縣' },
{ name: '澎湖縣' },
{ name: '金門縣' },
{ name: '連江縣' },
{ name: '線上', label: '線上' },
{ name: '台北市', label: '台北市' },
{ name: '新北市', label: '新北市' },
{ name: '基隆市', label: '基隆市' },
{ name: '桃園市', label: '桃園市' },
{ name: '新竹市', label: '新竹市' },
{ name: '新竹縣', label: '新竹縣' },
{ name: '苗栗縣', label: '苗栗縣' },
{ name: '台中市', label: '台中市' },
{ name: '南投縣', label: '南投縣' },
{ name: '彰化縣', label: '彰化縣' },
{ name: '雲林縣', label: '雲林縣' },
{ name: '嘉義市', label: '嘉義市' },
{ name: '嘉義縣', label: '嘉義縣' },
{ name: '台南市', label: '台南市' },
{ name: '高雄市', label: '高雄市' },
{ name: '屏東縣', label: '屏東縣' },
{ name: '台東縣', label: '台東縣' },
{ name: '花蓮縣', label: '花蓮縣' },
{ name: '宜蘭縣', label: '宜蘭縣' },
{ name: '澎湖縣', label: '澎湖縣' },
{ name: '金門縣', label: '金門縣' },
{ name: '連江縣', label: '連江縣' },
];
12 changes: 12 additions & 0 deletions constants/category.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,50 +62,62 @@ export const SEARCH_TAGS = {
export const CATEGORIES = [
{
key: 'language',
label: '語言與文學',
value: '語言與文學',
},
{
key: 'math',
label: '數學與邏輯',
value: '數學與邏輯',
},
{
key: 'comsci',
label: '資訊與工程',
value: '資訊與工程',
},
{
key: 'humanity',
label: '人文社會',
value: '人文社會',
},
{
key: 'natusci',
label: '自然科學',
value: '自然科學',
},
{
key: 'art',
label: '藝術',
value: '藝術',
},
{
key: 'education',
label: '教育',
value: '教育',
},
{
key: 'life',
label: '生活',
value: '生活',
},
{
key: 'health',
label: '運動/心理/醫學',
value: '運動/心理/醫學',
},
{
key: 'business',
label: '商業與社會創新',
value: '商業與社會創新',
},
{
key: 'multires',
label: '綜合型學習資源',
value: '綜合型學習資源',
},
{
key: 'learningtools',
label: '學習/教學工具',
value: '學習/教學工具',
},
];
Expand Down
Loading
Loading