From da0ec3217e969c29376e0309baf819d38a2f0217 Mon Sep 17 00:00:00 2001 From: Gyuhan Park <rbgks1937@naver.com> Date: Tue, 4 Feb 2025 01:46:55 +0900 Subject: [PATCH 01/11] =?UTF-8?q?[YS-243]=20refactor:=20Banner=20=EC=8A=A4?= =?UTF-8?q?=ED=83=80=EC=9D=BC=EB=A7=81=20=EB=A7=88=EC=9D=B4=EA=B7=B8?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=85=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/home/components/Banner/Banner.css.ts | 51 +++++++++++++++++++ .../home/components/Banner/Banner.styles.ts | 51 ------------------- src/app/home/components/Banner/Banner.tsx | 20 ++++---- 3 files changed, 61 insertions(+), 61 deletions(-) create mode 100644 src/app/home/components/Banner/Banner.css.ts delete mode 100644 src/app/home/components/Banner/Banner.styles.ts diff --git a/src/app/home/components/Banner/Banner.css.ts b/src/app/home/components/Banner/Banner.css.ts new file mode 100644 index 0000000..87d5dd2 --- /dev/null +++ b/src/app/home/components/Banner/Banner.css.ts @@ -0,0 +1,51 @@ +import { style } from '@vanilla-extract/css'; + +export const bannerLayout = style({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + gap: '1.2rem', +}); + +export const bannerWrapper = style({ + position: 'relative', + height: '15vh', + display: 'flex', + alignItems: 'center', +}); + +export const navigationLeft = style({ + position: 'absolute', + left: '1.6rem', +}); + +export const bannerCarousel = style({ + position: 'relative', + overflow: 'hidden', +}); + +export const carouselContainer = style({ + display: 'flex', + transition: 'all 1s', +}); + +export const navigationRight = style({ + position: 'absolute', + right: '1.6rem', +}); + +export const bannerImage = style({ + width: '100%', + height: 'auto', +}); + +export const slideCircleContainer = style({ + display: 'flex', + gap: '0.6rem', +}); + +export const slideCircle = style({ + borderRadius: '50%', + width: '0.6rem', + height: '0.6rem', +}); diff --git a/src/app/home/components/Banner/Banner.styles.ts b/src/app/home/components/Banner/Banner.styles.ts deleted file mode 100644 index 26cbcdf..0000000 --- a/src/app/home/components/Banner/Banner.styles.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { css } from '@emotion/react'; - -export const bannerLayout = css` - display: flex; - flex-direction: column; - align-items: center; - gap: 1.2rem; -`; - -export const bannerWrapper = css` - position: relative; - height: 15vh; - display: flex; - align-items: center; -`; - -export const navigationLeft = css` - position: absolute; - left: 1.6rem; -`; - -export const bannerCarousel = css` - position: relative; - overflow: hidden; -`; - -export const carouselContainer = css` - display: flex; - transition: all 1s; -`; - -export const navigationRight = css` - position: absolute; - right: 1.6rem; -`; - -export const bannerImage = css` - width: 100%; - height: auto; -`; - -export const slideCircleContainer = css` - display: flex; - gap: 0.6rem; -`; - -export const slideCircle = css` - border-radius: 50%; - width: 0.6rem; - height: 0.6rem; -`; diff --git a/src/app/home/components/Banner/Banner.tsx b/src/app/home/components/Banner/Banner.tsx index 22afc7f..1094b96 100644 --- a/src/app/home/components/Banner/Banner.tsx +++ b/src/app/home/components/Banner/Banner.tsx @@ -11,7 +11,7 @@ import { carouselContainer, navigationLeft, navigationRight, -} from './Banner.styles'; +} from './Banner.css'; import BannerImage from '@/assets/images/banner.svg'; import Icon from '@/components/Icon'; @@ -31,26 +31,26 @@ const Banner = () => { }; return ( - <div css={bannerLayout}> - <div css={bannerWrapper}> - <div css={bannerCarousel} ref={carouselRef}> + <div className={bannerLayout}> + <div className={bannerWrapper}> + <div className={bannerCarousel} ref={carouselRef}> <div - css={carouselContainer} + className={carouselContainer} style={{ transform: carouselRef.current ? `translateX(-${(bannerIdx - 1) * carouselRef.current.clientWidth}px)` : 'none', }} > - <Image src={BannerImage} alt="배너1" css={bannerImage} priority /> - <Image src={BannerImage} alt="배너2" css={bannerImage} priority /> - <Image src={BannerImage} alt="배너3" css={bannerImage} priority /> + <Image src={BannerImage} alt="배너1" className={bannerImage} priority /> + <Image src={BannerImage} alt="배너2" className={bannerImage} priority /> + <Image src={BannerImage} alt="배너3" className={bannerImage} priority /> </div> </div> - <button css={navigationLeft} onClick={handleClickPrev}> + <button className={navigationLeft} onClick={handleClickPrev}> <Icon icon="ChevronSquare" rotate={-90} cursor="pointer" /> </button> - <button css={navigationRight} onClick={handleClickNext}> + <button className={navigationRight} onClick={handleClickNext}> <Icon icon="ChevronSquare" rotate={90} cursor="pointer" /> </button> </div> From ade2409cad1a6ac16049121cf04b04733399b1ee Mon Sep 17 00:00:00 2001 From: Gyuhan Park <rbgks1937@naver.com> Date: Tue, 4 Feb 2025 03:39:21 +0900 Subject: [PATCH 02/11] =?UTF-8?q?[YS-243]=20refactor:=20FilterContainer=20?= =?UTF-8?q?=EC=8A=A4=ED=83=80=EC=9D=BC=EB=A7=81=20=EB=A7=88=EC=9D=B4?= =?UTF-8?q?=EA=B7=B8=EB=A0=88=EC=9D=B4=EC=85=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AreaFilter/AreaFilter.css.ts | 211 ++++++++++++++++++ .../AreaFilter/AreaFilter.styles.ts | 176 --------------- .../PostContainer/AreaFilter/AreaFilter.tsx | 97 ++++---- .../ContactTargetFilter.css.ts | 125 +++++++++++ .../ContactTargetFilter.styles.ts | 122 ---------- .../ContactTargetFilter.tsx | 69 +++--- .../FilterContainer/FilterContainer.css.ts | 7 + .../FilterContainer/FilterContainer.styles.ts | 7 - .../FilterContainer/FilterContainer.tsx | 4 +- .../PostContainer/PostContainer.css.ts | 34 +++ .../PostContainer/PostContainer.styles.ts | 31 --- .../PostContainer/PostContainer.tsx | 12 +- .../ProgressMethodFilter.css.ts | 52 +++++ .../ProgressMethodFilter.styles.ts | 45 ---- .../ProgressMethodFilter.tsx | 23 +- 15 files changed, 538 insertions(+), 477 deletions(-) create mode 100644 src/app/home/components/PostContainer/AreaFilter/AreaFilter.css.ts delete mode 100644 src/app/home/components/PostContainer/AreaFilter/AreaFilter.styles.ts create mode 100644 src/app/home/components/PostContainer/ContactTargetPopover/ContactTargetFilter.css.ts delete mode 100644 src/app/home/components/PostContainer/ContactTargetPopover/ContactTargetFilter.styles.ts create mode 100644 src/app/home/components/PostContainer/FilterContainer/FilterContainer.css.ts delete mode 100644 src/app/home/components/PostContainer/FilterContainer/FilterContainer.styles.ts create mode 100644 src/app/home/components/PostContainer/PostContainer.css.ts delete mode 100644 src/app/home/components/PostContainer/PostContainer.styles.ts create mode 100644 src/app/home/components/PostContainer/ProgressMethodFilter/ProgressMethodFilter.css.ts delete mode 100644 src/app/home/components/PostContainer/ProgressMethodFilter/ProgressMethodFilter.styles.ts diff --git a/src/app/home/components/PostContainer/AreaFilter/AreaFilter.css.ts b/src/app/home/components/PostContainer/AreaFilter/AreaFilter.css.ts new file mode 100644 index 0000000..b2c66b8 --- /dev/null +++ b/src/app/home/components/PostContainer/AreaFilter/AreaFilter.css.ts @@ -0,0 +1,211 @@ +import { style } from '@vanilla-extract/css'; +import { recipe } from '@vanilla-extract/recipes'; + +import { colors } from '@/styles/colors'; +import { fonts } from '@/styles/fonts.css'; + +// Popover Trigger (동적 색상은 CSS 변수로 처리) +export const triggerWrapper = style({ + ...fonts.label.large.SB14, + color: 'var(--trigger-color)', + backgroundColor: 'var(--trigger-bg)', + display: 'flex', + alignItems: 'center', + gap: '0.4rem', + padding: '0.5rem 1.4rem', + borderRadius: '1.2rem', + selectors: { + '&:hover': { + boxShadow: '0px 4px 16px rgba(53, 59, 61, 0.2)', + }, + }, +}); + +// Popover Content 영역 +export const regionContentContainer = style({ + backgroundColor: colors.field01, + position: 'relative', + top: '0.8rem', + display: 'flex', + flexDirection: 'column', + gap: '1.2rem', + width: '36.4rem', + height: '35rem', + padding: '1.2rem', + borderRadius: '1.2rem', + boxShadow: '0px 4px 16px rgba(53, 59, 61, 0.2)', +}); + +// 내부 레이아웃 +export const contentWrapper = style({ + backgroundColor: colors.field02, + borderRadius: '1.2rem', + display: 'flex', +}); + +// 지역 목록 컨테이너 +export const areaListContainer = style({ + flex: '0.5', + display: 'flex', + flexDirection: 'column', + gap: '0.4rem', + padding: '1.2rem 0.8rem', + backgroundColor: colors.field02, + borderRadius: '1.2rem', + height: '28rem', + overflow: 'scroll', +}); + +// 기본 텍스트 스타일 +export const areaName = style({ + ...fonts.label.large.M14, + color: colors.text06, +}); + +// 선택된 지역 텍스트 스타일 +export const selectedAreaName = style({ + color: colors.textPrimary, +}); + +// 숫자 표시 스타일 +export const areaCount = style({ + ...fonts.label.medium.R13, + color: colors.text03, +}); + +// 지역 버튼을 recipe로 정의 (selected 여부에 따라 스타일이 변경됨) +export const areaButtonRecipe = recipe({ + base: { + display: 'flex', + gap: '0.4rem', + alignItems: 'center', + padding: '0.6rem 1.2rem', + borderRadius: '1.2rem', + }, + variants: { + selected: { + true: { + backgroundColor: colors.primaryTinted, + outline: `0.1rem solid ${colors.lineTinted}`, + fontWeight: 'bold', + }, + false: { + selectors: { + '&:hover': { + backgroundColor: colors.field03, + }, + }, + }, + }, + }, + defaultVariants: { + selected: false, + }, +}); + +// 세로 구분선 +export const verticalLine = style({ + position: 'relative', + selectors: { + '&::after': { + content: '""', + width: '0.1rem', + height: '100%', + position: 'absolute', + top: '50%', + right: '0', + transform: 'translateY(-50%)', + backgroundColor: colors.line01, + }, + '&:last-child::after': { + display: 'none', + }, + }, +}); + +// 서브 지역 리스트 컨테이너 +export const subAreaListContainer = style({ + flex: 1, + display: 'flex', + flexDirection: 'column', + gap: '0.4rem', + height: '28rem', + overflow: 'scroll', + padding: '1.2rem 0.8rem', + borderRadius: '1.2rem', +}); + +// 서브 지역 항목 (label) 기본 스타일 +export const subAreaItem = style({ + display: 'flex', + alignItems: 'center', + justifyContent: 'space-between', + gap: '0.4rem', + height: '100%', + padding: '0.6rem 0.8rem', + borderRadius: '1.2rem', +}); + +// 선택된 서브 지역 항목 스타일 +export const selectedSubAreaLabel = style({ + outline: `0.1rem solid ${colors.lineTinted}`, + backgroundColor: colors.primaryTinted, +}); + +// 체크박스 숨김 처리 +export const checkbox = style({ + position: 'absolute', + opacity: 0, + pointerEvents: 'none', +}); + +// 서브 지역 정보 컨테이너 +export const subAreaInfo = style({ + display: 'flex', + gap: '0.4rem', + alignItems: 'center', +}); + +// placeholder (지역 미선택 시) +export const placeholderArea = style({ + ...fonts.label.large.R14, + color: colors.text03, + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + height: '100%', +}); + +// Footer 영역들 +export const footerContainer = style({ + display: 'flex', + justifyContent: 'flex-end', +}); + +export const footerButtonContainer = style({ + display: 'flex', + gap: '0.8rem', + alignItems: 'center', +}); + +// 버튼 스타일을 recipe로 재사용 (중복되는 padding, borderRadius 등) +export const buttonRecipe = recipe({ + base: { + ...fonts.label.large.SB14, + padding: '0.6rem 1.4rem', + border: 'none', + borderRadius: '1.2rem', + }, + variants: { + type: { + reset: { + backgroundColor: colors.field03, + color: colors.text06, + }, + save: { + backgroundColor: colors.primaryMint, + color: colors.text01, + }, + }, + }, +}); diff --git a/src/app/home/components/PostContainer/AreaFilter/AreaFilter.styles.ts b/src/app/home/components/PostContainer/AreaFilter/AreaFilter.styles.ts deleted file mode 100644 index 023b641..0000000 --- a/src/app/home/components/PostContainer/AreaFilter/AreaFilter.styles.ts +++ /dev/null @@ -1,176 +0,0 @@ -import { css, Theme } from '@emotion/react'; - -export const triggerWrapper = (theme: Theme) => css` - ${theme.fonts.label.large.SB14}; - color: ${theme.colors.text06}; - display: flex; - align-items: center; - gap: 0.4rem; - padding: 0.5rem 1.4rem; - border-radius: 1.2rem; - background-color: ${theme.colors.field01}; - - &:hover { - box-shadow: 0px 4px 16px rgba(53, 59, 61, 0.2); - } -`; - -export const regionContentContainer = (theme: Theme) => css` - background-color: ${theme.colors.field01}; - position: relative; - top: 0.8rem; - display: flex; - flex-direction: column; - gap: 1.2rem; - width: 36.4rem; - height: 35rem; - padding: 1.2rem; - border-radius: 1.2rem; - box-shadow: 0px 4px 16px rgba(53, 59, 61, 0.2); -`; - -export const contentWrapper = (theme: Theme) => css` - background-color: ${theme.colors.field02}; - border-radius: 1.2rem; - display: flex; -`; - -export const areaListContainer = (theme: Theme) => css` - flex: 0.5; - display: flex; - flex-direction: column; - gap: 0.4rem; - padding: 1.2rem 0.8rem; - background-color: ${theme.colors.field02}; - border-radius: 1.2rem; - - height: 28rem; - overflow: scroll; -`; - -export const areaName = (theme: Theme) => css` - ${theme.fonts.label.large.M14}; - color: ${theme.colors.text06}; -`; - -export const selectedAreaName = (theme: Theme) => css` - color: ${theme.colors.textPrimary}; -`; - -export const areaCount = (theme: Theme) => css` - ${theme.fonts.label.medium.R13}; - color: ${theme.colors.text03}; -`; - -export const areaButton = (theme: Theme) => css` - display: flex; - gap: 0.4rem; - align-items: center; - padding: 0.6rem 1.2rem; - border-radius: 1.2rem; - - &:hover { - background-color: ${theme.colors.field03}; - } -`; - -export const selectedAreaButton = (theme: Theme) => css` - background-color: ${theme.colors.primaryTinted}; - outline: 0.1rem solid ${theme.colors.lineTinted}; - font-weight: bold; -`; - -export const verticalLine = (theme: Theme) => css` - position: relative; - - ::after { - content: ''; - width: 0.1rem; - height: 100%; - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - background-color: ${theme.colors.line01}; - } - - :last-child::after { - display: none; - } -`; - -export const subAreaListContainer = css` - flex: 1; - display: flex; - flex-direction: column; - gap: 0.4rem; - height: 28rem; - overflow: scroll; - padding: 1.2rem 0.8rem; - border-radius: 1.2rem; -`; - -export const subAreaItem = css` - display: flex; - align-items: center; - justify-content: space-between; - gap: 0.4rem; - height: 100%; - padding: 0.6rem 0.8rem; - border-radius: 1.2rem; -`; - -export const selectedSubAreaLabel = (theme: Theme) => css` - outline: 0.1rem solid ${theme.colors.lineTinted}; - background-color: ${theme.colors.primaryTinted}; -`; - -export const checkbox = css` - position: absolute; - opacity: 0; - pointer-events: none; -`; - -export const subAreaInfo = css` - display: flex; - gap: 0.4rem; - align-items: center; -`; - -export const placeholderArea = (theme: Theme) => css` - ${theme.fonts.label.large.R14}; - color: ${theme.colors.text03}; - display: flex; - justify-content: center; - align-items: center; - height: 100%; -`; - -export const footerContainer = css` - display: flex; - justify-content: flex-end; -`; - -export const footerButtonContainer = css` - display: flex; - gap: 0.8rem; - align-items: center; -`; - -export const resetButton = (theme: Theme) => css` - ${theme.fonts.label.large.SB14}; - background-color: ${theme.colors.field03}; - color: ${theme.colors.text06}; - padding: 0.6rem 1.4rem; - border: none; - border-radius: 1.2rem; -`; - -export const saveButton = (theme: Theme) => css` - ${theme.fonts.label.large.SB14}; - background-color: ${theme.colors.primaryMint}; - color: ${theme.colors.text01}; - padding: 0.6rem 1.4rem; - border: none; - border-radius: 1.2rem; -`; diff --git a/src/app/home/components/PostContainer/AreaFilter/AreaFilter.tsx b/src/app/home/components/PostContainer/AreaFilter/AreaFilter.tsx index 933e597..835f244 100644 --- a/src/app/home/components/PostContainer/AreaFilter/AreaFilter.tsx +++ b/src/app/home/components/PostContainer/AreaFilter/AreaFilter.tsx @@ -1,37 +1,36 @@ 'use client'; import * as Popover from '@radix-ui/react-popover'; +import { assignInlineVars } from '@vanilla-extract/dynamic'; import { useState } from 'react'; import { - areaButton, - areaCount, + triggerWrapper, + regionContentContainer, + contentWrapper, areaListContainer, areaName, - checkbox, - contentWrapper, - footerButtonContainer, - footerContainer, - placeholderArea, - regionContentContainer, - resetButton, - saveButton, - selectedAreaButton, selectedAreaName, + areaCount, + areaButtonRecipe, + verticalLine, + subAreaListContainer, + subAreaItem, selectedSubAreaLabel, + checkbox, subAreaInfo, - subAreaItem, - subAreaListContainer, - triggerWrapper, - verticalLine, -} from './AreaFilter.styles'; + placeholderArea, + footerContainer, + footerButtonContainer, + buttonRecipe, +} from './AreaFilter.css'; import { areaMapper, subAreaMapper } from '@/app/home/home.constants'; import { Area } from '@/app/home/home.types'; import useFilterAreaQuery from '@/app/home/hooks/useFilterAreaQuery'; import useFilterSubAreaQuery from '@/app/home/hooks/useFilterSubAreaQuery'; import Icon from '@/components/Icon'; -import theme from '@/styles/theme'; +import { colors } from '@/styles/colors'; interface AreaFilterProps { onChange: (key: string, value: string | number) => void; @@ -68,13 +67,13 @@ const AreaFilter = ({ onChange }: AreaFilterProps) => { const [isSelected, setIsSelected] = useState(false); return ( - <Popover.Root open={isOpen} onOpenChange={(open) => setIsOpen(open)}> + <Popover.Root open={isOpen} onOpenChange={setIsOpen}> <Popover.Trigger - css={triggerWrapper} - style={{ - color: isSelected ? theme.colors.text01 : theme.colors.text06, - backgroundColor: isSelected ? theme.colors.field09 : theme.colors.field01, - }} + className={triggerWrapper} + style={assignInlineVars({ + '--trigger-color': isSelected ? colors.text01 : colors.text06, + '--trigger-bg': isSelected ? colors.field09 : colors.field01, + })} > <span> {isSelected @@ -86,49 +85,55 @@ const AreaFilter = ({ onChange }: AreaFilterProps) => { <Icon icon="Chevron" width={20} rotate={isOpen ? -180 : 0} cursor="pointer" /> </Popover.Trigger> <Popover.Portal> - <Popover.Content css={regionContentContainer}> - <div css={contentWrapper}> - <div css={areaListContainer}> + <Popover.Content className={regionContentContainer}> + <div className={contentWrapper}> + <div className={areaListContainer}> <button - css={[areaButton, selectedArea === 'ALL' && selectedAreaButton]} + className={areaButtonRecipe({ selected: selectedArea === 'ALL' })} onClick={() => handleAreaClick('ALL')} > - <span css={[areaName, selectedArea === 'ALL' && selectedAreaName]}> + <span className={`${areaName} ${selectedArea === 'ALL' && selectedAreaName}`}> {areaMapper['ALL']} </span> - <span css={areaCount}>{postArea?.reduce((acc, cur) => acc + cur.count, 0)}</span> + <span className={areaCount}> + {postArea?.reduce((acc, cur) => acc + cur.count, 0)} + </span> </button> - {postArea?.map((area, idx) => ( <button key={idx} - css={[areaButton, area.name === selectedArea && selectedAreaButton]} + className={areaButtonRecipe({ selected: area.name === selectedArea })} onClick={() => handleAreaClick(area.name)} > - <span css={[areaName, area.name === selectedArea && selectedAreaName]}> + <span className={`${areaName} ${area.name === selectedArea && selectedAreaName}`}> {areaMapper[area.name]} </span> - <span css={areaCount}>{area.count}</span> + <span className={areaCount}>{area.count}</span> </button> ))} </div> - <span css={verticalLine} /> - <div css={subAreaListContainer}> + <span className={verticalLine} /> + <div className={subAreaListContainer}> {selectedArea ? ( postSubArea?.map((subArea, idx) => ( <label key={idx} - css={[subAreaItem, checkedSubAreas[subArea.name] && selectedSubAreaLabel]} + className={`${subAreaItem} + ${checkedSubAreas[subArea.name] && selectedSubAreaLabel}`} > - <div css={subAreaInfo}> - <span css={[areaName, checkedSubAreas[subArea.name] && selectedAreaName]}> + <div className={subAreaInfo}> + <span + className={`${areaName} ${ + checkedSubAreas[subArea.name] && selectedAreaName + }`} + > {subAreaMapper[subArea.name]} </span> - <span css={areaCount}>{subArea.count}</span> + <span className={areaCount}>{subArea.count}</span> </div> <input type="checkbox" - css={checkbox} + className={checkbox} checked={!!checkedSubAreas[subArea.name]} onChange={() => handleSubAreaCheck(subArea.name)} /> @@ -137,7 +142,7 @@ const AreaFilter = ({ onChange }: AreaFilterProps) => { icon="CheckSquareFill" width={20} height={20} - color={theme.colors.primaryMint} + color={colors.primaryMint} /> ) : ( <Icon icon="CheckSquareEmpty" width={20} height={20} /> @@ -145,16 +150,16 @@ const AreaFilter = ({ onChange }: AreaFilterProps) => { </label> )) ) : ( - <div css={placeholderArea}> + <div className={placeholderArea}> <span>지역을 먼저 선택해 주세요</span> </div> )} </div> </div> - <div css={footerContainer}> - <div css={footerButtonContainer}> + <div className={footerContainer}> + <div className={footerButtonContainer}> <button - css={resetButton} + className={buttonRecipe({ type: 'reset' })} onClick={() => { setSelectedArea(''); setCheckedSubAreas({}); @@ -162,7 +167,7 @@ const AreaFilter = ({ onChange }: AreaFilterProps) => { > 초기화 </button> - <button onClick={handleClickSave} css={saveButton}> + <button onClick={handleClickSave} className={buttonRecipe({ type: 'save' })}> 저장 </button> </div> diff --git a/src/app/home/components/PostContainer/ContactTargetPopover/ContactTargetFilter.css.ts b/src/app/home/components/PostContainer/ContactTargetPopover/ContactTargetFilter.css.ts new file mode 100644 index 0000000..72f239c --- /dev/null +++ b/src/app/home/components/PostContainer/ContactTargetPopover/ContactTargetFilter.css.ts @@ -0,0 +1,125 @@ +import { style } from '@vanilla-extract/css'; + +import { colors } from '@/styles/colors'; +import { fonts } from '@/styles/fonts.css'; + +export const genderSelectWrapper = style({ + display: 'flex', + flexDirection: 'column', + gap: '0.8rem', +}); + +export const ageSelectWrapper = style({ + display: 'flex', + flexDirection: 'column', + gap: '0.8rem', +}); + +export const popoverTrigger = style({ + ...fonts.label.large.SB14, + display: 'flex', + gap: '0.4rem', + alignItems: 'center', + width: 'fit-content', + padding: '0.6rem 1.4rem', + border: 'none', + borderRadius: '1.2rem', + color: 'var(--popover-trigger-color)', + backgroundColor: 'var(--popover-trigger-bg)', + selectors: { + '&:hover': { + boxShadow: '0px 4px 16px rgba(53, 59, 61, 0.2)', + }, + }, +}); + +export const popoverContent = style({ + display: 'flex', + flexDirection: 'column', + padding: '2rem', + borderRadius: '1.2rem', + backgroundColor: colors.field01, + boxShadow: '0px 4px 16px rgba(53, 59, 61, 0.2)', + gap: '1.6rem', + marginTop: '0.6rem', +}); + +export const labelWrapper = style({ + display: 'flex', + gap: '0.4rem', + alignItems: 'center', +}); + +export const label = style({ + ...fonts.body.normal.M16, + color: colors.text06, +}); + +export const subLabel = style({ + ...fonts.label.large.R14, + color: colors.text03, +}); + +export const genderButtonGroup = style({ + display: 'flex', + gap: '0.8rem', +}); + +export const genderButton = style({ + ...fonts.label.large.M14, + color: colors.text06, + padding: '0.6rem 2.15rem', + borderRadius: '1.2rem', + outline: `1px solid ${colors.line01}`, + transition: 'color 0.1s, background-color 0.1s, outline 0.1s', + width: '10.6rem', + selectors: { + '&.active': { + backgroundColor: colors.primaryTinted, + outline: `0.1rem solid ${colors.lineTinted}`, + color: colors.textPrimary, + }, + }, +}); + +export const ageInputContainer = style({ + display: 'flex', + gap: '1rem', + alignItems: 'center', +}); + +export const ageInput = style({ + ...fonts.label.large.M14, + width: '100%', + padding: '0.6rem 0 0.6rem 1.6rem', + border: `0.1rem solid ${colors.line01}`, + borderRadius: '1.2rem', + selectors: { + '&:focus': { + outline: 'none', + border: `0.1rem solid ${colors.primaryMint}`, + }, + }, +}); + +export const footerButtonContainer = style({ + display: 'flex', + gap: '0.8rem', + justifyContent: 'flex-end', +}); + +export const resetButton = style({ + ...fonts.label.large.SB14, + padding: '0.6rem 1.4rem', + borderRadius: '1.2rem', + backgroundColor: colors.field03, + color: colors.text06, +}); + +export const saveButton = style({ + ...fonts.label.large.SB14, + padding: '0.6rem 1.4rem', + borderRadius: '1.2rem', + backgroundColor: colors.primaryMint, + color: colors.text01, +}); diff --git a/src/app/home/components/PostContainer/ContactTargetPopover/ContactTargetFilter.styles.ts b/src/app/home/components/PostContainer/ContactTargetPopover/ContactTargetFilter.styles.ts deleted file mode 100644 index 7cd2d71..0000000 --- a/src/app/home/components/PostContainer/ContactTargetPopover/ContactTargetFilter.styles.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { css, Theme } from '@emotion/react'; - -export const genderSelectWrapper = css` - display: flex; - flex-direction: column; - gap: 0.8rem; -`; - -export const ageSelectWrapper = css` - display: flex; - flex-direction: column; - gap: 0.8rem; -`; - -export const popoverTrigger = (theme: Theme) => css` - ${theme.fonts.label.large.SB14}; - display: flex; - gap: 0.4rem; - align-items: center; - width: fit-content; - padding: 0.6rem 1.4rem; - border: none; - border-radius: 1.2rem; - - &:hover { - box-shadow: 0px 4px 16px rgba(53, 59, 61, 0.2); - } -`; - -export const popoverContent = (theme: Theme) => css` - display: flex; - flex-direction: column; - padding: 2rem; - border-radius: 1.2rem; - background-color: ${theme.colors.field01}; - box-shadow: 0px 4px 16px rgba(53, 59, 61, 0.2); - gap: 1.6rem; - margin-top: 0.6rem; -`; - -export const labelWrapper = css` - display: flex; - gap: 0.4rem; - align-items: center; -`; - -export const label = (theme: Theme) => css` - ${theme.fonts.body.normal.M16}; - color: ${theme.colors.text06}; -`; - -export const subLabel = (theme: Theme) => css` - ${theme.fonts.label.large.R14}; - color: ${theme.colors.text03}; -`; - -export const buttonGroup = (theme: Theme) => css` - display: flex; - gap: 0.8rem; - - button { - ${theme.fonts.label.large.M14}; - color: ${theme.colors.text06}; - padding: 0.6rem 2.15rem; - border-radius: 1.2rem; - outline: 1px solid ${theme.colors.line01}; - transition: color 0.1s, background-color 0.1s, outline 0.1s; - width: 10.6rem; - } - - button.active { - background-color: ${theme.colors.primaryTinted}; - outline: 0.1rem solid ${theme.colors.lineTinted}; - color: ${theme.colors.textPrimary}; - } -`; - -export const ageInputContainer = (theme: Theme) => css` - display: flex; - gap: 1rem; - align-items: center; - - input { - ${theme.fonts.label.large.M14}; - width: 100%; - padding: 0.6rem 0 0.6rem 1.6rem; - border: 0.1rem solid ${theme.colors.line01}; - border-radius: 1.2rem; - - :focus { - outline: none; - border: 0.1rem solid ${theme.colors.primaryMint}; - } - } -`; - -export const ageButtonWrapper = css` - display: flex; - gap: 0.4rem; -`; - -export const footerButtonContainer = (theme: Theme) => css` - display: flex; - gap: 0.8rem; - justify-content: flex-end; - - button { - ${theme.fonts.label.large.SB14}; - padding: 0.6rem 1.4rem; - border-radius: 1.2rem; - } -`; - -export const resetButton = (theme: Theme) => css` - background-color: ${theme.colors.field03}; - color: ${theme.colors.text06}; -`; - -export const saveButton = (theme: Theme) => css` - background-color: ${theme.colors.primaryMint}; - color: ${theme.colors.text01}; -`; diff --git a/src/app/home/components/PostContainer/ContactTargetPopover/ContactTargetFilter.tsx b/src/app/home/components/PostContainer/ContactTargetPopover/ContactTargetFilter.tsx index b92648a..669256c 100644 --- a/src/app/home/components/PostContainer/ContactTargetPopover/ContactTargetFilter.tsx +++ b/src/app/home/components/PostContainer/ContactTargetPopover/ContactTargetFilter.tsx @@ -1,24 +1,27 @@ 'use client'; import * as Popover from '@radix-ui/react-popover'; +import { assignInlineVars } from '@vanilla-extract/dynamic'; import { ChangeEvent, useState } from 'react'; import { - ageInputContainer, - ageSelectWrapper, - buttonGroup, - footerButtonContainer, genderSelectWrapper, - label, - labelWrapper, - popoverContent, + ageSelectWrapper, popoverTrigger, + popoverContent, + labelWrapper, + label, + ageInputContainer, + footerButtonContainer, resetButton, saveButton, -} from './ContactTargetFilter.styles'; + ageInput, + genderButton, + genderButtonGroup, +} from './ContactTargetFilter.css'; import Icon from '@/components/Icon'; -import theme from '@/styles/theme'; +import { colors } from '@/styles/colors'; const isEqualByKeys = ( obj1: Record<string, string>, @@ -81,44 +84,48 @@ const ContactTargetFilter = ({ onChange }: ContactTargetFilterProps) => { return ( <Popover.Root open={isOpen} onOpenChange={() => setIsOpen((prev) => !prev)}> <Popover.Trigger - css={popoverTrigger} - style={{ - color: isSelected ? theme.colors.text01 : theme.colors.text06, - backgroundColor: isSelected ? theme.colors.field09 : theme.colors.field01, - }} + className={popoverTrigger} + style={assignInlineVars({ + '--popover-trigger-color': isSelected ? colors.text01 : colors.text06, + '--popover-trigger-bg': isSelected ? colors.field09 : colors.field01, + })} > <span>{isSelected ? `${age}세 ${gender.label}` : '모집 대상'}</span> <Icon icon="Chevron" width={20} rotate={isOpen ? -180 : 0} cursor="pointer" /> </Popover.Trigger> <Popover.Portal> - <Popover.Content css={popoverContent}> - <div css={genderSelectWrapper}> - <span css={label}>성별</span> - <div css={buttonGroup}> - {GENDER.map((gender) => ( + <Popover.Content className={popoverContent}> + <div className={genderSelectWrapper}> + <span className={label}>성별</span> + <div className={genderButtonGroup}> + {GENDER.map((g) => ( <button - key={gender.value} - className={gender === filteredGender ? 'active' : ''} - onClick={() => setFilteredGender(gender as Gender)} + key={g.value} + className={`${genderButton} ${g === filteredGender ? 'active' : ''}`} + onClick={() => setFilteredGender(g as Gender)} > - {gender.label} + {g.label} </button> ))} </div> </div> - <div css={ageSelectWrapper}> - <div css={labelWrapper}> - <span css={label}>나이</span> + <div className={ageSelectWrapper}> + <div className={labelWrapper}> + <span className={label}>나이</span> </div> - <div css={ageInputContainer}> - <input onChange={handleChangeFilteredAge} placeholder="만 나이 입력" /> + <div className={ageInputContainer}> + <input + className={ageInput} + onChange={handleChangeFilteredAge} + placeholder="만 나이 입력" + /> </div> </div> - <div css={footerButtonContainer}> - <button onClick={handleReset} css={resetButton}> + <div className={footerButtonContainer}> + <button onClick={handleReset} className={resetButton}> 초기화 </button> - <button onClick={handleSave} css={saveButton}> + <button onClick={handleSave} className={saveButton}> 저장 </button> </div> diff --git a/src/app/home/components/PostContainer/FilterContainer/FilterContainer.css.ts b/src/app/home/components/PostContainer/FilterContainer/FilterContainer.css.ts new file mode 100644 index 0000000..f413ced --- /dev/null +++ b/src/app/home/components/PostContainer/FilterContainer/FilterContainer.css.ts @@ -0,0 +1,7 @@ +import { style } from '@vanilla-extract/css'; + +export const filterLayout = style({ + display: 'flex', + gap: '0.8rem', + height: '3.2rem', +}); diff --git a/src/app/home/components/PostContainer/FilterContainer/FilterContainer.styles.ts b/src/app/home/components/PostContainer/FilterContainer/FilterContainer.styles.ts deleted file mode 100644 index 526f540..0000000 --- a/src/app/home/components/PostContainer/FilterContainer/FilterContainer.styles.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { css } from '@emotion/react'; - -export const filterLayout = css` - display: flex; - gap: 0.8rem; - height: 3.2rem; -`; diff --git a/src/app/home/components/PostContainer/FilterContainer/FilterContainer.tsx b/src/app/home/components/PostContainer/FilterContainer/FilterContainer.tsx index 151616a..d507a8a 100644 --- a/src/app/home/components/PostContainer/FilterContainer/FilterContainer.tsx +++ b/src/app/home/components/PostContainer/FilterContainer/FilterContainer.tsx @@ -1,4 +1,4 @@ -import { filterLayout } from './FilterContainer.styles'; +import { filterLayout } from './FilterContainer.css'; import AreaFilter from '../AreaFilter/AreaFilter'; import ContactTargetFilter from '../ContactTargetPopover/ContactTargetFilter'; import ProgressMethodFilter from '../ProgressMethodFilter/ProgressMethodFilter'; @@ -9,7 +9,7 @@ interface FilterContainerProps { const FilterContainer = ({ handleFilterChange }: FilterContainerProps) => { return ( - <div css={filterLayout}> + <div className={filterLayout}> <ProgressMethodFilter onChange={(value) => handleFilterChange('matchType', value)} /> <ContactTargetFilter onChange={handleFilterChange} /> <AreaFilter onChange={handleFilterChange} /> diff --git a/src/app/home/components/PostContainer/PostContainer.css.ts b/src/app/home/components/PostContainer/PostContainer.css.ts new file mode 100644 index 0000000..7e359b0 --- /dev/null +++ b/src/app/home/components/PostContainer/PostContainer.css.ts @@ -0,0 +1,34 @@ +import { style } from '@vanilla-extract/css'; + +import { colors } from '@/styles/colors'; +import { fonts } from '@/styles/fonts.css'; + +export const postContainerLayout = style({ + margin: '2rem 0', + display: 'flex', + flexDirection: 'column', + gap: '1.6rem', +}); + +export const postContainerTitle = style({ + ...fonts.title.medium.SB20, + color: colors.text06, +}); + +export const postCardContainer = style({ + display: 'flex', + flexDirection: 'column', + gap: '0.6rem', + minHeight: '40rem', +}); + +export const totalPostCount = style({ + ...fonts.label.large.R14, + color: colors.text03, +}); + +export const filterWrapper = style({ + display: 'flex', + alignItems: 'center', + justifyContent: 'space-between', +}); diff --git a/src/app/home/components/PostContainer/PostContainer.styles.ts b/src/app/home/components/PostContainer/PostContainer.styles.ts deleted file mode 100644 index 535d32d..0000000 --- a/src/app/home/components/PostContainer/PostContainer.styles.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { css, Theme } from '@emotion/react'; - -export const postContainerLayout = css` - margin: 2rem 0; - display: flex; - flex-direction: column; - gap: 1.6rem; -`; - -export const postContainerTitle = (theme: Theme) => css` - ${theme.fonts.title.medium.SB20}; - color: ${theme.colors.text06}; -`; - -export const postCardContainer = css` - display: flex; - flex-direction: column; - gap: 0.6rem; - min-height: 40rem; -`; - -export const totalPostCount = (theme: Theme) => css` - ${theme.fonts.label.large.R14}; - color: ${theme.colors.text03}; -`; - -export const filterWrapper = css` - display: flex; - align-items: center; - justify-content: space-between; -`; diff --git a/src/app/home/components/PostContainer/PostContainer.tsx b/src/app/home/components/PostContainer/PostContainer.tsx index dbdb730..babfddb 100644 --- a/src/app/home/components/PostContainer/PostContainer.tsx +++ b/src/app/home/components/PostContainer/PostContainer.tsx @@ -11,7 +11,7 @@ import { postContainerLayout, postContainerTitle, totalPostCount, -} from './PostContainer.styles'; +} from './PostContainer.css'; import { filterParticipantInfo } from '../../home.utils'; import useUserInfo from '../../hooks/useUserInfo'; @@ -63,9 +63,9 @@ const PostContainer = () => { }, [participantInfo]); return ( - <div css={postContainerLayout}> - <h2 css={postContainerTitle}>공고를 확인해 보세요</h2> - <div css={filterWrapper}> + <div className={postContainerLayout}> + <h2 className={postContainerTitle}>공고를 확인해 보세요</h2> + <div className={filterWrapper}> <FilterContainer handleFilterChange={handleFilterChange} /> <JoinCheckbox label="모집 중인 공고만 보기" @@ -74,8 +74,8 @@ const PostContainer = () => { isArrow={false} /> </div> - <div css={postCardContainer}> - <span css={totalPostCount}>총 {postListData?.content.length}개</span> + <div className={postCardContainer}> + <span className={totalPostCount}>총 {postListData?.content.length}개</span> <PostCardList postList={postListData?.content} /> </div> </div> diff --git a/src/app/home/components/PostContainer/ProgressMethodFilter/ProgressMethodFilter.css.ts b/src/app/home/components/PostContainer/ProgressMethodFilter/ProgressMethodFilter.css.ts new file mode 100644 index 0000000..36ade5b --- /dev/null +++ b/src/app/home/components/PostContainer/ProgressMethodFilter/ProgressMethodFilter.css.ts @@ -0,0 +1,52 @@ +import { style } from '@vanilla-extract/css'; + +import { colors } from '@/styles/colors'; +import { fonts } from '@/styles/fonts.css'; + +export const triggerWrapper = style({ + ...fonts.label.large.SB14, + // color: colors.text06, + color: 'var(--trigger-color)', + backgroundColor: 'var(--trigger-bg)', + display: 'flex', + alignItems: 'center', + justifyContent: 'space-between', + gap: '0.4rem', + borderRadius: '1.2rem', + padding: '0.5rem 1.4rem', + // backgroundColor: colors.field01, + cursor: 'pointer', + selectors: { + '&:hover': { + boxShadow: '0px 4px 16px rgba(53, 59, 61, 0.2)', + }, + }, +}); + +export const contentContainer = style({ + position: 'relative', + top: '3.6rem', + width: '10rem', + padding: '0.8rem', + backgroundColor: colors.field01, + borderRadius: '0.8rem', + boxShadow: '0px 4px 16px rgba(53, 59, 61, 0.2)', + overflow: 'hidden', +}); + +export const selectItem = style({ + ...fonts.label.large.M14, + color: colors.text06, + display: 'flex', + paddingLeft: '1.2rem', + alignItems: 'center', + height: '3.4rem', + borderRadius: '1.2rem', + cursor: 'pointer', + selectors: { + '&[data-highlighted]': { + backgroundColor: colors.field02, + outline: 'none', + }, + }, +}); diff --git a/src/app/home/components/PostContainer/ProgressMethodFilter/ProgressMethodFilter.styles.ts b/src/app/home/components/PostContainer/ProgressMethodFilter/ProgressMethodFilter.styles.ts deleted file mode 100644 index da7435c..0000000 --- a/src/app/home/components/PostContainer/ProgressMethodFilter/ProgressMethodFilter.styles.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { css, Theme } from '@emotion/react'; - -export const triggerWrapper = (theme: Theme) => css` - ${theme.fonts.label.large.SB14}; - color: ${theme.colors.text06}; - display: flex; - align-items: center; - justify-content: space-between; - gap: 0.4rem; - border-radius: 1.2rem; - padding: 0.5rem 1.4rem; - background-color: ${theme.colors.field01}; - cursor: pointer; - - &:hover { - box-shadow: 0px 4px 16px rgba(53, 59, 61, 0.2); - } -`; - -export const contentContainer = (theme: Theme) => css` - position: relative; - top: 3.6rem; - width: 10rem; - padding: 0.8rem; - background-color: ${theme.colors.field01}; - border-radius: 0.8rem; - box-shadow: 0px 4px 16px rgba(53, 59, 61, 0.2); - overflow: hidden; -`; - -export const selectItem = (theme: Theme) => css` - ${theme.fonts.label.large.M14}; - color: ${theme.colors.text06}; - display: flex; - padding-left: 1.2rem; - align-items: center; - height: 3.4rem; - border-radius: 1.2rem; - cursor: pointer; - - &[data-highlighted] { - background-color: ${theme.colors.field02}; - outline: none; - } -`; diff --git a/src/app/home/components/PostContainer/ProgressMethodFilter/ProgressMethodFilter.tsx b/src/app/home/components/PostContainer/ProgressMethodFilter/ProgressMethodFilter.tsx index 56fe2cb..da88816 100644 --- a/src/app/home/components/PostContainer/ProgressMethodFilter/ProgressMethodFilter.tsx +++ b/src/app/home/components/PostContainer/ProgressMethodFilter/ProgressMethodFilter.tsx @@ -1,12 +1,13 @@ 'use client'; import * as Select from '@radix-ui/react-select'; +import { assignInlineVars } from '@vanilla-extract/dynamic'; import { useState } from 'react'; -import { contentContainer, selectItem, triggerWrapper } from './ProgressMethodFilter.styles'; +import { triggerWrapper, contentContainer, selectItem } from './ProgressMethodFilter.css'; import Icon from '@/components/Icon'; -import theme from '@/styles/theme'; +import { colors } from '@/styles/colors'; interface FilterOption { label: '전체' | '대면' | '비대면'; @@ -45,27 +46,27 @@ const ProgressMethodFilter = ({ onChange }: ProgressMethodFilterProps) => { onOpenChange={(open) => setIsOpen(open)} > <Select.Trigger - css={triggerWrapper} - style={{ - color: isSelected ? theme.colors.text01 : theme.colors.text06, - backgroundColor: isSelected ? theme.colors.field09 : theme.colors.field01, - }} + className={triggerWrapper} + style={assignInlineVars({ + '--trigger-color': isSelected ? colors.text01 : colors.text06, + '--trigger-bg': isSelected ? colors.field09 : colors.field01, + })} > <span>{selectedValue.label}</span> <Select.Icon> <Icon icon="Chevron" width={20} rotate={isOpen ? -180 : 0} cursor="pointer" /> </Select.Icon> </Select.Trigger> - <Select.Content css={contentContainer}> + <Select.Content className={contentContainer}> <Select.Viewport> <Select.Group> - <Select.Item value="ALL" css={selectItem}> + <Select.Item value="ALL" className={selectItem}> <Select.ItemText>전체</Select.ItemText> </Select.Item> - <Select.Item value="ONLINE" css={selectItem}> + <Select.Item value="ONLINE" className={selectItem}> <Select.ItemText>대면</Select.ItemText> </Select.Item> - <Select.Item value="OFFLINE" css={selectItem}> + <Select.Item value="OFFLINE" className={selectItem}> <Select.ItemText>비대면</Select.ItemText> </Select.Item> </Select.Group> From ed1215632e295c887abc13ec7bb86b2a4a18c94b Mon Sep 17 00:00:00 2001 From: Gyuhan Park <rbgks1937@naver.com> Date: Tue, 4 Feb 2025 04:00:05 +0900 Subject: [PATCH 03/11] =?UTF-8?q?[YS-243]=20refactor:=20PostCardList=20?= =?UTF-8?q?=EC=8A=A4=ED=83=80=EC=9D=BC=EB=A7=81=20=EB=A7=88=EC=9D=B4?= =?UTF-8?q?=EA=B7=B8=EB=A0=88=EC=9D=B4=EC=85=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../home/components/PostCard/PostCard.css.ts | 88 +++++++++++++++++++ .../components/PostCard/PostCard.styles.ts | 83 ----------------- src/app/home/components/PostCard/PostCard.tsx | 30 +++---- .../EmptyPostCard/EmptyPostCard.css.ts | 30 +++++++ .../EmptyPostCard/EmptyPostCard.styles.ts | 27 ------ .../EmptyPostCard/EmptyPostCard.tsx | 10 +-- .../PostCardList/PostCardList.css.ts | 7 ++ .../PostCardList/PostCardList.styles.ts | 7 -- .../components/PostCardList/PostCardList.tsx | 4 +- .../JoinCheckbox/JoinCheckbox.css.ts | 52 +++++++++++ .../JoinCheckbox/JoinCheckbox.tsx | 26 +++--- src/app/page.tsx | 1 - src/components/Icon/icons/AllEmpty.tsx | 5 +- 13 files changed, 215 insertions(+), 155 deletions(-) create mode 100644 src/app/home/components/PostCard/PostCard.css.ts delete mode 100644 src/app/home/components/PostCard/PostCard.styles.ts create mode 100644 src/app/home/components/PostCardList/EmptyPostCard/EmptyPostCard.css.ts delete mode 100644 src/app/home/components/PostCardList/EmptyPostCard/EmptyPostCard.styles.ts create mode 100644 src/app/home/components/PostCardList/PostCardList.css.ts delete mode 100644 src/app/home/components/PostCardList/PostCardList.styles.ts create mode 100644 src/app/join/components/JoinCheckboxContainer/JoinCheckbox/JoinCheckbox.css.ts diff --git a/src/app/home/components/PostCard/PostCard.css.ts b/src/app/home/components/PostCard/PostCard.css.ts new file mode 100644 index 0000000..d3e656c --- /dev/null +++ b/src/app/home/components/PostCard/PostCard.css.ts @@ -0,0 +1,88 @@ +import { style } from '@vanilla-extract/css'; + +import { colors } from '@/styles/colors'; +import { fonts } from '@/styles/fonts.css'; + +export const postCardLayout = style({ + display: 'flex', + flexDirection: 'column', + justifyContent: 'space-between', + gap: '1.6rem', + + border: 'none', + borderRadius: '1.2rem', + + height: '20rem', + padding: '1.6rem 2rem', + backgroundColor: colors.field01, + + selectors: { + '&:hover': { + boxShadow: '0px 4px 16px rgba(53, 59, 61, 0.08)', + }, + }, +}); + +export const postHeader = style({ + display: 'flex', + flexDirection: 'column', + gap: '0.8rem', +}); + +export const postCardHeader = style({ + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + gap: '1.6rem', +}); + +export const postLocation = style({ + ...fonts.label.medium.R13, + color: colors.text03, +}); + +export const postCardRightHeader = style({ + display: 'flex', + alignItems: 'center', + gap: '0.4rem', +}); + +export const postViews = style({ + ...fonts.label.medium.R13, + color: colors.text03, +}); + +export const postTitle = style({ + ...fonts.title.small.SB18, + color: colors.text06, +}); + +export const contactedPostTag = style({ + width: 'fit-content', + padding: '0.6rem 0.85rem', + ...fonts.label.small.SB12, + color: colors.text05, + backgroundColor: colors.field03, + borderRadius: '3rem', +}); + +export const postRewardContainer = style({ + display: 'flex', + gap: '0.8rem', + alignItems: 'center', +}); + +export const announceText = style({ + ...fonts.label.medium.M13, + color: colors.text03, +}); + +export const postReward = style({ + ...fonts.label.medium.SB13, + color: colors.primaryMint, +}); + +export const postDate = style({ + ...fonts.label.medium.M13, + color: colors.text04, +}); diff --git a/src/app/home/components/PostCard/PostCard.styles.ts b/src/app/home/components/PostCard/PostCard.styles.ts deleted file mode 100644 index fee3c45..0000000 --- a/src/app/home/components/PostCard/PostCard.styles.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { css, Theme } from '@emotion/react'; - -export const postCardLayout = (theme: Theme) => css` - display: flex; - flex-direction: column; - gap: 1.6rem; - border: 1px solid black; - padding: 1.6rem 2rem; - - border: none; - border-radius: 1.2rem; - justify-content: space-between; - height: 20rem; - background-color: ${theme.colors.field01}; - - &:hover { - box-shadow: 0px 4px 16px rgba(53, 59, 61, 0.08); - } -`; - -export const postHeader = css` - display: flex; - flex-direction: column; - gap: 0.8rem; -`; - -export const postCardHeader = css` - display: flex; - justify-content: space-between; - align-items: center; - gap: 1.6rem; -`; - -export const postLocation = (theme: Theme) => css` - ${theme.fonts.label.medium.R13}; - color: ${theme.colors.text03}; -`; - -export const postCardRightHeader = css` - display: flex; - align-items: center; - gap: 0.4rem; -`; - -export const postViews = (theme: Theme) => css` - ${theme.fonts.label.medium.R13}; - color: ${theme.colors.text03}; -`; - -export const postTitle = (theme: Theme) => css` - ${theme.fonts.title.small.SB18}; - color: ${theme.colors.text06}; -`; - -export const contactedPostTag = (theme: Theme) => css` - width: fit-content; - padding: 0.6rem 0.85rem; - ${theme.fonts.label.small.SB12}; - color: ${theme.colors.text05}; - background-color: ${theme.colors.field03}; - border-radius: 3rem; -`; - -export const postRewardContainer = css` - display: flex; - gap: 0.8rem; - align-items: center; -`; - -export const announceText = (theme: Theme) => css` - ${theme.fonts.label.medium.M13}; - color: ${theme.colors.text03}; -`; - -export const postReward = (theme: Theme) => css` - ${theme.fonts.label.medium.SB13}; - color: ${theme.colors.primaryMint}; -`; - -export const postDate = (theme: Theme) => css` - ${theme.fonts.label.medium.M13}; - color: ${theme.colors.text04}; -`; diff --git a/src/app/home/components/PostCard/PostCard.tsx b/src/app/home/components/PostCard/PostCard.tsx index dd573fd..86667d9 100644 --- a/src/app/home/components/PostCard/PostCard.tsx +++ b/src/app/home/components/PostCard/PostCard.tsx @@ -13,7 +13,7 @@ import { postRewardContainer, postTitle, postViews, -} from './PostCard.styles'; +} from './PostCard.css'; import { formatPostDate } from '../../home.utils'; import Icon from '@/components/Icon'; @@ -31,27 +31,27 @@ const PostCard = ({ post }: PostCardProps) => { return ( <li> - <Link href={`/post/${experimentPostId}`} key={experimentPostId} css={postCardLayout}> - <div css={postHeader}> - <div css={postCardHeader}> - <span css={postLocation}>{univName}</span> - <div css={postCardRightHeader}> + <Link href={`/post/${experimentPostId}`} key={experimentPostId} className={postCardLayout}> + <div className={postHeader}> + <div className={postCardHeader}> + <span className={postLocation}>{univName}</span> + <div className={postCardRightHeader}> <Icon icon="Eye" width={18} /> - <span css={postViews}>{views}</span> + <span className={postViews}>{views}</span> </div> </div> - <h3 css={postTitle}>{title}</h3> + <h3 className={postTitle}>{title}</h3> </div> <div> {recruitStatus ? ( <> - <div css={postRewardContainer}> - <span css={announceText}>보상</span> - <span css={postReward}>{reward}</span> + <div className={postRewardContainer}> + <span className={announceText}>보상</span> + <span className={postReward}>{reward}</span> </div> - <div css={postRewardContainer}> - <span css={announceText}>일시</span> - <span css={postDate}> + <div className={postRewardContainer}> + <span className={announceText}>일시</span> + <span className={postDate}> {formatPostDate({ startDate: durationInfo.startDate, endDate: durationInfo.endDate, @@ -60,7 +60,7 @@ const PostCard = ({ post }: PostCardProps) => { </div> </> ) : ( - <div css={contactedPostTag}> + <div className={contactedPostTag}> <span>모집 완료</span> </div> )} diff --git a/src/app/home/components/PostCardList/EmptyPostCard/EmptyPostCard.css.ts b/src/app/home/components/PostCardList/EmptyPostCard/EmptyPostCard.css.ts new file mode 100644 index 0000000..b1ab253 --- /dev/null +++ b/src/app/home/components/PostCardList/EmptyPostCard/EmptyPostCard.css.ts @@ -0,0 +1,30 @@ +import { style } from '@vanilla-extract/css'; + +import { colors } from '@/styles/colors'; +import { fonts } from '@/styles/fonts.css'; + +export const emptyPostCardLayout = style({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + gap: '1.6rem', + height: '30.8rem', +}); + +export const emptyPostCardContent = style({ + display: 'flex', + flexDirection: 'column', + gap: '0.8rem', + textAlign: 'center', +}); + +export const emptyListTitle = style({ + ...fonts.body.normal.M16, + color: colors.text04, +}); + +export const emptyListContent = style({ + ...fonts.label.small.M12, + color: colors.text04, +}); diff --git a/src/app/home/components/PostCardList/EmptyPostCard/EmptyPostCard.styles.ts b/src/app/home/components/PostCardList/EmptyPostCard/EmptyPostCard.styles.ts deleted file mode 100644 index b613d0a..0000000 --- a/src/app/home/components/PostCardList/EmptyPostCard/EmptyPostCard.styles.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { css, Theme } from '@emotion/react'; - -export const emptyPostCardLayout = css` - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 1.6rem; - height: 30.8rem; -`; - -export const emptyPostCardContent = css` - display: flex; - flex-direction: column; - gap: 0.8rem; - text-align: center; -`; - -export const emptyListTitle = (theme: Theme) => css` - ${theme.fonts.body.normal.M16}; - color: ${theme.colors.text04}; -`; - -export const emptyListContent = (theme: Theme) => css` - ${theme.fonts.label.small.M12}; - color: ${theme.colors.text04}; -`; diff --git a/src/app/home/components/PostCardList/EmptyPostCard/EmptyPostCard.tsx b/src/app/home/components/PostCardList/EmptyPostCard/EmptyPostCard.tsx index 208770e..4682729 100644 --- a/src/app/home/components/PostCardList/EmptyPostCard/EmptyPostCard.tsx +++ b/src/app/home/components/PostCardList/EmptyPostCard/EmptyPostCard.tsx @@ -5,17 +5,17 @@ import { emptyListTitle, emptyPostCardContent, emptyPostCardLayout, -} from './EmptyPostCard.styles'; +} from './EmptyPostCard.css'; import Icon from '@/components/Icon'; const EmptyPostCard = () => { return ( - <div css={emptyPostCardLayout}> + <div className={emptyPostCardLayout}> <Icon icon="AllEmpty" width={60} height={60} /> - <div css={emptyPostCardContent}> - <h4 css={emptyListTitle}>검색 결과가 없어요</h4> - <div css={emptyListContent}> + <div className={emptyPostCardContent}> + <h4 className={emptyListTitle}>검색 결과가 없어요</h4> + <div className={emptyListContent}> <span>조건을 다르게 하면</span> <br /> <span>좋은 공고가 더 많을지도 몰라요</span> diff --git a/src/app/home/components/PostCardList/PostCardList.css.ts b/src/app/home/components/PostCardList/PostCardList.css.ts new file mode 100644 index 0000000..2d5fb03 --- /dev/null +++ b/src/app/home/components/PostCardList/PostCardList.css.ts @@ -0,0 +1,7 @@ +import { style } from '@vanilla-extract/css'; + +export const postCardListLayout = style({ + display: 'grid', + gridTemplateColumns: '1fr 1fr 1fr', + gap: '1.2rem', +}); diff --git a/src/app/home/components/PostCardList/PostCardList.styles.ts b/src/app/home/components/PostCardList/PostCardList.styles.ts deleted file mode 100644 index 1a2fae6..0000000 --- a/src/app/home/components/PostCardList/PostCardList.styles.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { css } from '@emotion/react'; - -export const postCardListLayout = css` - display: grid; - grid-template-columns: 1fr 1fr 1fr; - gap: 1.2rem; -`; diff --git a/src/app/home/components/PostCardList/PostCardList.tsx b/src/app/home/components/PostCardList/PostCardList.tsx index aed1284..0595bc4 100644 --- a/src/app/home/components/PostCardList/PostCardList.tsx +++ b/src/app/home/components/PostCardList/PostCardList.tsx @@ -1,6 +1,6 @@ -import { postCardListLayout } from './PostCardList.styles'; import PostCard from '../PostCard/PostCard'; import EmptyPostCard from './EmptyPostCard/EmptyPostCard'; +import { postCardListLayout } from './PostCardList.css'; import { Post } from '@/types/post'; @@ -18,7 +18,7 @@ const PostCardList = ({ postList }: PostCardListProps) => { } return ( - <ul css={postCardListLayout}> + <ul className={postCardListLayout}> {postList.map((post) => ( <PostCard key={post.postInfo.experimentPostId} post={post} /> ))} diff --git a/src/app/join/components/JoinCheckboxContainer/JoinCheckbox/JoinCheckbox.css.ts b/src/app/join/components/JoinCheckboxContainer/JoinCheckbox/JoinCheckbox.css.ts new file mode 100644 index 0000000..645851a --- /dev/null +++ b/src/app/join/components/JoinCheckboxContainer/JoinCheckbox/JoinCheckbox.css.ts @@ -0,0 +1,52 @@ +import { style } from '@vanilla-extract/css'; + +import { colors } from '@/styles/colors'; +import { fonts } from '@/styles/fonts.css'; + +export const checkboxLayout = style({ + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', +}); + +export const checkboxWrapper = style({ + display: 'flex', + alignItems: 'center', + gap: '0.8rem', + selectors: { + '&:span': { + userSelect: 'none', + }, + }, +}); + +export const allCheckWrapper = style({ + borderBottom: `0.1rem solid ${colors.line01}`, + paddingBottom: '1.6rem', +}); + +export const checkbox = style({ + position: 'absolute', + opacity: 0, + pointerEvents: 'none', +}); + +export const requiredCheckboxText = style({ + color: colors.textPrimary, +}); + +export const labelWrapper = style({ + display: 'flex', + gap: '0.4rem', +}); + +export const tipWrapper = style({ + ...fonts.label.small.M12, + display: 'flex', + gap: '0.4rem', + color: colors.text02, +}); + +export const tipAlert = style({ + color: colors.textPrimary, +}); diff --git a/src/app/join/components/JoinCheckboxContainer/JoinCheckbox/JoinCheckbox.tsx b/src/app/join/components/JoinCheckboxContainer/JoinCheckbox/JoinCheckbox.tsx index e0f0551..f64b077 100644 --- a/src/app/join/components/JoinCheckboxContainer/JoinCheckbox/JoinCheckbox.tsx +++ b/src/app/join/components/JoinCheckboxContainer/JoinCheckbox/JoinCheckbox.tsx @@ -1,12 +1,13 @@ import { - allCheckWrapper, - checkbox, checkboxLayout, checkboxWrapper, - labelWrapper, + allCheckWrapper, + checkbox, requiredCheckboxText, -} from './JoinCheckbox.styles'; -import { tipAlert, tipWrapper } from '../../JoinInput/JoinInput.styles'; + labelWrapper, + tipWrapper, + tipAlert, +} from './JoinCheckbox.css'; import Icon from '@/components/Icon'; import theme from '@/styles/theme'; @@ -32,27 +33,26 @@ const JoinCheckbox = ({ isAlert, }: JoinCheckboxProps) => { return ( - <div css={[checkboxLayout, isAllCheck && allCheckWrapper]}> - <label css={checkboxWrapper}> - <input css={checkbox} type="checkbox" checked={isChecked} onChange={onChange} /> + <div className={`${checkboxLayout} ${isAllCheck ? allCheckWrapper : ''}`}> + <label className={checkboxWrapper}> + <input className={checkbox} type="checkbox" checked={isChecked} onChange={onChange} /> {isChecked ? ( <Icon icon="CheckSquareFill" color={theme.colors.primaryMint} /> ) : ( <Icon icon="CheckSquareEmpty" /> )} <div> - <div css={labelWrapper}> - {isRequired && <span css={requiredCheckboxText}>[필수]</span>} + <div className={labelWrapper}> + {isRequired && <span className={requiredCheckboxText}>[필수]</span>} <span>{label}</span> </div> {isAlert && ( - <div css={tipWrapper}> - <span css={tipAlert}>* 내가 참여할 수 있는 실험 알림을 보내드려요</span> + <div className={tipWrapper}> + <span className={tipAlert}>* 내가 참여할 수 있는 실험 알림을 보내드려요</span> </div> )} </div> </label> - {isArrow && <Icon icon="Chevron" width={20} height={20} />} </div> ); diff --git a/src/app/page.tsx b/src/app/page.tsx index ea34a95..750fe02 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,4 +1,3 @@ - import Banner from './home/components/Banner/Banner'; import PostContainer from './home/components/PostContainer/PostContainer'; diff --git a/src/components/Icon/icons/AllEmpty.tsx b/src/components/Icon/icons/AllEmpty.tsx index 1db0b07..2b182ba 100644 --- a/src/components/Icon/icons/AllEmpty.tsx +++ b/src/components/Icon/icons/AllEmpty.tsx @@ -5,11 +5,12 @@ import theme from '@/styles/theme'; function AllEmpty(props: SVGProps<SVGSVGElement>) { return ( <svg - width={props.width} - height={props.height} + width="24" + height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" + {...props} > <path fillRule="evenodd" From 6372d78c2393bf10fc0c1070f6c016ab0fd8c350 Mon Sep 17 00:00:00 2001 From: Gyuhan Park <rbgks1937@naver.com> Date: Tue, 4 Feb 2025 04:29:37 +0900 Subject: [PATCH 04/11] =?UTF-8?q?[YS-243]=20refactor:=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EA=B0=80=EC=9E=85=20=EA=B3=B5=ED=86=B5=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EC=8A=A4=ED=83=80=EC=9D=BC=EB=A7=81=20?= =?UTF-8?q?=EB=A7=88=EC=9D=B4=EA=B7=B8=EB=A0=88=EC=9D=B4=EC=85=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/join/JoinPage.css.ts | 65 ++++++++++++++++ src/app/join/JoinPage.styles.ts | 48 ------------ .../components/EmailToast/EmailToast.css.ts | 37 +++++++++ .../EmailToast/EmailToast.styles.ts | 43 ---------- .../join/components/EmailToast/EmailToast.tsx | 10 ++- .../JoinCheckbox/JoinCheckbox.css.ts | 6 +- .../JoinCheckbox/JoinCheckbox.styles.ts | 37 --------- .../JoinCheckboxContainer.css.ts | 16 ++++ .../JoinCheckboxContainer.styles.ts | 13 ---- .../JoinCheckboxContainer.tsx | 4 +- .../components/JoinInput/JoinInput.css.ts | 78 +++++++++++++++++++ .../components/JoinInput/JoinInput.styles.ts | 78 ------------------- .../join/components/JoinInput/JoinInput.tsx | 35 +++++---- .../JoinSuccessStep/JoinSuccessStep.css.ts | 39 ++++++++++ .../JoinSuccessStep/JoinSuccessStep.styles.ts | 36 --------- .../JoinSuccessStep/JoinSuccessStep.tsx | 14 ++-- src/app/join/page.tsx | 30 +++++-- 17 files changed, 294 insertions(+), 295 deletions(-) create mode 100644 src/app/join/JoinPage.css.ts create mode 100644 src/app/join/components/EmailToast/EmailToast.css.ts delete mode 100644 src/app/join/components/EmailToast/EmailToast.styles.ts delete mode 100644 src/app/join/components/JoinCheckboxContainer/JoinCheckbox/JoinCheckbox.styles.ts create mode 100644 src/app/join/components/JoinCheckboxContainer/JoinCheckboxContainer.css.ts delete mode 100644 src/app/join/components/JoinCheckboxContainer/JoinCheckboxContainer.styles.ts create mode 100644 src/app/join/components/JoinInput/JoinInput.css.ts delete mode 100644 src/app/join/components/JoinInput/JoinInput.styles.ts create mode 100644 src/app/join/components/JoinSuccessStep/JoinSuccessStep.css.ts delete mode 100644 src/app/join/components/JoinSuccessStep/JoinSuccessStep.styles.ts diff --git a/src/app/join/JoinPage.css.ts b/src/app/join/JoinPage.css.ts new file mode 100644 index 0000000..5ddbc56 --- /dev/null +++ b/src/app/join/JoinPage.css.ts @@ -0,0 +1,65 @@ +import { style } from '@vanilla-extract/css'; + +import { colors } from '@/styles/colors'; +import { fonts } from '@/styles/fonts.css'; + +export const joinLayout = style({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + gap: '4rem', + paddingTop: '8.4rem', + flexGrow: 1, +}); + +export const contentContainer = style({ + display: 'flex', + flexDirection: 'column', + gap: '1.6rem', + width: '100%', +}); + +export const titleContainer = style({ + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', +}); + +export const joinContentContainer = style({ + backgroundColor: colors.field02, + width: '100%', + display: 'flex', + flexDirection: 'column', + gap: '2.8rem', + borderRadius: '1.2rem', + padding: '3.2rem 4rem', +}); + +export const joinTitle = style({ + ...fonts.title.medium.SB20, + color: colors.text06, +}); + +export const progressBarContainer = style({ + width: '8rem', + height: '0.6rem', + backgroundColor: colors.field03, + borderRadius: '0.6rem', +}); + +export const progressBarFill = style({ + width: 'var(--progress-width)', + height: '100%', + backgroundColor: colors.primaryMint, + borderRadius: '0.6rem', + transition: 'width 1s', +}); + +export const joinForm = style({ + width: '100%', + height: '100%', + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + gap: '4rem', +}); diff --git a/src/app/join/JoinPage.styles.ts b/src/app/join/JoinPage.styles.ts index 61b8884..d639fba 100644 --- a/src/app/join/JoinPage.styles.ts +++ b/src/app/join/JoinPage.styles.ts @@ -1,27 +1,5 @@ import { css, Theme } from '@emotion/react'; -export const joinLayout = css` - display: flex; - flex-direction: column; - align-items: center; - gap: 4rem; - padding-top: 8.4rem; - flex-grow: 1; -`; - -export const contentContainer = css` - display: flex; - flex-direction: column; - gap: 1.6rem; - width: 100%; -`; - -export const titleContainer = css` - display: flex; - justify-content: space-between; - align-items: center; -`; - export const joinContentContainer = (theme: Theme) => css` background-color: ${theme.colors.field02}; width: 100%; @@ -32,32 +10,6 @@ export const joinContentContainer = (theme: Theme) => css` padding: 3.2rem 4rem; `; -export const joinTitle = (theme: Theme) => css` - ${theme.fonts.title.medium.SB20}; - color: ${theme.colors.text06}; -`; - -export const progressBar = (theme: Theme) => css` - width: 8rem; - height: 0.6rem; - background-color: ${theme.colors.field03}; - border-radius: 3rem; -`; - -export const progressBarContainer = (theme: Theme) => css` - width: 8rem; - height: 0.6rem; - background-color: ${theme.colors.field03}; - border-radius: 0.6rem; -`; - -export const progressBarFill = (theme: Theme) => css` - height: 100%; - background-color: ${theme.colors.primaryMint}; - border-radius: 0.6rem; - transition: width 1s; -`; - export const joinForm = css` width: 100%; height: 100%; diff --git a/src/app/join/components/EmailToast/EmailToast.css.ts b/src/app/join/components/EmailToast/EmailToast.css.ts new file mode 100644 index 0000000..a5fcee9 --- /dev/null +++ b/src/app/join/components/EmailToast/EmailToast.css.ts @@ -0,0 +1,37 @@ +import { style } from '@vanilla-extract/css'; + +import { colors } from '@/styles/colors'; +import { fonts } from '@/styles/fonts.css'; +import theme from '@/styles/theme'; + +export const toastLayout = style({ + color: colors.text06, + height: '5.2rem', + backgroundColor: colors.fieldToast, + boxShadow: '0px 4px 16px rgba(53, 59, 61, 0.2)', + borderRadius: '8rem', + padding: '1.4rem 2.4rem', + position: 'fixed', + top: 0, + left: '50%', + transform: 'translateX(-50%)', + zIndex: theme.zIndex.toastContent, +}); + +export const toastTitle = style({ + ...fonts.body.normal.SB16, + color: colors.text01, + display: 'flex', + flexFlow: 'row nowrap', + alignItems: 'center', + gap: '1rem', + width: 'max-content', +}); + +export const toastViewport = style({ + position: 'fixed', + top: '6rem', + left: '50%', + transform: 'translateX(-50%)', + zIndex: theme.zIndex.toastViewport, +}); diff --git a/src/app/join/components/EmailToast/EmailToast.styles.ts b/src/app/join/components/EmailToast/EmailToast.styles.ts deleted file mode 100644 index 362ac22..0000000 --- a/src/app/join/components/EmailToast/EmailToast.styles.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { css, Theme } from '@emotion/react'; - -export const toastLayout = (theme: Theme) => css` - color: ${theme.colors.text06}; - - height: 5.2rem; - - background-color: ${theme.colors.fieldToast}; - color: ${theme.colors.text06}; - box-shadow: 0px 4px 16px rgba(53, 59, 61, 0.2); - - border-radius: 8rem; - - padding: 1.4rem 2.4rem; - - position: fixed; - top: 0; - left: 50%; - transform: translateX(-50%); - - z-index: ${theme.zIndex.toastContent}; -`; - -export const toastTitle = (theme: Theme) => css` - ${theme.fonts.body.normal.SB16}; - color: ${theme.colors.text01}; - - display: flex; - flex-flow: row nowrap; - align-items: center; - gap: 1rem; - - width: max-content; -`; - -export const toastViewport = (theme: Theme) => css` - position: fixed; - top: 6rem; - left: 50%; - transform: translateX(-50%); - - z-index: ${theme.zIndex.toastViewport}; -`; diff --git a/src/app/join/components/EmailToast/EmailToast.tsx b/src/app/join/components/EmailToast/EmailToast.tsx index ebfbf6d..b9bd973 100644 --- a/src/app/join/components/EmailToast/EmailToast.tsx +++ b/src/app/join/components/EmailToast/EmailToast.tsx @@ -1,6 +1,8 @@ +'use client'; + import * as Toast from '@radix-ui/react-toast'; -import { toastLayout, toastTitle, toastViewport } from './EmailToast.styles'; +import { toastLayout, toastTitle, toastViewport } from './EmailToast.css'; import Icon from '@/components/Icon'; import theme from '@/styles/theme'; @@ -15,17 +17,17 @@ const EmailToast = ({ title, isToastOpen, setIsToastOpen }: EmailToastProps) => return ( <Toast.Provider swipeDirection="up"> <Toast.Root - css={toastLayout} + className={toastLayout} open={isToastOpen} onOpenChange={setIsToastOpen} duration={1500} > - <Toast.Title css={toastTitle}> + <Toast.Title className={toastTitle}> <Icon icon="CheckRound" color={theme.colors.primaryMint} width={24} height={24} /> <p>{title}</p> </Toast.Title> </Toast.Root> - <Toast.Viewport css={toastViewport} /> + <Toast.Viewport className={toastViewport} /> </Toast.Provider> ); }; diff --git a/src/app/join/components/JoinCheckboxContainer/JoinCheckbox/JoinCheckbox.css.ts b/src/app/join/components/JoinCheckboxContainer/JoinCheckbox/JoinCheckbox.css.ts index 645851a..ea75858 100644 --- a/src/app/join/components/JoinCheckboxContainer/JoinCheckbox/JoinCheckbox.css.ts +++ b/src/app/join/components/JoinCheckboxContainer/JoinCheckbox/JoinCheckbox.css.ts @@ -13,11 +13,7 @@ export const checkboxWrapper = style({ display: 'flex', alignItems: 'center', gap: '0.8rem', - selectors: { - '&:span': { - userSelect: 'none', - }, - }, + userSelect: 'none', }); export const allCheckWrapper = style({ diff --git a/src/app/join/components/JoinCheckboxContainer/JoinCheckbox/JoinCheckbox.styles.ts b/src/app/join/components/JoinCheckboxContainer/JoinCheckbox/JoinCheckbox.styles.ts deleted file mode 100644 index a85cfcb..0000000 --- a/src/app/join/components/JoinCheckboxContainer/JoinCheckbox/JoinCheckbox.styles.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { css, Theme } from '@emotion/react'; - -export const checkboxLayout = css` - display: flex; - justify-content: space-between; - align-items: center; -`; - -export const checkboxWrapper = css` - display: flex; - align-items: center; - gap: 0.8rem; - - span { - user-select: none; - } -`; - -export const allCheckWrapper = (theme: Theme) => css` - border-bottom: 0.1rem solid ${theme.colors.line01}; - padding-bottom: 1.6rem; -`; - -export const checkbox = css` - position: absolute; - opacity: 0; - pointer-events: none; -`; - -export const requiredCheckboxText = (theme: Theme) => css` - color: ${theme.colors.textPrimary}; -`; - -export const labelWrapper = css` - display: flex; - gap: 0.4rem; -`; diff --git a/src/app/join/components/JoinCheckboxContainer/JoinCheckboxContainer.css.ts b/src/app/join/components/JoinCheckboxContainer/JoinCheckboxContainer.css.ts new file mode 100644 index 0000000..37bb1b2 --- /dev/null +++ b/src/app/join/components/JoinCheckboxContainer/JoinCheckboxContainer.css.ts @@ -0,0 +1,16 @@ +import { style } from '@vanilla-extract/css'; + +import { colors } from '@/styles/colors'; +import { fonts } from '@/styles/fonts.css'; + +export const termContainer = style({ + ...fonts.body.normal.M16, + color: colors.text06, + backgroundColor: colors.field01, + border: `0.1rem solid ${colors.line01}`, + borderRadius: '1.2rem', + display: 'flex', + flexDirection: 'column', + padding: '1.6rem', + gap: '1.2rem', +}); diff --git a/src/app/join/components/JoinCheckboxContainer/JoinCheckboxContainer.styles.ts b/src/app/join/components/JoinCheckboxContainer/JoinCheckboxContainer.styles.ts deleted file mode 100644 index f0fd978..0000000 --- a/src/app/join/components/JoinCheckboxContainer/JoinCheckboxContainer.styles.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { css, Theme } from '@emotion/react'; - -export const termContainer = (theme: Theme) => css` - ${theme.fonts.body.normal.M16}; - color: ${theme.colors.text06}; - background-color: ${theme.colors.field01}; - border: 0.1rem solid ${theme.colors.line01}; - border-radius: 1.2rem; - display: flex; - flex-direction: column; - padding: 1.6rem; - gap: 1.2rem; -`; diff --git a/src/app/join/components/JoinCheckboxContainer/JoinCheckboxContainer.tsx b/src/app/join/components/JoinCheckboxContainer/JoinCheckboxContainer.tsx index 519a3be..8d80967 100644 --- a/src/app/join/components/JoinCheckboxContainer/JoinCheckboxContainer.tsx +++ b/src/app/join/components/JoinCheckboxContainer/JoinCheckboxContainer.tsx @@ -1,6 +1,6 @@ import { ServiceAgreeCheck } from '../../JoinPage.types'; import JoinCheckbox from './JoinCheckbox/JoinCheckbox'; -import { termContainer } from './JoinCheckboxContainer.styles'; +import { termContainer } from './JoinCheckboxContainer.css'; interface JoinCheckboxContainerProps { serviceAgreeCheck: ServiceAgreeCheck; @@ -18,7 +18,7 @@ const JoinCheckboxContainer = ({ const isAllCheck = isTermOfService && isPrivacy && isAdvertise && (isRecommend ?? true); return ( - <div css={termContainer}> + <div className={termContainer}> <JoinCheckbox label="이용약관에 모두 동의합니다" isChecked={isAllCheck} diff --git a/src/app/join/components/JoinInput/JoinInput.css.ts b/src/app/join/components/JoinInput/JoinInput.css.ts new file mode 100644 index 0000000..bf8dc34 --- /dev/null +++ b/src/app/join/components/JoinInput/JoinInput.css.ts @@ -0,0 +1,78 @@ +import { style } from '@vanilla-extract/css'; + +import { colors } from '@/styles/colors'; +import { fonts } from '@/styles/fonts.css'; + +export const inputContainer = style({ + display: 'flex', + flexDirection: 'column', + gap: '0.6rem', +}); + +export const inputLabel = style({ + ...fonts.label.large.M14, + color: colors.text06, + display: 'flex', + gap: '0.4rem', +}); + +export const joinInput = style({ + ...fonts.body.normal.M16, + color: colors.text06, + border: `0.1rem solid ${colors.line01}`, + padding: '1.6rem', + borderRadius: '1.2rem', + selectors: { + '&:disabled': { + color: colors.text03, + backgroundColor: colors.field03, + }, + '&::placeholder': { + color: colors.text03, + }, + '&:focus': { + outline: `0.1rem solid ${colors.lineTinted}`, + }, + "&[aria-invalid='true']": { + outline: `0.1rem solid ${colors.textAlert}`, + }, + }, +}); + +export const requiredStar = style({ + color: colors.textAlert, +}); + +export const inputWrapper = style({ + position: 'relative', +}); + +export const inputResetButton = style({ + position: 'absolute', + top: '50%', + transform: 'translateY(-50%)', + right: '1.7rem', +}); + +export const errorMessage = style({ + ...fonts.label.large.R14, + color: colors.textAlert, +}); + +export const tipWrapper = style({ + ...fonts.label.small.M12, + display: 'flex', + gap: '0.4rem', + color: colors.text02, +}); + +export const textCount = style({ + ...fonts.label.small.M12, + display: 'flex', + justifyContent: 'flex-end', + color: colors.text02, +}); + +export const tipAlert = style({ + color: colors.textPrimary, +}); diff --git a/src/app/join/components/JoinInput/JoinInput.styles.ts b/src/app/join/components/JoinInput/JoinInput.styles.ts deleted file mode 100644 index 19eb2c0..0000000 --- a/src/app/join/components/JoinInput/JoinInput.styles.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { css, Theme } from '@emotion/react'; - -export const inputContainer = (theme: Theme) => css` - display: flex; - flex-direction: column; - gap: 0.6rem; - - label { - ${theme.fonts.label.large.M14}; - color: ${theme.colors.text06}; - display: flex; - gap: 0.4rem; - } - - input, - textarea { - ${theme.fonts.body.normal.M16}; - color: ${theme.colors.text06}; - border: 0.1rem solid ${theme.colors.line01}; - padding: 1.6rem; - border-radius: 1.2rem; - - :disabled { - color: ${theme.colors.text03}; - background-color: ${theme.colors.field03}; - } - - ::placeholder { - color: ${theme.colors.text03}; - } - - :focus { - outline: 0.1rem solid ${theme.colors.lineTinted}; - } - - &[aria-invalid='true'] { - outline: 0.1rem solid ${theme.colors.textAlert}; - } - } -`; - -export const requiredStar = (theme: Theme) => css` - color: ${theme.colors.textAlert}; -`; - -export const inputWrapper = css` - position: relative; -`; - -export const inputResetButton = css` - position: absolute; - top: 50%; - transform: translateY(-50%); - right: 1.7rem; -`; - -export const errorMessage = (theme: Theme) => css` - ${theme.fonts.label.large.R14}; - color: ${theme.colors.textAlert}; -`; - -export const tipWrapper = (theme: Theme) => css` - ${theme.fonts.label.small.M12}; - display: flex; - gap: 0.4rem; - color: ${theme.colors.text02}; -`; - -export const textCount = (theme: Theme) => css` - ${theme.fonts.label.small.M12}; - display: flex; - justify-content: flex-end; - color: ${theme.colors.text02}; -`; - -export const tipAlert = (theme: Theme) => css` - color: ${theme.colors.textPrimary}; -`; diff --git a/src/app/join/components/JoinInput/JoinInput.tsx b/src/app/join/components/JoinInput/JoinInput.tsx index 525a06f..7434537 100644 --- a/src/app/join/components/JoinInput/JoinInput.tsx +++ b/src/app/join/components/JoinInput/JoinInput.tsx @@ -1,16 +1,20 @@ +'use client'; + import { useRef, useState } from 'react'; import { Control, Controller, FieldValues, Path, PathValue } from 'react-hook-form'; import { - errorMessage, inputContainer, inputResetButton, - inputWrapper, requiredStar, + errorMessage, + tipWrapper, textCount, tipAlert, - tipWrapper, -} from './JoinInput.styles'; + joinInput, + inputWrapper, + inputLabel, +} from './JoinInput.css'; import Icon from '@/components/Icon'; @@ -55,7 +59,6 @@ const JoinInput = <T extends FieldValues>({ if (resetButtonRef.current && resetButtonRef.current.contains(e.relatedTarget)) { return; } - onBlur(); setIsFocused(false); }; @@ -67,11 +70,11 @@ const JoinInput = <T extends FieldValues>({ }; return ( - <div css={inputContainer}> + <div className={inputContainer}> {label && ( - <label> + <label className={inputLabel}> <span>{label}</span> - {required && <span css={requiredStar}>*</span>} + {required && <span className={requiredStar}>*</span>} </label> )} <Controller @@ -81,7 +84,7 @@ const JoinInput = <T extends FieldValues>({ defaultValue={value} render={({ field, fieldState }) => ( <> - <div css={inputWrapper}> + <div className={inputWrapper}> {type === 'input' ? ( <input {...field} @@ -91,6 +94,7 @@ const JoinInput = <T extends FieldValues>({ maxLength={maxLength} aria-invalid={fieldState.invalid ? true : false} style={{ width: '100%' }} + className={joinInput} onFocus={() => setIsFocused(true)} onBlur={(e) => handleBlur(e, field.onBlur)} /> @@ -104,12 +108,13 @@ const JoinInput = <T extends FieldValues>({ rows={3} maxLength={maxLength ?? 0} style={{ width: '100%' }} + className={joinInput} onFocus={() => setIsFocused(true)} onBlur={(e) => handleBlur(e, field.onBlur)} /> )} {isFocused && field.value && !disabled && ( - <button css={inputResetButton} ref={resetButtonRef}> + <button className={inputResetButton} ref={resetButtonRef}> <Icon icon="CloseRound" width={22} @@ -120,15 +125,15 @@ const JoinInput = <T extends FieldValues>({ </button> )} </div> - {fieldState.error && <span css={errorMessage}>{fieldState.error.message}</span>} + {fieldState.error && <span className={errorMessage}>{fieldState.error.message}</span>} {type === 'textarea' && ( - <span css={textCount}> + <span className={textCount}> {field.value?.length || 0}/{maxLength} </span> )} - {tip && Boolean(!fieldState.error) && ( - <div css={tipWrapper}> - {isTip && <span css={tipAlert}>Tip</span>} + {tip && !fieldState.error && ( + <div className={tipWrapper}> + {isTip && <span className={tipAlert}>Tip</span>} <span>{tip}</span> </div> )} diff --git a/src/app/join/components/JoinSuccessStep/JoinSuccessStep.css.ts b/src/app/join/components/JoinSuccessStep/JoinSuccessStep.css.ts new file mode 100644 index 0000000..16d2998 --- /dev/null +++ b/src/app/join/components/JoinSuccessStep/JoinSuccessStep.css.ts @@ -0,0 +1,39 @@ +import { style } from '@vanilla-extract/css'; + +import { colors } from '@/styles/colors'; +import { fonts } from '@/styles/fonts.css'; + +export const joinSuccessLayout = style({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + gap: '9rem', + paddingTop: '3.6rem', +}); + +export const joinTitleContainer = style({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + gap: '6.4rem', + textAlign: 'center', +}); + +export const title = style({ + ...fonts.title.large.SB28, + color: colors.text06, +}); + +export const image = style({ + margin: '3.2rem 0', +}); + +export const homeLink = style({ + ...fonts.body.normal.SB16, + backgroundColor: colors.primaryMint, + color: colors.text01, + borderRadius: '1.2rem', + padding: '1.2rem 3.35rem', + marginTop: '2.6rem', +}); diff --git a/src/app/join/components/JoinSuccessStep/JoinSuccessStep.styles.ts b/src/app/join/components/JoinSuccessStep/JoinSuccessStep.styles.ts deleted file mode 100644 index 8b3fb2a..0000000 --- a/src/app/join/components/JoinSuccessStep/JoinSuccessStep.styles.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { css, Theme } from '@emotion/react'; - -export const joinSuccessLayout = css` - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 9rem; - padding-top: 3.6rem; -`; - -export const joinTitleContainer = css` - display: flex; - flex-direction: column; - align-items: center; - gap: 6.4rem; - text-align: center; -`; - -export const title = (theme: Theme) => css` - ${theme.fonts.title.large.SB28}; - color: ${theme.colors.text06}; -`; - -export const image = css` - margin: 3.2rem 0; -`; - -export const homeLink = (theme: Theme) => css` - ${theme.fonts.body.normal.SB16}; - background-color: ${theme.colors.primaryMint}; - color: ${theme.colors.text01}; - border-radius: 1.2rem; - padding: 1.2rem 3.35rem; - margin-top: 2.6rem; -`; diff --git a/src/app/join/components/JoinSuccessStep/JoinSuccessStep.tsx b/src/app/join/components/JoinSuccessStep/JoinSuccessStep.tsx index 1656d15..df13d16 100644 --- a/src/app/join/components/JoinSuccessStep/JoinSuccessStep.tsx +++ b/src/app/join/components/JoinSuccessStep/JoinSuccessStep.tsx @@ -8,7 +8,7 @@ import { joinSuccessLayout, joinTitleContainer, title, -} from './JoinSuccessStep.styles'; +} from './JoinSuccessStep.css'; import JoinSuccess from '@/assets/images/joinSuccess.svg'; @@ -18,15 +18,15 @@ interface JoinSuccessStepProps { const JoinSuccessStep = ({ name }: JoinSuccessStepProps) => { return ( - <div css={joinSuccessLayout}> - <div css={joinTitleContainer}> + <div className={joinSuccessLayout}> + <div className={joinTitleContainer}> <div> - <h2 css={title}>{name} 님,</h2> - <h2 css={title}>그라밋 가입을 환영해요!</h2> + <h2 className={title}>{name} 님,</h2> + <h2 className={title}>그라밋 가입을 환영해요!</h2> </div> - <Image src={JoinSuccess} alt="회원가입 성공" width={160} height={140} css={image} /> + <Image src={JoinSuccess} alt="회원가입 성공" width={160} height={140} className={image} /> </div> - <Link href="/" css={homeLink}> + <Link href="/" className={homeLink}> 홈 화면으로 돌아가기 </Link> </div> diff --git a/src/app/join/page.tsx b/src/app/join/page.tsx index df1f882..9a19748 100644 --- a/src/app/join/page.tsx +++ b/src/app/join/page.tsx @@ -1,5 +1,6 @@ 'use client'; +import { assignInlineVars } from '@vanilla-extract/dynamic'; import Image from 'next/image'; import ParticipantForm from './components/Participant/ParticipantForm'; @@ -13,7 +14,7 @@ import { progressBarContainer, progressBarFill, titleContainer, -} from './JoinPage.styles'; +} from './JoinPage.css'; import Logo from '@/assets/images/logo.svg'; import { ROLE } from '@/constants/config'; @@ -26,16 +27,31 @@ export default function JoinPage() { // TODO: 추후 스켈레톤 처리 if (!role) return null; + if (step === STEP.success) { + return ( + <section className={joinLayout}> + <div className={contentContainer}> + {role === ROLE.researcher ? <ResearcherForm /> : <ParticipantForm />} + </div> + </section> + ); + } + return ( - <section css={joinLayout}> + <section className={joinLayout}> <Image src={Logo} alt="로고" width={80} height={28} /> - <div css={contentContainer}> - <div css={titleContainer}> - <h2 css={joinTitle}> + <div className={contentContainer}> + <div className={titleContainer}> + <h2 className={joinTitle}> {role === ROLE.researcher ? '연구자 회원가입' : '참여자 회원가입'} </h2> - <div css={progressBarContainer}> - <div css={progressBarFill} style={{ width: step === STEP.email ? '50%' : '100%' }} /> + <div className={progressBarContainer}> + <div + className={progressBarFill} + style={assignInlineVars({ + '--progress-width': step === STEP.email ? '50%' : '100%', + })} + /> </div> </div> {role === ROLE.researcher ? <ResearcherForm /> : <ParticipantForm />} From c8750687e19f860528da000fc3de0ee30ca8ffff Mon Sep 17 00:00:00 2001 From: Gyuhan Park <rbgks1937@naver.com> Date: Wed, 5 Feb 2025 00:51:31 +0900 Subject: [PATCH 05/11] =?UTF-8?q?[YS-243]=20refactor:=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=8A=A4=ED=83=80?= =?UTF-8?q?=EC=9D=BC=EB=A7=81=20=EB=A7=88=EC=9D=B4=EA=B7=B8=EB=A0=88?= =?UTF-8?q?=EC=9D=B4=EC=85=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/login/LoginPage.css.ts | 44 +++++++++++++++++ src/app/login/LoginPage.styles.ts | 34 -------------- src/app/login/components/LoginCard.styles.ts | 43 ----------------- .../components/LoginCard/LoginCard.css.ts | 47 +++++++++++++++++++ .../components/{ => LoginCard}/LoginCard.tsx | 30 +++++++----- src/app/login/google/GoogleLoginPage.css.ts | 5 ++ .../login/google/GoogleLoginPage.styles.ts | 5 -- src/app/login/google/page.tsx | 4 +- src/app/login/layout.tsx | 14 +----- src/app/login/naver/NaverLoginPage.css.ts | 5 ++ src/app/login/naver/NaverLoginPage.styles.ts | 5 -- src/app/login/naver/page.tsx | 6 +-- src/app/login/page.tsx | 18 ++++--- 13 files changed, 133 insertions(+), 127 deletions(-) create mode 100644 src/app/login/LoginPage.css.ts delete mode 100644 src/app/login/LoginPage.styles.ts delete mode 100644 src/app/login/components/LoginCard.styles.ts create mode 100644 src/app/login/components/LoginCard/LoginCard.css.ts rename src/app/login/components/{ => LoginCard}/LoginCard.tsx (74%) create mode 100644 src/app/login/google/GoogleLoginPage.css.ts delete mode 100644 src/app/login/google/GoogleLoginPage.styles.ts create mode 100644 src/app/login/naver/NaverLoginPage.css.ts delete mode 100644 src/app/login/naver/NaverLoginPage.styles.ts diff --git a/src/app/login/LoginPage.css.ts b/src/app/login/LoginPage.css.ts new file mode 100644 index 0000000..d489d71 --- /dev/null +++ b/src/app/login/LoginPage.css.ts @@ -0,0 +1,44 @@ +import { style } from '@vanilla-extract/css'; + +import { colors } from '@/styles/colors'; +import { fonts } from '@/styles/fonts.css'; + +export const loginLayout = style({ + backgroundColor: colors.field01, + minWidth: '100rem', + height: 'calc(100vh - 12.2rem)', + margin: '0 auto', +}); + +export const loginPageLayout = style({ + display: 'flex', + flexDirection: 'column', + gap: '6.5rem', + paddingTop: '8.4rem', +}); + +export const descriptionWrapper = style({ + ...fonts.title.medium.SB20, + color: colors.text06, +}); + +export const sloganContainer = style({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + gap: '1rem', +}); + +export const sloganWrapper = style({ + ...fonts.title.medium.SB20, + color: colors.text06, + textAlign: 'center', +}); + +export const loginCardContainer = style({ + display: 'flex', + justifyContent: 'center', + gap: '2rem', + marginBottom: '2.8rem', + minHeight: '37rem', +}); diff --git a/src/app/login/LoginPage.styles.ts b/src/app/login/LoginPage.styles.ts deleted file mode 100644 index 0a47687..0000000 --- a/src/app/login/LoginPage.styles.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { css, Theme } from '@emotion/react'; - -export const loginLayout = css` - display: flex; - flex-direction: column; - gap: 6.5rem; - padding-top: 8.4rem; -`; - -export const descriptionWrapper = (theme: Theme) => css` - ${theme.fonts.title.medium.SB20}; - color: ${theme.colors.text06}; -`; - -export const sloganContainer = css` - display: flex; - flex-direction: column; - align-items: center; - gap: 1rem; -`; - -export const sloganWrapper = (theme: Theme) => css` - ${theme.fonts.title.medium.SB20}; - color: ${theme.colors.text06}; - text-align: center; -`; - -export const loginCardContainer = css` - display: flex; - justify-content: center; - gap: 2rem; - margin-bottom: 2.8rem; - min-height: 37rem; -`; diff --git a/src/app/login/components/LoginCard.styles.ts b/src/app/login/components/LoginCard.styles.ts deleted file mode 100644 index 89db78a..0000000 --- a/src/app/login/components/LoginCard.styles.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { css, Theme } from '@emotion/react'; - -export const loginCardLayout = (theme: Theme) => css` - background-color: ${theme.colors.field02}; - width: 32.7rem; - - display: flex; - flex-direction: column; - border-radius: 1.2rem; - padding: 3rem; - justify-content: space-between; -`; - -export const cardTitleContainer = css` - display: flex; - flex-direction: column; - gap: 0.8rem; -`; - -export const badge = (theme: Theme) => css` - ${theme.fonts.label.large.SB14}; - width: fit-content; - padding: 0.4rem 0.8rem; - border-radius: 1.2rem; -`; - -export const buttonContainer = css` - display: flex; - flex-direction: column; - gap: 0.8rem; -`; - -export const loginButton = (theme: Theme) => css` - ${theme.fonts.label.large.R14}; - background-color: ${theme.colors.field01}; - color: ${theme.colors.text06}; - display: flex; - align-items: center; - justify-content: center; - gap: 0.4rem; - padding: 0.8rem; - border-radius: 0.8rem; -`; diff --git a/src/app/login/components/LoginCard/LoginCard.css.ts b/src/app/login/components/LoginCard/LoginCard.css.ts new file mode 100644 index 0000000..ee508e6 --- /dev/null +++ b/src/app/login/components/LoginCard/LoginCard.css.ts @@ -0,0 +1,47 @@ +import { style } from '@vanilla-extract/css'; + +import { colors } from '@/styles/colors'; +import { fonts } from '@/styles/fonts.css'; + +export const loginCardLayout = style({ + backgroundColor: colors.field02, + width: '32.7rem', + display: 'flex', + flexDirection: 'column', + borderRadius: '1.2rem', + padding: '3rem', + justifyContent: 'space-between', +}); + +export const cardTitleContainer = style({ + display: 'flex', + flexDirection: 'column', + gap: '0.8rem', +}); + +export const badge = style({ + ...fonts.label.large.SB14, + width: 'fit-content', + padding: '0.4rem 0.8rem', + borderRadius: '1.2rem', + color: 'var(--badge-color)', + backgroundColor: 'var(--badge-bg)', +}); + +export const buttonContainer = style({ + display: 'flex', + flexDirection: 'column', + gap: '0.8rem', +}); + +export const loginButton = style({ + ...fonts.label.large.R14, + backgroundColor: colors.field01, + color: colors.text06, + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + gap: '0.4rem', + padding: '0.8rem', + borderRadius: '0.8rem', +}); diff --git a/src/app/login/components/LoginCard.tsx b/src/app/login/components/LoginCard/LoginCard.tsx similarity index 74% rename from src/app/login/components/LoginCard.tsx rename to src/app/login/components/LoginCard/LoginCard.tsx index 85e2b25..7324211 100644 --- a/src/app/login/components/LoginCard.tsx +++ b/src/app/login/components/LoginCard/LoginCard.tsx @@ -1,3 +1,6 @@ +'use client'; + +import { assignInlineVars } from '@vanilla-extract/dynamic'; import Image from 'next/image'; import { useRouter } from 'next/navigation'; @@ -7,8 +10,8 @@ import { cardTitleContainer, loginButton, loginCardLayout, -} from './LoginCard.styles'; -import { descriptionWrapper } from '../LoginPage.styles'; +} from './LoginCard.css'; +import { descriptionWrapper } from '../../LoginPage.css'; import Google from '@/assets/images/google.svg'; import Naver from '@/assets/images/naver.svg'; @@ -40,19 +43,20 @@ const LoginCard = ({ role, description }: LoginCardProps) => { }; return ( - <div css={loginCardLayout}> - <div css={cardTitleContainer}> + <div className={loginCardLayout}> + <div className={cardTitleContainer}> <div - css={badge} - style={{ - color: role === '연구자' ? theme.colors.secondaryPink : theme.colors.primaryMint, - backgroundColor: + className={badge} + style={assignInlineVars({ + '--badge-color': + role === '연구자' ? theme.colors.secondaryPink : theme.colors.primaryMint, + '--badge-bg': role === '연구자' ? theme.colors.secondaryTinted : theme.colors.primaryTinted, - }} + })} > {role} </div> - <div css={descriptionWrapper}> + <div className={descriptionWrapper}> {description.map((text, idx) => ( <span key={idx}> {text} @@ -61,12 +65,12 @@ const LoginCard = ({ role, description }: LoginCardProps) => { ))} </div> </div> - <div css={buttonContainer}> - <button css={loginButton} onClick={goToLoginNaver}> + <div className={buttonContainer}> + <button className={loginButton} onClick={goToLoginNaver}> <Image src={Naver} alt="네이버" width={24} height={24} /> <span>네이버 계정으로 로그인</span> </button> - <button css={loginButton} onClick={goToLoginGoogle}> + <button className={loginButton} onClick={goToLoginGoogle}> <Image src={Google} alt="구글" width={24} height={24} /> <span>구글 계정으로 로그인</span> </button> diff --git a/src/app/login/google/GoogleLoginPage.css.ts b/src/app/login/google/GoogleLoginPage.css.ts new file mode 100644 index 0000000..750f61f --- /dev/null +++ b/src/app/login/google/GoogleLoginPage.css.ts @@ -0,0 +1,5 @@ +import { style } from '@vanilla-extract/css'; + +export const emptyLayout = style({ + height: 'calc(100vh - 17.8rem)', +}); diff --git a/src/app/login/google/GoogleLoginPage.styles.ts b/src/app/login/google/GoogleLoginPage.styles.ts deleted file mode 100644 index 470c7c4..0000000 --- a/src/app/login/google/GoogleLoginPage.styles.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { css } from '@emotion/react'; - -export const emptyLayout = css` - height: calc(100vh - 17.8rem); -`; diff --git a/src/app/login/google/page.tsx b/src/app/login/google/page.tsx index 7f2fd44..01df6c5 100644 --- a/src/app/login/google/page.tsx +++ b/src/app/login/google/page.tsx @@ -3,7 +3,7 @@ import { useSearchParams } from 'next/navigation'; import React, { useEffect, useRef } from 'react'; -import { emptyLayout } from './GoogleLoginPage.styles'; +import { emptyLayout } from './GoogleLoginPage.css'; import useGoogleLoginMutation from '../hooks/useGoogleLoginMutation'; export default function GoogleLoginPage() { @@ -23,5 +23,5 @@ export default function GoogleLoginPage() { } }, [code, role, googleLogin]); - return <div css={emptyLayout}></div>; + return <div className={emptyLayout}></div>; } diff --git a/src/app/login/layout.tsx b/src/app/login/layout.tsx index a8ae284..3ff28e5 100644 --- a/src/app/login/layout.tsx +++ b/src/app/login/layout.tsx @@ -1,17 +1,7 @@ -'use client'; - -import { Theme } from '@emotion/react'; -import { css } from '@emotion/react'; +import { loginLayout } from './LoginPage.css'; function LoginLayout({ children }: { children: React.ReactNode }) { - return <div css={loginLayout}>{children}</div>; + return <div className={loginLayout}>{children}</div>; } -const loginLayout = (theme: Theme) => css` - background-color: ${theme.colors.field01}; - min-width: 100rem; - height: calc(100vh - 12.2rem); - margin: 0 auto; -`; - export default LoginLayout; diff --git a/src/app/login/naver/NaverLoginPage.css.ts b/src/app/login/naver/NaverLoginPage.css.ts new file mode 100644 index 0000000..750f61f --- /dev/null +++ b/src/app/login/naver/NaverLoginPage.css.ts @@ -0,0 +1,5 @@ +import { style } from '@vanilla-extract/css'; + +export const emptyLayout = style({ + height: 'calc(100vh - 17.8rem)', +}); diff --git a/src/app/login/naver/NaverLoginPage.styles.ts b/src/app/login/naver/NaverLoginPage.styles.ts deleted file mode 100644 index 470c7c4..0000000 --- a/src/app/login/naver/NaverLoginPage.styles.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { css } from '@emotion/react'; - -export const emptyLayout = css` - height: calc(100vh - 17.8rem); -`; diff --git a/src/app/login/naver/page.tsx b/src/app/login/naver/page.tsx index d8910be..274deb8 100644 --- a/src/app/login/naver/page.tsx +++ b/src/app/login/naver/page.tsx @@ -1,9 +1,9 @@ 'use client'; import { useSearchParams } from 'next/navigation'; -import React, { useEffect, useRef } from 'react'; +import { useEffect, useRef } from 'react'; -import { emptyLayout } from './NaverLoginPage.styles'; +import { emptyLayout } from './NaverLoginPage.css'; import useNaverLoginMutation from '../hooks/useNaverLoginMutation'; export default function NaverLoginPage() { @@ -24,5 +24,5 @@ export default function NaverLoginPage() { } }, [code, stateParams, naverLogin]); - return <div css={emptyLayout}></div>; + return <div className={emptyLayout}></div>; } diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index 1d77a28..be9caa4 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -1,29 +1,27 @@ -'use client'; - import Image from 'next/image'; -import LoginCard from './components/LoginCard'; +import LoginCard from './components/LoginCard/LoginCard'; import { - loginCardContainer, - loginLayout, + loginPageLayout, sloganContainer, sloganWrapper, -} from './LoginPage.styles'; + loginCardContainer, +} from './LoginPage.css'; import Logo from '@/assets/images/logo.svg'; export default function LoginPage() { return ( - <div css={loginLayout}> - <div css={sloganContainer}> + <div className={loginPageLayout}> + <div className={sloganContainer}> <Image src={Logo} alt="로고" width={80} height={28} /> - <div css={sloganWrapper}> + <div className={sloganWrapper}> <span>작은 연결로 시작되는 큰 발견</span> <br /> <span>그라밋이 도울게요</span> </div> </div> - <div css={loginCardContainer}> + <div className={loginCardContainer}> <LoginCard role="연구자" description={['그라밋에서 손쉽게', '연구 참여자를 모아보세요']} /> <LoginCard role="참여자" description={['정보를 등록하면', '딱 맞는 실험을 찾아드려요']} /> </div> From e415bda56f6fe6bf6d42045489ed181e8e98b684 Mon Sep 17 00:00:00 2001 From: Gyuhan Park <rbgks1937@naver.com> Date: Wed, 5 Feb 2025 01:19:28 +0900 Subject: [PATCH 06/11] =?UTF-8?q?[YS-243]=20refactor:=20=EC=B0=B8=EC=97=AC?= =?UTF-8?q?=EC=9E=90=20=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20=EC=8A=A4?= =?UTF-8?q?=ED=83=80=EC=9D=BC=EB=A7=81=20=EB=A7=88=EC=9D=B4=EA=B7=B8?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=85=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../JoinEmailStep/JoinEmailStep.css.ts | 21 ++++++ .../JoinEmailStep/JoinEmailStep.styles.ts | 43 ------------ .../JoinEmailStep/JoinEmailStep.tsx | 16 +++-- .../AreaTooltip/AreaTooltip.css.ts | 33 ++++++++++ .../AreaTooltip/AreaTooltip.styles.ts | 36 ---------- .../JoinInfoStep/AreaTooltip/AreaTooltip.tsx | 8 ++- .../JoinInfoStep/JoinInfoStep.css.ts | 48 ++++++++++++++ .../JoinInfoStep/JoinInfoStep.styles.ts | 54 --------------- .../Participant/JoinInfoStep/JoinInfoStep.tsx | 63 +++++++++--------- .../JoinInfoStep/JoinSelect/JoinSelect.css.ts | 65 ++++++++++++++++++ .../JoinSelect/JoinSelect.styles.ts | 66 ------------------- .../JoinInfoStep/JoinSelect/JoinSelect.tsx | 12 ++-- .../RadioButtonGroup/RadioButtonGroup.css.ts | 45 +++++++++++++ .../RadioButtonGroup.styles.ts | 48 -------------- .../RadioButtonGroup/RadioButtonGroup.tsx | 16 +++-- .../RadioButtonGroupContainer.css.ts | 28 ++++++++ .../RadioButtonGroupContainer.styles.ts | 25 ------- .../RadioButtonGroupContainer.tsx | 12 ++-- 18 files changed, 308 insertions(+), 331 deletions(-) create mode 100644 src/app/join/components/Participant/JoinEmailStep/JoinEmailStep.css.ts delete mode 100644 src/app/join/components/Participant/JoinEmailStep/JoinEmailStep.styles.ts create mode 100644 src/app/join/components/Participant/JoinInfoStep/AreaTooltip/AreaTooltip.css.ts delete mode 100644 src/app/join/components/Participant/JoinInfoStep/AreaTooltip/AreaTooltip.styles.ts create mode 100644 src/app/join/components/Participant/JoinInfoStep/JoinInfoStep.css.ts delete mode 100644 src/app/join/components/Participant/JoinInfoStep/JoinInfoStep.styles.ts create mode 100644 src/app/join/components/Participant/JoinInfoStep/JoinSelect/JoinSelect.css.ts delete mode 100644 src/app/join/components/Participant/JoinInfoStep/JoinSelect/JoinSelect.styles.ts create mode 100644 src/app/join/components/Participant/JoinInfoStep/RadioButtonGroupContainer/RadioButtonGroup/RadioButtonGroup.css.ts delete mode 100644 src/app/join/components/Participant/JoinInfoStep/RadioButtonGroupContainer/RadioButtonGroup/RadioButtonGroup.styles.ts create mode 100644 src/app/join/components/Participant/JoinInfoStep/RadioButtonGroupContainer/RadioButtonGroupContainer.css.ts delete mode 100644 src/app/join/components/Participant/JoinInfoStep/RadioButtonGroupContainer/RadioButtonGroupContainer.styles.ts diff --git a/src/app/join/components/Participant/JoinEmailStep/JoinEmailStep.css.ts b/src/app/join/components/Participant/JoinEmailStep/JoinEmailStep.css.ts new file mode 100644 index 0000000..f279b0b --- /dev/null +++ b/src/app/join/components/Participant/JoinEmailStep/JoinEmailStep.css.ts @@ -0,0 +1,21 @@ +import { style } from '@vanilla-extract/css'; + +import { colors } from '@/styles/colors'; +import { fonts } from '@/styles/fonts.css'; + +export const nextButton = style({ + ...fonts.body.normal.SB16, + backgroundColor: colors.primaryMint, + color: colors.text01, + borderRadius: '1.2rem', + padding: '1.2rem 0', + width: '20rem', + alignItems: 'center', + marginBottom: '5.6rem', + selectors: { + '&:disabled': { + color: colors.text02, + backgroundColor: colors.field04, + }, + }, +}); diff --git a/src/app/join/components/Participant/JoinEmailStep/JoinEmailStep.styles.ts b/src/app/join/components/Participant/JoinEmailStep/JoinEmailStep.styles.ts deleted file mode 100644 index c3a60de..0000000 --- a/src/app/join/components/Participant/JoinEmailStep/JoinEmailStep.styles.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { css, Theme } from '@emotion/react'; - -export const joinContentContainer = (theme: Theme) => css` - background-color: ${theme.colors.field02}; - width: 100%; - display: flex; - flex-direction: column; - gap: 2.8rem; - border-radius: 1.2rem; - padding: 3.2rem 4rem; -`; - -export const nextButton = (theme: Theme) => css` - ${theme.fonts.body.normal.SB16}; - background-color: ${theme.colors.primaryMint}; - color: ${theme.colors.text01}; - border-radius: 1.2rem; - padding: 1.2rem 0; - width: 20rem; - align-items: center; - margin-bottom: 5.6rem; - - :disabled { - color: ${theme.colors.text02}; - background-color: ${theme.colors.field04}; - } -`; - -export const joinButton = (theme: Theme) => css` - ${theme.fonts.body.normal.SB16}; - background-color: ${theme.colors.primaryMint}; - color: ${theme.colors.text01}; - border-radius: 1.2rem; - padding: 1.2rem 0; - width: 20rem; - align-items: center; - margin-bottom: 5.6rem; - - :disabled { - color: ${theme.colors.text02}; - background-color: ${theme.colors.field04}; - } -`; diff --git a/src/app/join/components/Participant/JoinEmailStep/JoinEmailStep.tsx b/src/app/join/components/Participant/JoinEmailStep/JoinEmailStep.tsx index 39c034f..40401ab 100644 --- a/src/app/join/components/Participant/JoinEmailStep/JoinEmailStep.tsx +++ b/src/app/join/components/Participant/JoinEmailStep/JoinEmailStep.tsx @@ -1,11 +1,13 @@ +'use client'; + import { useFormContext, useWatch } from 'react-hook-form'; -import { nextButton } from './JoinEmailStep.styles'; +import { nextButton } from './JoinEmailStep.css'; import JoinCheckboxContainer from '../../JoinCheckboxContainer/JoinCheckboxContainer'; import JoinInput from '../../JoinInput/JoinInput'; import useServiceAgreeCheck from '@/app/join/hooks/useServiceAgreeCheck'; -import { joinContentContainer, joinForm } from '@/app/join/JoinPage.styles'; +import { joinContentContainer, joinForm } from '@/app/join/JoinPage.css'; import { ParticipantJoinSchemaType } from '@/schema/join/ParticipantJoinSchema'; interface JoinEmailStepProps { @@ -18,27 +20,27 @@ const JoinEmailStep = ({ onNext }: JoinEmailStepProps) => { trigger, formState: { errors }, } = useFormContext<ParticipantJoinSchemaType>(); + const { serviceAgreeCheck, handleAllCheck, handleChangeCheck } = useServiceAgreeCheck(); const oauthEmail = useWatch({ name: 'oauthEmail', control }); const contactEmail = useWatch({ name: 'contactEmail', control }); const allValid = contactEmail && - Boolean(!errors.contactEmail) && + !errors.contactEmail && serviceAgreeCheck.isTermOfService && serviceAgreeCheck.isPrivacy; const handleNextStep = async () => { const isValid = await trigger(['oauthEmail', 'contactEmail']); - if (isValid) { onNext(); } }; return ( - <section css={joinForm}> - <div css={joinContentContainer}> + <section className={joinForm}> + <div className={joinContentContainer}> <JoinInput<ParticipantJoinSchemaType> name="oauthEmail" control={control} @@ -61,7 +63,7 @@ const JoinEmailStep = ({ onNext }: JoinEmailStepProps) => { handleChange={handleChangeCheck} /> </div> - <button css={nextButton} onClick={handleNextStep} disabled={!allValid}> + <button className={nextButton} onClick={handleNextStep} disabled={!allValid}> 다음 </button> </section> diff --git a/src/app/join/components/Participant/JoinInfoStep/AreaTooltip/AreaTooltip.css.ts b/src/app/join/components/Participant/JoinInfoStep/AreaTooltip/AreaTooltip.css.ts new file mode 100644 index 0000000..c7c6c9f --- /dev/null +++ b/src/app/join/components/Participant/JoinInfoStep/AreaTooltip/AreaTooltip.css.ts @@ -0,0 +1,33 @@ +import { style, keyframes } from '@vanilla-extract/css'; + +import { colors } from '@/styles/colors'; +import { fonts } from '@/styles/fonts.css'; + +export const slideDownAndFade = keyframes({ + from: { opacity: 0, transform: 'translateY(-2px)' }, + to: { opacity: 1, transform: 'translateY(0)' }, +}); + +export const tooltipContent = style({ + ...fonts.label.medium.M13, + width: '20rem', + left: '2.4rem', + backgroundColor: colors.field01, + borderRadius: '0.6rem', + padding: '0.8rem 1.6rem', + color: colors.text05, + boxShadow: '0 4px 8px rgba(16, 17, 18, 0.1)', + border: `0.15rem solid ${colors.line01}`, + userSelect: 'none', + animationDuration: '100ms', + animationTimingFunction: 'cubic-bezier(0.16, 1, 0.3, 1)', + selectors: { + '&[data-state="delayed-open"][data-side="bottom"]': { + animationName: slideDownAndFade, + }, + }, +}); + +export const tooltipArrow = style({ + fill: colors.field01, +}); diff --git a/src/app/join/components/Participant/JoinInfoStep/AreaTooltip/AreaTooltip.styles.ts b/src/app/join/components/Participant/JoinInfoStep/AreaTooltip/AreaTooltip.styles.ts deleted file mode 100644 index bf1cfaf..0000000 --- a/src/app/join/components/Participant/JoinInfoStep/AreaTooltip/AreaTooltip.styles.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { css, keyframes, Theme } from '@emotion/react'; - -export const tooltipContent = (theme: Theme) => css` - ${theme.fonts.label.medium.M13}; - width: 20rem; - left: 2.4rem; - background-color: ${theme.colors.field01}; - border-radius: 0.6rem; - padding: 0.8rem 1.6rem; - color: ${theme.colors.text05}; - box-shadow: 0 4px 8px rgba(16, 17, 18, 0.1); - border: 0.15rem solid ${theme.colors.line01}; - - user-select: none; - animation-duration: 100ms; - animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); - - &[data-state='delayed-open'][data-side='bottom'] { - animation-name: ${slideDownAndFade}; - } -`; - -export const tooltipArrow = (theme: Theme) => css` - fill: ${theme.colors.field01}; -`; - -export const slideDownAndFade = keyframes` - from { - opacity: 0; - transform: translateY(-2px); - } - to { - opacity: 1; - transform: translateY(0); - } -`; diff --git a/src/app/join/components/Participant/JoinInfoStep/AreaTooltip/AreaTooltip.tsx b/src/app/join/components/Participant/JoinInfoStep/AreaTooltip/AreaTooltip.tsx index c19f241..ae21952 100644 --- a/src/app/join/components/Participant/JoinInfoStep/AreaTooltip/AreaTooltip.tsx +++ b/src/app/join/components/Participant/JoinInfoStep/AreaTooltip/AreaTooltip.tsx @@ -1,6 +1,8 @@ +'use client'; + import * as Tooltip from '@radix-ui/react-tooltip'; -import { tooltipArrow, tooltipContent } from './AreaTooltip.styles'; +import { tooltipArrow, tooltipContent } from './AreaTooltip.css'; import Icon from '@/components/Icon'; @@ -14,9 +16,9 @@ const AreaTooltip = () => { </button> </Tooltip.Trigger> <Tooltip.Portal> - <Tooltip.Content side="bottom" sideOffset={2} css={tooltipContent}> + <Tooltip.Content side="bottom" sideOffset={2} className={tooltipContent}> 학교 소재지 등 자주 가는 지역을 추가로 입력할 수 있어요 - <Tooltip.Arrow css={tooltipArrow} /> + <Tooltip.Arrow className={tooltipArrow} /> </Tooltip.Content> </Tooltip.Portal> </Tooltip.Root> diff --git a/src/app/join/components/Participant/JoinInfoStep/JoinInfoStep.css.ts b/src/app/join/components/Participant/JoinInfoStep/JoinInfoStep.css.ts new file mode 100644 index 0000000..fde409d --- /dev/null +++ b/src/app/join/components/Participant/JoinInfoStep/JoinInfoStep.css.ts @@ -0,0 +1,48 @@ +import { style } from '@vanilla-extract/css'; + +import { colors } from '@/styles/colors'; +import { fonts } from '@/styles/fonts.css'; + +export const joinButton = style({ + ...fonts.body.normal.SB16, + backgroundColor: colors.primaryMint, + color: colors.text01, + borderRadius: '1.2rem', + padding: '1.2rem 0', + width: '20rem', + alignItems: 'center', + marginBottom: '5.6rem', + selectors: { + '&:disabled': { + color: colors.text02, + backgroundColor: colors.field04, + }, + }, +}); + +export const joinAreaFilterContainer = style({ + display: 'flex', + flexDirection: 'column', + gap: '0.6rem', +}); + +export const filterTitleWrapper = style({ + ...fonts.label.large.M14, + color: colors.text06, + display: 'flex', + gap: '0.4rem', + alignItems: 'center', +}); + +export const filterTitle = style({ + ...fonts.label.large.M14, +}); + +export const requiredStar = style({ + color: colors.textAlert, +}); + +export const joinAreaFilterWrapper = style({ + display: 'flex', + gap: '0.8rem', +}); diff --git a/src/app/join/components/Participant/JoinInfoStep/JoinInfoStep.styles.ts b/src/app/join/components/Participant/JoinInfoStep/JoinInfoStep.styles.ts deleted file mode 100644 index d02c8f5..0000000 --- a/src/app/join/components/Participant/JoinInfoStep/JoinInfoStep.styles.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { css, Theme } from '@emotion/react'; - -export const joinContentContainer = (theme: Theme) => css` - background-color: ${theme.colors.field02}; - width: 100%; - display: flex; - flex-direction: column; - gap: 2.8rem; - border-radius: 1.2rem; - padding: 3.2rem 4rem; -`; - -export const joinButton = (theme: Theme) => css` - ${theme.fonts.body.normal.SB16}; - background-color: ${theme.colors.primaryMint}; - color: ${theme.colors.text01}; - border-radius: 1.2rem; - padding: 1.2rem 0; - width: 20rem; - align-items: center; - margin-bottom: 5.6rem; - - :disabled { - color: ${theme.colors.text02}; - background-color: ${theme.colors.field04}; - } -`; - -export const joinAreaFilterContainer = css` - display: flex; - flex-direction: column; - gap: 0.6rem; -`; - -export const filterTitleWrapper = (theme: Theme) => css` - ${theme.fonts.label.large.M14}; - color: ${theme.colors.text06}; - display: flex; - gap: 0.4rem; - align-items: center; -`; - -export const filterTitle = (theme: Theme) => css` - ${theme.fonts.label.large.M14}; -`; - -export const requiredStar = (theme: Theme) => css` - color: ${theme.colors.textAlert}; -`; - -export const joinAreaFilterWrapper = css` - display: flex; - gap: 0.8rem; -`; diff --git a/src/app/join/components/Participant/JoinInfoStep/JoinInfoStep.tsx b/src/app/join/components/Participant/JoinInfoStep/JoinInfoStep.tsx index 434c87c..b1aa4ac 100644 --- a/src/app/join/components/Participant/JoinInfoStep/JoinInfoStep.tsx +++ b/src/app/join/components/Participant/JoinInfoStep/JoinInfoStep.tsx @@ -1,21 +1,22 @@ +'use client'; + import { Controller, useFormContext, useWatch } from 'react-hook-form'; import AreaTooltip from './AreaTooltip/AreaTooltip'; import { - filterTitle, - filterTitleWrapper, - joinAreaFilterContainer, - joinAreaFilterWrapper, joinButton, - joinContentContainer, + joinAreaFilterContainer, + filterTitleWrapper, + filterTitle, requiredStar, -} from './JoinInfoStep.styles'; + joinAreaFilterWrapper, +} from './JoinInfoStep.css'; import JoinSelect from './JoinSelect/JoinSelect'; import RadioButtonGroupContainer from './RadioButtonGroupContainer/RadioButtonGroupContainer'; import JoinInput from '../../JoinInput/JoinInput'; import { JOIN_REGION, JOIN_SUB_REGION } from '@/app/join/JoinPage.constants'; -import { joinForm } from '@/app/join/JoinPage.styles'; +import { joinContentContainer, joinForm } from '@/app/join/JoinPage.css'; // 이미 vanilla‐extract로 변환된 JoinPage 스타일 파일 import { Gender, MatchType } from '@/app/join/JoinPage.types'; import { ParticipantJoinSchemaType } from '@/schema/join/ParticipantJoinSchema'; @@ -41,8 +42,8 @@ const JoinInfoStep = ({ handleSubmit }: JoinInfoStepProps) => { const isAllFilled = values.every((value) => (value ?? '').trim() !== '' && value !== undefined); return ( - <section css={joinForm}> - <div css={joinContentContainer}> + <section className={joinForm}> + <div className={joinContentContainer}> {/* 이름 */} <JoinInput<ParticipantJoinSchemaType> name="name" @@ -80,12 +81,12 @@ const JoinInfoStep = ({ handleSubmit }: JoinInfoStepProps) => { /> {/* 거주 지역 */} - <div css={joinAreaFilterContainer}> - <div css={filterTitleWrapper}> - <span css={filterTitle}>거주 지역</span> - <span css={requiredStar}>*</span> + <div className={joinAreaFilterContainer}> + <div className={filterTitleWrapper}> + <span className={filterTitle}>거주 지역</span> + <span className={requiredStar}>*</span> </div> - <div css={joinAreaFilterWrapper}> + <div className={joinAreaFilterWrapper}> <Controller name="basicAddressInfo.region" control={control} @@ -95,7 +96,7 @@ const JoinInfoStep = ({ handleSubmit }: JoinInfoStepProps) => { onChange={(value) => setValue('basicAddressInfo.region', value)} placeholder="시·도" options={JOIN_REGION} - isError={Boolean(fieldState.error) && Boolean(!field.value)} + isError={Boolean(fieldState.error) && !field.value} /> )} /> @@ -109,7 +110,7 @@ const JoinInfoStep = ({ handleSubmit }: JoinInfoStepProps) => { onChange={(value) => setValue('basicAddressInfo.area', value)} placeholder="시·군·구" options={JOIN_SUB_REGION[selectedArea] || []} - isError={Boolean(fieldState.error) && Boolean(!field.value)} + isError={Boolean(fieldState.error) && !field.value} /> )} /> @@ -117,26 +118,24 @@ const JoinInfoStep = ({ handleSubmit }: JoinInfoStepProps) => { </div> {/* 추가 활동 지역 */} - <div css={joinAreaFilterContainer}> - <div css={filterTitleWrapper}> - <span css={filterTitle}>추가 활동 지역</span> + <div className={joinAreaFilterContainer}> + <div className={filterTitleWrapper}> + <span className={filterTitle}>추가 활동 지역</span> <AreaTooltip /> </div> - <div css={joinAreaFilterWrapper}> + <div className={joinAreaFilterWrapper}> <Controller name="additionalAddressInfo.region" control={control} - render={({ field, fieldState }) => { - return ( - <JoinSelect - value={field.value} - onChange={(value) => setValue('additionalAddressInfo.region', value)} - placeholder="시·도" - options={JOIN_REGION} - isError={Boolean(fieldState.error)} - /> - ); - }} + render={({ field, fieldState }) => ( + <JoinSelect + value={field.value} + onChange={(value) => setValue('additionalAddressInfo.region', value)} + placeholder="시·도" + options={JOIN_REGION} + isError={Boolean(fieldState.error)} + /> + )} /> <Controller @@ -170,7 +169,7 @@ const JoinInfoStep = ({ handleSubmit }: JoinInfoStepProps) => { </div> <button - css={joinButton} + className={joinButton} onClick={handleSubmit} disabled={!(isAllFilled && Object.keys(errors).length === 0)} > diff --git a/src/app/join/components/Participant/JoinInfoStep/JoinSelect/JoinSelect.css.ts b/src/app/join/components/Participant/JoinInfoStep/JoinSelect/JoinSelect.css.ts new file mode 100644 index 0000000..fdf2e5d --- /dev/null +++ b/src/app/join/components/Participant/JoinInfoStep/JoinSelect/JoinSelect.css.ts @@ -0,0 +1,65 @@ +import { style } from '@vanilla-extract/css'; + +import { colors } from '@/styles/colors'; +import { fonts } from '@/styles/fonts.css'; + +export const triggerWrapper = style({ + ...fonts.body.normal.M16, + color: colors.text06, + display: 'flex', + alignItems: 'center', + justifyContent: 'space-between', + gap: '0.4rem', + borderRadius: '1.2rem', + padding: '1.6rem', + backgroundColor: colors.field01, + cursor: 'pointer', + width: '100%', + selectors: { + '&[data-placeholder]': { + ...fonts.body.normal.M16, + color: colors.text02, + }, + "&[aria-invalid='true']": { + outline: `0.1rem solid ${colors.textAlert}`, + }, + }, +}); + +export const selectContent = style({ + width: '23.6rem', + maxHeight: '34rem', + padding: '1rem 0.8rem', + backgroundColor: colors.field01, + border: `0.1rem solid ${colors.line01}`, + borderRadius: '1.2rem', + boxShadow: '0px 4px 16px rgba(53, 59, 61, 0.2)', + overflowY: 'scroll', +}); + +export const selectList = style({ + display: 'flex', + flexDirection: 'column', + gap: '0.8rem', +}); + +export const selectItem = style({ + ...fonts.body.normal.M16, + color: colors.text06, + display: 'flex', + padding: '0.6rem 1.2rem', + alignItems: 'center', + borderRadius: '1.2rem', + cursor: 'pointer', + selectors: { + '&[data-highlighted]': { + backgroundColor: colors.field02, + outline: 'none', + }, + "&[data-state='checked']": { + backgroundColor: colors.primaryTinted, + color: colors.textPrimary, + border: `0.1rem solid ${colors.textPrimary}`, + }, + }, +}); diff --git a/src/app/join/components/Participant/JoinInfoStep/JoinSelect/JoinSelect.styles.ts b/src/app/join/components/Participant/JoinInfoStep/JoinSelect/JoinSelect.styles.ts deleted file mode 100644 index 90a6726..0000000 --- a/src/app/join/components/Participant/JoinInfoStep/JoinSelect/JoinSelect.styles.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { css, Theme } from '@emotion/react'; - -export const triggerWrapper = (theme: Theme) => css` - ${theme.fonts.body.normal.M16}; - color: ${theme.colors.text06}; - display: flex; - align-items: center; - justify-content: space-between; - gap: 0.4rem; - border-radius: 1.2rem; - padding: 1.6rem; - background-color: ${theme.colors.field01}; - cursor: pointer; - width: 100%; - - &[data-placeholder] { - ${theme.fonts.body.normal.M16}; - color: ${theme.colors.text02}; - } - - &[aria-invalid='true'] { - outline: 0.1rem solid ${theme.colors.textAlert}; - } -`; - -export const selectContent = (theme: Theme) => css` - width: 23.6rem; - max-height: 34rem; - - padding: 1rem 0.8rem; - - background-color: ${theme.colors.field01}; - border: 0.1rem solid ${theme.colors.line01}; - border-radius: 1.2rem; - - box-shadow: 0px 4px 16px rgba(53, 59, 61, 0.2); - overflow-y: scroll; -`; - -export const selectList = css` - display: flex; - flex-direction: column; - gap: 0.8rem; -`; - -export const selectItem = (theme: Theme) => css` - ${theme.fonts.body.normal.M16}; - color: ${theme.colors.text06}; - display: flex; - padding: 0.6rem 1.2rem; - align-items: center; - border-radius: 1.2rem; - cursor: pointer; - - &[data-highlighted] { - background-color: ${theme.colors.field02}; - outline: none; - } - - &[data-state='checked'] { - background-color: ${theme.colors.primaryTinted}; - color: ${theme.colors.textPrimary}; - - border: 0.1rem solid ${theme.colors.textPrimary}; - } -`; diff --git a/src/app/join/components/Participant/JoinInfoStep/JoinSelect/JoinSelect.tsx b/src/app/join/components/Participant/JoinInfoStep/JoinSelect/JoinSelect.tsx index 84d84ec..1e893df 100644 --- a/src/app/join/components/Participant/JoinInfoStep/JoinSelect/JoinSelect.tsx +++ b/src/app/join/components/Participant/JoinInfoStep/JoinSelect/JoinSelect.tsx @@ -1,7 +1,9 @@ +'use client'; + import * as Select from '@radix-ui/react-select'; import { useState } from 'react'; -import { selectContent, selectItem, selectList, triggerWrapper } from './JoinSelect.styles'; +import { triggerWrapper, selectContent, selectList, selectItem } from './JoinSelect.css'; import { FilterOption } from '@/app/join/JoinPage.types'; import Icon from '@/components/Icon'; @@ -19,17 +21,17 @@ const JoinSelect = ({ placeholder, onChange, isError, options, value }: JoinSele return ( <Select.Root value={value} onValueChange={onChange} onOpenChange={(open) => setIsOpen(open)}> - <Select.Trigger css={triggerWrapper} aria-invalid={isError}> + <Select.Trigger className={triggerWrapper} aria-invalid={isError}> <Select.Value placeholder={placeholder} /> <Select.Icon> <Icon icon="Chevron" width={20} rotate={isOpen ? -180 : 0} cursor="pointer" /> </Select.Icon> </Select.Trigger> <Select.Portal> - <Select.Content css={selectContent} position="popper" sideOffset={4}> - <Select.Group css={selectList}> + <Select.Content className={selectContent} position="popper" sideOffset={4}> + <Select.Group className={selectList}> {options?.map((option) => ( - <Select.Item key={option.value} value={option.value} css={selectItem}> + <Select.Item key={option.value} value={option.value} className={selectItem}> <Select.ItemText>{option.label}</Select.ItemText> </Select.Item> ))} diff --git a/src/app/join/components/Participant/JoinInfoStep/RadioButtonGroupContainer/RadioButtonGroup/RadioButtonGroup.css.ts b/src/app/join/components/Participant/JoinInfoStep/RadioButtonGroupContainer/RadioButtonGroup/RadioButtonGroup.css.ts new file mode 100644 index 0000000..b767afd --- /dev/null +++ b/src/app/join/components/Participant/JoinInfoStep/RadioButtonGroupContainer/RadioButtonGroup/RadioButtonGroup.css.ts @@ -0,0 +1,45 @@ +import { style } from '@vanilla-extract/css'; + +import { colors } from '@/styles/colors'; +import { fonts } from '@/styles/fonts.css'; + +export const customRadioGroup = style({ + display: 'flex', + flexFlow: 'row nowrap', + gap: '0.8rem', +}); + +export const customRadioButton = style({ + ...fonts.label.large.M14, + flexGrow: 1, + height: '4.8rem', + padding: '1rem 2rem', + border: `0.1rem solid ${colors.line01}`, + borderRadius: '1.2rem', + backgroundColor: colors.field01, + cursor: 'pointer', + transition: 'all 0.2s ease', + selectors: { + '&:hover': { + backgroundColor: colors.field02, + }, + "&[aria-invalid='true']": { + outline: `0.1rem solid ${colors.textAlert}`, + }, + }, +}); + +export const activeRadioButton = style({ + border: `0.1rem solid ${colors.lineTinted}`, + backgroundColor: colors.primaryTinted, + color: colors.textPrimary, + selectors: { + '&:hover': { + backgroundColor: colors.primaryTinted, + }, + }, +}); + +export const errorRadioButton = style({ + borderColor: colors.textAlert, +}); diff --git a/src/app/join/components/Participant/JoinInfoStep/RadioButtonGroupContainer/RadioButtonGroup/RadioButtonGroup.styles.ts b/src/app/join/components/Participant/JoinInfoStep/RadioButtonGroupContainer/RadioButtonGroup/RadioButtonGroup.styles.ts deleted file mode 100644 index f20781e..0000000 --- a/src/app/join/components/Participant/JoinInfoStep/RadioButtonGroupContainer/RadioButtonGroup/RadioButtonGroup.styles.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { css, Theme } from '@emotion/react'; - -export const customRadioGroup = css` - display: flex; - flex-flow: row nowrap; - gap: 0.8rem; -`; - -export const customRadioButton = (theme: Theme) => css` - ${theme.fonts.label.large.M14}; - - flex-grow: 1; - height: 4.8rem; - - padding: 1rem 2rem; - - border: 0.1rem solid ${theme.colors.line01}; - border-radius: 1.2rem; - - background-color: ${theme.colors.field01}; - - cursor: pointer; - - transition: all 0.2s ease; - - &:hover { - background-color: ${theme.colors.field02}; - } - - &[aria-invalid='true'] { - outline: 0.1rem solid ${theme.colors.textAlert}; - } -`; - -export const activeRadioButton = (theme: Theme) => css` - border: 0.1rem solid ${theme.colors.lineTinted}; - - background-color: ${theme.colors.primaryTinted}; - color: ${theme.colors.textPrimary}; - - &:hover { - background-color: ${theme.colors.primaryTinted}; - } -`; - -export const errorRadioButton = (theme: Theme) => css` - border-color: ${theme.colors.textAlert}; -`; diff --git a/src/app/join/components/Participant/JoinInfoStep/RadioButtonGroupContainer/RadioButtonGroup/RadioButtonGroup.tsx b/src/app/join/components/Participant/JoinInfoStep/RadioButtonGroupContainer/RadioButtonGroup/RadioButtonGroup.tsx index d31fc8e..05005b9 100644 --- a/src/app/join/components/Participant/JoinInfoStep/RadioButtonGroupContainer/RadioButtonGroup/RadioButtonGroup.tsx +++ b/src/app/join/components/Participant/JoinInfoStep/RadioButtonGroupContainer/RadioButtonGroup/RadioButtonGroup.tsx @@ -1,9 +1,11 @@ +'use client'; + import { customRadioGroup, customRadioButton, activeRadioButton, errorRadioButton, -} from './RadioButtonGroup.styles'; +} from './RadioButtonGroup.css'; interface RadioButtonGroupProps<T> { options: { value: T; label: string }[]; @@ -19,16 +21,16 @@ const RadioButtonGroup = <T extends string>({ isError, }: RadioButtonGroupProps<T>) => { return ( - <div css={customRadioGroup}> + <div className={customRadioGroup}> {options.map((option) => ( <button key={option.value} type="button" - css={[ - customRadioButton, - selectedValue === option.value && activeRadioButton, - isError && errorRadioButton, - ]} + className={` + ${customRadioButton} + ${selectedValue === option.value ? activeRadioButton : ''} + ${isError ? errorRadioButton : ''} + `} onClick={() => onChange(option.value)} > {option.label} diff --git a/src/app/join/components/Participant/JoinInfoStep/RadioButtonGroupContainer/RadioButtonGroupContainer.css.ts b/src/app/join/components/Participant/JoinInfoStep/RadioButtonGroupContainer/RadioButtonGroupContainer.css.ts new file mode 100644 index 0000000..a50f196 --- /dev/null +++ b/src/app/join/components/Participant/JoinInfoStep/RadioButtonGroupContainer/RadioButtonGroupContainer.css.ts @@ -0,0 +1,28 @@ +import { style } from '@vanilla-extract/css'; + +import { colors } from '@/styles/colors'; +import { fonts } from '@/styles/fonts.css'; + +export const radioButtonGroupContainerLayout = style({ + display: 'flex', + flexDirection: 'column', + gap: '0.6rem', +}); + +export const labelWrapper = style({ + ...fonts.label.large.M14, + display: 'flex', + gap: '0.4rem', + color: colors.text06, +}); + +export const requiredStar = style({ + color: colors.textAlert, +}); + +export const tipWrapper = style({ + ...fonts.label.small.M12, + display: 'flex', + gap: '0.4rem', + color: colors.text02, +}); diff --git a/src/app/join/components/Participant/JoinInfoStep/RadioButtonGroupContainer/RadioButtonGroupContainer.styles.ts b/src/app/join/components/Participant/JoinInfoStep/RadioButtonGroupContainer/RadioButtonGroupContainer.styles.ts deleted file mode 100644 index c6d4e61..0000000 --- a/src/app/join/components/Participant/JoinInfoStep/RadioButtonGroupContainer/RadioButtonGroupContainer.styles.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { css, Theme } from '@emotion/react'; - -export const radioButtonGroupContainerLayout = css` - display: flex; - flex-direction: column; - gap: 0.6rem; -`; - -export const labelWrapper = (theme: Theme) => css` - display: flex; - gap: 0.4rem; - ${theme.fonts.label.large.M14}; - color: ${theme.colors.text06}; -`; - -export const requiredStar = (theme: Theme) => css` - color: ${theme.colors.textAlert}; -`; - -export const tipWrapper = (theme: Theme) => css` - ${theme.fonts.label.small.M12}; - display: flex; - gap: 0.4rem; - color: ${theme.colors.text02}; -`; diff --git a/src/app/join/components/Participant/JoinInfoStep/RadioButtonGroupContainer/RadioButtonGroupContainer.tsx b/src/app/join/components/Participant/JoinInfoStep/RadioButtonGroupContainer/RadioButtonGroupContainer.tsx index 2d715f5..ce3c801 100644 --- a/src/app/join/components/Participant/JoinInfoStep/RadioButtonGroupContainer/RadioButtonGroupContainer.tsx +++ b/src/app/join/components/Participant/JoinInfoStep/RadioButtonGroupContainer/RadioButtonGroupContainer.tsx @@ -1,3 +1,5 @@ +'use client'; + import { Controller } from 'react-hook-form'; import RadioButtonGroup from './RadioButtonGroup/RadioButtonGroup'; @@ -6,7 +8,7 @@ import { radioButtonGroupContainerLayout, requiredStar, tipWrapper, -} from './RadioButtonGroupContainer.styles'; +} from './RadioButtonGroupContainer.css'; interface RadioButtonGroupProps<T> { // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -29,10 +31,10 @@ const RadioButtonGroupContainer = <T extends string>({ tip, }: RadioButtonGroupProps<T>) => { return ( - <div css={radioButtonGroupContainerLayout}> - <div css={labelWrapper}> + <div className={radioButtonGroupContainerLayout}> + <div className={labelWrapper}> <span>{title}</span> - {required && <span css={requiredStar}>*</span>} + {required && <span className={requiredStar}>*</span>} </div> <Controller @@ -51,7 +53,7 @@ const RadioButtonGroupContainer = <T extends string>({ /> {tip && ( - <div css={tipWrapper}> + <div className={tipWrapper}> <span>{tip}</span> </div> )} From 0ce1c19b89bdb1c1a71576b559e6a23e4205b2fa Mon Sep 17 00:00:00 2001 From: Gyuhan Park <rbgks1937@naver.com> Date: Wed, 5 Feb 2025 01:50:17 +0900 Subject: [PATCH 07/11] =?UTF-8?q?[YS-243]=20refactor:=20=EC=97=B0=EA=B5=AC?= =?UTF-8?q?=EC=9E=90=20=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20=EC=8A=A4?= =?UTF-8?q?=ED=83=80=EC=9D=BC=EB=A7=81=20=EB=A7=88=EC=9D=B4=EA=B7=B8?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=85=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/join/JoinPage.css.ts | 17 ++++ .../JoinEmailStep/JoinEmailStep.tsx | 3 +- .../JoinEmailStep/JoinEmailStep.css.ts | 0 .../JoinEmailStep/JoinEmailStep.styles.ts | 43 ---------- .../JoinEmailStep/JoinEmailStep.tsx | 17 ++-- .../AuthCodeInput/AuthCodeInput.css.ts | 44 ++++++++++ .../AuthCodeInput/AuthCodeInput.tsx | 26 +++--- .../UnivAuthInput/UnivAuthInput.css.ts | 43 ++++++++++ .../UnivAuthInput/UnivAuthInput.styles.ts | 86 ------------------- .../UnivAuthInput/UnivAuthInput.tsx | 73 +++++++++------- .../JoinInfoStep/JoinInfoStep.styles.ts | 27 ------ .../Researcher/JoinInfoStep/JoinInfoStep.tsx | 17 ++-- 12 files changed, 178 insertions(+), 218 deletions(-) rename src/app/join/components/{Participant => Researcher}/JoinEmailStep/JoinEmailStep.css.ts (100%) delete mode 100644 src/app/join/components/Researcher/JoinEmailStep/JoinEmailStep.styles.ts create mode 100644 src/app/join/components/Researcher/JoinEmailStep/UnivAuthInput/AuthCodeInput/AuthCodeInput.css.ts create mode 100644 src/app/join/components/Researcher/JoinEmailStep/UnivAuthInput/UnivAuthInput.css.ts delete mode 100644 src/app/join/components/Researcher/JoinEmailStep/UnivAuthInput/UnivAuthInput.styles.ts delete mode 100644 src/app/join/components/Researcher/JoinInfoStep/JoinInfoStep.styles.ts diff --git a/src/app/join/JoinPage.css.ts b/src/app/join/JoinPage.css.ts index 5ddbc56..60820c3 100644 --- a/src/app/join/JoinPage.css.ts +++ b/src/app/join/JoinPage.css.ts @@ -63,3 +63,20 @@ export const joinForm = style({ alignItems: 'center', gap: '4rem', }); + +export const nextButton = style({ + ...fonts.body.normal.SB16, + backgroundColor: colors.primaryMint, + color: colors.text01, + borderRadius: '1.2rem', + padding: '1.2rem 0', + width: '20rem', + alignItems: 'center', + marginBottom: '5.6rem', + selectors: { + '&:disabled': { + color: colors.text02, + backgroundColor: colors.field04, + }, + }, +}); diff --git a/src/app/join/components/Participant/JoinEmailStep/JoinEmailStep.tsx b/src/app/join/components/Participant/JoinEmailStep/JoinEmailStep.tsx index 40401ab..3e8f13a 100644 --- a/src/app/join/components/Participant/JoinEmailStep/JoinEmailStep.tsx +++ b/src/app/join/components/Participant/JoinEmailStep/JoinEmailStep.tsx @@ -2,12 +2,11 @@ import { useFormContext, useWatch } from 'react-hook-form'; -import { nextButton } from './JoinEmailStep.css'; import JoinCheckboxContainer from '../../JoinCheckboxContainer/JoinCheckboxContainer'; import JoinInput from '../../JoinInput/JoinInput'; import useServiceAgreeCheck from '@/app/join/hooks/useServiceAgreeCheck'; -import { joinContentContainer, joinForm } from '@/app/join/JoinPage.css'; +import { joinContentContainer, joinForm, nextButton } from '@/app/join/JoinPage.css'; import { ParticipantJoinSchemaType } from '@/schema/join/ParticipantJoinSchema'; interface JoinEmailStepProps { diff --git a/src/app/join/components/Participant/JoinEmailStep/JoinEmailStep.css.ts b/src/app/join/components/Researcher/JoinEmailStep/JoinEmailStep.css.ts similarity index 100% rename from src/app/join/components/Participant/JoinEmailStep/JoinEmailStep.css.ts rename to src/app/join/components/Researcher/JoinEmailStep/JoinEmailStep.css.ts diff --git a/src/app/join/components/Researcher/JoinEmailStep/JoinEmailStep.styles.ts b/src/app/join/components/Researcher/JoinEmailStep/JoinEmailStep.styles.ts deleted file mode 100644 index c3a60de..0000000 --- a/src/app/join/components/Researcher/JoinEmailStep/JoinEmailStep.styles.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { css, Theme } from '@emotion/react'; - -export const joinContentContainer = (theme: Theme) => css` - background-color: ${theme.colors.field02}; - width: 100%; - display: flex; - flex-direction: column; - gap: 2.8rem; - border-radius: 1.2rem; - padding: 3.2rem 4rem; -`; - -export const nextButton = (theme: Theme) => css` - ${theme.fonts.body.normal.SB16}; - background-color: ${theme.colors.primaryMint}; - color: ${theme.colors.text01}; - border-radius: 1.2rem; - padding: 1.2rem 0; - width: 20rem; - align-items: center; - margin-bottom: 5.6rem; - - :disabled { - color: ${theme.colors.text02}; - background-color: ${theme.colors.field04}; - } -`; - -export const joinButton = (theme: Theme) => css` - ${theme.fonts.body.normal.SB16}; - background-color: ${theme.colors.primaryMint}; - color: ${theme.colors.text01}; - border-radius: 1.2rem; - padding: 1.2rem 0; - width: 20rem; - align-items: center; - margin-bottom: 5.6rem; - - :disabled { - color: ${theme.colors.text02}; - background-color: ${theme.colors.field04}; - } -`; diff --git a/src/app/join/components/Researcher/JoinEmailStep/JoinEmailStep.tsx b/src/app/join/components/Researcher/JoinEmailStep/JoinEmailStep.tsx index f21a023..c904290 100644 --- a/src/app/join/components/Researcher/JoinEmailStep/JoinEmailStep.tsx +++ b/src/app/join/components/Researcher/JoinEmailStep/JoinEmailStep.tsx @@ -1,13 +1,15 @@ +'use client'; + import { useState } from 'react'; import { useFormContext, useWatch } from 'react-hook-form'; -import { joinContentContainer, nextButton } from './JoinEmailStep.styles'; +import { nextButton } from './JoinEmailStep.css'; import UnivAuthInput from './UnivAuthInput/UnivAuthInput'; import JoinCheckboxContainer from '../../JoinCheckboxContainer/JoinCheckboxContainer'; import JoinInput from '../../JoinInput/JoinInput'; import useServiceAgreeCheck from '@/app/join/hooks/useServiceAgreeCheck'; -import { joinForm } from '@/app/join/JoinPage.styles'; +import { joinContentContainer, joinForm } from '@/app/join/JoinPage.css'; import { ResearcherJoinSchemaType } from '@/schema/join/ResearcherJoinSchema'; interface JoinEmailStepProps { @@ -28,7 +30,6 @@ const JoinEmailStep = ({ onNext }: JoinEmailStepProps) => { const handleNextStep = async () => { const isValid = await trigger(['oauthEmail', 'contactEmail', 'univEmail']); - if (isValid) { onNext(); } @@ -37,8 +38,8 @@ const JoinEmailStep = ({ onNext }: JoinEmailStepProps) => { const allValid = oauthEmail && univEmail && - Boolean(!errors.contactEmail) && - Boolean(!errors.univEmail) && + !errors.contactEmail && + !errors.univEmail && isEmailVerified && serviceAgreeCheck.isTermOfService && serviceAgreeCheck.isPrivacy; @@ -48,8 +49,8 @@ const JoinEmailStep = ({ onNext }: JoinEmailStepProps) => { }; return ( - <section css={joinForm}> - <div css={joinContentContainer}> + <section className={joinForm}> + <div className={joinContentContainer}> <JoinInput<ResearcherJoinSchemaType> name="oauthEmail" control={control} @@ -73,7 +74,7 @@ const JoinEmailStep = ({ onNext }: JoinEmailStepProps) => { handleChange={handleChangeCheck} /> </div> - <button css={nextButton} onClick={handleNextStep} disabled={!allValid}> + <button className={nextButton} onClick={handleNextStep} disabled={!allValid}> 다음 </button> </section> diff --git a/src/app/join/components/Researcher/JoinEmailStep/UnivAuthInput/AuthCodeInput/AuthCodeInput.css.ts b/src/app/join/components/Researcher/JoinEmailStep/UnivAuthInput/AuthCodeInput/AuthCodeInput.css.ts new file mode 100644 index 0000000..e7415a8 --- /dev/null +++ b/src/app/join/components/Researcher/JoinEmailStep/UnivAuthInput/AuthCodeInput/AuthCodeInput.css.ts @@ -0,0 +1,44 @@ +import { style } from '@vanilla-extract/css'; + +import { colors } from '@/styles/colors'; +import { fonts } from '@/styles/fonts.css'; + +export const authInputLayout = style({ + display: 'flex', + flexDirection: 'column', +}); + +export const authTimerWrapper = style({ + position: 'absolute', + right: '1.2rem', + top: '1rem', + display: 'flex', + alignItems: 'center', + gap: '0.8rem', +}); + +export const authTimerText = style({ + ...fonts.label.large.M14, + color: colors.text03, +}); + +export const authCodeButton = style({ + ...fonts.label.large.SB14, + padding: '0.7rem 1.6rem', + borderRadius: '1rem', + backgroundColor: colors.primaryMint, + color: colors.text01, + selectors: { + '&:disabled': { + backgroundColor: colors.field04, + color: colors.text02, + }, + }, +}); + +export const sendAgainButton = style({ + ...fonts.label.large.M14, + color: colors.text03, + textDecorationLine: 'underline', + alignSelf: 'flex-end', +}); diff --git a/src/app/join/components/Researcher/JoinEmailStep/UnivAuthInput/AuthCodeInput/AuthCodeInput.tsx b/src/app/join/components/Researcher/JoinEmailStep/UnivAuthInput/AuthCodeInput/AuthCodeInput.tsx index 3630ae7..c765b01 100644 --- a/src/app/join/components/Researcher/JoinEmailStep/UnivAuthInput/AuthCodeInput/AuthCodeInput.tsx +++ b/src/app/join/components/Researcher/JoinEmailStep/UnivAuthInput/AuthCodeInput/AuthCodeInput.tsx @@ -1,15 +1,19 @@ +'use client'; + import { ChangeEvent, useState } from 'react'; import { useFormContext } from 'react-hook-form'; import { - authCodeButton, authInputLayout, authTimerWrapper, + authCodeButton, sendAgainButton, -} from './AuthCodeInput.styles'; -import { univInputWrapper } from '../UnivAuthInput.styles'; + authTimerText, +} from './AuthCodeInput.css'; +import { univInputWrapper } from '../UnivAuthInput.css'; import EmailToast from '@/app/join/components/EmailToast/EmailToast'; +import { joinInput } from '@/app/join/components/JoinInput/JoinInput.css'; import useVerifyUnivAuthCodeMutation from '@/app/join/hooks/useVerifyUnivAuthCodeMutation'; import { formatAuthTimer } from '@/app/join/JoinPage.utils'; import { ResearcherJoinSchemaType } from '@/schema/join/ResearcherJoinSchema'; @@ -29,7 +33,6 @@ const AuthCodeInput = ({ }: AuthCodeInputProps) => { const { getValues } = useFormContext<ResearcherJoinSchemaType>(); const { mutate: verifyEmail, isSuccess: isUnivVerify } = useVerifyUnivAuthCodeMutation(); - const [isToastOpen, setIsToastOpen] = useState(false); const [authCode, setAuthCode] = useState(''); @@ -41,7 +44,6 @@ const AuthCodeInput = ({ const handleVerifyUniv = () => { const univEmail = getValues('univEmail'); - verifyEmail( { univEmail, inputCode: authCode }, { @@ -55,9 +57,11 @@ const AuthCodeInput = ({ return ( <> - <div css={authInputLayout}> - <div css={univInputWrapper}> + <div className={authInputLayout}> + <div className={univInputWrapper}> <input + style={{ width: '100%' }} + className={joinInput} placeholder="인증번호 6자리 입력" type="number" disabled={isUnivVerify} @@ -65,11 +69,11 @@ const AuthCodeInput = ({ onChange={handleChangeAuthCode} /> {!isUnivVerify && ( - <div css={authTimerWrapper}> - <span>{formatAuthTimer(authTimer)}</span> + <div className={authTimerWrapper}> + <span className={authTimerText}>{formatAuthTimer(authTimer)}</span> <button type="button" - css={authCodeButton} + className={authCodeButton} disabled={!authCode || authCode.length < AUTH_CODE_VALID_LENGTH} onClick={handleVerifyUniv} > @@ -78,7 +82,7 @@ const AuthCodeInput = ({ </div> )} </div> - <button type="button" css={sendAgainButton} onClick={handleSendUnivAuthCode}> + <button type="button" className={sendAgainButton} onClick={handleSendUnivAuthCode}> 인증번호 재전송 </button> </div> diff --git a/src/app/join/components/Researcher/JoinEmailStep/UnivAuthInput/UnivAuthInput.css.ts b/src/app/join/components/Researcher/JoinEmailStep/UnivAuthInput/UnivAuthInput.css.ts new file mode 100644 index 0000000..5d9cb45 --- /dev/null +++ b/src/app/join/components/Researcher/JoinEmailStep/UnivAuthInput/UnivAuthInput.css.ts @@ -0,0 +1,43 @@ +import { style } from '@vanilla-extract/css'; + +import { colors } from '@/styles/colors'; +import { fonts } from '@/styles/fonts.css'; + +export const univInputWrapper = style({ + position: 'relative', + backgroundColor: colors.field01, + borderRadius: '1rem', +}); + +export const required = style({ + color: colors.textAlert, +}); + +export const univAuthButton = style({ + ...fonts.label.large.SB14, + position: 'absolute', + right: '1.2rem', + top: '1rem', + padding: '0.7rem 1.6rem', + borderRadius: '1rem', + color: colors.text01, + backgroundColor: colors.primaryMint, + border: 'none', + selectors: { + '&:disabled': { + color: colors.text02, + backgroundColor: colors.field04, + }, + }, +}); + +export const editButton = style({ + color: colors.text06, + backgroundColor: colors.field01, + border: `0.1rem solid ${colors.line02}`, +}); + +export const errorMessage = style({ + ...fonts.label.large.R14, + color: colors.textAlert, +}); diff --git a/src/app/join/components/Researcher/JoinEmailStep/UnivAuthInput/UnivAuthInput.styles.ts b/src/app/join/components/Researcher/JoinEmailStep/UnivAuthInput/UnivAuthInput.styles.ts deleted file mode 100644 index bbdcd97..0000000 --- a/src/app/join/components/Researcher/JoinEmailStep/UnivAuthInput/UnivAuthInput.styles.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { css, Theme } from '@emotion/react'; - -export const inputContainer = (theme: Theme) => css` - display: flex; - flex-direction: column; - gap: 0.6rem; - - label { - ${theme.fonts.label.large.M14}; - color: ${theme.colors.text06}; - display: flex; - gap: 0.4rem; - } - - input { - ${theme.fonts.body.normal.M16}; - color: ${theme.colors.text06}; - border: 0.1rem solid ${theme.colors.line01}; - padding: 1.6rem; - border-radius: 1.2rem; - - :disabled { - color: ${theme.colors.text03}; - background-color: ${theme.colors.field03}; - } - - ::placeholder { - color: ${theme.colors.text03}; - } - - :focus { - outline: 0.1rem solid ${theme.colors.lineTinted}; - } - } - - input[aria-invalid='true'] { - outline: 0.1rem solid ${theme.colors.textAlert}; - } -`; - -export const univInputWrapper = (theme: Theme) => css` - position: relative; - background-color: ${theme.colors.field01}; - border-radius: 1rem; - - input { - width: 100%; - } - - button:disabled { - background-color: ${theme.colors.field04}; - color: ${theme.colors.text02}; - } -`; - -export const required = (theme: Theme) => css` - color: ${theme.colors.textAlert}; -`; - -export const univAuthButton = (theme: Theme) => css` - ${theme.fonts.label.large.SB14}; - position: absolute; - right: 1.2rem; - top: 1rem; - padding: 0.7rem 1.6rem; - border-radius: 1rem; - color: ${theme.colors.text01}; - background-color: ${theme.colors.primaryMint}; - border: none; - - :disabled { - color: ${theme.colors.text02}; - background-color: ${theme.colors.field04}; - } -`; - -export const editButton = (theme: Theme) => css` - color: ${theme.colors.text06}; - background-color: ${theme.colors.field01}; - border: 0.1rem solid ${theme.colors.line02}; -`; - -export const errorMessage = (theme: Theme) => css` - ${theme.fonts.label.large.R14}; - color: ${theme.colors.textAlert}; -`; diff --git a/src/app/join/components/Researcher/JoinEmailStep/UnivAuthInput/UnivAuthInput.tsx b/src/app/join/components/Researcher/JoinEmailStep/UnivAuthInput/UnivAuthInput.tsx index 50110a3..a45ef46 100644 --- a/src/app/join/components/Researcher/JoinEmailStep/UnivAuthInput/UnivAuthInput.tsx +++ b/src/app/join/components/Researcher/JoinEmailStep/UnivAuthInput/UnivAuthInput.tsx @@ -1,16 +1,18 @@ +'use client'; + import { useState } from 'react'; import { Controller, useFormContext, useWatch } from 'react-hook-form'; import AuthCodeInput from './AuthCodeInput/AuthCodeInput'; import { - editButton, - errorMessage, - inputContainer, + univInputWrapper, required, univAuthButton, - univInputWrapper, -} from './UnivAuthInput.styles'; + editButton, + errorMessage, +} from './UnivAuthInput.css'; import EmailToast from '../../../EmailToast/EmailToast'; +import { inputContainer, inputLabel, joinInput } from '../../../JoinInput/JoinInput.css'; import useAuthCodeTimer from '@/app/join/hooks/useAuthCodeTimer'; import useSendUnivAuthCodeMutation from '@/app/join/hooks/useSendUnivAuthCodeMutation'; @@ -24,7 +26,12 @@ interface UnivAuthInputProps { const UnivAuthInput = ({ isEmailVerified, handleVerifyEmail }: UnivAuthInputProps) => { const { control } = useFormContext<ResearcherJoinSchemaType>(); - const { mutate: sendEmail, error: sendError } = useSendUnivAuthCodeMutation(); + const { + mutate: sendEmail, + error: sendError, + isPending: isLoadingSend, + } = useSendUnivAuthCodeMutation(); + const [isEmailSent, setIsEmailSent] = useState(false); const [isToastOpen, setIsToastOpen] = useState(false); @@ -52,39 +59,39 @@ const UnivAuthInput = ({ isEmailVerified, handleVerifyEmail }: UnivAuthInputProp }; return ( - <div css={inputContainer}> - <label> + <div className={inputContainer}> + <label className={inputLabel}> <span>학교 메일 인증</span> - <span css={required}>*</span> + <span className={required}>*</span> </label> <Controller name="univEmail" control={control} - render={({ field, fieldState }) => { - return ( - <> - <div css={univInputWrapper}> - <input - {...field} - placeholder="학교 메일 입력" - aria-invalid={fieldState.invalid ? true : false} - disabled={isEmailSent || isEmailVerified} - /> - <button - type="button" - css={[univAuthButton, isEmailSent && editButton]} - disabled={(!isEmailSent && !field.value) || isEmailVerified} - onClick={isEmailSent ? handleClickEdit : handleSendUnivAuthCode} - > - {isEmailSent ? '수정' : '인증번호 전송'} - </button> - </div> - {fieldState.error && <span css={errorMessage}>{fieldState.error.message}</span>} - {sendError && <span css={errorMessage}>{sendError.message}</span>} - </> - ); - }} + render={({ field, fieldState }) => ( + <> + <div className={univInputWrapper}> + <input + {...field} + style={{ width: '100%' }} + className={joinInput} + placeholder="학교 메일 입력" + aria-invalid={fieldState.invalid ? true : false} + disabled={isEmailSent || isEmailVerified} + /> + <button + type="button" + className={`${univAuthButton} ${isEmailSent ? editButton : ''}`} + disabled={(!isEmailSent && !field.value) || isEmailVerified || isLoadingSend} + onClick={isEmailSent ? handleClickEdit : handleSendUnivAuthCode} + > + {isLoadingSend ? '전송 중...' : isEmailSent ? '수정' : '인증번호 전송'} + </button> + </div> + {fieldState.error && <span className={errorMessage}>{fieldState.error.message}</span>} + {sendError && <span className={errorMessage}>{sendError.message}</span>} + </> + )} /> {isEmailSent && ( diff --git a/src/app/join/components/Researcher/JoinInfoStep/JoinInfoStep.styles.ts b/src/app/join/components/Researcher/JoinInfoStep/JoinInfoStep.styles.ts deleted file mode 100644 index 8694378..0000000 --- a/src/app/join/components/Researcher/JoinInfoStep/JoinInfoStep.styles.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { css, Theme } from '@emotion/react'; - -export const joinContentContainer = (theme: Theme) => css` - background-color: ${theme.colors.field02}; - width: 100%; - display: flex; - flex-direction: column; - gap: 2.8rem; - border-radius: 1.2rem; - padding: 3.2rem 4rem; -`; - -export const joinButton = (theme: Theme) => css` - ${theme.fonts.body.normal.SB16}; - background-color: ${theme.colors.primaryMint}; - color: ${theme.colors.text01}; - border-radius: 1.2rem; - padding: 1.2rem 0; - width: 20rem; - align-items: center; - margin-bottom: 5.6rem; - - :disabled { - color: ${theme.colors.text02}; - background-color: ${theme.colors.field04}; - } -`; diff --git a/src/app/join/components/Researcher/JoinInfoStep/JoinInfoStep.tsx b/src/app/join/components/Researcher/JoinInfoStep/JoinInfoStep.tsx index 94ecebc..8646078 100644 --- a/src/app/join/components/Researcher/JoinInfoStep/JoinInfoStep.tsx +++ b/src/app/join/components/Researcher/JoinInfoStep/JoinInfoStep.tsx @@ -1,9 +1,10 @@ -import { useFormContext, useWatch } from 'react-hook-form'; +'use client'; -import { joinButton } from './JoinInfoStep.styles'; -import { joinContentContainer, joinForm } from '../../../JoinPage.styles'; -import JoinInput from '../../JoinInput/JoinInput'; +import { useFormContext, useWatch } from 'react-hook-form'; +import JoinInput from '@/app/join/components/JoinInput/JoinInput'; +import { joinButton } from '@/app/join/components/Participant/JoinInfoStep/JoinInfoStep.css'; +import { joinContentContainer, joinForm } from '@/app/join/JoinPage.css'; import { ResearcherJoinSchemaType } from '@/schema/join/ResearcherJoinSchema'; interface JoinInfoStepProps { @@ -15,13 +16,13 @@ const JoinInfoStep = ({ handleSubmit }: JoinInfoStepProps) => { control, formState: { errors }, } = useFormContext<ResearcherJoinSchemaType>(); - const values = useWatch({ name: ['name', 'univName', 'major'], control }); + const values = useWatch({ name: ['name', 'univName', 'major'], control }); const isAllFilled = values.every((value) => (value ?? '').trim() !== '' && value !== undefined); return ( - <section css={joinForm}> - <div css={joinContentContainer}> + <section className={joinForm}> + <div className={joinContentContainer}> <JoinInput<ResearcherJoinSchemaType> name="name" control={control} @@ -53,7 +54,7 @@ const JoinInfoStep = ({ handleSubmit }: JoinInfoStepProps) => { /> </div> <button - css={joinButton} + className={joinButton} onClick={handleSubmit} disabled={!(isAllFilled && Object.keys(errors).length === 0)} > From f54e675ad87d0f35d20bcb094549935efdec899e Mon Sep 17 00:00:00 2001 From: Gyuhan Park <rbgks1937@naver.com> Date: Wed, 5 Feb 2025 20:49:24 +0900 Subject: [PATCH 08/11] =?UTF-8?q?[YS-243]=20design:=20joinLayout=20?= =?UTF-8?q?=EC=8A=A4=ED=83=80=EC=9D=BC=EB=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/join/JoinPage.css.ts | 8 ++++++++ src/app/join/layout.tsx | 16 +++------------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/app/join/JoinPage.css.ts b/src/app/join/JoinPage.css.ts index 60820c3..47a3da1 100644 --- a/src/app/join/JoinPage.css.ts +++ b/src/app/join/JoinPage.css.ts @@ -3,6 +3,14 @@ import { style } from '@vanilla-extract/css'; import { colors } from '@/styles/colors'; import { fonts } from '@/styles/fonts.css'; +export const joinPageLayout = style({ + display: 'flex', + backgroundColor: colors.field01, + width: '56rem', + margin: '0 auto', + minHeight: 'calc(100vh - 12.2rem)', +}); + export const joinLayout = style({ display: 'flex', flexDirection: 'column', diff --git a/src/app/join/layout.tsx b/src/app/join/layout.tsx index 5df3534..260b7b9 100644 --- a/src/app/join/layout.tsx +++ b/src/app/join/layout.tsx @@ -1,23 +1,13 @@ -'use client'; - -import { Theme } from '@emotion/react'; -import { css } from '@emotion/react'; import { Suspense } from 'react'; +import { joinPageLayout } from './JoinPage.css'; + function JoinLayout({ children }: { children: React.ReactNode }) { return ( - <div css={joinLayout}> + <div className={joinPageLayout}> <Suspense>{children}</Suspense> </div> ); } -const joinLayout = (theme: Theme) => css` - display: flex; - background-color: ${theme.colors.field01}; - width: 56rem; - margin: 0 auto; - min-height: calc(100vh - 12.2rem); -`; - export default JoinLayout; From 628c4f37a0a0025ff5e942fc19e222a908980d1e Mon Sep 17 00:00:00 2001 From: Gyuhan Park <rbgks1937@naver.com> Date: Wed, 5 Feb 2025 20:56:06 +0900 Subject: [PATCH 09/11] =?UTF-8?q?[YS-243]=20feat:=20beusable=20=EC=8A=A4?= =?UTF-8?q?=ED=81=AC=EB=A6=BD=ED=8A=B8=20=ED=83=9C=EA=B7=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/layout.tsx | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 98c004d..035ebc2 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,4 +1,5 @@ import type { Metadata } from 'next'; +import Script from 'next/script'; import Providers from './providers'; @@ -23,6 +24,25 @@ export default function RootLayout({ {children} <Footer /> </Providers> + <Script + id="beusable-script" + dangerouslySetInnerHTML={{ + __html: ` + (function(w, d, a){ + w.__beusablerumclient__ = { + load: function(src){ + var b = d.createElement("script"); + b.src = src; + b.async = true; + b.type = "text/javascript"; + d.getElementsByTagName("head")[0].appendChild(b); + } + }; + w.__beusablerumclient__.load(a + "?url=" + encodeURIComponent(d.URL)); + })(window, document, "//rum.beusable.net/load/b250203e183750u380"); + `, + }} + /> </body> </html> ); From 01b1109fcc516c402584d3e65cb907fc09d5572f Mon Sep 17 00:00:00 2001 From: Gyuhan Park <rbgks1937@naver.com> Date: Wed, 5 Feb 2025 20:56:38 +0900 Subject: [PATCH 10/11] =?UTF-8?q?[YS-243]=20fix:=20=EB=B9=84=EB=8C=80?= =?UTF-8?q?=EB=A9=B4=EC=9D=BC=20=EA=B2=BD=EC=9A=B0=20=ED=99=88=20=EC=8B=A4?= =?UTF-8?q?=ED=97=98=EA=B3=B5=EA=B3=A0=20=EC=9E=A5=EC=86=8C=20=ED=85=8D?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EB=B9=84=EB=8C=80=EB=A9=B4=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/home/components/PostCard/PostCard.tsx | 2 +- src/types/post.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/home/components/PostCard/PostCard.tsx b/src/app/home/components/PostCard/PostCard.tsx index 86667d9..8258577 100644 --- a/src/app/home/components/PostCard/PostCard.tsx +++ b/src/app/home/components/PostCard/PostCard.tsx @@ -34,7 +34,7 @@ const PostCard = ({ post }: PostCardProps) => { <Link href={`/post/${experimentPostId}`} key={experimentPostId} className={postCardLayout}> <div className={postHeader}> <div className={postCardHeader}> - <span className={postLocation}>{univName}</span> + <span className={postLocation}>{univName ? univName : '비대면'}</span> <div className={postCardRightHeader}> <Icon icon="Eye" width={18} /> <span className={postViews}>{views}</span> diff --git a/src/types/post.ts b/src/types/post.ts index 5ee8c8c..d3d7269 100644 --- a/src/types/post.ts +++ b/src/types/post.ts @@ -7,7 +7,7 @@ export interface PostInfo { experimentPostId: number; title: string; views: number; - univName: string; + univName: string | null; reward: string; durationInfo: { startDate: string | null; From 03a5b8d9aad4f8dd4d22aea3f6f2a1eabcb09235 Mon Sep 17 00:00:00 2001 From: Gyuhan Park <rbgks1937@naver.com> Date: Wed, 5 Feb 2025 20:56:57 +0900 Subject: [PATCH 11/11] =?UTF-8?q?[YS-243]=20fix:=20=EB=8C=80=EB=A9=B4/?= =?UTF-8?q?=EB=B9=84=EB=8C=80=EB=A9=B4=20value=20=EB=B0=98=EB=8C=80?= =?UTF-8?q?=EB=A1=9C=20=EC=B2=98=EB=A6=AC=ED=95=9C=20=EB=AC=B8=EC=A0=9C=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProgressMethodFilter/ProgressMethodFilter.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/home/components/PostContainer/ProgressMethodFilter/ProgressMethodFilter.tsx b/src/app/home/components/PostContainer/ProgressMethodFilter/ProgressMethodFilter.tsx index da88816..af35b06 100644 --- a/src/app/home/components/PostContainer/ProgressMethodFilter/ProgressMethodFilter.tsx +++ b/src/app/home/components/PostContainer/ProgressMethodFilter/ProgressMethodFilter.tsx @@ -16,8 +16,8 @@ interface FilterOption { const options: FilterOption[] = [ { label: '전체', value: 'ALL' }, - { label: '대면', value: 'ONLINE' }, - { label: '비대면', value: 'OFFLINE' }, + { label: '대면', value: 'OFFLINE' }, + { label: '비대면', value: 'ONLINE' }, ]; interface ProgressMethodFilterProps { @@ -63,10 +63,10 @@ const ProgressMethodFilter = ({ onChange }: ProgressMethodFilterProps) => { <Select.Item value="ALL" className={selectItem}> <Select.ItemText>전체</Select.ItemText> </Select.Item> - <Select.Item value="ONLINE" className={selectItem}> + <Select.Item value="OFFLINE" className={selectItem}> <Select.ItemText>대면</Select.ItemText> </Select.Item> - <Select.Item value="OFFLINE" className={selectItem}> + <Select.Item value="ONLINE" className={selectItem}> <Select.ItemText>비대면</Select.ItemText> </Select.Item> </Select.Group>