diff --git a/components/agenda/Form/AdminTeamForm.tsx b/components/agenda/Form/AdminTeamForm.tsx index abd4be503..868de14fc 100644 --- a/components/agenda/Form/AdminTeamForm.tsx +++ b/components/agenda/Form/AdminTeamForm.tsx @@ -2,7 +2,7 @@ import router from 'next/router'; import { useState } from 'react'; import { TeamDetailProps } from 'types/agenda/teamDetail/TeamDetailTypes'; import { transformTeamLocation } from 'utils/agenda/transformLocation'; -import { Coalition } from 'constants/agenda/agenda'; +import { Coalition, TeamStatus } from 'constants/agenda/agenda'; import Participant from 'components/agenda/agendaDetail/tabs/Participant'; import { AddElementBtn, CancelBtn } from 'components/agenda/button/Buttons'; import CheckBoxInput from 'components/agenda/Input/CheckboxInput'; @@ -18,7 +18,7 @@ interface AdminTeamFormProps { teamLocation: string; } -const AdminTeamFrom = ({ +const AdminTeamForm = ({ teamKey, teamData, teamLocation, @@ -27,18 +27,14 @@ const AdminTeamFrom = ({ const [teamMates, setTeamMates] = useState(teamData.teamMates); const transformFormData = (formData: FormData) => { - const data = JSON.parse(JSON.stringify(Object.fromEntries(formData))); - - data.teamIsPrivate = data.teamIsPrivate === 'on'; - - // 팀 위치 변환 - data.teamLocation = transformTeamLocation(data.teamLocation); - - // 트림 처리 - data.teamName = data.teamName.trim(); - data.teamContent = data.teamContent.trim(); // 추가 - - return data; + const data = Object.fromEntries(formData) as any; + return { + ...data, + teamIsPrivate: data.teamIsPrivate === 'on', + teamLocation: transformTeamLocation(data.teamLocation), + teamName: data.teamName.trim(), + teamContent: data.teamContent.trim(), + }; }; const handleDeleteParticipant = (index: number) => { @@ -50,12 +46,11 @@ const AdminTeamFrom = ({ }; const handleAddMember = () => { - const newMemberIdInput = document.getElementById( - 'newMemberId' - ) as HTMLInputElement; - const newMemberId = newMemberIdInput?.value.trim(); + const newMemberId = ( + document.getElementById('newMemberId') as HTMLInputElement + )?.value.trim(); - if (newMemberId === '') { + if (!newMemberId) { alert('intra ID를 입력해주세요.'); return; } @@ -67,40 +62,51 @@ const AdminTeamFrom = ({ ...prev, { intraId: newMemberId, coalition: Coalition.OTHER }, ]); - newMemberIdInput.value = ''; // 입력 필드 초기화 + (document.getElementById('newMemberId') as HTMLInputElement).value = ''; + }; + + const AddLeader = (e: React.ChangeEvent) => { + if ( + teamData.teamStatus === TeamStatus.CANCEL && + e.target.value !== TeamStatus.CANCEL + ) { + if ( + !teamMates.some( + (member) => member.intraId === teamData.teamLeaderIntraId + ) + ) { + setTeamMates((prev) => [ + { intraId: teamData.teamLeaderIntraId, coalition: Coalition.OTHER }, + ...prev, + ]); + } + } }; - const SubmitTeamForm = (target: React.FormEvent) => { - target.preventDefault(); + const SubmitTeamForm = (event: React.FormEvent) => { + event.preventDefault(); - const formData = new FormData(target.currentTarget); + const formData = new FormData(event.currentTarget); const data = transformFormData(formData); - if ( - data.teamName === '' || - data.teamContent === '' || - data.teamStatus === '' - ) { - alert('모든 항목을 입력해주세요.'); // 임시 + if (!data.teamName || !data.teamContent || !data.teamStatus) { + alert('모든 항목을 입력해주세요.'); return; } - data.teamKey = teamKey; - data.teamMates = teamMates; - data.teamAward = teamData.teamAward; - data.teamAwardPriority = teamData.teamAwardPriority; - sendRequest( 'PATCH', 'admin/team', - data, - {}, - (res: any) => { - router.back(); + { + ...data, + teamKey, + teamMates, + teamAward: teamData.teamAward, + teamAwardPriority: teamData.teamAwardPriority, }, - (err: string) => { - console.error(err); - } + {}, + () => router.back(), + (err: string) => console.error(err) ); }; @@ -111,6 +117,18 @@ const AdminTeamFrom = ({ className={styles.container} >
+ {teamData.teamStatus === TeamStatus.CANCEL ? ( +
+
+ 팀 상태 : CANCEL +
+
+ CANCEL 상태에서는 수정이 불가능합니다.{' '} + [ OPEN/CONFIM ]으로 팀 상태를 + 변경 후 이용해주세요. +
+
+ ) : null} { + AddLeader(e); + }} /> - {teamLocation === 'MIX' ? ( ) : ( @@ -148,7 +168,7 @@ const AdminTeamFrom = ({
상 이름 : {teamData.teamAward}
@@ -202,4 +222,4 @@ const AdminTeamFrom = ({ ); }; -export default AdminTeamFrom; +export default AdminTeamForm; diff --git a/components/agenda/Profile/CurrentList.tsx b/components/agenda/Profile/CurrentList.tsx index 6591eb7ea..c137c4f8f 100644 --- a/components/agenda/Profile/CurrentList.tsx +++ b/components/agenda/Profile/CurrentList.tsx @@ -11,8 +11,9 @@ const CurrentList = ({ isHost: boolean; }) => { const listTitle = isHost ? '개최중 아젠다' : '참여중 아젠다'; + const bottomMargin = isHost ? '' : styles.bottomMargin; return ( -
+
{listTitle}
diff --git a/components/agenda/agendaDetail/tabs/AgendaDescription.tsx b/components/agenda/agendaDetail/tabs/AgendaDescription.tsx index 9080fede9..fc7bf383f 100644 --- a/components/agenda/agendaDetail/tabs/AgendaDescription.tsx +++ b/components/agenda/agendaDetail/tabs/AgendaDescription.tsx @@ -35,6 +35,10 @@ export default function AgendaDescription({ agendaData }: AgendaProps) { {AgendaTags(agendaData)}
+
+

대회 설명

+ {agendaContent} +

모집 완료 기간

{formatDate(agendaDeadLine)} diff --git a/components/agenda/agendaDetail/tabs/Participant.tsx b/components/agenda/agendaDetail/tabs/Participant.tsx index 7486ee24c..6507273dc 100644 --- a/components/agenda/agendaDetail/tabs/Participant.tsx +++ b/components/agenda/agendaDetail/tabs/Participant.tsx @@ -1,3 +1,4 @@ +import Link from 'next/link'; import React from 'react'; import { ParticipantProps } from 'types/agenda/agendaDetail/tabs/participantTypes'; import { colorMapping, iconMapping } from 'types/agenda/utils/colorList'; @@ -18,13 +19,17 @@ export default function Participant({ const IconComponent = iconMapping[coalitionEnum[0]]; return ( -
-
-
{teamName}
- {IconComponent ? : ''} + +
+
+
{teamName}
+ {IconComponent ? : ''} +
-
+ ); } diff --git a/components/error/AgendaError.tsx b/components/error/AgendaError.tsx index f9064711f..52c57551c 100644 --- a/components/error/AgendaError.tsx +++ b/components/error/AgendaError.tsx @@ -1,7 +1,6 @@ import { useEffect } from 'react'; -import { useRecoilState, useResetRecoilState, useSetRecoilState } from 'recoil'; +import { useRecoilState, useResetRecoilState } from 'recoil'; import { agendaErrorState } from 'utils/recoil/agendaError'; -import { loginState } from 'utils/recoil/login'; import { modalState } from 'utils/recoil/takgu/modal'; import { useRouter } from 'next/router'; import useErrorPage from 'hooks/error/useErrorPage'; @@ -12,20 +11,10 @@ export default function ErrorPage() { const { goHome } = useErrorPage(); const [error, setError] = useRecoilState(agendaErrorState); const { msg, status } = error; - const setLoggedIn = useSetRecoilState(loginState); const resetModal = useResetRecoilState(modalState); const router = useRouter(); - if (status === 401) { - localStorage.removeItem('42gg-token'); - setLoggedIn(false); - } - const resetHandler = () => { - if (status === 401) { - localStorage.removeItem('42gg-token'); - setLoggedIn(false); - } setError({ msg: '', status: 0 }); goHome(); }; diff --git a/hooks/agenda/usePageNation.ts b/hooks/agenda/usePageNation.ts index c22888734..7afd1afff 100644 --- a/hooks/agenda/usePageNation.ts +++ b/hooks/agenda/usePageNation.ts @@ -27,45 +27,54 @@ const usePageNation = ({ const getData = useCallback( async (page: number, size: number) => { - const res = await instanceInAgenda.get(url, { params }); - const content = res.data.content ? res.data.content : []; - const totalSize = res.data.totalSize ? res.data.totalSize : 0; + const res = await instanceInAgenda.get(url, { + params: { ...params, page, size }, + }); + const content = res.data.content || []; + const totalSize = res.data.totalSize || 0; if (useIdx) { - res.data.content = res.data.content.map((c: T, idx: number) => { - const temp = c as T & { idx: number }; - temp.idx = idx + 1 + size * (page - 1); - return temp; + content.forEach((c: T, idx: number) => { + (c as T & { idx: number }).idx = idx + 1 + size * (page - 1); }); } - status.current = res.status; // 상태 업데이트 + status.current = res.status; return { totalSize, content }; }, [url, params, useIdx] ); + const fetchData = async () => { + const data = await getData(currentPage.current, size); + totalPages.current = Math.ceil(data.totalSize / size); + setContent(data.content); + }; + const pageChangeHandler = async (pageNumber: number) => { if (pageNumber < 1 || pageNumber > totalPages.current) return; - const res = await getData(pageNumber, size); currentPage.current = pageNumber; - setContent(res.content); + await fetchData(); }; useEffect(() => { - const fetchData = async () => { - const data = await getData(currentPage.current, size); - totalPages.current = Math.ceil(data.totalSize / size); - setContent(data.content); - }; - if ( - isReady == true && + isReady === true && (!status.current || Math.floor(status.current / 100) !== 2) ) { fetchData(); } - }, [getData, size, params]); // getData와 size에 의존 + }, [getData, size, params, isReady]); + + useEffect(() => { + currentPage.current = 1; + + setContent(null); + + if (isReady) { + fetchData(); + } + }, [url, isReady]); const PagaNationElementProps = { curPage: currentPage.current, diff --git a/pages/agenda/profile/user.tsx b/pages/agenda/profile/user.tsx index 65e76e0da..a23543aea 100644 --- a/pages/agenda/profile/user.tsx +++ b/pages/agenda/profile/user.tsx @@ -21,10 +21,11 @@ import styles from 'styles/agenda/Profile/AgendaProfile.module.scss'; const AgendaProfile = () => { const queryIntraId = useIntraId(); // 쿼리의 id const myIntraId = useUser()?.intraId; // 현재 나의 intraId - const [profileUrl, setProfileUrl] = useState('/profile'); const isMyProfile = useRef(false); // 내 프로필 페이지인지 아닌지 확인 const [isIntraId, setIsIntraId] = useState(false); // 인트라 아이디가 42에 있는지 확인 const [isAgendaId, setIsAgendaId] = useState(false); // 인트라 아이디가 agenda에 있는지 확인 + const [agendaProfileData, setAgendaProfileData] = + useState(null); // agendaProfileData 상태 추가 /** API GET */ // GET: intraData (42 인트라 데이터 가져오기) @@ -33,11 +34,12 @@ const AgendaProfile = () => { isReady: Boolean(queryIntraId), }); // GET: agendaProfileData (GG 아젠다 유저 데이터 가져오기) - const { data: agendaProfileData, getData: getAgendaProfileData } = + const { data: fetchedAgendaProfileData, getData: getAgendaProfileData } = useFetchGet({ - url: profileUrl, + url: `/profile/${queryIntraId}`, isReady: isIntraId, }); + // GET: host current const { content: hostCurrentListData, @@ -70,24 +72,26 @@ const AgendaProfile = () => { /** useEffect */ useEffect(() => { - // 1. queryIntraId와 myIntraId가 있을 때 프로필 URL 설정 - if (queryIntraId && myIntraId) { - if (queryIntraId === myIntraId) { - isMyProfile.current = true; + const updateProfileStatus = () => { + // 1. queryIntraId와 myIntraId가 있을 때 프로필 URL 설정 + isMyProfile.current = queryIntraId === myIntraId; + // 2. intraData가 있으면 인트라 아이디가 42에 있다는 뜻이므로 isIntraId = true + setIsIntraId(!!intraData); + // 3. agendaProfileData가 있으면 아젠다에 등록된 사용자이므로 isAgendaId = true + setIsAgendaId(!!fetchedAgendaProfileData); + if (isAgendaId) { + setAgendaProfileData(fetchedAgendaProfileData); } else { - isMyProfile.current = false; - setProfileUrl(`/profile/${queryIntraId}`); // 다른 유저 프로필 URL 설정 + setAgendaProfileData(null); // fetchedAgendaProfileData가 없을 때 초기화 } - } - // 2. intraData가 있으면 인트라 아이디가 42에 있다는 뜻이므로 isIntraId = true - if (intraData) { - setIsIntraId(true); - } - // 3. agendaProfileData가 있으면 아젠다에 등록된 사용자이므로 isAgendaId = true - if (agendaProfileData) { - setIsAgendaId(true); - } - }, [queryIntraId, myIntraId, intraData, agendaProfileData]); + }; + updateProfileStatus(); + }, [queryIntraId, intraData, fetchedAgendaProfileData]); + + useEffect(() => { + setIsIntraId(false); + setIsAgendaId(false); + }, [queryIntraId]); /** UI Rendering */ if (!queryIntraId || !myIntraId) { diff --git a/pages/agenda/ticket/history.tsx b/pages/agenda/ticket/history.tsx index 1e32e34ad..b38bbff7f 100644 --- a/pages/agenda/ticket/history.tsx +++ b/pages/agenda/ticket/history.tsx @@ -10,6 +10,7 @@ const TicketHistoryPage = () => { url: '/ticket/history', size: size, useIdx: true, + isReady: true, } ); diff --git a/styles/agenda/Home/AgendaInfo.module.scss b/styles/agenda/Home/AgendaInfo.module.scss index 92732a29b..0d8cfaaf0 100644 --- a/styles/agenda/Home/AgendaInfo.module.scss +++ b/styles/agenda/Home/AgendaInfo.module.scss @@ -28,7 +28,7 @@ display: flex; width: 100%; height: max-content; - align-items: center; + align-items: flex-start; gap: 1.5rem; justify-content: space-between; @include text(description); diff --git a/styles/agenda/Home/AgendaList.module.scss b/styles/agenda/Home/AgendaList.module.scss index 4a401e17f..456f463b4 100644 --- a/styles/agenda/Home/AgendaList.module.scss +++ b/styles/agenda/Home/AgendaList.module.scss @@ -29,12 +29,13 @@ justify-content: space-between; align-items: center; > h2 { - margin: 0.5rem; + margin: 1rem; @include text(sub-menu); } > div { + max-width: 15rem; height: max-content; - margin-right: 0.5rem; + margin-right: 1rem; color: var(--text-color); } } diff --git a/styles/agenda/Layout/Layout.module.scss b/styles/agenda/Layout/Layout.module.scss index ba0d5c09f..3d2873246 100644 --- a/styles/agenda/Layout/Layout.module.scss +++ b/styles/agenda/Layout/Layout.module.scss @@ -22,6 +22,8 @@ position: fixed; right: 2rem; bottom: 2rem; + + display: flex; width: 2.5rem; height: 2.5rem; font-size: var(--font-size-xl); @@ -33,6 +35,8 @@ border-radius: $radius-circle; box-shadow: var(--box-shadow-light); transition: background-color 0.3s; + align-items: center; + justify-content: center; &:hover { width: 3rem; diff --git a/styles/agenda/Profile/AgendaProfile.module.scss b/styles/agenda/Profile/AgendaProfile.module.scss index 690cb01df..ae0f09802 100644 --- a/styles/agenda/Profile/AgendaProfile.module.scss +++ b/styles/agenda/Profile/AgendaProfile.module.scss @@ -6,7 +6,7 @@ justify-content: flex-start; align-items: center; padding: 1rem; - gap: 1.5rem; + gap: 1rem; } .agendaUserSearchBarWrap { diff --git a/styles/agenda/Profile/CurrentList.module.scss b/styles/agenda/Profile/CurrentList.module.scss index d8c43fa22..0222bba56 100644 --- a/styles/agenda/Profile/CurrentList.module.scss +++ b/styles/agenda/Profile/CurrentList.module.scss @@ -11,6 +11,9 @@ border-radius: $radius-big; box-shadow: var(--default-box-shadow); gap: 1rem; + &.bottomMargin { + margin-bottom: 1rem; + } } .currentListTitle { @@ -22,7 +25,7 @@ width: 100%; height: 100%; flex-direction: column; - gap: 0.5rem; + gap: 0.7rem; } .currentTeamEmpty { diff --git a/styles/agenda/Profile/HistoryList.module.scss b/styles/agenda/Profile/HistoryList.module.scss index 0a3adee78..be6e11aa9 100644 --- a/styles/agenda/Profile/HistoryList.module.scss +++ b/styles/agenda/Profile/HistoryList.module.scss @@ -4,7 +4,7 @@ display: flex; width: 22rem; height: auto; - max-height: 32rem; + max-height: 34rem; flex-direction: column; padding: 1rem 1.5rem; background-color: var(--box-bg-2); @@ -22,7 +22,7 @@ width: 100%; height: 100%; flex-direction: column; - gap: 0.5rem; + gap: 0.7rem; } .historyEmpty { diff --git a/styles/agenda/Profile/ProfileCard.module.scss b/styles/agenda/Profile/ProfileCard.module.scss index 86c76c85a..de91d199d 100644 --- a/styles/agenda/Profile/ProfileCard.module.scss +++ b/styles/agenda/Profile/ProfileCard.module.scss @@ -4,6 +4,7 @@ width: 22rem; height: 31rem; perspective: 1000px; + margin-bottom: 1rem; } .cardInner { diff --git a/styles/agenda/agendaDetail/AgendaDetail.module.scss b/styles/agenda/agendaDetail/AgendaDetail.module.scss index e91672a22..b898ca251 100644 --- a/styles/agenda/agendaDetail/AgendaDetail.module.scss +++ b/styles/agenda/agendaDetail/AgendaDetail.module.scss @@ -10,7 +10,7 @@ @include pageContainer; max-width: 100%; height: 100%; - padding: 0 2rem; + padding: 0 1rem; } .headWrapper { // @include gridHidden(web); diff --git a/styles/agenda/agendaDetail/tabs/AgendaDescription.module.scss b/styles/agenda/agendaDetail/tabs/AgendaDescription.module.scss index 99ee8c820..5f3fd4da4 100644 --- a/styles/agenda/agendaDetail/tabs/AgendaDescription.module.scss +++ b/styles/agenda/agendaDetail/tabs/AgendaDescription.module.scss @@ -72,7 +72,7 @@ p { margin: 0; } - @media screen and (max-width: 481px) { + @media screen and (max-width: 520px) { flex-direction: column; } } diff --git a/styles/agenda/utils/AgendaTag.module.scss b/styles/agenda/utils/AgendaTag.module.scss index d3ebf8d22..cc6696ed6 100644 --- a/styles/agenda/utils/AgendaTag.module.scss +++ b/styles/agenda/utils/AgendaTag.module.scss @@ -1,8 +1,10 @@ -@import '../common.scss'; +@import 'styles/agenda/common.scss'; .agendaItemTagBox { display: flex; gap: 0.3rem; + max-width: 18rem; + flex-wrap: wrap; } $tags: ( @@ -38,7 +40,7 @@ $tags: ( width: max-content; min-width: 3.3rem; height: 1.2rem; - padding: 0.2rem 0.5rem; + padding: 0.2rem 0.3rem; background-color: var(--box-bg-2-light); border-radius: $radius-medium;