Skip to content

Commit

Permalink
Merge pull request #166 from KNU-HAEDAL/Refactor/cta-#165
Browse files Browse the repository at this point in the history
CTA 버튼, textarea 리팩토링 & 모듈화 #165
  • Loading branch information
joojjang authored Sep 28, 2024
2 parents 363ea5e + 830b4b7 commit 872ce51
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 82 deletions.
59 changes: 59 additions & 0 deletions src/components/common/cta/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import styled from '@emotion/styled';

type CTAProps = {
label: string;
disabled?: boolean;
onClick: () => void;
};

const CTA = ({ label, disabled, onClick }: CTAProps) => {
return (
<StyledCTA disabled={disabled} onClick={onClick}>
{label}
</StyledCTA>
);
};

export default CTA;

const StyledCTA = styled.button<{ disabled?: boolean }>`
width: calc(100% - 16px); // 부모 요소의 좌우 padding 빼고
border: none;
border-radius: 10px;
background-color: var(--color-green-01);
color: var(--color-white);
font-size: var(--font-size-md);
font-weight: bold;
outline: none;
padding: 10px 8px;
margin: 0 auto;
&:disabled {
cursor: not-allowed;
color: var(--color-grey-01);
background-color: var(--color-grey-02);
}
/* &:hover와 &:focus는 disabled === false일 때만 적용 */
&:hover,
&:focus {
${({ disabled }) =>
!disabled &&
`
opacity: 0.8 !important;
background-color: var(--color-green-01) !important;
color: var(--color-white) !important;
`}
}
`;

// 컨테이너 필요할 때 따로 임포트하여 사용
export const CTAContainer = styled.div`
position: sticky;
bottom: 0;
display: flex;
width: 100%;
height: 4rem;
padding: 8px 16px;
background-color: var(--color-white);
`;
48 changes: 48 additions & 0 deletions src/components/common/form/textarea/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import styled from '@emotion/styled';

type TextareaProps = {
placeholder?: string;
value: string;
onChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
valid?: boolean;
};

const Textarea = ({ placeholder, value, onChange, valid }: TextareaProps) => {
return (
<StyledTextarea
placeholder={placeholder}
value={value}
onChange={onChange}
valid={valid}
/>
);
};

export default Textarea;

const StyledTextarea = styled.textarea<{ valid?: boolean }>`
font-size: var(--font-size-sm);
color: var(--color-black);
border-radius: 20px;
border: ${({ valid }) =>
valid
? 'var(--color-grey-02) 1px solid'
: 'var(--color-class-05) 1px solid'};
padding: 12px;
width: 100%;
height: 180px;
resize: none;
outline: none;
&::placeholder {
color: var(--color-grey-01);
opacity: 1; /* Firefox에서 placeholder 색상을 명시적으로 설정하기 위해 추가 */
}
&:focus {
border: ${({ valid }) =>
valid
? 'var(--color-green-01) 1px solid'
: 'var(--color-class-05) 1px solid'};
}
`;
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import * as S from './styles';
import { joinChallenge } from '@/apis/challenge-detail/challenge.detail.api';
import { type Challenge } from '@/apis/challenge-detail/challenge.detail.response';
import { Chip } from '@/components/common/chip';
import CTA from '@/components/common/cta';
import { getDynamicPath } from '@/routes/protected-route';
import { Box } from '@chakra-ui/react';

