Skip to content

Commit 8824dff

Browse files
authored
이벤트 생성 페이지 API 연동 기능 추가 (#38)
1 parent ae1f707 commit 8824dff

File tree

7 files changed

+208
-176
lines changed

7 files changed

+208
-176
lines changed

fe/package-lock.json

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

fe/src/app/api/event/route.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// pages/api/event.ts
2+
import { NextResponse } from "next/server";
3+
4+
const BASE_API_URL = process.env.NEXT_PUBLIC_API_BASE_URL;
5+
6+
export async function POST(req: Request) {
7+
try {
8+
const { neighborhood, px, py, eventName } = await req.json();
9+
10+
const response = await fetch(`${BASE_API_URL}/event`, {
11+
method: "POST",
12+
headers: {
13+
"Content-Type": "application/json",
14+
},
15+
body: JSON.stringify({ neighborhood, px, py, eventName }),
16+
});
17+
18+
if (!response.ok) {
19+
throw new Error(`Failed to create event: ${response.status}`);
20+
}
21+
22+
const data = await response.json();
23+
return NextResponse.json(data);
24+
} catch (error) {
25+
return NextResponse.json(
26+
{ message: "Error creating event" },
27+
{ status: 500 }
28+
);
29+
}
30+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// pages/api/nonmembers/pings.ts
2+
import { NextRequest, NextResponse } from "next/server";
3+
4+
const BASE_API_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:8080";
5+
6+
export async function GET(req: NextRequest) {
7+
const { searchParams } = new URL(req.url);
8+
const uuid = searchParams.get("uuid");
9+
10+
if (!uuid) {
11+
return NextResponse.json({ error: "UUID is required" }, { status: 400 });
12+
}
13+
14+
try {
15+
const response = await fetch(
16+
`${BASE_API_URL}/nonmembers/pings?uuid=${uuid}`,
17+
{
18+
method: "GET",
19+
headers: {
20+
"Content-Type": "application/json",
21+
},
22+
}
23+
);
24+
25+
if (!response.ok) {
26+
throw new Error(`Failed to fetch pings data: ${response.statusText}`);
27+
}
28+
29+
const data = await response.json();
30+
return NextResponse.json(data);
31+
} catch (error) {
32+
console.error("Error fetching pings data:", error);
33+
return NextResponse.json(
34+
{ message: "Failed to fetch pings data" },
35+
{ status: 500 }
36+
);
37+
}
38+
}

fe/src/app/api/places/route.ts

Lines changed: 0 additions & 99 deletions
This file was deleted.

fe/src/app/eventcreate-page/components/LocationInput.tsx

Lines changed: 63 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,54 @@
1+
// LocationInput.tsx
2+
13
import React, { useState } from "react";
24
import Image from "next/image";
35
import SearchResults from "./SearchResults";
46

57
interface LocationInputProps {
68
className?: string;
7-
onSelect: (location: string) => void;
9+
onSelect: (place: { name: string; address: string }) => void; // 타입 수정
810
}
911

1012
function LocationInput({ className, onSelect }: LocationInputProps) {
11-
const [location, setLocation] = useState("");
13+
const [location, setLocation] = useState<string>("");
1214
const [results, setResults] = useState<{ name: string; address: string }[]>(
1315
[]
1416
);
15-
16-
const fetchPlaces = async (latitude: string, longitude: string) => {
17-
try {
18-
const response = await fetch(
19-
`${process.env.NEXT_PUBLIC_API_BASE_URL}/places?lat=${latitude}&lon=${longitude}`,
20-
{
21-
headers: { accept: "*/*" },
22-
}
23-
);
24-
25-
if (!response.ok) {
26-
throw new Error(`HTTP error! status: ${response.status}`);
27-
}
28-
29-
const data = await response.json();
30-
31-
if (data.places && data.places.length > 0) {
32-
setResults(data.places); // 결과 저장
33-
} else {
34-
alert("현재 위치에 대한 장소를 찾을 수 없습니다.");
35-
}
36-
} catch (error) {
37-
const err = error as Error;
38-
alert(`위치 정보를 가져오는 중 오류가 발생했습니다: ${err.message}`);
39-
}
40-
};
17+
const [isFetching, setIsFetching] = useState(false); // 중복 요청 방지 상태
4118

4219
const fetchPlacesBySearch = async (query: string) => {
20+
if (isFetching) return;
21+
setIsFetching(true);
22+
4323
try {
4424
const response = await fetch(
45-
`${process.env.NEXT_PUBLIC_API_BASE_URL}/places/search/${encodeURIComponent(query)}`,
25+
`${process.env.NEXT_PUBLIC_API_BASE_URL}/places/search?keyword=${encodeURIComponent(query)}`,
4626
{
4727
headers: { accept: "*/*" },
4828
}
4929
);
5030

5131
if (!response.ok) {
32+
const errorText = await response.text();
33+
console.error("Error fetching search results:", errorText);
5234
throw new Error(`HTTP error! status: ${response.status}`);
5335
}
5436

5537
const data = await response.json();
5638
if (data.code === 200) {
57-
setResults(data.data); // 검색 결과 저장
39+
setResults(data.data);
5840
} else {
5941
setResults([]);
6042
alert(`장소 검색에 실패했습니다: ${data.message}`);
6143
}
6244
} catch (error) {
63-
const err = error as Error;
64-
alert(`API 요청 중 오류가 발생했습니다: ${err.message}`);
45+
if (error instanceof Error) {
46+
alert(`API 요청 중 오류가 발생했습니다: ${error.message}`);
47+
} else {
48+
alert("API 요청 중 알 수 없는 오류가 발생했습니다.");
49+
}
50+
} finally {
51+
setIsFetching(false);
6552
}
6653
};
6754

@@ -70,31 +57,67 @@ function LocationInput({ className, onSelect }: LocationInputProps) {
7057
setLocation(value);
7158

7259
if (value.length > 0) {
73-
fetchPlacesBySearch(value); // 검색 실행
60+
fetchPlacesBySearch(value);
7461
} else {
75-
setResults([]); // 입력이 없으면 결과 초기화
62+
setResults([]);
7663
}
7764
};
7865

79-
const handleSelectPlace = ({ name }: { name: string }) => {
80-
setLocation(name);
66+
const handleSelectPlace = (place: { name: string; address: string }) => {
67+
// 매개변수 타입 수정
68+
setLocation(place.name); // 입력 필드를 선택된 장소의 이름으로 업데이트
8169
setResults([]);
82-
onSelect(name); // 부모 컴포넌트에 선택된 장소 전달
70+
onSelect(place); // place 객체 전달
8371
};
8472

8573
const handleCurrentLocation = async () => {
74+
if (isFetching) return;
75+
setIsFetching(true);
76+
8677
if (!navigator.geolocation) {
8778
alert("현재 위치를 지원하지 않는 브라우저입니다.");
79+
setIsFetching(false);
8880
return;
8981
}
9082

9183
navigator.geolocation.getCurrentPosition(
9284
async ({ coords }) => {
93-
const { latitude, longitude } = coords;
94-
await fetchPlaces(latitude.toString(), longitude.toString()); // 현재 위치를 이용해 장소 검색
85+
const { latitude: py, longitude: px } = coords;
86+
87+
try {
88+
const response = await fetch(
89+
`${process.env.NEXT_PUBLIC_API_BASE_URL}/places/geocode?py=${py}&px=${px}`,
90+
{
91+
headers: { accept: "*/*" },
92+
}
93+
);
94+
95+
if (!response.ok) {
96+
const errorText = await response.text();
97+
console.error("Error fetching places:", errorText);
98+
throw new Error(`HTTP error! status: ${response.status}`);
99+
}
100+
101+
const data = await response.json();
102+
103+
if (data.data && data.data.length > 0) {
104+
const selectedPlace = data.data[0];
105+
setResults(data.data);
106+
setLocation(selectedPlace.name);
107+
handleSelectPlace(selectedPlace); // 선택된 장소를 전달
108+
} else {
109+
alert("현재 위치에 대한 장소를 찾을 수 없습니다.");
110+
}
111+
} catch (error) {
112+
console.error("Error fetching places:", error);
113+
alert("위치 정보를 가져오는 중 오류가 발생했습니다.");
114+
} finally {
115+
setIsFetching(false);
116+
}
95117
},
96118
() => {
97119
alert("위치 정보를 가져오는 중 오류가 발생했습니다.");
120+
setIsFetching(false);
98121
}
99122
);
100123
};
@@ -104,7 +127,6 @@ function LocationInput({ className, onSelect }: LocationInputProps) {
104127
<div className="text-text-default text-xl font-semibold leading-loose mb-[12px]">
105128
어떤 공간을 찾고 계신가요?
106129
</div>
107-
108130
<div className="relative w-[328px] h-14 p-4 bg-background-light rounded-lg flex justify-between items-center">
109131
<div className="flex items-center gap-3">
110132
<Image
@@ -121,8 +143,6 @@ function LocationInput({ className, onSelect }: LocationInputProps) {
121143
className="bg-transparent border-none grow shrink basis-0 text-text-default text-base font-medium font-['Pretendard'] leading-normal outline-none flex-1 placeholder-mediumGray"
122144
/>
123145
</div>
124-
125-
{/* 현재 위치 찾기 버튼 복원 */}
126146
<div
127147
role="button"
128148
tabIndex={0}
@@ -140,12 +160,11 @@ function LocationInput({ className, onSelect }: LocationInputProps) {
140160
/>
141161
</div>
142162
</div>
143-
144163
{results.length > 0 && (
145164
<SearchResults
146165
results={results}
147166
searchTerm={location}
148-
onSelect={handleSelectPlace}
167+
onSelect={handleSelectPlace} // 수정된 handleSelectPlace 함수 전달
149168
/>
150169
)}
151170
</div>

0 commit comments

Comments
 (0)