Skip to content

Commit

Permalink
refactor: extract header component & use color constants
Browse files Browse the repository at this point in the history
  • Loading branch information
ooooorobo committed Sep 8, 2024
1 parent 44935fc commit 07b2e9a
Show file tree
Hide file tree
Showing 20 changed files with 170 additions and 94 deletions.
10 changes: 10 additions & 0 deletions src/pages/form/confirm/FormConfirmPage.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@
height: 100%;
}

.Header {
flex-shrink: 0;
width: 100%;
display: grid;
grid-template-columns: 1fr 3fr 1fr;
align-items: center;
text-align: center;
height: 44px;
}

.TitleSection {
margin-bottom: 20px;

Expand Down
8 changes: 2 additions & 6 deletions src/pages/form/confirm/FormConfirmPage.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
import { ArrowLeft } from 'src/shared/ui/icons';
import { Button } from 'src/shared/ui/Button/Button';
import { useMyProfileStore } from 'src/entities/profile/model/myProfileStore';
import { useIdealPartnerStore } from 'src/entities/ideal_partner/model/idealPartnerStore';
import styles from './FormConfirmPage.module.css';
import { ProfileTab } from 'src/widgets/ProfileTab/ProfileTab';
import { Header } from 'src/shared/ui/layout/Header/Header';

export const FormConfirmPage = ({ onClickNextStep }: { onClickNextStep: () => void }) => {
const profile = useMyProfileStore((state) => state);
const idealPartner = useIdealPartnerStore((state) => state);
return (
<>
<div className={styles.Wrapper}>
<div>
<Button variant={'ghost'} color={'neutral'} widthType={'fill'} size={'fit'}>
<ArrowLeft />
</Button>
</div>
<Header onPrev={console.log} />
<div className={styles.TitleSection}>
<h2>입력한 정보를 마지막으로 확인해주세요.</h2>
<small>각 답변을 선택하면 수정이 가능합니다.</small>
Expand Down
15 changes: 3 additions & 12 deletions src/pages/form/ideal_partner/IdealPartnerPage.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,15 @@
overflow: hidden;
}

.Header {

.TitleSection {
margin-bottom: 30px;
}

.HeaderBar {
margin-bottom: 15px;
height: 44px;
display: flex;
justify-content: space-between;
align-items: center;

.FormCount {
font-weight: 500;
font-size: 16px;
color: var(--color-neutral-40);

& span {
margin-left: auto;
}
}

.Description {
Expand Down
26 changes: 16 additions & 10 deletions src/pages/form/ideal_partner/IdealPartnerPage.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { useEffect, useState } from 'react';
import { useCallback, useEffect, useState } from 'react';
import { useProfileFirstName } from 'src/entities/profile/lib/useProfileFirstName';
import styles from './IdealPartnerPage.module.css';
import { ArrowLeft } from 'src/shared/ui/icons';
import { Button } from 'src/shared/ui/Button/Button';
import { IdealPartnerStepMeta } from 'src/pages/form/ideal_partner/IdealPartnerStepMeta';
import { useIdealPartnerStore } from 'src/entities/ideal_partner/model/idealPartnerStore';
import { useIdealPartnerFormProcessStore } from 'src/processes/ideal_partner/_store/idealPartnerFormProcessStore';
import { Header } from 'src/shared/ui/layout/Header/Header';
import { Spacing } from 'src/shared/ui/Spacing/Spacing';

const Steps = Object.values(IdealPartnerStepMeta);
const StepKeys = Object.keys(IdealPartnerStepMeta);
Expand All @@ -30,20 +31,25 @@ export const IdealPartnerPage = ({ onClickNextStep }: { onClickNextStep: () => v
}
};

const handleClickPrev = useCallback(() => {
setCurrentStep((prev) => Math.max(0, prev - 1));
}, []);

return (
<div className={styles.Container}>
<header className={styles.Header}>
<div className={styles.HeaderBar}>
{currentStepIdx > 0 && (
<ArrowLeft type={'button'} onClick={() => setCurrentStep((prev) => Math.max(0, prev - 1))} />
)}
<span>
<Header
onPrev={currentStepIdx > 0 ? handleClickPrev : undefined}
suffixSlot={
<span className={styles.FormCount}>
{currentStepIdx + 1}/{Steps.length}
</span>
</div>
}
/>
<Spacing size={15} />
<div className={styles.TitleSection}>
<h2>{currentStep.title({ name })}</h2>
{currentStep.description && <small className={styles.Description}>{currentStep.description()}</small>}
</header>
</div>
<main className={styles.Main}>{currentStep.form({})}</main>
<footer className={styles.Footer}>
<Button variant={'filled'} widthType={'fill'} color={'primary'} disabled={!canGoNext} onClick={handleClickNext}>
Expand Down
12 changes: 1 addition & 11 deletions src/pages/form/my_profile/MyProfilePage.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,10 @@
margin-bottom: 30px;
}

.HeaderBar {
margin-bottom: 15px;
height: 44px;
display: flex;
justify-content: space-between;
align-items: center;

.FormCount {
font-weight: 500;
font-size: 16px;
color: var(--color-neutral-40);

& span {
margin-left: auto;
}
}

.Description {
Expand Down
22 changes: 13 additions & 9 deletions src/pages/form/my_profile/MyProfilePage.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { useCallback, useEffect, useState } from 'react';
import { Button } from 'src/shared/ui/Button/Button';
import { ArrowLeft } from 'src/shared/ui/icons';
import styles from 'src/pages/form/my_profile/MyProfilePage.module.css';
import { useProfileFirstName } from 'src/entities/profile/lib/useProfileFirstName';
import { useMyProfileStore } from 'src/entities/profile/model/myProfileStore';
import { MyProfileStepMeta } from 'src/pages/form/my_profile/MyProfileStepMeta';
import { useMyProfileFormProcessStore } from 'src/processes/my_profile/_store/myProfileFormProcessStore';
import { Header } from 'src/shared/ui/layout/Header/Header';
import { Spacing } from 'src/shared/ui/Spacing/Spacing';

const Steps = Object.values(MyProfileStepMeta);
const StepKeys = Object.keys(MyProfileStepMeta);
Expand All @@ -31,18 +32,21 @@ export const MyProfilePage = ({ onClickNextStep }: { onClickNextStep: () => void
}
}, [currentStepIdx, onClickNextStep]);

const handleClickPrev = useCallback(() => {
setCurrentStep((prev) => Math.max(0, prev - 1));
}, []);

return (
<div className={styles.Container}>
<header className={styles.Header}>
<div className={styles.HeaderBar}>
{currentStepIdx > 0 && (
<ArrowLeft type={'button'} onClick={() => setCurrentStep((prev) => Math.max(0, prev - 1))} />
)}
<span>
<Header
onPrev={currentStepIdx > 0 ? handleClickPrev : undefined}
suffixSlot={
<span className={styles.FormCount}>
{currentStepIdx + 1}/{Steps.length}
</span>
</div>
</header>
}
/>
<Spacing size={15} />
{(currentStep.showTitle ?? true) && (
<div className={styles.TitleSection}>
<h2>{currentStep.title({ name })}</h2>
Expand Down
37 changes: 22 additions & 15 deletions src/pages/profile/ProfilePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { useInView } from 'react-intersection-observer';
import { useMyProfileStore } from 'src/entities/profile/model/myProfileStore';
import { useIdealPartnerStore } from 'src/entities/ideal_partner/model/idealPartnerStore';
import { Link } from '@remix-run/react';
import { Header } from 'src/shared/ui/layout/Header/Header';
import { Theme } from 'src/shared/styles/constants';

export const ProfilePage = () => {
const { ref, inView } = useInView();
Expand All @@ -27,28 +29,33 @@ export const ProfilePage = () => {

return (
<div className={styles.Wrapper}>
<div className={styles.Header}>
<Link to={'/'}>
<IconButton>
<ArrowLeft />
</IconButton>
</Link>
<Header
prefixSlot={
<Link to={'/'}>
<IconButton>
<ArrowLeft color={Theme.color.neutral50} />
</IconButton>
</Link>
}
suffixSlot={
<div className={styles.HeaderIconSection}>
<IconButton>
<Edit color={Theme.color.neutral50} />
</IconButton>
<IconButton>
<Share color={Theme.color.neutral50} />
</IconButton>
</div>
}
>
{inView ? (
<span />
) : (
<p>
{profile.name}({profile.gender}, {age})
</p>
)}
<div className={styles.HeaderIconSection}>
<IconButton>
<Edit />
</IconButton>
<IconButton>
<Share />
</IconButton>
</div>
</div>
</Header>
<ScrollView rootClassName={styles.Body}>
<div className={styles.ImageLayout} data-itemcount={Math.min(urls.length, 5)}>
{urls.map((url) => (
Expand Down
3 changes: 2 additions & 1 deletion src/processes/my_profile/QuestionForm/QuestionForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { DateStyleForm } from 'src/processes/my_profile/QuestionForm/DateStyleFo
import { FoodForm } from 'src/processes/my_profile/QuestionForm/FoodForm/FoodForm';
import { MovieForm } from 'src/processes/my_profile/QuestionForm/MovieForm/MovieForm';
import { PetForm } from 'src/processes/my_profile/QuestionForm/PetForm/PetForm';
import { Theme } from 'src/shared/styles/constants';

type QuestionType = 'PET' | 'DATE_STYLE' | 'FOOD' | 'DRIVING' | 'BOOK' | 'MOVIE';

Expand Down Expand Up @@ -76,7 +77,7 @@ const QuestionButton = ({ text, filled, onClick }: { text: string; filled: boole
widthType={'fill'}
size={'M'}
textAlign={'left'}
suffixSlot={filled ? <Check color={'#D752FF'} width={24} /> : <Plus color={'#cdcace'} />}
suffixSlot={filled ? <Check color={Theme.color.primary} width={24} /> : <Plus color={Theme.color.neutral30} />}
onClick={onClick}
>
{text}
Expand Down
2 changes: 2 additions & 0 deletions src/processes/my_profile/_store/myProfileFormProcessStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ type MyProfileFormProcessStore = {

type Action = {
addTouchedStep: (step: MyProfileStepKey) => void;
hasTouchedStep: (step: MyProfileStepKey) => boolean;
};

export const useMyProfileFormProcessStore = create<MyProfileFormProcessStore & Action>((set, get) => ({
touchedSteps: new Set(),
addTouchedStep: (step) => set({ touchedSteps: new Set([...get().touchedSteps, step]) }),
hasTouchedStep: (step) => get().touchedSteps.has(step),
}));
16 changes: 16 additions & 0 deletions src/shared/styles/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export const Theme = {
color: {
primary: '#d752ff',
positive: '#3bb5a3',
negative: '#f35b5b',
neutral90: '#121113',
neutral80: '#333036',
neutral70: '#534e55',
neutral60: '#726d74',
neutral50: '#918b92',
neutral40: '#afaab1',
neutral30: '#cdcace',
neutral20: '#ebeaeb',
neutral10: '#f5f5f5',
},
} as const;
3 changes: 2 additions & 1 deletion src/shared/ui/Accordion/Accordion.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { PropsWithChildren } from 'react';
import styles from './Accordion.module.css';
import { ArrowRight } from 'src/shared/ui/icons';
import { Theme } from 'src/shared/styles/constants';

type AccordionProps = PropsWithChildren<{
summary: string;
Expand All @@ -12,7 +13,7 @@ export const Accordion = ({ summary, initialOpen = false, children }: AccordionP
<summary className={styles.Summary}>
{summary}
<span className={styles.SummaryMarker}>
<ArrowRight />
<ArrowRight color={Theme.color.neutral50} />
</span>
</summary>
{children}
Expand Down
26 changes: 4 additions & 22 deletions src/shared/ui/BottomSheet/BottomSheet.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { Sheet } from 'react-modal-sheet';
import { PropsWithChildren, ReactNode } from 'react';
import { Button } from 'src/shared/ui/Button/Button';
import { ArrowLeft, Close } from 'src/shared/ui/icons';
import styles from './BottomSheet.module.css';
import { Header } from 'src/shared/ui/layout/Header/Header';

type BottomSheetProps = PropsWithChildren<Parameters<typeof Sheet>[0]>;

Expand All @@ -20,27 +19,10 @@ type BottomSheetHeaderProps = PropsWithChildren<{
onPrev?: () => void;
}>;

const BottomSheetHeader = ({ onPrev, onClose, children }: BottomSheetHeaderProps) => {
const BottomSheetHeader = (props: BottomSheetHeaderProps) => {
return (
<Sheet.Header className={styles.Header}>
{onPrev && (
<Button variant={'ghost'} color={'neutral'} widthType={'hug'} size={'fit'} onClick={onPrev}>
<ArrowLeft width={24} />
</Button>
)}
{children}
{onClose && (
<Button
className={styles.CloseButton}
variant={'ghost'}
color={'neutral'}
widthType={'hug'}
size={'fit'}
onClick={onClose}
>
<Close width={24} />
</Button>
)}
<Sheet.Header>
<Header {...props} />
</Sheet.Header>
);
};
Expand Down
3 changes: 2 additions & 1 deletion src/shared/ui/Chip/InputTriggerChip/InputTriggerChip.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Chip } from 'src/shared/ui/Chip/Chip';
import { Plus } from 'src/shared/ui/icons';
import styles from './InputTriggerChip.module.css';
import { Theme } from 'src/shared/styles/constants';

type InputTriggerChipProps = {
onClick: () => void;
Expand All @@ -10,7 +11,7 @@ export const InputTriggerChip = ({ onClick }: InputTriggerChipProps) => {
return (
<Chip onClick={onClick}>
<div className={styles.Wrapper}>
<Plus width={16} height={16} color={'#cdcace'} />
<Plus width={16} height={16} color={Theme.color.neutral30} />
직접 추가하기
</div>
</Chip>
Expand Down
3 changes: 2 additions & 1 deletion src/shared/ui/Profile/ProfileCellHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import styles from './Profile.module.css';
import { Edit } from 'src/shared/ui/icons';
import { Theme } from 'src/shared/styles/constants';

export const ProfileCellHeader = ({ title }: { title: string }) => {
return (
<div className={styles.CellHeader}>
<span className={styles.CellHeaderTitle}>{title}</span>
<Edit width={15} height={15} />
<Edit width={15} height={15} color={Theme.color.neutral50} />
</div>
);
};
7 changes: 6 additions & 1 deletion src/shared/ui/Radio/Radio.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import styles from './Radio.module.css';
import { DetailedHTMLProps, InputHTMLAttributes } from 'react';
import { CheckedRadio, UncheckedRadio } from 'src/shared/ui/icons';
import { Theme } from 'src/shared/styles/constants';

export type RadioProps = Exclude<DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, 'type'> & {
label: string;
Expand All @@ -10,7 +11,11 @@ export const Radio = ({ className, label, ...props }: RadioProps) => {
return (
<label className={`${styles.Label} ${className}`}>
<input className={styles.Radio} type={'radio'} {...props} />
{props.checked ? <CheckedRadio color={'#CDCACE'} /> : <UncheckedRadio color={'#CDCACE'} />}
{props.checked ? (
<CheckedRadio color={Theme.color.neutral30} />
) : (
<UncheckedRadio color={Theme.color.neutral30} />
)}
{label}
</label>
);
Expand Down
Loading

0 comments on commit 07b2e9a

Please sign in to comment.