diff --git a/src/components/calendar/addModal.js b/src/components/calendar/addModal.js index ba3e188e45258ae7f076269209eec71a82f821d3..91a1531203dec5f48d4e2ed4bca0b0842eb39e53 100644 --- a/src/components/calendar/addModal.js +++ b/src/components/calendar/addModal.js @@ -41,12 +41,13 @@ const ScheduleAddModal = ({ isOpen, onClose, onSave }) => { } } + const isSameTime =formData.startHour === formData.endHour && formData.startMinute === formData.endMinute; if (isSameTime) { isValid = false; alert('시작 시간과 종료 시간은 같을 수 없습니다.'); } - + if (formData.repeatPeriod === '' || isNaN(formData.repeatPeriod) || formData.repeatPeriod <= 0) { isValid = false; errors.repeatPeriod = "반복 주기는 1 이상의 숫자여야 합니다."; diff --git a/src/components/calendar/calendar.js b/src/components/calendar/calendar.js index 7fabe2528dcab0fbf08eebd8411451f707432654..89732028ac7a4f532e346e3b19cb7a65972e18b4 100644 --- a/src/components/calendar/calendar.js +++ b/src/components/calendar/calendar.js @@ -102,6 +102,10 @@ const MySchedulerApp = () => { }; const handleSaveEvent = async(formData) => { try{ + if (formData.endTime < formData.startTime) { + alert('종료 시간은 시작 시간보다 늦어야 합니다.'); + return; + } const jsonData=JSON.stringify(formData); console.log('Sending data to the server:', jsonData); fetch('api/schedules', { diff --git a/src/components/channel/channel.js b/src/components/channel/channel.js index c8f52cf0300b73b84acedd7a2f357243a6fe1439..1e65c49540bb173f940d6f956cb9daaff2c24305 100644 --- a/src/components/channel/channel.js +++ b/src/components/channel/channel.js @@ -11,50 +11,7 @@ const Channel=({data})=>{ const toggleSubscribe=()=>{ setSubscribeState(!subscribeState); } - const exampleData={"recruits": [ - { - "id": 2, - "title": "[방탈출]홍대 거상 2인구합니다", - "content": "나이, 성별 상관없습니다. 즐겁게 하실 분 구해요~", - "peopleNum": 4, - "participateNum": 1, - "regionFirst": "강원도", - "regionSecond": "양양군", - "startDate": "2023-10-17", - "endDate": "2023-12-31", - "timeCategory": "D", - "startTime": "13:00:00", - "endTime": "16:00:00", - "state": "Recruiting", - "Writer": { - "id":"jojojo", - "nickname":"jk" - }, - "participants":[1,3,323,108], - "imagePath": "uploads/recruits/default.jpg" - }, - { - "id": 2, - "title": "[방탈출]홍대 거상 2인구합니다", - "content": "나이, 성별 상관없습니다. 즐겁게 하실 분 구해요~", - "peopleNum": 4, - "participateNum": 1, - "regionFirst": "강원도", - "regionSecond": "양양군", - "startDate": "2023-10-17", - "endDate": "2023-12-31", - "timeCategory": "D", - "startTime": "13:00:00", - "endTime": "16:00:00", - "state": "Recruiting", - "Writer": { - "id":"jojojo", - "nickname":"jk" - }, - "participants":[1,3,323,108], - "imagePath": "uploads/recruits/default.jpg" - } - ]} + const handleClick=(e)=>{ const target=e.target.innerText; console.log(target); @@ -128,7 +85,7 @@ function handleSubscribe() { <div className={channel_styles.channelTitle}>{data.data.title}</div> <div className={channel_styles.info}>구독자 {data.data.followerNum}명 모집글{data.data.recruitNum}개</div> <div className={channel_styles.description}>{data.data.content}</div> - <button onClick={handleSubscribe}>{subscribeState ? '구독 취소' : '구독중'}</button> + <button onClick={handleSubscribe}>구독</button> </div> )} </div> diff --git a/src/components/channel/channelList.js b/src/components/channel/channelList.js index 3f5cb46accbe7f8fd3d64461e40ce88b7c20730b..162bb02db514fc0f9a71922c841d57329b0628ae 100644 --- a/src/components/channel/channelList.js +++ b/src/components/channel/channelList.js @@ -17,7 +17,7 @@ function ChannelItem(props){ function handleClick() { try { // 아래 URL을 실제 사용하는 API 엔드포인트로 변경하세요. - const apiUrl = `/api/channels/${props.userID}`; + const apiUrl = `/api/channels/${props.props.id}`; openModal(); fetch(apiUrl, { method: 'GET', @@ -45,19 +45,7 @@ function ChannelItem(props){ } catch (error) { console.error('Error:', error); } - } - // const props = - - - // { - // "userID": 5, - // "nickname":"liel", - // "title": "채널명", - // "content": "소개글", - // "imagePath": "uploads/recruits/default.jpg", - // } - - + } return ( <div className={channelListStyles.flex}> @@ -65,7 +53,7 @@ function ChannelItem(props){ <span className={channelListStyles.channel}> <div className={channelListStyles.container} onClick={handleClick}> <div className={channelListStyles.imgContainer}> - {props.thumbnailImgPath ? (<img className={channelListStyles.img} src={props.thumbnailImgPath} alt='recruit img' />) : (<img src={props.thumbnailImgPath} />)} + <img className={channelListStyles.img} src={props.props.thumbnailImgPath} alt='recruit img' /> </div> <div className={channelListStyles.mouseover}> <p className={channelListStyles.content}> @@ -91,7 +79,8 @@ function ChannelList(){ <div className={channelListStyles.RecruitList}> <InfiniteScroll pagename='channels' queryString1="" - queryString2="" /> + queryString2="" + min="minDate" /> </div> ) } diff --git a/src/components/channel/iconModal.module.css b/src/components/channel/iconModal.module.css index 013b7f894cff3064a2ee07fdfbad62206fa12b8b..8c1138fa576bc81d71d87a2dd8cb7b1d03a9834d 100644 --- a/src/components/channel/iconModal.module.css +++ b/src/components/channel/iconModal.module.css @@ -26,10 +26,16 @@ .profile_image { - width:150px; + display: flex; + justify-content: center; + align-items: center; + width: 150px; height: 150px; - overflow: hidden; border-radius: 50%; + margin-bottom: 10px; + margin-top:5%; + margin-left:30% + } /* .profile_image img { diff --git a/src/components/channel/pictureModal.module.css b/src/components/channel/pictureModal.module.css index ba84512f28a972e6c102f70a85bd8e3c12997fdc..1ae06e251d77814796ee5487dc1dd35163b80b83 100644 --- a/src/components/channel/pictureModal.module.css +++ b/src/components/channel/pictureModal.module.css @@ -26,10 +26,14 @@ .profile_image { - width:200px; + display: flex; + justify-content: center; + align-items: center; + width: 200px; height: 150px; - overflow: hidden; - border-radius: 50%; + margin-bottom: 10px; + margin-top:5%; + margin-left:23% } /* .profile_image img { diff --git a/src/components/infiniteScroll.js b/src/components/infiniteScroll.js index c4def3c636343d13375a22bfd8f901580d637d4d..e0a447360effbcf33ccc2a3f97973fd191121710 100644 --- a/src/components/infiniteScroll.js +++ b/src/components/infiniteScroll.js @@ -2,26 +2,27 @@ import React, { useState, useEffect } from 'react'; import {PageItem} from "./recruit/recruitList"; import InfiniteScrollStyles from './infiniteScroll.module.css' import {ChannelItem} from "./channel/channelList"; -import { json } from 'react-router-dom'; function InfiniteScroll(props){ const [items, setItems] = useState([]); const [minId, setMinId] = useState(0); - const [midDate, setMinDate]=useState(''); + const [minDate, setMinDate] = useState(''); const [isLoading, setIsLoading] = useState(false); + const [search, setSearch] =useState([]); + const page = props.pagename; const queryString1 = props.queryString1; const queryString2 = props.queryString2; + const min = props.min; const initialFetchData = async ()=>{ try{ const response = await fetch(`/api/${page}${queryString1}`); const jsonData = await response.json(); - - const newData = jsonData[page]; - setMinId(jsonData['minId']); - setMinDate(jsonData['minDate']); + if(page==='channels'){ + setMinDate(jsonData['minDate']); + const newData = jsonData[page]; if (newData.length > 0) { const components = []; for (let i = 0; i < newData.length; i += 2) { @@ -35,21 +36,31 @@ function InfiniteScroll(props){ ); components.push(component); - console.log('ne', newData[i]); } setItems((prevItem) => [...prevItem, ...components]); } - }else { - + }else if(page === 'recruits'){ + setMinId(jsonData['minId']); + const newData = jsonData[page]; if(newData.length > 0) { const components = newData.map((item) => ( <PageItem data={item}/> )); - + setItems(prevItem => [...prevItem, ...components]); } - console.log(`/api/${page}${queryString1}`); - } + } else{ + setMinId(jsonData['minId']); + const newData = jsonData['recruits']; + if(newData.length > 0) { + const components = newData.map((item) => ( + <PageItem data={item}/> + )); + + setSearch([]); + setSearch(prevItem => [...prevItem, ...components]); + } + } } catch(error){ console.log('Error during fetch:', error); @@ -58,24 +69,20 @@ function InfiniteScroll(props){ useEffect(() => { initialFetchData(); // 최초 렌더링 시에 데이터 가져오기 - console.log(`/api/${page}${queryString1}`); }, [page, queryString1, queryString2]); const fetchData = async ()=>{ - if (isLoading || minId === 0) return; + if (isLoading || minId === 0 || minDate === null) return; setIsLoading(true); - try{ - const response = await fetch(`/api/${page}?minId=${minId}${queryString2}`); - console.log(`/api/${page}?minId=${minId}${queryString2}`); - const jsonData = await response.json(); - - const newData = jsonData[page]; - setMinId(jsonData['minId']); + try{ if(page==='channels'){ - + const response = await fetch(`/api/${page}?${min}=${minDate}${queryString2}`); + const jsonData = await response.json(); + setMinDate(jsonData['minDate']); + const newData = jsonData[page]; if (newData.length > 0) { const components = []; for (let i = 0; i < newData.length; i += 2) { @@ -93,8 +100,11 @@ function InfiniteScroll(props){ } setItems((prevItem) => [...prevItem, ...components]); } - }else { - + }else if(page==='recruits'){ + const response = await fetch(`/api/${page}?${min}=${minId}${queryString2}`); + const jsonData = await response.json(); + setMinId(jsonData['minId']); + const newData = jsonData[page]; if(newData.length > 0) { const components = newData.map((item) => ( <PageItem data={item}/> @@ -102,7 +112,19 @@ function InfiniteScroll(props){ setItems(prevItem => [...prevItem, ...components]); } - } + } else{ + const response = await fetch(`/api/${page}?${min}=${minId}${queryString2}`); + const jsonData = await response.json(); + setMinId(jsonData['minId']); + const newData = jsonData["recruits"]; + if(newData.length > 0) { + const components = newData.map((item) => ( + <PageItem data={item}/> + )); + + setSearch(prevItem => [...prevItem, ...components]); + } + } } catch(error){ console.log('Error during fetch:', error); @@ -135,7 +157,11 @@ function InfiniteScroll(props){ return ( <div className="itemList"> - {items} + {page === "recruits" || page === "channels" ?( + items + ):( + search + )} {/* 로딩 중일 때 로딩 표시 */} {isLoading && <div className={InfiniteScrollStyles.loading}>Loading...</div>} diff --git a/src/components/mainAside.module.css b/src/components/mainAside.module.css index 8a7f79dc1d897e40f71a1b7a6d3182304556124a..785107d4569aa0f9297f0c379a0949fe52f79695 100644 --- a/src/components/mainAside.module.css +++ b/src/components/mainAside.module.css @@ -53,7 +53,9 @@ .noticeContent{ display: grid; grid-template-columns: 1fr; /* 한 개의 열 */ - height: auto; + + width: 300px; + height: 100px; border: 2px solid #d6d6d6; border-radius: 3px; } diff --git a/src/components/mypage/my_editModal.js b/src/components/mypage/my_editModal.js index 139762616553ec0f43b829d4aece9a395039dd0c..a06c7faa9acfd8da764c126ae253081344e0fad8 100644 --- a/src/components/mypage/my_editModal.js +++ b/src/components/mypage/my_editModal.js @@ -1,28 +1,32 @@ -import React, { useState } from 'react'; +import React, { useState ,useContext, useEffect} from 'react'; import editmodal_styles from './my_editModal.module.css'; - +import { AuthContext } from '../../App'; const MypageEdittModal=({ isOpen, closeModal, onSave, user})=> { const [image, setImage] = useState(null); const [nickname, setNickname] = useState(''); const [statusMessage, setStatusMessage] = useState(''); const [isNicknameAvailable, setIsNicknameAvailable] = useState(false); + const { userData, setUserData } = useContext(AuthContext); const handleImageChange = (e) => { const selectedImage = e.target.files[0]; setImage(selectedImage); }; - + const handleSave = () => { if (!isNicknameAvailable) { alert('닉네임 중복 확인을 해주세요.'); return; } onSave({ image, nickname, statusMessage }); + setUserData({ ...userData, nickname, statusMessage }); + setIsNicknameAvailable(false); closeModal(); }; const handlecheckBtn = async ()=>{ try{ const response = await fetch(`/api/users/nickname/${nickname}`); const data = await response.json(); + if (response.status === 200){ alert(data.message); diff --git a/src/components/mypage/my_group.js b/src/components/mypage/my_group.js index d05fe0cb24d6e3ca7ac166b91a27c1f5f464df32..ffca5290f24f267e081bb465b0ca50d1a70132c2 100644 --- a/src/components/mypage/my_group.js +++ b/src/components/mypage/my_group.js @@ -13,7 +13,7 @@ const MypagegroupModal=({ isOpen,closeModal})=> { if (!response.ok) { // 서버에서 에러 응답이 온 경우 처리합니다. const errorData = await response.json(); - throw new Error(`회원탈퇴 실패: ${errorData.message}`); + throw new Error(`조회 실패: ${errorData.message}`); } // 성공적으로 처리된 경우, 추가적인 로직을 작성할 수 있습니다. diff --git a/src/components/mypage/mywritingModal.js b/src/components/mypage/mywritingModal.js index 96adef2607c8e03e8435fb0253d3a98924b65f6e..03338560dc069d381fd8b22b877efe5705c667dc 100644 --- a/src/components/mypage/mywritingModal.js +++ b/src/components/mypage/mywritingModal.js @@ -15,7 +15,7 @@ const MywritingModal=({ isOpen,closeModal})=> { if (!response.ok) { // 서버에서 에러 응답이 온 경우 처리합니다. const errorData = await response.json(); - throw new Error(`회원탈퇴 실패: ${errorData.message}`); + throw new Error(`조회 실패: ${errorData.message}`); } // 성공적으로 처리된 경우, 추가적인 로직을 작성할 수 있습니다. diff --git a/src/components/mypage/quit.module.css b/src/components/mypage/quit.module.css deleted file mode 100644 index 4d9199203c64e581d83b531b2f1cc904c3ac297d..0000000000000000000000000000000000000000 --- a/src/components/mypage/quit.module.css +++ /dev/null @@ -1,68 +0,0 @@ -/* Modal.css */ - - -.quitmodal{ - display: none; - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: rgba(0, 0, 0, 0.5); /* 반투명한 배경 */ - justify-content: center; - align-items: center; - z-index: 1000; -} - -.quitmodal.open{ - display: flex; - z-index: 1000; - - -} -.qumodal_overlay { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: rgba(0, 0, 0, 0.5); - display: flex; - align-items: center; - justify-content: center; - z-index:1000; - -} - -.qumodal { - background: #fff; - width: 300px; - padding: 20px; - border-radius: 8px; - box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); - text-align: center; - z-index:1000; - -} - -.qumodal p { - margin-bottom: 20px; -} - -.qumodal button { - cursor: pointer; - padding: 10px 20px; - background-color: #9FB8AB; - color: #fff; - border: none; - border-radius: 5px; - margin-right: 10px; - border: none; - border-radius: 5px; - box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2); /* 그림자 추가 */ - transition: background-color 0.3s, color 0.3s, transform 0.3s; -} - - - -/* Header.js에서 Modal 컴포넌트 사용 시에는 .modal-overlay 스타일을 포함해야 합니다. */ diff --git a/src/components/mypage/quitModal.js b/src/components/mypage/quitModal.js deleted file mode 100644 index ec44ff9ca8d88ca8a548734c0b9cc95df8793c47..0000000000000000000000000000000000000000 --- a/src/components/mypage/quitModal.js +++ /dev/null @@ -1,24 +0,0 @@ -import React, {useState} from 'react'; -import { useNavigate } from 'react-router-dom'; -import quit_styles from "./quit.module.css" - - -const MyQuitModal=({modalOpen, closeModal, handleDeleteAccount})=>{ - return( - <div className={`${quit_styles.quitmodal} ${modalOpen ? quit_styles.open : ''}`}> - - - <div className={quit_styles.qumodal_overlay}> - <div className={quit_styles.qumodal}> - <p>정말 탈퇴하시겠습니까?</p> - <button onClick={handleDeleteAccount}>탈퇴</button> - <button onClick={closeModal}>취소</button> - </div> - </div> - - - </div> - ) -} -export default MyQuitModal; - diff --git a/src/pages/login.module.css b/src/pages/login.module.css index 067947a4b02566fb51c0ec0b0d2e9a8bda066000..98a429717a9030b244d3368ca66f2b0baccd59dd 100644 --- a/src/pages/login.module.css +++ b/src/pages/login.module.css @@ -120,3 +120,6 @@ } +.loginText{ + cursor: pointer; +} diff --git a/src/pages/mypage.js b/src/pages/mypage.js index aa5fb6e3e92b0a4df06552759919c43d00797dd0..a18fe7444a9a7138932f6a13dc7f35fc35dfd4e7 100644 --- a/src/pages/mypage.js +++ b/src/pages/mypage.js @@ -4,9 +4,7 @@ import Header from '../components/Header' import MypageEdittModal from '../components/mypage/my_editModal'; import MypageInfoModal from '../components/mypage/my_infoModal'; import MypagegroupModal from '../components/mypage/my_group'; -import MyQuitModal from '../components/mypage/quitModal'; import MywritingModal from '../components/mypage/mywritingModal'; -import { useRouteLoaderData } from 'react-router-dom'; import { AuthContext } from '../App'; const Mypage=()=>{ const [isEditModal, setIsEditModal]=useState(false); @@ -16,7 +14,6 @@ const Mypage=()=>{ const [isInfoModal, setIsinfoModal]=useState(false); const [isMygroup, setIsmygroup]=useState(false); const { userData } = useContext(AuthContext); - const [quitModalOpen, setQuitModalOpen] = useState(false); const [isProcessing, setProcessing] = useState(false); const [isMywriting, setIsmyWriting]=useState(false); const [channelList, setChannelList]=useState([]); @@ -39,12 +36,6 @@ const Mypage=()=>{ const closeMygroup=()=>{ setIsmygroup(false); } - const openQuitModal=()=>{ - setQuitModalOpen(true); - } - const closeQuitModal=()=>{ - setQuitModalOpen(false); - } const toggleChannelList = () => { setIsChannelListOpen(!isChannelListOpen); }; @@ -108,7 +99,7 @@ const Mypage=()=>{ }); if (!response.ok) { const errorData = await response.json(); - throw new Error(`회원탈퇴 실패: ${errorData.message}`); + throw new Error(`실패: ${errorData.message}`); }