Skip to content

Commit

Permalink
feat(app/form): integrate form page
Browse files Browse the repository at this point in the history
  • Loading branch information
ooooorobo committed Jul 21, 2024
1 parent 103939b commit 32513ff
Show file tree
Hide file tree
Showing 20 changed files with 139 additions and 47 deletions.
42 changes: 42 additions & 0 deletions src/app/routes/form._index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { ProfileFormIntroPage } from 'src/pages/form/intro/ProfileFormIntroPage';
import { useState } from 'react';
import { SwitchCase } from 'src/shared/ui/SwitchCase';
import { MyProfilePage } from 'src/pages/form/my_profile/MyProfilePage';
import { IdealPartnerIntroPage } from 'src/pages/form/intro/IdealPartnerIntroPage';
import { IdealPartnerPage } from 'src/pages/form/ideal_partner/IdealPartnerPage';
import { FormConfirmPage } from 'src/pages/form/confirm/FormConfirmPage';
import { UploadLoadingPage } from 'src/pages/form/complete/UploadLoadingPage';
import { CompletePage } from 'src/pages/form/complete/CompletePage';
import { useProfileFirstName } from 'src/entities/profile/lib/useProfileFirstName';
import { Shortcut } from 'src/processes/shortcut/Shortcut';
import styles from 'src/app/styles/form.module.css';

const MAX_STEP_COUNT = 7;

export default function ProfileFormPage() {
const [step, setStep] = useState(0);

const increase = () => setStep((prev) => (prev + 1 < MAX_STEP_COUNT ? prev + 1 : prev));

const name = useProfileFirstName();

const showShortcut = [1, 3, 4].includes(step);

return (
<div className={styles.Wrapper}>
<SwitchCase
value={step}
caseBy={{
0: <ProfileFormIntroPage onClickNextStep={increase} />,
1: <MyProfilePage onClickNextStep={increase} />,
2: <IdealPartnerIntroPage name={name} onClickNextStep={increase} />,
3: <IdealPartnerPage onClickNextStep={increase} />,
4: <FormConfirmPage onClickNextStep={increase} />,
5: <UploadLoadingPage name={name} onComplete={increase} />,
6: <CompletePage />,
}}
/>
{showShortcut && <Shortcut right={'20px'} bottom={'100px'} />}
</div>
);
}
14 changes: 9 additions & 5 deletions src/app/routes/form.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { ProfileFormIntroPage } from 'src/pages/form/intro/ProfileFormIntroPage';
import { Outlet } from '@remix-run/react';
import { MyProfileProvider } from 'src/entities/profile/model/myProfileStore';
import { IdealPartnerProvider } from 'src/entities/ideal_partner/model/idealPartnerStore';

