From c853192dbc50c12ca92c9ca23fa36b139b3050d5 Mon Sep 17 00:00:00 2001 From: karnelll <165611407+karnelll@users.noreply.github.com> Date: Thu, 28 Nov 2024 19:48:40 +0900 Subject: [PATCH 01/11] [refactor] Update exit modal functionality and improve data handling --- .../app/components/test/NaverLoginButton.tsx | 30 ------------ .../load-mappin-edit/components/EditLink.tsx | 48 +++++++++---------- .../[nonMemberId]/load-mappin-edit/page.tsx | 9 ++-- .../[id]/load-mappin/forms/links/page.tsx | 13 ++--- 4 files changed, 35 insertions(+), 65 deletions(-) delete mode 100644 fe/src/app/components/test/NaverLoginButton.tsx diff --git a/fe/src/app/components/test/NaverLoginButton.tsx b/fe/src/app/components/test/NaverLoginButton.tsx deleted file mode 100644 index 884799e..0000000 --- a/fe/src/app/components/test/NaverLoginButton.tsx +++ /dev/null @@ -1,30 +0,0 @@ -"use client"; - -export default function NaverLoginButton() { - const handleLogin = () => { - const clientId = process.env.NEXT_PUBLIC_NAVER_CLIENT_ID; - const redirectUri = process.env.NEXT_PUBLIC_REDIRECT_URI; - const state = Math.random().toString(36).substring(2, 15); - - if (!clientId || !redirectUri) { - alert("환경 변수가 제대로 설정되지 않았습니다."); - return; - } - - const naverAuthUrl = `https://nid.naver.com/oauth2.0/authorize?response_type=code&client_id=${clientId}&redirect_uri=${encodeURIComponent( - redirectUri - )}&state=${state}`; - - window.location.href = naverAuthUrl; - }; - - return ( - - ); -} diff --git a/fe/src/app/event-maps/[id]/[nonMemberId]/load-mappin-edit/components/EditLink.tsx b/fe/src/app/event-maps/[id]/[nonMemberId]/load-mappin-edit/components/EditLink.tsx index 82d34a2..1cab0b3 100644 --- a/fe/src/app/event-maps/[id]/[nonMemberId]/load-mappin-edit/components/EditLink.tsx +++ b/fe/src/app/event-maps/[id]/[nonMemberId]/load-mappin-edit/components/EditLink.tsx @@ -32,7 +32,7 @@ export default function LinkFieldEdit({ id: nanoid(), text: val, error: "", - isValid: true, + isValid: !!val, isTyping: false, })) : [ @@ -110,28 +110,6 @@ export default function LinkFieldEdit({ } }; - const handlePasteFromClipboard = async (fieldId: string) => { - try { - const clipboardText = await navigator.clipboard.readText(); - - const cleanedValue = cleanURL(clipboardText); - - if (cleanedValue) { - setInputFields((prevFields) => - prevFields.map((fieldItem) => - fieldItem.id === fieldId - ? { ...fieldItem, text: cleanedValue, isValid: false } - : fieldItem - ) - ); - - validateLink(fieldId, cleanedValue, label); - } - } catch (error) { - console.error("클립보드에서 텍스트를 읽는 데 실패했습니다:", error); - } - }; - const handleInputChange = (fieldId: string, inputValue: string) => { const cleanedValue = cleanURL(inputValue); setInputFields((prevFields) => @@ -147,14 +125,33 @@ export default function LinkFieldEdit({ } }; - const handleFocus = (fieldId: string) => { + const handleFocus = async (fieldId: string) => { setInputFields((prevFields) => prevFields.map((fieldItem) => fieldItem.id === fieldId ? { ...fieldItem, isTyping: true } : fieldItem ) ); - handlePasteFromClipboard(fieldId); + // 자동 클립보드 붙여넣기 기능 + if (navigator.clipboard) { + try { + const clipboardText = await navigator.clipboard.readText(); + const cleanedValue = cleanURL(clipboardText); + if (cleanedValue) { + setInputFields((prevFields) => + prevFields.map((fieldItem) => + fieldItem.id === fieldId + ? { ...fieldItem, text: cleanedValue, isValid: false } + : fieldItem + ) + ); + + validateLink(fieldId, cleanedValue, label); + } + } catch (error) { + console.error("클립보드에서 텍스트를 읽는 데 실패했습니다:", error); + } + } }; const handleBlur = (fieldId: string) => { @@ -199,6 +196,7 @@ export default function LinkFieldEdit({ }; const getClassNames = (item: InputField): string => { + if (!item.text) return "bg-[#F8F8F8]"; if (item.error && !item.isTyping) return "border-2 border-[#f73a2c] bg-[#F8F8F8]"; if (item.isValid) return "bg-[#EBF4FD] text-[#3a91ea]"; diff --git a/fe/src/app/event-maps/[id]/[nonMemberId]/load-mappin-edit/page.tsx b/fe/src/app/event-maps/[id]/[nonMemberId]/load-mappin-edit/page.tsx index 0708664..fe69f59 100644 --- a/fe/src/app/event-maps/[id]/[nonMemberId]/load-mappin-edit/page.tsx +++ b/fe/src/app/event-maps/[id]/[nonMemberId]/load-mappin-edit/page.tsx @@ -98,13 +98,14 @@ export default function LinkEditPage() { }; const handleBack = () => { - router.push(`/event-maps/${id}`); + setShowExitModal(true); // ExitModal을 표시 }; - const handleExit = () => { + const handleExitConfirm = () => { + // 데이터 삭제 후 뒤로가기 localStorage.removeItem("userData"); localStorage.removeItem("formData"); - router.back(); + router.push(`/event-maps/${id}`); }; const handleCancel = () => { @@ -175,7 +176,7 @@ export default function LinkEditPage() { /> {showExitModal && ( - + )} ); diff --git a/fe/src/app/event-maps/[id]/load-mappin/forms/links/page.tsx b/fe/src/app/event-maps/[id]/load-mappin/forms/links/page.tsx index ccdeb7b..83432e4 100644 --- a/fe/src/app/event-maps/[id]/load-mappin/forms/links/page.tsx +++ b/fe/src/app/event-maps/[id]/load-mappin/forms/links/page.tsx @@ -63,7 +63,6 @@ export default function LinksPage() { localStorage.clear(); router.push(`/event-maps/${id}`); } else if (response.status === 409) { - // 405 에러 처리 alert("이미 존재하는 이름입니다. 다시 시도해주세요."); } else { setIsFormComplete(false); @@ -93,11 +92,13 @@ export default function LinksPage() {
-
- 마음에 쏙 든 공간을 불러와요 -
-
- 네이버지도에 북마크 해 둔 공간을 불러와요 +
+
+ 마음에 쏙 든 공간을 불러와요 +
+
+ 네이버지도에 북마크 해 둔 공간을 불러와요 +
From 6ae43466c7dd4aba0a64e765f0fe5930a725d981 Mon Sep 17 00:00:00 2001 From: karnelll <165611407+karnelll@users.noreply.github.com> Date: Thu, 28 Nov 2024 21:21:12 +0900 Subject: [PATCH 02/11] [fix] implement feedback --- .../load-mappin-edit/components/EditLink.tsx | 1 - .../load-mappin-edit/components/ExitModal.tsx | 1 - .../eventcreate-page/\butils/formHelpers.ts" | 8 +++++ .../components/EventNameInput.tsx | 30 ++++++++++++------- .../eventcreate-page/location-search/page.tsx | 5 ++-- fe/src/app/robots.ts | 1 - 6 files changed, 29 insertions(+), 17 deletions(-) create mode 100644 "fe/src/app/eventcreate-page/\butils/formHelpers.ts" diff --git a/fe/src/app/event-maps/[id]/[nonMemberId]/load-mappin-edit/components/EditLink.tsx b/fe/src/app/event-maps/[id]/[nonMemberId]/load-mappin-edit/components/EditLink.tsx index 1cab0b3..3b7fffb 100644 --- a/fe/src/app/event-maps/[id]/[nonMemberId]/load-mappin-edit/components/EditLink.tsx +++ b/fe/src/app/event-maps/[id]/[nonMemberId]/load-mappin-edit/components/EditLink.tsx @@ -132,7 +132,6 @@ export default function LinkFieldEdit({ ) ); - // 자동 클립보드 붙여넣기 기능 if (navigator.clipboard) { try { const clipboardText = await navigator.clipboard.readText(); diff --git a/fe/src/app/event-maps/[id]/[nonMemberId]/load-mappin-edit/components/ExitModal.tsx b/fe/src/app/event-maps/[id]/[nonMemberId]/load-mappin-edit/components/ExitModal.tsx index 0ca1649..16357c1 100644 --- a/fe/src/app/event-maps/[id]/[nonMemberId]/load-mappin-edit/components/ExitModal.tsx +++ b/fe/src/app/event-maps/[id]/[nonMemberId]/load-mappin-edit/components/ExitModal.tsx @@ -36,7 +36,6 @@ const ExitModal: React.FC = function ExitModal({
- {/* Buttons */}
{showExitModal && ( - + )} ); diff --git "a/fe/src/app/event-maps/[id]/load-mappin/forms/links/\bcomponents/LinkField.tsx" "b/fe/src/app/event-maps/[id]/load-mappin/forms/links/\bcomponents/LinkField.tsx" index 1ac557d..e244ed7 100644 --- "a/fe/src/app/event-maps/[id]/load-mappin/forms/links/\bcomponents/LinkField.tsx" +++ "b/fe/src/app/event-maps/[id]/load-mappin/forms/links/\bcomponents/LinkField.tsx" @@ -5,11 +5,13 @@ import { nanoid } from "nanoid"; import Image from "next/image"; import { useRouter, useParams } from "next/navigation"; -interface LinkFieldEditProps { +interface LinkFieldProps { label: string; placeholder: string; value: string[]; onChange: (value: string[]) => void; + showTooltip?: boolean; + onInfoClick?: () => void; } interface InputField { @@ -18,14 +20,15 @@ interface InputField { error: string; isValid: boolean; isTyping: boolean; + canEdit: boolean; } -export default function LinkFieldEdit({ +export default function LinkField({ label, placeholder, value, onChange, -}: LinkFieldEditProps) { +}: LinkFieldProps) { const [inputFields, setInputFields] = useState( value.length > 0 ? value.map((val) => ({ @@ -34,6 +37,7 @@ export default function LinkFieldEdit({ error: "", isValid: true, isTyping: false, + canEdit: true, })) : [ { @@ -42,6 +46,7 @@ export default function LinkFieldEdit({ error: "", isValid: false, isTyping: false, + canEdit: true, }, ] ); @@ -57,11 +62,6 @@ export default function LinkFieldEdit({ onChange(validLinks); }, [inputFields, onChange]); - const cleanURL = (url: string): string => { - const match = url.match(/https?:\/\/[^\s]+/); - return match ? match[0].trim() : ""; - }; - const validateLink = async (fieldId: string, url: string, type: string) => { const endpoint = type === "북마크 공유 링크" ? "/pings/bookmark" : "/pings/store"; @@ -113,17 +113,16 @@ export default function LinkFieldEdit({ const handlePasteFromClipboard = async (fieldId: string) => { try { const clipboardText = await navigator.clipboard.readText(); - const cleanedValue = cleanURL(clipboardText); - if (cleanedValue) { + if (clipboardText.trim()) { setInputFields((prevFields) => prevFields.map((fieldItem) => fieldItem.id === fieldId - ? { ...fieldItem, text: cleanedValue, isValid: false } + ? { ...fieldItem, text: clipboardText, isValid: false } : fieldItem ) ); - validateLink(fieldId, cleanedValue, label); + validateLink(fieldId, clipboardText, label); } } catch (error) { console.error("클립보드에서 텍스트를 읽는 데 실패했습니다:", error); @@ -131,18 +130,15 @@ export default function LinkFieldEdit({ }; const handleInputChange = (fieldId: string, inputValue: string) => { - const cleanedValue = cleanURL(inputValue); // URL 정리 setInputFields((prevFields) => prevFields.map((fieldItem) => fieldItem.id === fieldId - ? { ...fieldItem, text: cleanedValue, isValid: false, isTyping: true } + ? { ...fieldItem, text: inputValue, isValid: false, isTyping: true } : fieldItem ) ); - if (cleanedValue) { - validateLink(fieldId, cleanedValue, label); - } + validateLink(fieldId, inputValue, label); }; const handleFocus = (fieldId: string) => { @@ -172,6 +168,7 @@ export default function LinkFieldEdit({ error: "", isValid: false, isTyping: false, + canEdit: true, }, ]); }; @@ -248,9 +245,7 @@ export default function LinkFieldEdit({ {inputFields.map((item, index) => (
- {/* 체크박스 */}
@@ -125,7 +124,6 @@ export default function LinksPage() {
- {/* 하단 버튼 */}
diff --git a/fe/src/app/eventcreate-page/page.tsx b/fe/src/app/eventcreate-page/page.tsx index eedf5f4..b68ad4e 100644 --- a/fe/src/app/eventcreate-page/page.tsx +++ b/fe/src/app/eventcreate-page/page.tsx @@ -74,12 +74,8 @@ function EventCreatePage() { label="다음" type="next" onClick={handleNextClick} - className={`w-[328px] h-[60px] py-[17px] rounded-lg text-lg font-['Pretendard'] font-medium ${ - isFormComplete && !isSubmitting - ? "bg-black text-white" - : "bg-[#E4E4E4] text-[#8E8E8E]" - }`} disabled={!isFormComplete || isSubmitting} + isSubmitting={isSubmitting} />
diff --git a/fe/src/app/page.tsx b/fe/src/app/page.tsx index 83e3e2e..1c6648d 100644 --- a/fe/src/app/page.tsx +++ b/fe/src/app/page.tsx @@ -13,7 +13,7 @@ function LoadingPage() { }; return ( -
+
From d8cc864acb20bc0ec6b07c2331a0f508eda52bc9 Mon Sep 17 00:00:00 2001 From: karnelll <165611407+karnelll@users.noreply.github.com> Date: Sat, 30 Nov 2024 03:56:42 +0900 Subject: [PATCH 10/11] [feature] Add cleanURL function and clean URL validation --- .../forms/links/\bcomponents/LinkField.tsx" | 17 +++++++++++------ .../[id]/load-mappin/forms/links/page.tsx | 12 ++++++++++-- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git "a/fe/src/app/event-maps/[id]/load-mappin/forms/links/\bcomponents/LinkField.tsx" "b/fe/src/app/event-maps/[id]/load-mappin/forms/links/\bcomponents/LinkField.tsx" index e244ed7..983ea05 100644 --- "a/fe/src/app/event-maps/[id]/load-mappin/forms/links/\bcomponents/LinkField.tsx" +++ "b/fe/src/app/event-maps/[id]/load-mappin/forms/links/\bcomponents/LinkField.tsx" @@ -55,6 +55,11 @@ export default function LinkField({ const router = useRouter(); const { id } = useParams(); + const cleanURL = (url: string): string => { + const match = url.match(/https?:\/\/[^\s]+/); + return match ? match[0].trim() : ""; + }; + useEffect(() => { const validLinks = inputFields .filter((field) => field.isValid) @@ -114,15 +119,15 @@ export default function LinkField({ try { const clipboardText = await navigator.clipboard.readText(); if (clipboardText.trim()) { + const cleanedText = cleanURL(clipboardText); setInputFields((prevFields) => prevFields.map((fieldItem) => fieldItem.id === fieldId - ? { ...fieldItem, text: clipboardText, isValid: false } + ? { ...fieldItem, text: cleanedText, isValid: false } : fieldItem ) ); - - validateLink(fieldId, clipboardText, label); + validateLink(fieldId, cleanedText, label); } } catch (error) { console.error("클립보드에서 텍스트를 읽는 데 실패했습니다:", error); @@ -130,15 +135,15 @@ export default function LinkField({ }; const handleInputChange = (fieldId: string, inputValue: string) => { + const cleanedValue = cleanURL(inputValue); // URL 정리 setInputFields((prevFields) => prevFields.map((fieldItem) => fieldItem.id === fieldId - ? { ...fieldItem, text: inputValue, isValid: false, isTyping: true } + ? { ...fieldItem, text: cleanedValue, isValid: false, isTyping: true } : fieldItem ) ); - - validateLink(fieldId, inputValue, label); + validateLink(fieldId, cleanedValue, label); }; const handleFocus = (fieldId: string) => { diff --git a/fe/src/app/event-maps/[id]/load-mappin/forms/links/page.tsx b/fe/src/app/event-maps/[id]/load-mappin/forms/links/page.tsx index 3c5dc01..cf82d8a 100644 --- a/fe/src/app/event-maps/[id]/load-mappin/forms/links/page.tsx +++ b/fe/src/app/event-maps/[id]/load-mappin/forms/links/page.tsx @@ -27,6 +27,11 @@ export default function LinksPage() { setIsFormComplete(isComplete); }, [mapLinks, storeLinks, isChecked, isSubmitting]); + const cleanURL = (url: string): string => { + const match = url.match(/https?:\/\/[^\s]+/); + return match ? match[0].trim() : ""; + }; + const handleSubmit = async (e?: React.FormEvent) => { if (e) e.preventDefault(); @@ -40,12 +45,15 @@ export default function LinksPage() { return; } + const cleanedMapLinks = mapLinks.map(cleanURL).filter(Boolean); + const cleanedStoreLinks = storeLinks.map(cleanURL).filter(Boolean); + const requestBody = { uuid: id, name, password: pin, - bookmarkUrls: mapLinks, - storeUrls: storeLinks, + bookmarkUrls: cleanedMapLinks, + storeUrls: cleanedStoreLinks, }; try { From bfac6a897114ec99584636c755be0c1c811e8877 Mon Sep 17 00:00:00 2001 From: karnelll <165611407+karnelll@users.noreply.github.com> Date: Sat, 30 Nov 2024 04:01:23 +0900 Subject: [PATCH 11/11] [fix] Update build.yml --- .../[id]/load-mappin/forms/links/\bcomponents/LinkField.tsx" | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git "a/fe/src/app/event-maps/[id]/load-mappin/forms/links/\bcomponents/LinkField.tsx" "b/fe/src/app/event-maps/[id]/load-mappin/forms/links/\bcomponents/LinkField.tsx" index fc9f52d..983ea05 100644 --- "a/fe/src/app/event-maps/[id]/load-mappin/forms/links/\bcomponents/LinkField.tsx" +++ "b/fe/src/app/event-maps/[id]/load-mappin/forms/links/\bcomponents/LinkField.tsx" @@ -135,15 +135,15 @@ export default function LinkField({ }; const handleInputChange = (fieldId: string, inputValue: string) => { + const cleanedValue = cleanURL(inputValue); // URL 정리 setInputFields((prevFields) => prevFields.map((fieldItem) => fieldItem.id === fieldId - ? { ...fieldItem, text: inputValue, isValid: false, isTyping: true } + ? { ...fieldItem, text: cleanedValue, isValid: false, isTyping: true } : fieldItem ) ); validateLink(fieldId, cleanedValue, label); - }; const handleFocus = (fieldId: string) => {