Skip to content

Commit df0f555

Browse files
author
์กฐ์˜ˆ์€
committed
๐Ÿ”ฅ Remove: ์˜›๋‚  develop ํŒŒ์ผ ์‚ญ์ œ
1 parent 54887f9 commit df0f555

File tree

4 files changed

+183
-0
lines changed

4 files changed

+183
-0
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { useState } from 'react';
2+
import Image from 'next/image';
3+
import activeHeart from '@/public/assets/icons/active-heart.svg';
4+
import defaultHeart from '@/public/assets/icons/default-heart.svg';
5+
6+
interface ButtonHeartsProps {
7+
onChange: (score: number) => void;
8+
}
9+
10+
export default function ButtonHearts({ onChange }: ButtonHeartsProps) {
11+
const [clickedArray, setClickedArray] = useState<boolean[]>(Array(5).fill(false));
12+
13+
const handleClick = (index: number) => {
14+
setClickedArray((prev) => prev.map((_, i) => i <= index));
15+
onChange(index + 1);
16+
};
17+
18+
return (
19+
<div className="flex w-full flex-col items-start justify-between gap-[12px]">
20+
<p className="font-base font-semibold">๋งŒ์กฑ์Šค๋Ÿฌ์šด ๊ฒฝํ—˜์ด์—ˆ๋‚˜์š”?</p>
21+
<div>
22+
{Array.from({ length: 5 }).map((_, index) => (
23+
<button type="button" onClick={() => handleClick(index)} key={`btn ${index + 1}`}>
24+
<Image
25+
src={clickedArray[index] ? activeHeart : defaultHeart}
26+
width={24}
27+
height={24}
28+
alt="heartbtn"
29+
/>
30+
</button>
31+
))}
32+
</div>
33+
</div>
34+
);
35+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { useState } from 'react';
2+
import { useForm } from 'react-hook-form';
3+
import { useApiMutation } from '@/src/hooks/useApi';
4+
import Button from '@/src/components/common/button';
5+
import Textarea from '@/src/components/common/input/textarea';
6+
import ButtonHearts from './button-hearts';
7+
8+
type FormValues = {
9+
reviewText: string;
10+
score: number;
11+
};
12+
13+
interface ReviewProps {
14+
onCancel: () => void;
15+
}
16+
17+
export default function ReviewForm({ onCancel }: ReviewProps) {
18+
const { register, handleSubmit } = useForm<FormValues>();
19+
const [textReview, setTextReview] = useState<string>('');
20+
const [point, setPoint] = useState<number>(0);
21+
22+
// TODO : ์ฃผ์„ ๋ถ€๋ถ„(api ์—ฐ๊ฒฐ) ์ˆ˜์ •
23+
// TODO : form์— ๋„ฃ๊ธฐ: onSubmit={handleSubmit(clickSubmit)}
24+
25+
const handleTextChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
26+
setTextReview(e.target.value);
27+
};
28+
29+
const handleScoreChange = (newScore: number) => {
30+
setPoint(newScore);
31+
};
32+
33+
return (
34+
<form className="flex h-[308px] w-[472px] flex-col justify-between gap-[24px]">
35+
<ButtonHearts onChange={handleScoreChange} />
36+
<Textarea
37+
placeholder="๋‚จ๊ฒจ์ฃผ์‹  ๋ฆฌ๋ทฐ๋Š” ํ”„๋กœ๊ทธ๋žจ ์šด์˜ ๋ฐ ๋‹ค๋ฅธ ํšŒ์› ๋ถ„๋“ค๊ป˜ ํฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค."
38+
inputClassNames="w-[471px] h-[120px] bg-gray-50 text-gray-400"
39+
value={textReview}
40+
onChange={handleTextChange}
41+
register={register('reviewText')}
42+
label="๊ฒฝํ—˜์— ๋Œ€ํ•ด ๋‚จ๊ฒจ์ฃผ์„ธ์š”"
43+
styles={{
44+
input: {
45+
'::placeholder': {
46+
color: 'gray - 400',
47+
fontWeight: 500,
48+
fontSize: '1rem',
49+
},
50+
},
51+
label: {
52+
fontWeight: 600,
53+
fontSize: '1rem',
54+
},
55+
}}
56+
/>
57+
<input type="hidden" value={point} {...register('score')} />
58+
<div className="font-base flex justify-between gap-[16px] font-semibold">
59+
<Button
60+
onClick={onCancel}
61+
className="h-[44px] w-[228px] border border-blue-500 text-blue-500"
62+
>
63+
์ทจ์†Œ
64+
</Button>
65+
<Button type="submit" className="h-[44px] w-[228px] border-none bg-blue-500 text-white">
66+
๋ฆฌ๋ทฐ ๋“ฑ๋ก
67+
</Button>
68+
</div>
69+
</form>
70+
);
71+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { useEffect, useState } from 'react';
2+
import { Button } from '@mantine/core';
3+
import { action } from '@storybook/addon-actions';
4+
import { Meta, StoryFn } from '@storybook/react';
5+
import ReviewingModal, { ReviewingModalProps } from './reviewing-modal';
6+
7+
const meta: Meta<typeof ReviewingModal> = {
8+
title: 'Modal/ReviewingModal',
9+
component: ReviewingModal,
10+
argTypes: { opened: { control: 'boolean' } },
11+
};
12+
13+
export default meta;
14+
const Template: StoryFn<ReviewingModalProps> = function GatheringDetailModalStory({
15+
opened,
16+
}: ReviewingModalProps) {
17+
const [isOpened, setIsOpened] = useState(opened);
18+
19+
const handleOpen = () => {
20+
action('Modal Opened')();
21+
setIsOpened(true);
22+
};
23+
24+
const handleClose = () => {
25+
action('Modal Closed')();
26+
setIsOpened(false);
27+
};
28+
29+
useEffect(() => {
30+
setIsOpened(opened);
31+
}, [opened]);
32+
33+
return (
34+
<>
35+
<Button onClick={handleOpen}>Open Modal</Button>
36+
<ReviewingModal opened={isOpened} close={handleClose} />
37+
</>
38+
);
39+
};
40+
41+
export const Default = Template.bind({});
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
'use client';
2+
3+
import React from 'react';
4+
import { Modal } from '@mantine/core';
5+
import ReviewForm from './review-form';
6+
7+
export interface ReviewingModalProps {
8+
opened: boolean;
9+
close: () => void;
10+
}
11+
12+
export default function ReviewingModal({ opened, close }: ReviewingModalProps) {
13+
return (
14+
<Modal
15+
opened={opened}
16+
centered
17+
title="๋ฆฌ๋ทฐ ์“ฐ๊ธฐ"
18+
onClose={close}
19+
size="auto"
20+
padding={24}
21+
radius={12}
22+
overlayProps={{ backgroundOpacity: 0.5 }}
23+
styles={{
24+
title: {
25+
fontWeight: 600,
26+
fontSize: '1.125rem',
27+
},
28+
body: {
29+
fontFamily: 'var(--font-pretendard)',
30+
},
31+
}}
32+
>
33+
<ReviewForm onCancel={close} />
34+
</Modal>
35+
);
36+
}

0 commit comments

Comments
ย (0)