Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/40 api connect #42

Merged
merged 5 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
36 changes: 0 additions & 36 deletions fe/src/app/dashboard/page.tsx

This file was deleted.

138 changes: 43 additions & 95 deletions fe/src/app/event-maps/[id]/[nonMemberId]/components/PincheckInput.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,29 @@
"use client";

import React, { useRef, useState, useEffect } from "react";
import React, { useRef, useState, useEffect, useCallback } from "react";
import { useRouter, useParams } from "next/navigation";
import { v4 as uuidv4 } from "uuid";

export default function PasswordInput() {
const [password, setPassword] = useState(["", "", "", ""]);
const [currentIndex, setCurrentIndex] = useState(0);
const [hasError, setHasError] = useState(false); // 변수명 변경
const [hasError, setHasError] = useState(false);
const inputRefs = useRef<(HTMLInputElement | null)[]>([]);
const router = useRouter();
const { id, nonMemberId } = useParams();

const submitPassword = async () => {
// Define submitPassword before useEffect
const submitPassword = useCallback(async () => {
const fullPassword = password.join("");
console.log(password);
console.log("Password submitted:", fullPassword);

if (fullPassword.length !== 4) {
setHasError(true);
return;
}

try {
const response = await fetch(
"http://110.165.17.236:8081/api/v1/nonmembers/login",
`${process.env.NEXT_PUBLIC_API_BASE_URL}/nonmembers/login`,
{
method: "PUT",
headers: {
Expand All @@ -35,15 +40,20 @@ export default function PasswordInput() {
if (response.ok) {
router.push(`/event-maps/${id}/${nonMemberId}/load-mappin-edit`);
} else {
setHasError(true); // hasError로 변경
setHasError(true);
setPassword(["", "", "", ""]);
setCurrentIndex(0);
}
} catch (error) {
console.error("서버 오류:", error);
setHasError(true); // hasError로 변경
setHasError(true);
}
};
}, [id, nonMemberId, password, router]);

useEffect(() => {
if (password.every((digit) => digit !== "")) {
submitPassword();
}
}, [password, submitPassword]);

const handleInputChange = (
e: React.ChangeEvent<HTMLInputElement>,
Expand Down Expand Up @@ -75,7 +85,7 @@ export default function PasswordInput() {
}

setPassword(newPass);
setHasError(false); // hasError로 변경
setHasError(false);
}
};

Expand All @@ -86,97 +96,35 @@ export default function PasswordInput() {
return (
<div className="flex flex-col items-center">
<div className="inline-flex items-center justify-start gap-4 mb-4">
<div
className={`w-14 h-14 p-4 bg-[#f7f7f7] rounded-lg inline-flex items-center ${
hasError ? "border-2 border-primary-50" : ""
} ${currentIndex === 0 ? "border-2 border-gray-950" : ""}`}
>
<input
ref={(el) => {
inputRefs.current[0] = el;
}}
type="text"
inputMode="numeric"
pattern="[0-9]*"
className="grow text-center w-full h-full bg-transparent outline-none text-2xl"
maxLength={1}
value={password[0]}
onChange={(e) => handleInputChange(e, 0)}
onKeyDown={(e) => handleKeyDown(e, 0)}
/>
</div>
<div
className={`w-14 h-14 p-4 bg-[#f7f7f7] rounded-lg inline-flex items-center ${
hasError ? "border-2 border-primary-50" : ""
} ${currentIndex === 1 ? "border-2 border-gray-950" : ""}`}
>
<input
ref={(el) => {
inputRefs.current[1] = el;
}}
type="text"
inputMode="numeric"
pattern="[0-9]*"
className="grow text-center w-full h-full bg-transparent outline-none text-2xl"
maxLength={1}
value={password[1]}
onChange={(e) => handleInputChange(e, 1)}
onKeyDown={(e) => handleKeyDown(e, 1)}
/>
</div>
<div
className={`w-14 h-14 p-4 bg-[#f7f7f7] rounded-lg inline-flex items-center ${
hasError ? "border-2 border-primary-50" : ""
} ${currentIndex === 2 ? "border-2 border-gray-950" : ""}`}
>
<input
ref={(el) => {
inputRefs.current[2] = el;
}}
type="text"
inputMode="numeric"
pattern="[0-9]*"
className="grow text-center w-full h-full bg-transparent outline-none text-2xl"
maxLength={1}
value={password[2]}
onChange={(e) => handleInputChange(e, 2)}
onKeyDown={(e) => handleKeyDown(e, 2)}
/>
</div>
<div
className={`w-14 h-14 p-4 bg-[#f7f7f7] rounded-lg inline-flex items-center ${
hasError ? "border-2 border-primary-50" : ""
} ${currentIndex === 3 ? "border-2 border-gray-950" : ""}`}
>
<input
ref={(el) => {
inputRefs.current[3] = el;
}}
type="text"
inputMode="numeric"
pattern="[0-9]*"
className="grow text-center w-full h-full bg-transparent outline-none text-2xl"
maxLength={1}
value={password[3]}
onChange={(e) => handleInputChange(e, 3)}
onKeyDown={(e) => handleKeyDown(e, 3)}
/>
</div>
{password.map((_, i) => (
<div
key={uuidv4()} // Unique key for each render
className={`w-14 h-14 p-4 bg-[#f7f7f7] rounded-lg inline-flex items-center ${
hasError ? "border-2 border-primary-50" : ""
} ${currentIndex === i ? "border-2 border-gray-950" : ""}`}
>
<input
ref={(el) => {
inputRefs.current[i] = el;
}}
type="text"
inputMode="numeric"
pattern="[0-9]*"
className="grow text-center w-full h-full bg-transparent outline-none text-2xl"
maxLength={1}
value={password[i]}
onChange={(e) => handleInputChange(e, i)}
onKeyDown={(e) => handleKeyDown(e, i)}
/>
</div>
))}
</div>

{hasError && (
<p className="text-primary-50 text-left w-full max-w-sm">
비밀번호가 일치하지 않아요
</p>
)}

<button
type="button"
onClick={submitPassword}
className="mt-4 px-6 py-2 bg-primary-50 text-white rounded-lg"
>
제출
</button>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import React, { useState } from "react";
import Image from "next/image";
import { useRouter, useParams } from "next/navigation";
import ExitModal from "@/app/components/common/ExitModal";
import ExitModal from "@/app/event-maps/[id]/[nonMemberId]/components/PinExitModal";
import Form from "./components/Form";

export default function Page() {
Expand Down
52 changes: 52 additions & 0 deletions fe/src/app/event-maps/[id]/components/EventMapExitModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React from "react";

interface ExitModalProps {
onCancel: () => void;
onExit: () => void;
}

function ExitModal({ onCancel, onExit }: ExitModalProps) {
return (
<div className="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50 z-50">
<div className="w-[272px] h-[202px] flex flex-col items-center bg-white rounded-lg overflow-hidden shadow-lg">
<div className="w-full h-[148px] px-[39px] pt-6 pb-7 flex flex-col items-center gap-2.5">
{" "}
{/* pt 값을 줄여서 위로 올림 */}
<div className="w-full flex flex-col items-center gap-2">
<div className="text-center text-[#1d1d1d] text-xl font-semibold font-['Pretendard'] leading-7">
이벤트를 저장하지 않고 나갈까요?
</div>
<div className="text-center text-[#8e8e8e] text-base font-medium font-['Pretendard'] leading-normal">
이대로 나가면
<br /> 발급된 이벤트가 초기화됩니다.
</div>
</div>
</div>

<div className="w-full flex border-t">
<button
type="button"
onClick={onCancel}
className="w-1/2 h-[54px] bg-[#f0f0f0] flex items-center justify-center hover:bg-[#e0e0e0] transition-colors duration-200"
>
<span className="text-center text-[#2c2c2c] text-lg font-medium font-['Pretendard']">
취소
</span>
</button>

<button
type="button"
onClick={onExit}
className="w-1/2 h-[54px] bg-[#1d1d1d] flex items-center justify-center hover:bg-[#333] transition-colors duration-200"
>
<span className="text-center text-white text-lg font-medium font-['Pretendard']">
나가기
</span>
</button>
</div>
</div>
</div>
);
}

export default ExitModal;
45 changes: 33 additions & 12 deletions fe/src/app/event-maps/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

import React, { useEffect, useState } from "react";
import { useParams, useRouter } from "next/navigation";
import Image from "next/image"; // 외부 라이브러리
import { a } from "@react-spring/web"; // 외부 라이브러리
import { useDrag } from "@use-gesture/react"; // 외부 라이브러리
import Image from "next/image";
import { a } from "@react-spring/web";
import { useDrag } from "@use-gesture/react";
import MapComponent from "./components/MapComponent";
import BottomDrawer from "./components/BottomDrawer";
import useDrawer from "./hooks/useDrawer"; // 내부 모듈
import { useLocationStore } from "./stores/useLocationStore"; // 내부 모듈
import useDrawer from "./hooks/useDrawer";
import { useLocationStore } from "./stores/useLocationStore";
import { useMarkerStore } from "./load-mappin/stores/useMarkerStore";
import ExitModal from "./components/EventMapExitModal";

interface NonMember {
nonMemberId: number;
Expand Down Expand Up @@ -38,15 +39,20 @@ export default function Page() {
const { id } = useParams();
const parsedId = Array.isArray(id) ? id[0] : id;
const [data, setData] = useState<Data | null>(null);
const [isModalOpen, setIsModalOpen] = useState(false); // 모달 열림 상태 추가
const moveToLocation = useLocationStore((state) => state.moveToLocation);
const setCustomMarkers = useMarkerStore((state) => state.setCustomMarkers);
const router = useRouter();

useEffect(() => {
console.log("useEffect triggered with id:", id);

const fetchData = async () => {
try {
console.log("Fetching data for id:", id);

const response = await fetch(
`http://110.165.17.236:8081/api/v1/nonmembers/pings?uuid=${id}`,
`${process.env.NEXT_PUBLIC_API_BASE_URL}/nonmembers/pings?uuid=${id}`,
{
method: "GET",
headers: {
Expand All @@ -58,22 +64,25 @@ export default function Page() {
if (response.ok) {
const result = await response.json();
setData(result);
console.log("Response Data:", JSON.stringify(result, null, 2));
console.log("API Response Data:", JSON.stringify(result, null, 2));

// 처음 px, py 값을 useLocationStore에 저장
if (result.px && result.py) {
console.log("Moving to location:", result.py, result.px);
moveToLocation(result.py, result.px);
}

// pings 데이터를 useMarkerStore에 저장
if (result.pings) {
console.log("Setting custom markers:", result.pings);
setCustomMarkers(result.pings);
}
} else {
console.error("데이터 가져오기에 실패했습니다.");
console.error(
"Failed to fetch data from API. Status:",
response.status
);
}
} catch (error) {
console.error("서버 오류:", error);
console.error("Server error:", error);
}
};

Expand All @@ -83,8 +92,18 @@ export default function Page() {
}, [id, data, moveToLocation, setCustomMarkers]);

const handleBackbtn = () => {
router.push(`eventcreate-page`);
setIsModalOpen(true); // 뒤로 가기 버튼 클릭 시 모달 열기
};

const handleExit = () => {
setIsModalOpen(false);
router.replace("/eventcreate-page"); // UUID 초기화 후 이벤트 생성 페이지로 이동
};

const handleCancel = () => {
setIsModalOpen(false); // 모달 닫기
};

const bind = useDrag(
({ last, movement: [, my], memo = y.get() }) => {
if (last) {
Expand Down Expand Up @@ -131,6 +150,8 @@ export default function Page() {
</a.div>
</>
)}
{/* isModalOpen 상태에 따라 모달을 조건부 렌더링 */}
{isModalOpen && <ExitModal onCancel={handleCancel} onExit={handleExit} />}
</div>
);
}
Loading
Loading