Skip to content

Commit

Permalink
Feat: 등록 정보 확인하기 페이지 - 객실, 수정 기능 완료
Browse files Browse the repository at this point in the history
Co-authored-by: 89882 <[email protected]>
  • Loading branch information
xxxjinn and gahyuun authored Jan 20, 2024
1 parent e5eefa5 commit 642915d
Show file tree
Hide file tree
Showing 16 changed files with 307 additions and 98 deletions.
1 change: 0 additions & 1 deletion src/api/room/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ export type Options = {
};

export type Image = {
id?: number;
url: string;
};

Expand Down
12 changes: 11 additions & 1 deletion src/components/init/ButtonContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ export const ButtonContainer = ({
});
};

/*
StyledButton에 disabled를 임의로 true로 변경했습니다
추후 {!isValid} 로 바꿔주세요!
*/
return (
<StyledWrapper $buttonStyle={buttonStyle}>
{buttonStyle === 'navigate' && (
Expand All @@ -90,12 +94,18 @@ export const ButtonContainer = ({
size="large"
onClick={confirm}
data-testid="request-button"
disabled={!isValid}
>
등록 요청
</StyledButton>
)}
{buttonStyle === 'edit' && (
<StyledButton type="primary" size="large" disabled={!isValid}>
<StyledButton
type="primary"
size="large"
disabled={!isValid}
htmlType="submit"
>
수정하기
</StyledButton>
)}
Expand Down
7 changes: 7 additions & 0 deletions src/components/init/CheckBoxContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,24 @@ import {
checkedRoomOptions,
} from '@stores/init/atoms';
import { Options, RoomOptions } from './init-accommodation-registration/type';
import { useEffect } from 'react';

export const CheckBoxContainer = ({
options,
header,
defaultValue,
}: CheckBoxContainerProps) => {
const [selectedAccommodationOptions, setSelectedAccommodationOptions] =
useRecoilState(checkedAccommodationOptions);

const [selectedInitRoomOptions, setSelectedInitRoomOptions] =
useRecoilState(checkedRoomOptions);

useEffect(() => {
if (defaultValue) {
setSelectedInitRoomOptions(defaultValue);
}
}, [defaultValue]);
const handleCheckboxChange = (event: CheckboxChangeEvent) => {
const checkedOption = event.target.value;

Expand Down
93 changes: 37 additions & 56 deletions src/components/init/ImageUploadContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,35 @@
import { TextBox } from '@components/text-box';
import { Modal, message } from 'antd';
import { message } from 'antd';
import { styled } from 'styled-components';
import { CloseCircleTwoTone, PlusOutlined } from '@ant-design/icons';
import { useState, useRef, ChangeEvent } from 'react';
import { ImageUploadFileItem, StyledImageContainerProps } from './type';
import { useRef, ChangeEvent, useEffect } from 'react';
import { StyledImageContainerProps } from './type';
import { IMAGE_MAX_CAPACITY, IMAGE_MAX_COUNT } from '@/constants/init';
import { colors } from '@/constants/colors';
import { useSetRecoilState } from 'recoil';
import { useRecoilState } from 'recoil';
import { imageFileState } from '@stores/init/atoms';
import { ROUTES } from '@/constants/routes';

export const ImageUploadContainer = ({ header }: { header: string }) => {
const [previewOpen, setPreviewOpen] = useState(false);
const [previewTitle, setPreviewTitle] = useState('');
const [fileList, setFileList] = useState<ImageUploadFileItem[]>([]);
import { Image } from '@api/room/type';

export const ImageUploadContainer = ({
header,
images,
}: {
header: string;
images?: Image[];
}) => {
const fileInputRef = useRef<HTMLInputElement | null>(null);

const handleCancel = () => setPreviewOpen(false);
const setImageFile = useSetRecoilState(imageFileState);
useEffect(() => {
if (images) {
const data = images.map((image, index) => {
return { key: index, url: image.url, file: null };
});
setImageFile(data);
}
}, [images]);

const [imageFile, setImageFile] = useRecoilState(imageFileState);

const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
const inputElement = event.target;
Expand Down Expand Up @@ -47,23 +59,10 @@ export const ImageUploadContainer = ({ header }: { header: string }) => {
});
}
if (selectedFile.size <= IMAGE_MAX_CAPACITY * 1024 * 1024) {
setImageFile((prev) => [...prev, selectedFile]);

const reader = new FileReader();
reader.onload = () => {
const imageUrl = reader.result as string;

setFileList((prevFileList) => [
...prevFileList,
{
uid: Date.now(),
name: selectedFile.name,
url: imageUrl,
},
]);
};

reader.readAsDataURL(selectedFile);
setImageFile((prev) => [
...prev,
{ key: imageFile.length, url: '', file: selectedFile },
]);
} else {
message.error({
content: `최대 ${IMAGE_MAX_CAPACITY}MB 파일 크기로 업로드 가능합니다.`,
Expand All @@ -85,14 +84,9 @@ export const ImageUploadContainer = ({ header }: { header: string }) => {
}
};

const handleImageClick = (file: ImageUploadFileItem) => {
setPreviewOpen(true);
setPreviewTitle(file.name);
};

const handleRemove = (file: ImageUploadFileItem) => {
const newFileList = fileList.filter((item) => item.uid !== file.uid);
setFileList(newFileList);
const handleRemove = (key: number) => {
const newFileList = imageFile.filter((item) => item.key !== key);
setImageFile(newFileList);
};

return (
Expand All @@ -105,21 +99,20 @@ export const ImageUploadContainer = ({ header }: { header: string }) => {
이미지는 최대 {IMAGE_MAX_COUNT}개까지 등록 가능합니다.
</TextBox>
</StyledHeadTextContainer>
<StyledImageContainer $fileList={fileList} header={header}>
{fileList.map((file) => (
<div key={file.uid}>
<StyledImageContainer $fileList={imageFile} header={header}>
{imageFile.map((obj) => (
<div key={obj.key}>
<StyledCloseButton
onClick={() => handleRemove(file)}
onClick={() => handleRemove(obj.key)}
twoToneColor={colors.black600}
/>
<img
src={file.url}
alt={file.name}
onClick={() => handleImageClick(file)}
src={obj.file !== null ? URL.createObjectURL(obj.file) : obj.url}
alt={'이미지'}
/>
</div>
))}
{fileList.length < IMAGE_MAX_COUNT && (
{imageFile.length < IMAGE_MAX_COUNT && (
<StyledUploadButtonWrapper onClick={openFileInput}>
<PlusOutlined />
<TextBox typography="body3" color="black600">
Expand All @@ -137,18 +130,6 @@ export const ImageUploadContainer = ({ header }: { header: string }) => {
</StyledUploadButtonWrapper>
)}
</StyledImageContainer>
<Modal
open={previewOpen}
title={previewTitle}
footer={null}
onCancel={handleCancel}
>
<img
alt={previewTitle}
style={{ width: '100%' }}
src={fileList.find((file) => file.name === previewTitle)?.url}
/>
</Modal>
</StyledInputWrapper>
);
};
Expand Down
5 changes: 5 additions & 0 deletions src/components/init/init-accommodation-registration/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ export type Room = {
options: RoomOptions;
};

export type defaultRoom = {
images: Image[] | undefined;
options: RoomOptions | undefined;
};
export type onFinishValues = {
'room-name': string;
price: string;
Expand All @@ -80,4 +84,5 @@ export type UserInputValue = {
images: Image[];
options: Options;
rooms: Room[];
editRoomIndex?: number | undefined;
};
36 changes: 32 additions & 4 deletions src/components/init/init-info-confirmation/RoomItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,31 @@ import { DeleteOutlined, EditOutlined } from '@ant-design/icons';
import { BsPeopleFill } from 'react-icons/bs';
import { ImageCarousel } from './ImageCarousel';
import { Room } from '../init-accommodation-registration/type';
import { useRecoilState } from 'recoil';
import { userInputValueState } from '@stores/init/atoms';
import { useRecoilState, useSetRecoilState } from 'recoil';
import {
checkedRoomOptions,
imageFileState,
userInputValueState,
} from '@stores/init/atoms';
import { useNavigate } from 'react-router-dom';
import { useEffect } from 'react';

export const RoomItem = () => {
const [userInputValue, setUserInputValue] =
useRecoilState(userInputValueState);
const setImageFile = useSetRecoilState(imageFileState);
const setSelectedOptions = useSetRecoilState(checkedRoomOptions);
const navigate = useNavigate();

useEffect(() => {
setUserInputValue([{ ...userInputValue[0], editRoomIndex: -1 }]);
setImageFile([]);
setSelectedOptions({
airCondition: false,
internet: false,
tv: false,
});
}, []);

const removeRoom = (room: Room) => {
if (userInputValue[0].rooms.length === 1) {
Expand Down Expand Up @@ -57,9 +76,14 @@ export const RoomItem = () => {
});
};

const roomEdit = (index: number) => {
setUserInputValue([{ ...userInputValue[0], editRoomIndex: index }]);
navigate('/init/room-registration');
};

return (
<>
{userInputValue[0].rooms.map((room: Room) => (
{userInputValue[0].rooms.map((room: Room, index) => (
<StyledRoomItemContainer key={room.name}>
<ImageCarousel images={room.images} />
<StyledRoomInfoContainer>
Expand All @@ -68,7 +92,11 @@ export const RoomItem = () => {
{room.name}
</TextBox>
<StyledButtonContainer>
<CustomButton text="수정" icon={<EditOutlined />} />
<CustomButton
text="수정"
icon={<EditOutlined />}
onClick={() => roomEdit(index)}
/>
<CustomButton
text="삭제"
icon={<DeleteOutlined />}
Expand Down
7 changes: 5 additions & 2 deletions src/components/init/type.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { FormInstance } from 'antd';
import { RoomOptions } from './init-accommodation-registration/type';
import { ImageFile } from '@stores/init/type';

export type ButtonContainerProps = {
buttonStyle: 'navigate' | 'request' | 'edit';
Expand All @@ -12,17 +14,18 @@ export type ButtonContainerStyledWrapperProps = {
export type CheckBoxContainerProps = {
options: { [key: string]: string };
header: string;
defaultValue?: RoomOptions;
};

export type ImageUploadFileItem = {
uid: number;
name: string;
url: string;
originFileObj?: File;
originFileObj?: File | null;
};

export type StyledImageContainerProps = {
$fileList: ImageUploadFileItem[];
$fileList: ImageFile[];
header: string;
};

Expand Down
1 change: 0 additions & 1 deletion src/components/room/capacity-container/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ export const CapacityContainer = ({ header, form }: CapacityContainerProps) => {
setError('최대 인원은 기준 인원보다 작을 수 없습니다.');
}
}, [defaultCapacity, maxCapacity]);

const validateInput = ({ value }: ValidateInputProps) => {
setError(null);
if (value < MIN_CAPACITY || value > MAX_CAPACITY) {
Expand Down
1 change: 0 additions & 1 deletion src/components/room/price-container/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ export const PriceContainer = ({ header, form }: PriceContainerProps) => {
<Form.Item name="price">
<StyledInput
id="price"
placeholder={''}
type="text"
style={{
height: 40,
Expand Down
21 changes: 18 additions & 3 deletions src/components/room/time-container/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ import { TimeContainerProps } from './type';
import locale from 'antd/es/date-picker/locale/de_DE';
import moment, { Moment } from 'moment';

export const TimeContainer = ({ header, form }: TimeContainerProps) => {
export const TimeContainer = ({
header,
form,
defaultCheckInTime,
defaultCheckOutTime,
}: TimeContainerProps) => {
const format = 'HH:mm';
const specificTime = moment().hours(9).minutes(0);
const [checkInTime, setCheckInTime] = useState<Moment>(specificTime);
Expand Down Expand Up @@ -47,7 +52,12 @@ export const TimeContainer = ({ header, form }: TimeContainerProps) => {
체크인
</TextBox>
</StyledTextBoxWrapper>
<Form.Item name={'checkInTime'}>
<Form.Item
name={'checkInTime'}
initialValue={
defaultCheckInTime ? moment(defaultCheckInTime, 'HH:mm') : ''
}
>
<StyledTimePicker
placeholder="00:00"
format={format}
Expand All @@ -73,7 +83,12 @@ export const TimeContainer = ({ header, form }: TimeContainerProps) => {
체크아웃
</TextBox>
</StyledTextBoxWrapper>
<Form.Item name={'checkOutTime'}>
<Form.Item
name={'checkOutTime'}
initialValue={
defaultCheckOutTime ? moment(defaultCheckOutTime, 'HH:mm') : ''
}
>
<StyledTimePicker
placeholder="00:00"
format={format}
Expand Down
2 changes: 2 additions & 0 deletions src/components/room/time-container/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@ import { FormInstance } from 'antd';
export type TimeContainerProps = {
header: string;
form: FormInstance;
defaultCheckInTime?: string;
defaultCheckOutTime?: string;
};
Loading

0 comments on commit 642915d

Please sign in to comment.