Skip to content

Commit

Permalink
Merge pull request #35 from daodaoedu/feature/group-detail
Browse files Browse the repository at this point in the history
Feature/group detail
  • Loading branch information
JohnsonMao authored Feb 10, 2024
2 parents fa0c22b + fdc6ab1 commit 4c88a0d
Show file tree
Hide file tree
Showing 32 changed files with 1,259 additions and 110 deletions.
41 changes: 41 additions & 0 deletions components/Group/Form/Form.styled.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import styled from '@emotion/styled';
import InputLabel from '@mui/material/InputLabel';

export const StyledHeading = styled.h1`
margin-bottom: 8px;
text-align: center;
font-size: 22px;
font-weight: 700;
color: #536166;
`;

export const StyledDescription = styled.p`
margin-bottom: 40px;
text-align: center;
font-size: 14px;
font-weight: 400;
color: #536166;
`;

export const StyledContainer = styled.main`
position: relative;
margin: 0 auto;
width: 720px;
@media (max-width: 760px) {
padding: 20px;
width: 100%;
}
`;

export const StyledLabel = styled(InputLabel)`
display: block;
margin-bottom: 8px;
font-size: 16px;
font-weight: 500;
color: #293a3d;
`;

export const StyledGroup = styled.div`
margin-bottom: 20px;
`;
85 changes: 85 additions & 0 deletions components/Group/Form/FormItem.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { useId } from 'react';
import Box from '@mui/material/Box';
import TextField from '@mui/material/TextField';
import FormControlLabel from '@mui/material/FormControlLabel';
import Checkbox from '@mui/material/Checkbox';
import { StyledLabel, StyledGroup } from './Form.styled';
import Select from './Select';

function Wrapper({ id, required, label, children }) {
return (
<StyledGroup>
<StyledLabel htmlFor={id} required={required}>
{label}
</StyledLabel>
{children}
</StyledGroup>
);
}

export default function FormItem({
type,
label,
placeholder,
required,
options,
itemLabel,
itemValue,
value = '',
}) {
const id = useId();
const formItemId = `form-item-${id}`;
const wrapperProps = { id: formItemId, required, label };

if (type === 'select') {
return (
<Wrapper {...wrapperProps}>
<Select
id={formItemId}
options={options}
placeholder={placeholder}
value={value}
itemLabel={itemLabel}
itemValue={itemValue}
/>
</Wrapper>
);
}

if (type === 'location') {
return (
<Wrapper {...wrapperProps}>
<Box sx={{ display: 'flex', label: { whiteSpace: 'nowrap' } }}>
<FormControlLabel control={<Checkbox />} label="實體活動" />
<Select
id={formItemId}
options={options}
placeholder="地點"
value={value}
itemLabel={itemLabel}
itemValue={itemValue}
/>
</Box>
<div>
<FormControlLabel control={<Checkbox />} label="線上" />
</div>
<div>
<FormControlLabel control={<Checkbox />} label="待討論" />
</div>
</Wrapper>
);
}

return (
<Wrapper {...wrapperProps}>
<TextField
fullWidth
id={formItemId}
sx={{ '& legend': { display: 'none' } }}
size="small"
placeholder={placeholder}
value={value}
/>
</Wrapper>
);
}
45 changes: 45 additions & 0 deletions components/Group/Form/Select.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import MuiSelect from '@mui/material/Select';
import MenuItem from '@mui/material/MenuItem';

export default function Select({
id,
value,
placeholder,
options = [],
itemLabel = 'label',
itemValue = 'key',
fullWidth = true,
sx,
}) {
const getValue = (any, key) => (typeof any === 'object' ? any[key] : any);

return (
<MuiSelect
displayEmpty
fullWidth={fullWidth}
id={id}
size="small"
sx={{
color: value ? '#000' : '#92989A',
'& legend': { display: 'none' },
'& fieldset': { top: 0 },
...sx,
}}
value={value}
>
{placeholder && (
<MenuItem disabled value="">
{placeholder}
</MenuItem>
)}
{options.map((item) => (
<MenuItem
key={getValue(item, itemValue)}
value={getValue(item, itemValue)}
>
{getValue(item, itemLabel)}
</MenuItem>
))}
</MuiSelect>
);
}
70 changes: 70 additions & 0 deletions components/Group/Form/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import Box from '@mui/material/Box';
import { CATEGORIES } from '@/constants/category';
import { AREAS } from '@/constants/areas';
import StyledPaper from '../Paper.styled';
import FormItem from './FormItem';
import {
StyledHeading,
StyledDescription,
StyledContainer,
} from './Form.styled';

const TaiwanAreas = AREAS.filter((area) => area.label !== '線上');

