Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
49 changes: 46 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"next": "14.2.32",
"react": "^18",
"react-dom": "^18",
"react-responsive": "^10.0.1",
"tailwind-merge": "^3.3.1"
},
"devDependencies": {
Expand Down
50 changes: 50 additions & 0 deletions src/api/employer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import axios from '@/lib/axios';
import RegisterFormData from '@/types/myShop';
import { default as originAxios } from 'axios';

export async function postShop(body: RegisterFormData) {
const { address1, address2, category, description, name, originalHourlyPay, image } = body;

const imageUrl = image
? `https://bootcamp-project-api.s3.ap-northeast-2.amazonaws.com/${image.name}`
: '';

const tmpBody = {
address1,
address2,
category,
description,
name,
originalHourlyPay,
imageUrl,
};
const { data } = await axios.post('/shops', tmpBody);
}

export async function postPresignedUrl(imageName: string) {
const { data } = await axios.post('/images', { name: imageName });
console.log(data);
return data.item.url;
}

export async function uploadImage(presignedUrl: string, file: File) {
const result = await originAxios.put(presignedUrl, file);
}

export async function getPresignedUrl(presignedUrl: string) {
// 1. URL 객체 생성
const url = new URL(presignedUrl);

// 2. 쿼리 파라미터를 제거 (URL 객체의 search 속성을 비움)
url.search = '';

// 3. 쿼리 파라미터가 제거된 새 URL 문자열을 얻습니다.
const baseUrl = url.toString();

const result = await originAxios.get(baseUrl);
}

export async function getShop(shopId: string) {
const { data } = await axios.get(`/shops/${shopId}`);
return data;
}
45 changes: 45 additions & 0 deletions src/components/features/my-shop/registerAddress.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Dropdown, Input } from '@/components/ui';
import { ADDRESS_CODE } from '@/constants/dropdown';
import RegisterFormData from '@/types/myShop';

interface Props {
formData: RegisterFormData;
handleChange: (key: keyof RegisterFormData, value: string) => void;
}

const RegisterAddress = ({ formData, handleChange }: Props) => {
return (
<>
<div className='flex flex-col gap-6 tablet:flex-row'>
<div className='flex flex-col gap-2 tablet:w-1/2'>
<div>
<span>주소</span>
<span className='ml-0.5 text-red-500'>*</span>
</div>
<Dropdown
name='staus'
ariaLabel='어드레스'
placeholder='선택'
values={ADDRESS_CODE}
selected={formData.address1}
onChange={val => handleChange('address1', val)}
className='w-full'
/>
</div>
<div className='flex flex-col gap-2 tablet:w-1/2'>
<div>
<span>상세 주소</span>
<span className='ml-0.5 text-red-500'>*</span>
</div>
<Input
value={formData.address2}
onChange={e => handleChange('address2', e.target.value)}
placeholder='입력'
/>
</div>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dropdown 은 label 이 없지만 기본 input 은 label과 requiredMark 옵션이 있기에 활용해도 좋을것 같습니다 (
이외 다른 인풋도 동일하게 활용한다면 코드 작성량이 줄어들것 같습니다!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

작업 초반에 label 부분 font-size 가 달라서 저렇게 작업했는데 지금 다시 해보니 잘되네요 😂 다시 수정했습니다.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아 저도 그부분 font-size 가 달랐어서 제가 저번에 수정하고 PR 올렸습니다!

</div>
</>
);
};

export default RegisterAddress;
24 changes: 24 additions & 0 deletions src/components/features/my-shop/registerDescription.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import RegisterFormData from '@/types/myShop';

interface Props {
formData: RegisterFormData;
handleChange: (key: keyof RegisterFormData, value: string) => void;
}

const RegisterDescription = ({ formData, handleChange }: Props) => {
return (
<>
<div className='flex flex-col gap-2'>
<span>가게 설명</span>
<textarea
value={formData.description}
placeholder='입력'
className='h-[153px] resize-none rounded-md border border-gray-300 px-5 py-4'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

base-input 클래스네임을 사용하면 기존 input 스타일을 동일하게 가져갈 수 있습니다:)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네 base-input 적용하고 나머지 heigt 만 추가 했습니다!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

height 도 rows로 조절할 수 있으니 참고해보시면 좋을것 같습니다!

onChange={e => handleChange('description', e.target.value)}
></textarea>
</div>
</>
);
};