type Props = {
challenge: Challenge;
Expand Down Expand Up @@ -71,7 +73,8 @@ const ChallengeItem = ({ challenge, maxDifficulty }: Props) => {
</Chip>
</S.ContentGrid>

<S.CTA onClick={handleJoinChallenge}>참여하기</S.CTA>
<Box margin='0 0 16px 0' />
<CTA label='참여하기' onClick={handleJoinChallenge} />
</S.Wrapper>
);
};
Expand Down
13 changes: 0 additions & 13 deletions src/pages/challenge-detail/components/challenge-item/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,3 @@ export const Bar = styled(MaxBar)<{ width: number }>`
export const TimesPeriodContent = styled(Text)`
margin: 0 0 0 auto;
`;

export const CTA = styled.button`
width: calc(100% - 16px); // 부모 요소의 좌우 padding 빼고
padding: 10px 8px;
margin: auto;
border-radius: 10px;
background-color: var(--color-green-01);
color: var(--color-white);
font-weight: bold;
font-size: var(--font-size-md);
margin-top: 16px;
`;
80 changes: 12 additions & 68 deletions src/pages/review-write/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';

import { postReview } from '@/apis/review/review.api';
import CTA, { CTAContainer } from '@/components/common/cta';
import Textarea from '@/components/common/form/textarea';
import { StarRating } from '@/components/common/star-rating';
import TopBar from '@/components/features/layout/top-bar';
import { useChallengeStore } from '@/store/useChallengeStore';
Expand Down Expand Up @@ -61,12 +63,14 @@ const ReviewWrite = () => {
const handleContentChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
const newContent = e.target.value;
setContent(newContent);
// console.log(content); // test

if (newContent.trim() && newContent.length >= 20) {
setIsContentValid(true);
} else {
setIsContentValid(false);
}
// console.log(isContentValid); // test
};

const handleSaveReview = () => {
Expand Down Expand Up @@ -155,7 +159,7 @@ const ReviewWrite = () => {
<Text fontSize='var(--font-size-md)' fontWeight='600' lineHeight={10}>
소감
</Text>
<Content
<Textarea
placeholder='챌린지 완수 후 느낀 점을 적어주세요.'
value={content}
onChange={handleContentChange}
Expand Down Expand Up @@ -184,11 +188,13 @@ const ReviewWrite = () => {
될 수 있습니다.
</Text>
</FlexBox>
<CTABox>
<SubmitButton disabled={isButtonDisabled} onClick={handleSaveReview}>
등록하기
</SubmitButton>
</CTABox>
<CTAContainer>
<CTA
label='등록하기'
disabled={isButtonDisabled}
onClick={handleSaveReview}
/>
</CTAContainer>
</Wrapper>
</>
);
Expand Down Expand Up @@ -261,65 +267,3 @@ const Chip = styled.button<{ isSelected: boolean }>`
color: var(--color-green-01);
`}
`;

const Content = styled.textarea<{ valid?: boolean }>`
font-size: var(--font-size-sm);
color: var(--color-black);
border-radius: 20px;
border: ${({ valid }) =>
valid
? 'var(--color-grey-02) 1px solid'
: 'var(--color-class-05) 1px solid'};
padding: 12px;
width: 100%;
height: 180px;
resize: none;
outline: none;
&::placeholder {
color: var(--color-grey-01);
opacity: 1; /* Firefox에서 placeholder 색상을 명시적으로 설정하기 위해 추가 */
}
&:focus {
border: ${({ valid }) =>
valid
? 'var(--color-green-01) 1px solid'
: 'var(--color-class-05) 1px solid'};
}
`;

const CTABox = styled(Box)`
position: sticky;
bottom: 0;
display: flex;
width: 100%;
height: 4rem;
padding: 8px 16px;
background-color: var(--color-white);
`;

const SubmitButton = styled.button<{ disabled?: boolean }>`
width: 100%;
height: 100%;
border: none;
border-radius: 10px;
background-color: var(--color-green-01);
color: var(--color-white);
font-size: var(--font-size-md);
font-weight: bold;
outline: none;
&:disabled {
cursor: not-allowed;
color: var(--color-grey-01);
background-color: var(--color-grey-02);
}
&:focus,
&:hover {
opacity: 0.8 !important;
background-color: var(--color-green-01) !important;
color: var(--color-white) !important;
}
`;

0 comments on commit 872ce51

Please sign in to comment.