-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
17 changed files
with
908 additions
and
249 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { instance } from "./axios"; | ||
|
||
export const fetchAdminNickname = async () => { | ||
const response = await instance.get("/api/admin/nickname"); | ||
|
||
return response; | ||
}; | ||
|
||
export const fetchRegisterEvent = async (page: number, size: number) => { | ||
const response = await instance.get( | ||
`/api/admin/register?page=${page}&size=${size}` | ||
); | ||
|
||
return response; | ||
}; | ||
|
||
export const fetchRegisterEventDetail = async (id: number) => { | ||
const response = await instance.get( | ||
`/api/admin/register/detail?event_id=${id}` | ||
); | ||
|
||
return response; | ||
}; | ||
|
||
export const searchRegisterEvent = async ( | ||
page: number, | ||
size: number, | ||
keyword: string, | ||
state: string | ||
) => { | ||
const response = await instance.get( | ||
`/api/admin/register/search?name=${keyword}&page=${page}&size=${size}&state=${state}` | ||
); | ||
|
||
return response; | ||
}; | ||
|
||
export const resolveRegisterEvent = async (eventId: number, status: string) => { | ||
const response = await instance.patch("/api/admin/register", { | ||
event_id: eventId, | ||
status: status, | ||
}); | ||
|
||
return response; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,32 @@ | ||
// atoms/index.ts | ||
import RegisterEventDetailState from "@/interfaces/RegisterEventDetailState"; | ||
import RegisterEventState from "@/interfaces/RegisterEventState"; | ||
import UserNicknameState from "@/interfaces/UserNicknameState"; | ||
import { atom } from "recoil"; | ||
|
||
export const adminRegisterEventState = atom<RegisterEventState[]>({ | ||
key: "registerEventState", | ||
default: [], | ||
}); | ||
|
||
export const userNicknameState = atom<UserNicknameState>({ | ||
key: "userNicknameState", | ||
default: { nickname: "" }, | ||
}); | ||
|
||
export const totalPageState = atom<number>({ | ||
key: "totalPageState", | ||
default: 0, | ||
}); | ||
|
||
export const adminRegisterDetailState = atom<RegisterEventDetailState>({ | ||
key: "registerDetailState", | ||
default: { | ||
name: "", | ||
host_nickname: "", | ||
address: "", | ||
running_time: "", | ||
duration: "", | ||
description: "", | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,205 +1,50 @@ | ||
import React, { useState } from "react"; | ||
import back_logo from "@/assets/logo_back.svg"; | ||
import * as Styled from "./style"; | ||
import { instance } from "@/apis/axios"; | ||
import { useRecoilValue } from "recoil"; | ||
import { userNicknameState } from "@/atoms/atoms"; | ||
import { useFetchRegisterDetailEvent } from "@/hooks/useFetchRegisterDetailEvent"; | ||
import { adminRegisterDetailState } from "@/atoms/atoms"; | ||
|
||
interface SellRequestWriteProps { | ||
interface Props { | ||
id: number; | ||
open: boolean; | ||
handleClose: () => void; | ||
handleSave: (newItem: any) => void; | ||
} | ||
|
||
export const SellRequestWrite: React.FC<SellRequestWriteProps> = ({ | ||
open, | ||
handleClose, | ||
handleSave, | ||
}) => { | ||
const [name, setName] = useState(""); | ||
const [startDate, setStartDate] = useState(""); | ||
const [endDate, setEndDate] = useState(""); | ||
const [price, setPrice] = useState(""); | ||
const [seat, setSeat] = useState(""); | ||
const [runningTime, setRunningTime] = useState(""); | ||
const [address, setAddress] = useState(""); | ||
const [category, setCategory] = useState("MUSICAL"); | ||
const [rating, setRating] = useState(""); | ||
const [description, setDescription] = useState(""); | ||
const [eventImage, setEventImage] = useState<File | null>(null); | ||
const username = useRecoilValue(userNicknameState); | ||
export default function Modal({ id, open, handleClose }: Props) { | ||
const state = useRecoilValue(adminRegisterDetailState); | ||
|
||
const handleImageChange = (e: React.ChangeEvent<HTMLInputElement>) => { | ||
if (e.target.files && e.target.files[0]) { | ||
setEventImage(e.target.files[0]); | ||
} | ||
}; | ||
|
||
const handleSubmit = async () => { | ||
const formData = new FormData(); | ||
|
||
const requestJson = { | ||
event_name: name, | ||
start_date: startDate, | ||
end_date: endDate, | ||
seat_cnt: seat, | ||
price: price, | ||
running_time: runningTime, | ||
address: address, | ||
category: category, | ||
description: description, | ||
host_name: username.nickname, | ||
rating: rating, | ||
}; | ||
|
||
console.log(requestJson); | ||
|
||
if (eventImage) { | ||
formData.append("image", eventImage as Blob); | ||
} | ||
formData.append( | ||
"data", | ||
new Blob([JSON.stringify(requestJson)], { type: "application/json" }) | ||
); | ||
|
||
try { | ||
const response = await instance.post("/api/seller/apply", formData, { | ||
headers: { | ||
"Content-Type": "multipart/form-data", | ||
}, | ||
}); | ||
|
||
if (response.status === 200) { | ||
alert("신청이 완료되었습니다."); | ||
|
||
const newItem = response.data.data; | ||
|
||
handleSave(newItem); | ||
handleClose(); | ||
} else { | ||
alert("신청에 실패했습니다."); | ||
} | ||
} catch (error) { | ||
console.error("신청 요청 실패", error); | ||
alert("신청 요청 중 오류가 발생했습니다."); | ||
} | ||
}; | ||
useFetchRegisterDetailEvent(id); | ||
|
||
if (!open) return null; | ||
|
||
return ( | ||
<Styled.ModalOverlay> | ||
<Styled.ModalContent> | ||
<Styled.CloseButton onClick={handleClose}> | ||
<img src={back_logo} alt="Back Logo" /> | ||
</Styled.CloseButton> | ||
<Styled.FormContainer> | ||
<Styled.Label htmlFor="eventName">공연명</Styled.Label> | ||
<Styled.Input | ||
type="text" | ||
value={name} | ||
onChange={(e) => setName(e.target.value)} | ||
/> | ||
|
||
<Styled.Label htmlFor="eventDate">공연 날짜</Styled.Label> | ||
<Styled.DateRangeContainer> | ||
<Styled.Input | ||
type="date" | ||
value={startDate} | ||
onChange={(e) => setStartDate(e.target.value)} | ||
/> | ||
<span> ~ </span> | ||
<Styled.Input | ||
type="date" | ||
value={endDate} | ||
onChange={(e) => setEndDate(e.target.value)} | ||
/> | ||
</Styled.DateRangeContainer> | ||
|
||
<Styled.Label htmlFor="eventTime">공연 시간</Styled.Label> | ||
<Styled.TimeContainer> | ||
<Styled.Input | ||
type="text" | ||
value={runningTime} | ||
onChange={(e) => setRunningTime(e.target.value)} | ||
/> | ||
<span>분</span> | ||
</Styled.TimeContainer> | ||
<Styled.Label>공연명</Styled.Label> | ||
<Styled.Info>{state.name}</Styled.Info> | ||
|
||
<Styled.Label htmlFor="eventPlace">공연 장소</Styled.Label> | ||
<Styled.Input | ||
type="text" | ||
value={address} | ||
onChange={(e) => setAddress(e.target.value)} | ||
/> | ||
<Styled.Label>공연 날짜</Styled.Label> | ||
<Styled.Info>{state.duration}</Styled.Info> | ||
|
||
<Styled.AdditionalInfoContainer> | ||
<Styled.Label htmlFor="eventAge">관람등급</Styled.Label> | ||
<Styled.Input | ||
type="text" | ||
value={rating} | ||
onChange={(e) => setRating(e.target.value)} | ||
/> | ||
</Styled.AdditionalInfoContainer> | ||
<Styled.Label>공연 시간</Styled.Label> | ||
<Styled.Info>{state.running_time} 분</Styled.Info> | ||
|
||
<Styled.AdditionalInfoContainer> | ||
<Styled.Label>가격</Styled.Label> | ||
<Styled.Input | ||
type="number" | ||
value={price} | ||
onChange={(e) => setPrice(e.target.value)} | ||
/> | ||
</Styled.AdditionalInfoContainer> | ||
<Styled.Label>공연 장소</Styled.Label> | ||
<Styled.Info>{state.address}</Styled.Info> | ||
|
||
<Styled.AdditionalInfoContainer> | ||
<Styled.Label>좌석 수</Styled.Label> | ||
<Styled.Input | ||
type="number" | ||
value={seat} | ||
onChange={(e) => setSeat(e.target.value)} | ||
/> | ||
</Styled.AdditionalInfoContainer> | ||
<Styled.Label>주최자 닉네임</Styled.Label> | ||
<Styled.Info>{state.host_nickname}</Styled.Info> | ||
|
||
<Styled.AdditionalInfoContainer> | ||
<Styled.Label>종류</Styled.Label> | ||
<Styled.Select | ||
value={category} | ||
onChange={(e) => setCategory(e.target.value)} | ||
> | ||
<option value="MUSICAL">뮤지컬</option> | ||
<option value="EXHIBITION">전시</option> | ||
<option value="THEATER">연극</option> | ||
<option value="CONCERT">콘서트</option> | ||
<option value="SPORT">스포츠</option> | ||
</Styled.Select> | ||
</Styled.AdditionalInfoContainer> | ||
|
||
<Styled.ExplainContainer> | ||
<Styled.Label htmlFor="eventExplain">공연내용 요약</Styled.Label> | ||
<Styled.Textarea | ||
value={description} | ||
onChange={(e) => setDescription(e.target.value)} | ||
maxLength={500} | ||
/> | ||
</Styled.ExplainContainer> | ||
|
||
<Styled.AdditionalInfoContainer> | ||
<Styled.Label htmlFor="eventImage">공연 이미지</Styled.Label> | ||
<Styled.Input | ||
type="file" | ||
accept="image/*" | ||
onChange={handleImageChange} | ||
/> | ||
</Styled.AdditionalInfoContainer> | ||
<Styled.Label>공연 설명</Styled.Label> | ||
<Styled.Description>{state.description}</Styled.Description> | ||
|
||
<Styled.ButtonContainer> | ||
<Styled.SaveButton onClick={handleSubmit}>저장</Styled.SaveButton> | ||
<Styled.ClosedButton onClick={handleClose}> | ||
취소 | ||
닫기 | ||
</Styled.ClosedButton> | ||
</Styled.ButtonContainer> | ||
</Styled.FormContainer> | ||
</Styled.ModalContent> | ||
</Styled.ModalOverlay> | ||
); | ||
}; | ||
} |
Oops, something went wrong.