Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: [6] 디자인 변경 #7

Merged
merged 2 commits into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions public/calendar.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions public/check.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions public/logo-text.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 25 additions & 8 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,30 @@
import { Intro } from '@/components/intro';
import { Policy } from '@/components/policy';
import { UserInfoForm } from '@/components/user-info-form';
import { StepOne } from '@/components/home/step-one';
import { StepTwo } from '@/components/home/step-two';
import { Button } from '@/components/ui/button';
import Link from 'next/link';
import { redirect } from 'next/navigation';

export default function HomePage({
searchParams,
}: {
searchParams: { step: string };
}) {
if (!searchParams.step) {
redirect('/?step=1');
}

export default function HomePage() {
return (
<div className="bg-sub-2 flex min-h-screen w-full flex-col gap-2.5 p-5">
<Intro />
<Policy />
<UserInfoForm />
<div className="flex min-h-screen w-full flex-col gap-2.5 bg-sub-2 p-5">
{searchParams.step === '1' ? <StepOne /> : null}
{searchParams.step === '2' ? <StepTwo /> : null}
<Link href="/?step=2" className="mb-4 mt-[30px]">
<Button
variant="default"
className="head3 flex h-12 w-full items-center justify-center rounded-[10px] text-white hover:bg-primary hover:opacity-90"
>
{searchParams.step === '1' ? '다음으로' : '제출하기'}
</Button>
</Link>
</div>
);
}
4 changes: 2 additions & 2 deletions src/components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import Image from 'next/image';

export function Header() {
return (
<div className="flex w-full items-center p-5">
<Image src="/logo.svg" width={30} height={30} alt="logo" />
<div className="flex w-full items-center justify-center p-5">
<Image src="/logo-text.svg" width={116} height={51} alt="logo" />
</div>
);
}
11 changes: 11 additions & 0 deletions src/components/home/step-one.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Intro } from '@/components/intro';
import { Policy } from '@/components/policy';

export function StepOne() {
return (
<>
<Intro />
<Policy />
</>
);
}
34 changes: 34 additions & 0 deletions src/components/home/step-two.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { MultipleChoice } from '../multiple-choice';
import { SingleChoice } from '../single-choice';
import { Badge } from '../ui/badge';
import { Card } from '../ui/card';
import { UserInfoForm } from '../user-info-form';

const DUMMY_DATA = [
{ id: 'q1', text: '선택지 1' },
{ id: 'q2', text: '선택지 2' },
{ id: 'q3', text: '선택지 3' },
{ id: 'q4', text: '선택지 4' },
];

export function StepTwo() {
return (
<>
<UserInfoForm />
<Card className="flex flex-col gap-5">
<Badge>객관식 (복수선택)</Badge>
<h2 className="body1 px-1.5 text-gray-600">
1. 어떤 음식을 먹고 싶나요?
</h2>
<MultipleChoice choices={DUMMY_DATA} />
</Card>
<Card className="flex flex-col gap-5">
<Badge>객관식 (단일선택)</Badge>
<h2 className="body1 px-1.5 text-gray-600">
2. 학교에 조리 시설이 있나요?
</h2>
<SingleChoice q1="y" q2="n" q1Text="네" q2Text="아니요" />
</Card>
</>
);
}
19 changes: 10 additions & 9 deletions src/components/intro.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Image from 'next/image';
import { Box } from './ui/box';
import { Card } from './ui/card';
import { CheckBox } from './ui/check-box';
import { Paragraph } from './ui/paragraph';

export function Intro() {
Expand All @@ -15,26 +15,27 @@ export function Intro() {
recusandae beatae vero eos nihil, harum illo distinctio rem quae
voluptatum voluptates.
</Paragraph>
<div className="flex flex-col gap-4 md:flex-row md:items-center">
<Box className="flex flex-col gap-4 md:flex-row md:items-center">
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-gray-100">
<Image src="/calendar.svg" width={14} height={14} alt="calendar" />
</div>
<div className="flex flex-col gap-1.5 md:flex-1">
<h2 className="body2 text-[#677089]">이벤트 진행 기간</h2>
<Box className="flex items-center gap-3">
<CheckBox initialChecked={true} isEditable={false} />
<div className="flex items-center gap-3">
<span className="body3 line-clamp-1 text-[#3B404E]">
2024. 6. 20 13:00 ~ 2024. 7. 01 17:00
</span>
</Box>
</div>
</div>
<div className="flex flex-col gap-1.5 md:flex-1">
<h2 className="body2 text-[#677089]">당첨자 발표일</h2>
<Box className="flex items-center gap-3">
<CheckBox initialChecked={true} isEditable={false} />
<div className="flex items-center gap-3">
<span className="body3 line-clamp-1 text-[#3B404E]">
2024. 7. 4 17:00
</span>
</Box>
</div>
</div>
</div>
</Box>
</Card>
);
}
43 changes: 43 additions & 0 deletions src/components/multiple-choice.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
'use client';

import { useState } from 'react';
import { Box } from './ui/box';
import { CheckBox } from './ui/check-box';

type ChoiceType = {
id: string;
text: string;
};

type MultipleChoiceType = {
choices: ChoiceType[];
};