export default RegisterDescription;
36 changes: 36 additions & 0 deletions src/components/features/my-shop/registerImage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Icon } from '@/components/ui';
import Image from 'next/image';
import { ChangeEvent } from 'react';

interface Props {
preview: string | null;
handleImageChange: (e: ChangeEvent<HTMLInputElement>) => void;
}

const RegisterImage = ({ preview, handleImageChange }: Props) => {
return (
<>
<div className='flex flex-col gap-2'>
<span>가게 이미지</span>
<label className='relative flex h-[200px] w-full cursor-pointer flex-col items-center justify-center overflow-hidden rounded-xl border border-gray-300 tablet:h-[276px] tablet:w-[483px]'>
{preview ? (
<Image src={preview} alt='미리보기' fill />
) : (
<>
<Icon
iconName='camera'
iconSize='lg'
ariaLabel='카메라 아이콘'
className='bg-gray-400'
/>
<p className='text-gray-400'>이미지 추가하기</p>
</>
)}
<input type='file' accept='image/*' className='hidden' onChange={handleImageChange} />
</label>
</div>
</>
);
};

export default RegisterImage;
57 changes: 57 additions & 0 deletions src/components/features/my-shop/registerModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Modal } from '@/components/ui';
import { useRouter } from 'next/router';

interface Props {
openWarning: boolean;
setOpenWarning: (value: boolean) => void;
openCancel: boolean;
setOpenCancel: (value: boolean) => void;
openConfirm: boolean;
setOepnConfirm: (value: boolean) => void;
}

const RegisterModal = ({
openWarning,
setOpenWarning,
openCancel,
setOpenCancel,
openConfirm,
setOepnConfirm,
}: Props) => {
const router = useRouter();
return (
<>
<Modal
open={openWarning}
onClose={() => setOpenWarning(false)}
variant='warning'
title='필수 항목을 작성해주세요.'
primaryText='확인'
onPrimary={() => setOpenWarning(false)}
/>
<Modal
open={openCancel}
onClose={() => setOpenCancel(false)}
variant='warning'
title='취소하시겠습니까?'
primaryText='아니요'
secondaryText='예'
onSecondary={() => {
setOpenCancel(false);
router.push('/my-shop');
}}
onPrimary={() => setOpenCancel(false)}
/>
<Modal
open={openConfirm}
onClose={() => setOepnConfirm(false)}
variant='success'
title='등록이 완료되었습니다.'
primaryText='확인'
onPrimary={() => router.push('/my-shop')}
/>
</>
);
};

export default RegisterModal;
45 changes: 45 additions & 0 deletions src/components/features/my-shop/registerName.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Dropdown, Input } from '@/components/ui';
import { CATEGORY_CODE } from '@/constants/dropdown';
import RegisterFormData from '@/types/myShop';

interface Props {
formData: RegisterFormData;
handleChange: (key: keyof RegisterFormData, value: string) => void;
}

const RegisterName = ({ formData, handleChange }: Props) => {
return (
<>
<div className='flex flex-col gap-6 tablet:flex-row'>
<div className='flex flex-col gap-2 tablet:w-1/2'>
<div>
<span>가게 이름</span>
<span className='ml-0.5 text-red-500'>*</span>
</div>
<Input
value={formData.name}
onChange={e => handleChange('name', e.target.value)}
placeholder='입력'
/>
</div>
<div className='flex flex-col gap-2 tablet:w-1/2'>
<div>
<span>분류</span>
<span className='ml-0.5 text-red-500'>*</span>
</div>
<Dropdown
name='staus'
ariaLabel='카테고리'
placeholder='선택'
values={CATEGORY_CODE}
selected={formData.category}
onChange={val => handleChange('category', val)}
className='w-full'
/>
</div>
</div>
</>
);
};

export default RegisterName;
Loading