Skip to content

Commit

Permalink
Merge branch 'release'
Browse files Browse the repository at this point in the history
  • Loading branch information
aniku777tw committed Oct 26, 2023
2 parents 5ded49c + 0ca6992 commit 2394b39
Show file tree
Hide file tree
Showing 21 changed files with 706 additions and 731 deletions.
43 changes: 43 additions & 0 deletions src/components/common/CustomChakraSelect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { InputGroup, InputLeftElement } from '@chakra-ui/input'
import { Select } from '@chakra-ui/select'
import { LayoutProps } from '@chakra-ui/styled-system'
import React from 'react'
import styled from 'styled-components'

const StyledSelect = styled(Select)<{ 'with-icon'?: string }>`
${props =>
props['with-icon'] === 'leftIcon' &&
`
padding-left: 35px !important;
`}
`

const CustomChakraSelect: React.FC<{
options: { className?: string; value: string; name: string }[]
onChange: (event: React.ChangeEvent<HTMLSelectElement>) => void
defaultValue: string
className?: string
width?: LayoutProps['width']
leftIcon?: React.ReactNode
disabled?: boolean
}> = ({ className, width, options, leftIcon, onChange, defaultValue, disabled }) => {
return (
<InputGroup className={className} width={width} backgroundColor="white">
{leftIcon && <InputLeftElement>{leftIcon}</InputLeftElement>}
<StyledSelect
onChange={onChange}
defaultValue={defaultValue}
disabled={disabled}
with-icon={leftIcon ? 'leftIcon' : ''}
>
{options.map(option => (
<option key={option.value} className={option.className} value={option.value}>
{option.name}
</option>
))}
</StyledSelect>
</InputGroup>
)
}

export default CustomChakraSelect
24 changes: 24 additions & 0 deletions src/components/common/CustomMenuButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Menu, MenuButton, MenuItem, MenuList } from '@chakra-ui/menu'
import React from 'react'

const CustomMenuButton: React.FC<{
buttonElement: React.ReactNode | string
options: { className?: string; value: string; name: string }[]
onClick: (value: string) => void
className?: string
}> = ({ className, buttonElement, options, onClick }) => {
return (
<Menu>
<MenuButton className={className}>{buttonElement}</MenuButton>
<MenuList>
{options.map((option, index) => (
<MenuItem key={index} className={option.className} onClick={() => onClick(option.value)}>
{option.name}
</MenuItem>
))}
</MenuList>
</Menu>
)
}

export default CustomMenuButton
20 changes: 20 additions & 0 deletions src/components/common/CustomSearchInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Input, InputGroup, InputRightElement } from '@chakra-ui/input'
import { LayoutProps } from '@chakra-ui/styled-system'
import React from 'react'
const CustomSearchInput: React.FC<{
onChange: (event: React.ChangeEvent<HTMLInputElement>) => void
rightIcon?: React.ReactNode
width?: LayoutProps['width']
display?: LayoutProps['display']
placeholder?: string
className?: string
}> = ({ className, width, placeholder, onChange, rightIcon, display }) => {
return (
<InputGroup className={className} display={display} width={width} backgroundColor="white">
<Input placeholder={placeholder} onChange={onChange} />
{rightIcon && <InputRightElement>{rightIcon}</InputRightElement>}
</InputGroup>
)
}