export default function GroupForm({ mode }) {
const isCreateMode = mode === 'create';

return (
<Box sx={{ background: '#f3fcfc', py: '60px' }}>
<StyledContainer>
<StyledPaper sx={{ p: '40px', mb: '16px' }}>
<StyledHeading>
{isCreateMode ? '發起揪團' : '編輯揪團'}
</StyledHeading>
<StyledDescription>
填寫完整資訊可以幫助其他夥伴更了解揪團內容哦!
</StyledDescription>
<FormItem
label="主題"
placeholder="為你的揪團取個響亮的主題吧!"
required
/>
<FormItem label="活動圖片" />
<FormItem
type="select"
label="學習領域"
options={CATEGORIES}
placeholder="這個活動的學習領域?"
required
/>
<FormItem
type="location"
label="地點"
options={TaiwanAreas}
itemValue="label"
required
/>
<FormItem
type="datePicker"
label="時間"
placeholder="希望在什麼時間舉行?"
/>
</StyledPaper>
<StyledPaper sx={{ p: '40px' }}>
<FormItem label="想找的夥伴" placeholder="想找什麼類型的夥伴?" />
<FormItem
label="適合的教育階段"
placeholder="活動適合什麼教育階段的夥伴?"
required
/>
<FormItem
label="描述"
placeholder="簡單的跟大家介紹你是誰,說明你的揪團活動內容、運作方式,邀請志同道合的夥伴一起來參與!"
required
/>
<FormItem label="標籤" placeholder="搜尋或新增標籤" />
</StyledPaper>
</StyledContainer>
</Box>
);
}
8 changes: 5 additions & 3 deletions components/Group/GroupList/GroupCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ import {
StyledLabel,
StyledText,
StyledTitle,
StyledStatus,
} from './GroupCard.styled';

function GroupCard({
_id,
photoURL,
photoAlt,
title = '未定義主題',
Expand All @@ -25,7 +27,7 @@ function GroupCard({
updatedDate,
}) {
return (
<StyledGroupCard>
<StyledGroupCard href={`/group/detail?id=${_id}`}>
<Image alt={photoAlt || '未放封面'} src={photoURL || emptyCoverImg.src} />
<StyledContainer>
<StyledTitle>{title}</StyledTitle>
Expand All @@ -49,9 +51,9 @@ function GroupCard({
<StyledFooter>
<time>{timeDuration(updatedDate)}</time>
{isGrouping ? (
<div>揪團中</div>
<StyledStatus>揪團中</StyledStatus>
) : (
<div className="finished">已結束</div>
<StyledStatus className="finished">已結束</StyledStatus>
)}
</StyledFooter>
</StyledContainer>
Expand Down
59 changes: 30 additions & 29 deletions components/Group/GroupList/GroupCard.styled.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import styled from '@emotion/styled';
import Link from 'next/link';

export const StyledLabel = styled.span`
flex-basis: 50px;
Expand All @@ -21,6 +22,7 @@ export const StyledTitle = styled.h2`
font-weight: bold;
line-height: 1.4;
display: -webkit-box;
color: #293a3d;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
overflow: hidden;
Expand All @@ -39,41 +41,39 @@ export const StyledFooter = styled.footer`
justify-content: space-between;
align-items: center;
time,
div {
font-size: 12px;
}
time {
font-size: 12px;
font-weight: 300;
color: #92989a;
}
`;

div {
--bg-color: #def5f5;
--color: #16b9b3;
display: flex;
align-items: center;
padding: 4px 10px;
background: var(--bg-color);
color: var(--color);
border-radius: 4px;
font-weight: 500;
gap: 4px;
export const StyledStatus = styled.div`
--bg-color: #def5f5;
--color: #16b9b3;
display: flex;
align-items: center;
width: max-content;
font-size: 12px;
padding: 4px 10px;
background: var(--bg-color);
color: var(--color);
border-radius: 4px;
font-weight: 500;
gap: 4px;
&::before {
content: '';
display: block;
width: 8px;
height: 8px;
background: var(--color);
border-radius: 50%;
}
&::before {
content: '';
display: block;
width: 8px;
height: 8px;
background: var(--color);
border-radius: 50%;
}
&.finished {
--bg-color: #f3f3f3;
--color: #92989a;
}
&.finished {
--bg-color: #f3f3f3;
--color: #92989a;
}
`;

Expand All @@ -89,7 +89,8 @@ export const StyledAreas = styled.div`
align-items: center;
`;

export const StyledGroupCard = styled.div`
export const StyledGroupCard = styled(Link)`
display: block;
position: relative;
background: #fff;
padding: 0.5rem;
Expand Down
Loading

0 comments on commit 4c88a0d

Please sign in to comment.