export default function ProfileFormPage() {
export default function ProfileFormLayout() {
return (
<>
<ProfileFormIntroPage />
</>
<MyProfileProvider>
<IdealPartnerProvider>
<Outlet />
</IdealPartnerProvider>
</MyProfileProvider>
);
}
6 changes: 6 additions & 0 deletions src/app/styles/form.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.Wrapper {
height: 100%;
padding: 0 20px 40px;
overflow: hidden;
position: relative;
}
8 changes: 5 additions & 3 deletions src/pages/form/complete/CompletePage.module.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
.Wrapper {
padding: 0 24px;
position: relative;
height: 100%;
width: 100%;
}

.TitleSection {
Expand All @@ -8,7 +10,7 @@

.Image {
width: 80%;
position: fixed;
right: 0;
position: absolute;
right: -20px;
bottom: 80px;
}
1 change: 0 additions & 1 deletion src/pages/form/complete/UploadLoadingPage.module.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
.Wrapper {
padding: 0 24px 24px;
display: flex;
flex-direction: column;
justify-content: space-between;
Expand Down
10 changes: 9 additions & 1 deletion src/pages/form/complete/UploadLoadingPage.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import { InfoBox } from 'src/shared/ui/InfoBox/InfoBox';
import styles from './UploadLoadingPage.module.css';
import { useEffect } from 'react';

export const UploadLoadingPage = ({ name, onComplete }: { name: string; onComplete: () => void }) => {
useEffect(() => {
const timer = setTimeout(onComplete, 5_000);
return () => {
clearTimeout(timer);
};
}, []);

export const UploadLoadingPage = ({ name }: { name: string }) => {
return (
<div className={styles.Wrapper}>
<div className={styles.TitleSection}>
Expand Down
7 changes: 4 additions & 3 deletions src/pages/form/confirm/FormConfirmPage.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
}

.TitleSection {
padding: 16px 20px 20px;
margin-bottom: 20px;

& h2 {
margin-top: 16px;
margin-bottom: 8px;
}

Expand All @@ -24,9 +25,9 @@
}

.ContentViewport {
padding: 20px;
padding-top: 20px;
}

.Footer {
padding: 28px 20px 8px;
padding-top: 24px;
}
6 changes: 2 additions & 4 deletions src/pages/form/confirm/FormConfirmPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@ import { useIdealPartnerStore } from 'src/entities/ideal_partner/model/idealPart
import { IdealPartnerProfile } from 'src/entities/ideal_partner/ui/IdealPartnerProfile/IdealPartnerProfile';
import styles from './FormConfirmPage.module.css';
import { ScrollView } from 'src/shared/ui/ScrollView/ScrollView';
import { Shortcut } from 'src/processes/shortcut/Shortcut';

const TAB_TYPE_LIST = ['PROFILE', 'IDEAL_PARTNER'] as const;
type TabType = (typeof TAB_TYPE_LIST)[number];

export const FormConfirmPage = () => {
export const FormConfirmPage = ({ onClickNextStep }: { onClickNextStep: () => void }) => {
const profile = useMyProfileStore((state) => state);
const idealPartner = useIdealPartnerStore((state) => state);
return (
Expand Down Expand Up @@ -42,11 +41,10 @@ export const FormConfirmPage = () => {
</ScrollView>
</Tab>
<div className={styles.Footer}>
<Button variant={'filled'} widthType={'fill'} color={'primary'}>
<Button variant={'filled'} widthType={'fill'} color={'primary'} onClick={onClickNextStep}>
확인했어요
</Button>
</div>
<Shortcut />
</div>
</>
);
Expand Down
2 changes: 1 addition & 1 deletion src/pages/form/ideal_partner/IdealPartnerPage.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,5 @@

.Footer {
margin-top: auto;
padding: 15px 0;
padding-top: 24px;
}
18 changes: 10 additions & 8 deletions src/pages/form/ideal_partner/IdealPartnerPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,21 @@ import { IdealPartnerStepMeta } from 'src/pages/form/ideal_partner/IdealPartnerS
import { useIdealPartnerStore } from 'src/entities/ideal_partner/model/idealPartnerStore';

const Steps = Object.values(IdealPartnerStepMeta);
export const IdealPartnerPage = () => {
export const IdealPartnerPage = ({ onClickNextStep }: { onClickNextStep: () => void }) => {
const [currentStepIdx, setCurrentStep] = useState(0);
const name = useProfileFirstName();

const currentStep = Steps[currentStepIdx];
const canGoNext = useIdealPartnerStore(currentStep.canGoNext);

const handleClickNext = () => {
if (currentStepIdx < Steps.length - 1) {
setCurrentStep((prev) => prev + 1);
} else {
onClickNextStep();
}
};

return (
<div className={styles.Container}>
<header className={styles.Header}>
Expand All @@ -28,13 +36,7 @@ export const IdealPartnerPage = () => {
</header>
<main className={styles.Main}>{currentStep.form}</main>
<footer className={styles.Footer}>
<Button
variant={'filled'}
widthType={'fill'}
color={'primary'}
disabled={!canGoNext}
onClick={() => setCurrentStep((prev) => Math.min(prev + 1, Steps.length - 1))}
>
<Button variant={'filled'} widthType={'fill'} color={'primary'} disabled={!canGoNext} onClick={handleClickNext}>
다음
</Button>
</footer>
Expand Down
1 change: 0 additions & 1 deletion src/pages/form/intro/IdealParterIntroPage.module.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
.Wrapper {
height: 100%;
width: 100%;
padding: 0 20px 8px;

display: flex;
flex-direction: column;
Expand Down
5 changes: 3 additions & 2 deletions src/pages/form/intro/IdealPartnerIntroPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import styles from './IdealParterIntroPage.module.css';

type IdealPartnerIntroPageProps = {
name: string;
onClickNextStep: () => void;
};

export const IdealPartnerIntroPage = ({ name }: IdealPartnerIntroPageProps) => {
export const IdealPartnerIntroPage = ({ name, onClickNextStep }: IdealPartnerIntroPageProps) => {
return (
<div className={styles.Wrapper}>
<div />
Expand All @@ -22,7 +23,7 @@ export const IdealPartnerIntroPage = ({ name }: IdealPartnerIntroPageProps) => {
</p>
</div>
<img className={styles.Image} src={'/images/googoo_1.png'} alt={'종이를 든 구구'} />
<Button variant={'filled'} widthType={'fill'} color={'primary'} onClick={() => {}}>
<Button variant={'filled'} widthType={'fill'} color={'primary'} onClick={onClickNextStep}>
시작하기
</Button>
</div>
Expand Down
1 change: 0 additions & 1 deletion src/pages/form/intro/ProfileFormIntroPage.module.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
.Wrapper {
height: 100%;
width: 100%;
padding: 0 20px 8px;

display: flex;
flex-direction: column;
Expand Down
10 changes: 8 additions & 2 deletions src/pages/form/intro/ProfileFormIntroPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useBoolean } from 'src/shared/functions/useBoolean';
import styles from './ProfileFormIntroPage.module.css';
import { BottomSheet } from 'src/shared/ui/BottomSheet/BottomSheet';

export const ProfileFormIntroPage = () => {
export const ProfileFormIntroPage = ({ onClickNextStep }: { onClickNextStep: () => void }) => {
const { value: isOpen, setTrue: open, setFalse: close } = useBoolean(false);

const { value: checkedPrivacy, toggle: togglePrivacy } = useBoolean(false);
Expand All @@ -31,7 +31,13 @@ export const ProfileFormIntroPage = () => {
<BottomSheet.Header onClose={close} />
<BottomSheet.Content
footerSlot={
<Button variant={'filled'} widthType={'fill'} color={'primary'} disabled={!canGoNext}>
<Button
variant={'filled'}
widthType={'fill'}
color={'primary'}
disabled={!canGoNext}
onClick={onClickNextStep}
>
확인했어요
</Button>
}
Expand Down
2 changes: 1 addition & 1 deletion src/pages/form/my_profile/MyProfilePage.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,5 @@

.Footer {
margin-top: auto;
padding: 15px 0;
padding-top: 24px;
}
18 changes: 10 additions & 8 deletions src/pages/form/my_profile/MyProfilePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,21 @@ import { MyProfileStepMeta } from 'src/pages/form/my_profile/MyProfileStepMeta';

const Steps = Object.values(MyProfileStepMeta);

export const MyProfilePage = () => {
export const MyProfilePage = ({ onClickNextStep }: { onClickNextStep: () => void }) => {
const [currentStepIdx, setCurrentStep] = useState(0);
const name = useProfileFirstName();

const currentStep = Steps[currentStepIdx];
const canGoNext = useMyProfileStore(currentStep.canGoNext);

const handleClickNext = () => {
if (currentStepIdx < Steps.length - 1) {
setCurrentStep((prev) => prev + 1);
} else {
onClickNextStep();
}
};

return (
<div className={styles.Container}>
<header className={styles.Header}>
Expand All @@ -29,13 +37,7 @@ export const MyProfilePage = () => {
</header>
<main className={styles.Main}>{currentStep.form}</main>
<footer className={styles.Footer}>
<Button
variant={'filled'}
widthType={'fill'}
color={'primary'}
disabled={!canGoNext}
onClick={() => setCurrentStep((prev) => Math.min(prev + 1, Steps.length - 1))}
>
<Button variant={'filled'} widthType={'fill'} color={'primary'} disabled={!canGoNext} onClick={handleClickNext}>
다음
</Button>
</footer>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/layout/WideDeviceLayout.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
.Main {
height: 100%;
width: 100%;
overflow: hidden;
margin: auto;
box-shadow: 0 0 17px 2px #0000001A;
background-color: #fff;
z-index: 1;
}

.SideSection {
Expand Down
13 changes: 9 additions & 4 deletions src/processes/shortcut/Shortcut.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { ArrowLeft, ArrowRight, Close, List } from 'src/shared/ui/icons';
import styles from './Shortcut.module.css';
import { Sheet } from 'react-modal-sheet';
import { useState } from 'react';
import { useRef, useState } from 'react';
import { Button } from 'src/shared/ui/Button/Button';
import { MyProfileStepMeta } from 'src/pages/form/my_profile/MyProfileStepMeta';
import { IdealPartnerStepMeta } from 'src/pages/form/ideal_partner/IdealPartnerStepMeta';
import { useProfileFirstName } from 'src/entities/profile/lib/useProfileFirstName';
import { ScrollView } from 'src/shared/ui/ScrollView/ScrollView';
import { Spacing } from 'src/shared/ui/Spacing/Spacing';

export const Shortcut = () => {
export const Shortcut = ({ right, bottom }: { right: `${number}px`; bottom: `${number}px` }) => {
const floatingButtonPosition = useRef({ right, bottom });

const [open, setOpen] = useState(false);
const [selectedKey, setSelectedKey] = useState<
| {
Expand All @@ -23,7 +25,10 @@ export const Shortcut = () => {
| null
>(null);

const onClose = () => setOpen(false);
const onClose = () => {
setOpen(false);
setSelectedKey(null);
};

const selectedStep =
selectedKey &&
Expand All @@ -40,7 +45,7 @@ export const Shortcut = () => {

return (
<>
<button className={styles.FloatingButton} onClick={() => setOpen(true)}>
<button className={styles.FloatingButton} onClick={() => setOpen(true)} style={floatingButtonPosition.current}>
<List />
</button>
<Sheet detent={'full-height'} isOpen={open} onClose={onClose}>
Expand Down
2 changes: 1 addition & 1 deletion src/shared/ui/BottomSheet/BottomSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ type BottomSheetProps = PropsWithChildren<Parameters<typeof Sheet>[0]>;
export const BottomSheet = ({ children, ...props }: BottomSheetProps) => {
return (
<Sheet {...props}>
<Sheet.Backdrop />
<Sheet.Backdrop onTap={props.onClose} />
<Sheet.Container>{children}</Sheet.Container>
</Sheet>
);
Expand Down
18 changes: 18 additions & 0 deletions src/shared/ui/SwitchCase.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
type Props<Case extends string | number> = {
caseBy: Partial<Record<Case, JSX.Element | null>>;
value: Case;
defaultComponent?: JSX.Element | null;
};

// https://github.com/toss/slash/blob/main/packages/react/react/src/components/SwitchCase/SwitchCase.tsx
export const SwitchCase = <Case extends string | number>({
value,
caseBy,
defaultComponent: defaultComponent = null,
}: Props<Case>) => {
if (value == null) {
return defaultComponent;
}

return caseBy[value] ?? defaultComponent;
};

0 comments on commit 32513ff

Please sign in to comment.