export default CustomSearchInput
31 changes: 20 additions & 11 deletions src/components/common/MemberAvatar.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Text } from '@chakra-ui/react'
import { AvatarProps } from 'antd/lib/avatar'
import React from 'react'
import styled from 'styled-components'
Expand Down Expand Up @@ -45,19 +46,27 @@ const MemberAvatar: React.VFC<MemberAvatarProps> = ({
}

return (
<div className="d-flex align-items-center">
{renderAvatar ? (
renderAvatar(member)
) : noAvatar ? null : (
<AvatarImage src={member.pictureUrl || ''} shape={shape} size={size} />
)}
{renderText && renderText(member)}
{withName && (
<MemberName className={noAvatar ? '' : 'ml-3'} view={view}>
<>
{noAvatar ? (
<Text fontSize="14px" color="#9b9b9b" overflow="hidden" textOverflow="ellipsis" noOfLines={2}>
{member.name}
</MemberName>
</Text>
) : (
<div className="d-flex align-items-center">
{renderAvatar ? (
renderAvatar(member)
) : (
<AvatarImage src={member.pictureUrl || ''} shape={shape} size={size} />
)}
{renderText && renderText(member)}
{withName && (
<MemberName className="ml-3" view={view}>
{member.name}
</MemberName>
)}
</div>
)}
</div>
</>
)
}

Expand Down
9 changes: 6 additions & 3 deletions src/components/layout/DefaultLayout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ const StyledNotificationBar = styled.div<{ variant?: string }>`

const DefaultLayout: React.FC<{
white?: boolean
noHeader?: boolean
noFooter?: boolean
noHeader?: boolean | null
noFooter?: boolean | null
noCart?: boolean
noGeneralLogin?: boolean
noNotificationBar?: boolean
Expand Down Expand Up @@ -108,7 +108,10 @@ const DefaultLayout: React.FC<{
/>
)}

<StyledLayoutWrapper variant={white ? 'white' : undefined} header={noHeader ? 'noHeader' : ''}>
<StyledLayoutWrapper
variant={white ? 'white' : undefined}
header={noHeader ? 'noHeader' : '' /* for remove blank on the top */}
>
<StyledLayoutHeader className={`d-flex align-items-center justify-content-between ${noHeader ? 'hidden' : ''}`}>
<div className="d-flex align-items-center">
<LogoBlock className="mr-4">
Expand Down
150 changes: 125 additions & 25 deletions src/components/package/PackageCard.tsx
Original file line number Diff line number Diff line change
@@ -1,47 +1,147 @@
import { CommonTitleMixin } from 'lodestar-app-element/src/components/common'
import { Box, Text } from '@chakra-ui/react'
import { LayoutProps, SpaceProps } from '@chakra-ui/styled-system'
import dayjs from 'dayjs'
import { CommonTitleMixin, MultiLineTruncationMixin } from 'lodestar-app-element/src/components/common'
import React from 'react'
import { Link } from 'react-router-dom'
import styled from 'styled-components'
import { ProgramCover } from '../../components/common/Image'
import EmptyCover from '../../images/empty-cover.png'
import { ProgramPackageProps } from '../../types/programPackage'

const StyledCard = styled.div`
const StyledCard = styled(Box)`
overflow: hidden;
background: white;
border-radius: 4px;
box-shadow: 0 4px 12px 0 rgba(0, 0, 0, 0.15);
`
const StyledCover = styled.div<{ src: string }>`
padding-top: 56.25%;
background-image: url(${props => props.src});
background-size: cover;
background-position: center;
`
const StyledDescription = styled.div`
padding: 1.25rem;

const StyledTitle = styled(Text)<{ view?: string }>`
${MultiLineTruncationMixin}
${CommonTitleMixin}
${props =>
props.view === 'List'
? `
margin-bottom:0px;
display:block;
overflow: hidden;
text-overflow: ellipsis;
`
: `
margin-bottom: 1.25rem;
height: 3rem;
`}
`
const StyledTitle = styled.div`
&& {
margin-bottom: 1.25rem;
${CommonTitleMixin}
height: 3rem;
}

const StyledDescription = styled(Text)<{ view?: string }>`
${MultiLineTruncationMixin}
${props =>
props.view === 'List' &&
`
margin-top:4px;
`}
font-size: 12px;
color: var(--gray-dark);
letter-spacing: 0.4px;
`

const PackageDatetime: React.FC<{
deliveredAt: Date | undefined | null
lastViewedAt: Date | undefined | null
view?: string
display?: LayoutProps['display']
marginX?: SpaceProps['marginX']
marginBottom?: SpaceProps['marginBottom']
}> = ({ display, view, deliveredAt, lastViewedAt, marginX, marginBottom }) => {
return (
<StyledDescription display={display} marginX={marginX} marginBottom={marginBottom} view={view}>
{`${dayjs(deliveredAt).format('YYYY-MM-DD')} 購買`}
{lastViewedAt ? ` / ${dayjs(lastViewedAt).format('YYYY-MM-DD')} 上次觀看` : ` / 尚未觀看`}
</StyledDescription>
)
}

const PackageCard: React.VFC<
Pick<ProgramPackageProps, 'id' | 'coverUrl' | 'title'> & {
onClick?: () => void
isExpired?: boolean
memberId?: string
view?: string
programDateEnabled?: boolean
lastViewedAt?: Date | null
deliveredAt?: Date | null
}
> = ({ onClick, ...programPackage }) => {
> = ({
onClick,
id,
coverUrl,
title,
isExpired,
memberId,
view,
lastViewedAt,
programDateEnabled: datetimeEnabled,
deliveredAt,
}) => {
return (
<Link to={`/program-packages/${programPackage.id}`}>
<StyledCard>
<StyledCover src={programPackage.coverUrl || EmptyCover} />
<StyledDescription>
<StyledTitle>{programPackage.title}</StyledTitle>
</StyledDescription>
</StyledCard>
</Link>
<>
<Link to={isExpired ? `/program-packages/${id}` : `/program-packages/${id}/contents?memberId=${memberId}`}>
<StyledCard>
{view !== 'List' ? (
<>
<ProgramCover width="100%" paddingTop="calc(100% * 9/16)" src={coverUrl || EmptyCover} shape="rounded" />
<Box padding="1.25rem">
<StyledTitle>{title}</StyledTitle>
{datetimeEnabled && memberId && (
<PackageDatetime deliveredAt={deliveredAt} lastViewedAt={lastViewedAt} />
)}
</Box>
</>
) : (
<>
<Box
display="flex"
marginY={{ base: '16px', md: '0px' }}
marginX={{ base: '12px', md: '0px' }}
alignItems="center"
>
<ProgramCover
width={{ base: '40%', md: '15%' }}
height={{ base: '40%', md: '15%' }}
paddingTop={{ base: 'calc(40% * 9/16)', md: 'calc(15% * 9/16)' }}
margin={{ base: '0px 16px 0px 0px', md: '12px' }}
src={coverUrl || EmptyCover}
shape="rounded"
/>
<Box width="80%">
<StyledTitle fontSize="1rem" noOfLines={{ base: 2, md: 1 }} view={view}>
{title}
</StyledTitle>
{datetimeEnabled && memberId && (
<PackageDatetime
display={{ base: 'none', md: 'block' }}
view={view}
deliveredAt={deliveredAt}
lastViewedAt={lastViewedAt}
/>
)}
</Box>
</Box>
{datetimeEnabled && memberId && (
<PackageDatetime
display={{ base: 'block', md: 'none' }}
marginX="12px"
marginBottom="16px"
view={view}
deliveredAt={deliveredAt}
lastViewedAt={lastViewedAt}
/>
)}
</>
)}
</StyledCard>
</Link>
</>
)
}

Expand Down
Loading

0 comments on commit 2394b39

Please sign in to comment.