Skip to content

Commit

Permalink
♻️ 모달페이지를 모달창으로 구현 및 UIUX 개선
Browse files Browse the repository at this point in the history
  • Loading branch information
saebomnewspring committed Feb 1, 2025
1 parent ff396a6 commit c5acabf
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 86 deletions.
29 changes: 0 additions & 29 deletions app/modal/page.jsx

This file was deleted.

17 changes: 10 additions & 7 deletions app/signup/page.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,15 @@
import React, { useState } from 'react';
import Link from 'next/link';
import Title from '../../components/landing/Title';
import Modal from '../../components/modal/modal'; // 모달 컴포넌트 추가
import ModalComponent from '../../components/modal/modal-component'; // 모달 내용

const SignupPage = () => {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState('');

const handleCardClick = (path) => {
console.log(`Navigating to ${path}`);
window.location.href = path;
};
const [isModalOpen, setIsModalOpen] = useState(false); // 모달 상태 추가

const handleSignup = async (event) => {
event.preventDefault();
Expand All @@ -32,7 +30,7 @@ const SignupPage = () => {
});

if (res.ok) {
handleCardClick('../modal');
setIsModalOpen(true); // 회원가입 성공 시 모달 열기
} else {
const data = await res.json();
alert(data.message);
Expand Down Expand Up @@ -95,8 +93,13 @@ const SignupPage = () => {
</div>
</form>
</div>

{/* ✅ 회원가입 성공 시 모달 띄우기 */}
<Modal isOpen={isModalOpen} onClose={() => setIsModalOpen(false)}>
<ModalComponent />
</Modal>
</div>
);
};

export default SignupPage;
export default SignupPage;
59 changes: 32 additions & 27 deletions components/modal/category-selector.jsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
"use client";

import React, { useMemo } from 'react';
import React, { useMemo } from "react";

const categories = [
{ id : 1, name: '백엔드', icon: 'fas fa-server' },
{ id : 2, name: '프론트엔드', icon: 'fas fa-code' },
{ id : 3, name: '네트워크', icon: 'fas fa-network-wired' },
{ id : 4, name: '데이터베이스', icon: 'fas fa-database' },
{ id : 5, name: '운영체제', icon: 'fas fa-window-restore' },
{ id : 6, name: '자료구조', icon: 'fas fa-cubes' },
{ id: 1, name: "백엔드", icon: "fas fa-server" },
{ id: 2, name: "프론트엔드", icon: "fas fa-code" },
{ id: 3, name: "네트워크", icon: "fas fa-network-wired" },
{ id: 4, name: "데이터베이스", icon: "fas fa-database" },
{ id: 5, name: "운영체제", icon: "fas fa-window-restore" },
{ id: 6, name: "자료구조", icon: "fas fa-cubes" },
];

const CategoryButtons = ({ availableCategories, onSelect }) => {
return (
<div className="flex flex-wrap gap-2 p-6">
{availableCategories.map(category => (
<div className="flex flex-wrap gap-2 p-4">
{availableCategories.map((category) => (
<button
key={category.name}
className="flex justify-center items-center px-4 py-3 rounded-full bg-gray-400 text-white font-medium"
key={category.id}
className="px-4 py-2 rounded-full bg-gray-400 text-white font-medium"
onClick={() => onSelect(category)}
>
<i className={`${category.icon}`}></i>
{category.name}
</button>
))}
Expand All @@ -30,39 +29,45 @@ const CategoryButtons = ({ availableCategories, onSelect }) => {

const SelectedCategories = ({ selectedCategories, onDeselect }) => {
return (
<div className="flex flex-wrap gap-2 p-6">
{selectedCategories.map(category => (
<button
key={category.name}
className="flex justify-center items-center px-4 py-3 rounded-full bg-[#6DB1B2] text-white font-medium"
onClick={() => onDeselect(category)}
>
<i className={`${category.icon}`}></i>
{category.name}
</button>
))}
<div className="flex flex-wrap gap-2 p-4">
{selectedCategories.length > 0 ? (
selectedCategories.map((category) => (
<button
key={category.id}
className="px-4 py-2 rounded-full bg-[#6DB1B2] text-white font-medium"
onClick={() => onDeselect(category)}
>
{category.name}
</button>
))
) : (
<p className="text-gray-500">선택된 카테고리가 없습니다.</p>
)}
</div>
);
};

const CategorySelector = ({ selectedCategories, onSelect, onDeselect }) => {
const CategorySelector = ({ selectedCategories = [], onSelect, onDeselect }) => {
const availableCategories = useMemo(() => {
return categories.filter(
category => !selectedCategories.some(selected => selected.id === category.id)
(category) => !selectedCategories.some((selected) => selected.id === category.id)
);
}, [selectedCategories]);

return (
<div>
{/* ✅ 선택된 카테고리 표시 */}
<div className="bg-white rounded-lg shadow p-4 mb-4 w-full max-w-[800px]">
<h1 className="text-lg font-bold mb-3">선택된 카테고리</h1>
<h2 className="text-lg font-bold mb-3">선택된 카테고리</h2>
<SelectedCategories
selectedCategories={selectedCategories}
onDeselect={onDeselect}
/>
</div>

{/* ✅ 선택 가능한 카테고리 표시 */}
<div className="bg-white rounded-lg shadow p-4 w-full mb-4 max-w-[800px]">
<h1 className="text-lg font-bold mb-3">카테고리 선택</h1>
<h2 className="text-lg font-bold mb-3">카테고리 선택</h2>
<CategoryButtons
availableCategories={availableCategories}
onSelect={onSelect}
Expand Down
47 changes: 24 additions & 23 deletions components/modal/modal-component.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,28 @@ import React, { useState } from "react";
import dynamic from 'next/dynamic';
import Dropdown from './drop-down';

const TimeSelector = ({ value, onChange }) => {
const options = [
{ value: '7시', label: '오전 7시' },
{ value: '8시', label: '오전 8시' },
{ value: '9시', label: '오전 9시' }
];
return <Dropdown value={value} onChange={onChange} options={options} placeholder="학습 시간"/>;
};
const QuestionInput = ({ value, onChange }) => {
const options = [
{ value: '1개', label: '1개' },
{ value: '2개', label: '2개' },
{ value: '3개', label: '3개' },
{ value: '4개', label: '4개' },
{ value: '5개', label: '5개' }
];
return <Dropdown value={value} onChange={onChange} options={options} placeholder="문제 수"/>;
};


const CategorySelector = dynamic(() => import('./category-selector'), { ssr: false });
const TimeSelector = dynamic(() => import('./time-selector'), { ssr: false });
const QuestionInput = dynamic(() => import('./question-input'), { ssr: false });


export default function ModalComponent() {
const [selectedCategories, setSelectedCategories] = useState([]);
Expand Down Expand Up @@ -56,31 +74,14 @@ export default function ModalComponent() {
console.error("Error sending data:", error);
}
};
const TimeSelector = ({ value, onChange }) => {
const options = [
{ value: '7시', label: '오전 7시' },
{ value: '8시', label: '오전 8시' },
{ value: '9시', label: '오전 9시' }
];
return <Dropdown value={value} onChange={onChange} options={options} placeholder="학습 시간"/>;
};
const QuestionInput = ({ value, onChange }) => {
const options = [
{ value: '1개', label: '1개' },
{ value: '2개', label: '2개' },
{ value: '3개', label: '3개' },
{ value: '4개', label: '4개' },
{ value: '5개', label: '5개' }
];
return <Dropdown value={value} onChange={onChange} options={options} placeholder="문제 수"/>;
};




return (
<div className="bg-white rounded-lg shadow-lg p-7 mt-20 m-auto w-[450px]">
<div className="bg-white rounded-lg shadow-lg p-7 mt-20 m-auto w-[450px]">
<h1 className="text-2xl font-bold mb-6">학습 설정</h1>

{/* ✅ 선택된 카테고리가 정상적으로 렌더링되도록 설정 */}
<CategorySelector
selectedCategories={selectedCategories}
onSelect={handleCategorySelect}
Expand All @@ -98,4 +99,4 @@ export default function ModalComponent() {
</div>
</div>
);
}
}
43 changes: 43 additions & 0 deletions components/modal/modal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"use client";

import React, { useEffect } from "react";
import ModalComponent from "@/components/modal/modal-component";

const Modal = ({ isOpen, onClose, children }) => {
useEffect(() => {
const handleEsc = (event) => {
if (event.key === "Escape") {
onClose(); // ESC 키를 누르면 모달 닫기
}
};

if (isOpen) {
document.addEventListener("keydown", handleEsc);
}

return () => {
document.removeEventListener("keydown", handleEsc);
};
}, [isOpen, onClose]);

if (!isOpen) return null; // 모달이 닫혀있으면 렌더링 안 함

return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex justify-center items-center z-50">
{/* ✅ 모달 크기 자동 조절 + 스크롤 가능하도록 수정 */}
<div className="bg-white rounded-lg shadow-xl w-full max-w-lg max-h-[80vh] overflow-y-auto px-6 py-6 relative flex flex-col">
{/* ✅ 닫기 버튼 위치 조정 */}
<button
className="absolute top-3 right-3 text-gray-500 hover:text-gray-700"

>
</button>

<div className="w-full"><ModalComponent/></div>
</div>
</div>
);
};

export default Modal;

0 comments on commit c5acabf

Please sign in to comment.