export function MultipleChoice({ choices }: MultipleChoiceType) {
const [selected, setSelected] = useState<string[]>([]);

const toggleSelection = (id: string) => {
setSelected(prev =>
prev.includes(id) ? prev.filter(item => item !== id) : [...prev, id]
);
};

return (
<div className="flex w-full flex-col gap-2.5">
{choices.map(choice => (
<Box
key={choice.id}
className="flex items-center gap-3 md:w-full"
onClick={() => toggleSelection(choice.id)}
isActive={selected.includes(choice.id)}
>
<CheckBox
isChecked={selected.includes(choice.id)}
className="rounded-[5px]"
/>
<span className="body3 text-[#3B404E]">{choice.text}</span>
</Box>
))}
</div>
);
}
13 changes: 7 additions & 6 deletions src/components/policy.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { SingleChoice } from './single-choice';
import { Badge } from './ui/badge';
import { Box } from './ui/box';
import { Card } from './ui/card';
import { CheckBox } from './ui/check-box';
import { Paragraph } from './ui/paragraph';

export function Policy() {
Expand All @@ -14,10 +13,12 @@ export function Policy() {
praesentium debitis, fugiat cupiditate aut tempora eligendi quasi
aperiam, hic nihil veniam!
</Paragraph>
<Box className="flex w-full items-center gap-3 md:w-[8.25rem]">
<CheckBox initialChecked={false} />
<span className="body3 text-[#3B404E]">동의합니다.</span>
</Box>
<SingleChoice
q1="agree"
q2="disagree"
q1Text="네, 동의합니다."
q2Text="아니요, 동의하지 않습니다."
/>
</Card>
);
}
Empty file added src/components/short-answer.tsx
Empty file.
37 changes: 37 additions & 0 deletions src/components/single-choice.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
'use client';

import { useState } from 'react';
import { Box } from './ui/box';
import { CheckBox } from './ui/check-box';

type SingleChoiceType = {
q1: string;
q2: string;
q1Text: string;
q2Text: string;
};

export function SingleChoice({ q1, q2, q1Text, q2Text }: SingleChoiceType) {
const [select, setSelect] = useState<string>('');

return (
<div className="flex w-full flex-col gap-2.5">
<Box
className="flex items-center gap-3 md:w-full"
onClick={() => setSelect(q1)}
isActive={select === q1}
>
<CheckBox isChecked={select === q1} />
<span className="body3 text-[#3B404E]">{q1Text}</span>
</Box>
<Box
className="flex items-center gap-3 md:w-full"
onClick={() => setSelect(q2)}
isActive={select === q2}
>
<CheckBox isChecked={select === q2} />
<span className="body3 text-[#3B404E]">{q2Text}</span>
</Box>
</div>
);
}
2 changes: 1 addition & 1 deletion src/components/ui/badge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const badgeVariants = cva(
primary: 'bg-sub-2 text-primary',
},
size: {
md: 'h-[2rem] w-[5.5rem]',
md: 'h-[2rem] w-fit',
},
},
defaultVariants: {
Expand Down
10 changes: 7 additions & 3 deletions src/components/ui/box.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import { cn } from '@/lib/utils';
import { ComponentProps } from 'react';

type BoxProps = ComponentProps<'div'>;
type BoxProps = ComponentProps<'div'> & {
isActive?: boolean;
};

export function Box({ className, children }: BoxProps) {
export function Box({ className, children, isActive, onClick }: BoxProps) {
return (
<div
className={cn(
'rounded-[10px] border border-solid border-[#E9EAEE] bg-gray-50 px-3.5 py-3',
'rounded-[10px] border border-solid px-3.5 py-3',
isActive ? 'border-primary bg-sub-2' : 'border-gray-75 bg-gray-50',
className
)}
onClick={onClick}
>
{children}
</div>
Expand Down
43 changes: 12 additions & 31 deletions src/components/ui/check-box.tsx
Original file line number Diff line number Diff line change
@@ -1,48 +1,29 @@
'use client';

import { cn } from '@/lib/utils';
import { ComponentProps, useEffect, useState } from 'react';
import Image from 'next/image';
import { ComponentProps } from 'react';
import { Button } from './button';

type CheckBoxProps = Omit<ComponentProps<'button'>, 'onClick'> & {
initialChecked?: boolean;
onValueChange?: (isChecked: boolean) => void;
isEditable?: boolean;
isChecked: boolean;
};

export function CheckBox({
initialChecked = false,
onValueChange,
isEditable = true,
...props
}: CheckBoxProps) {
const [isChecked, setIsChecked] = useState<boolean>(initialChecked);

useEffect(() => {
if (onValueChange) {
onValueChange(isChecked);
}
}, [isChecked, onValueChange]);

const handleClick = () => {
if (!isEditable) {
return;
}
setIsChecked(prev => !prev);
};

export function CheckBox({ isChecked, className, ...props }: CheckBoxProps) {
return (
<Button
variant="outline"
size="icon"
className={cn(
'h-5 w-5 rounded-full transition-colors',
isChecked
? 'border-none bg-gray-100 hover:bg-gray-100'
: 'border-[#898F9F] bg-transparent hover:bg-transparent'
? 'border-none bg-primary hover:bg-primary'
: 'border-[#898F9F] bg-transparent hover:bg-transparent',
className
)}
onClick={handleClick}
{...props}
/>
>
{isChecked ? (
<Image src="/check.svg" alt="check" width={10} height={10} />
) : null}
</Button>
);
}
2 changes: 1 addition & 1 deletion src/components/ui/paragraph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ import { ComponentProps } from 'react';
type ParagraphProps = ComponentProps<'p'>;

export function Paragraph({ className, children }: ParagraphProps) {
return <p className={cn('body1 text-gray-500', className)}>{children}</p>;
return <p className={cn('body1 text-gray-600', className)}>{children}</p>;
}
Loading
Loading