Skip to content

Commit

Permalink
Merge branch 'main' into Feat/#1592-feat-전체일정-api
Browse files Browse the repository at this point in the history
  • Loading branch information
wwwlnyy committed Jan 8, 2025
2 parents 41d129b + 6987a5f commit 9e75ce0
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 153 deletions.
151 changes: 63 additions & 88 deletions components/takgu/Layout/MegaPhone.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useRouter } from 'next/router';
import { useState, useEffect, useRef } from 'react';
import { Virtuoso, VirtuosoHandle } from 'react-virtuoso';
import { useState, useEffect, useRef, forwardRef } from 'react';
import { Virtuoso, VirtuosoHandle, Components } from 'react-virtuoso';
import { Item } from 'types/takgu/itemTypes';
import useAxiosGet from 'hooks/useAxiosGet';
import useInterval from 'hooks/useInterval';
Expand All @@ -14,54 +14,13 @@ interface IMegaphoneContent {

type MegaphoneList = Array<IMegaphoneContent>;

// type MegaphoneContainerProps = {
// children: React.ReactNode;
// count: number;
// };

const adminContent: IMegaphoneContent = {
megaphoneId: 0,
content: '상점에서 아이템을 구매해서 확성기를 등록해보세요!(30자 제한)',
intraId: '관리자',
};

// export const MegaphoneContainer = ({
// children,
// count,
// }: MegaphoneContainerProps) => {
// const ref = useRef<HTMLDivElement>(null);
// const [selectedIndex, setSelectedIndex] = useState<number>(0);

// useInterval(() => {
// const nextIndex = (selectedIndex + 1) % count;
// setSelectedIndex(nextIndex);
// }, 4000);

// return (
// <div className={styles.rollingBanner}>
// <div
// className={styles.wrapper}
// style={{
// transition: 'all 1s ease-in-out',
// transform: `translateY(${selectedIndex * -100}%)`,
// }}
// ref={ref}
// >
// {children}
// </div>
// </div>
// );
// };

export const MegaphoneItem = ({ content, intraId }: IMegaphoneContent) => {
return (
<div className={styles.contentWrapper}>
<div className={styles.intraId}>{intraId}</div>
<div className={styles.content}>{content}</div>
</div>
);
};

// 메인 확성기 컴포넌트
const Megaphone = () => {
const [contents, setContents] = useState<MegaphoneList>([]);
const [itemList, setItemList] = useState<Item[]>([]);
Expand Down Expand Up @@ -127,60 +86,76 @@ const Megaphone = () => {
<div className={styles.wrapper}>
{!!megaphoneData && megaphoneData.length > 0 && (
<Virtuoso
className={styles.virtuoso}
totalCount={megaphoneData.length}
data={megaphoneData}
ref={virtuoso}
itemContent={(index) => (
<MegaphoneItem
content={megaphoneData[index].content}
intraId={megaphoneData[index].intraId}
/>
)}
itemContent={(_, data) => <MegaphoneItem {...data} />}
style={{ height: '100%' }}
components={{
Scroller: MegaphoneScroller,
}}
/>
)}
</div>
</div>
);
};

// return (
// <MegaphoneContainer count={megaphoneData.length}>
// {megaphoneData.map((content, idx) => (
// <MegaphoneItem
// content={content.content}
// intraId={content.intraId}
// key={idx}
// />
// ))}
// </MegaphoneContainer>
// );

// return contents.length > 0 ? (
// <MegaphoneContainer count={contents.length}>
// {contents.map((content, idx) => (
// <MegaphoneItem
// content={content.content}
// intraId={content.intraId}
// key={idx}
// />
// ))}
// </MegaphoneContainer>
// ) : (
// <MegaphoneContainer count={itemList.length + 1}>
// <MegaphoneItem
// content={adminContent.content}
// intraId={adminContent.intraId}
// />
// {itemList.map((item, idx) => (
// <MegaphoneItem
// content={item.itemName + ' : ' + item.mainContent}
// intraId={'절찬 판매 중!'}
// key={idx}
// />
// ))}
// </MegaphoneContainer>
// );
// 확성기 아이템 컴포넌트
export const MegaphoneItem = ({ content, intraId }: IMegaphoneContent) => {
return (
<div className={styles.contentWrapper}>
<div className={styles.intraId}>{intraId}</div>
<div className={styles.content}>{content}</div>
</div>
);
};

// 유저의 스크롤 이벤트 동작을 제거한 확성기 스크롤러 컴포넌트
const MegaphoneScroller: Components['Scroller'] = forwardRef(
({ children, ...props }, ref) => {
const localRef = useRef<HTMLDivElement | null>(null);

// 전달받은 ref와 내부 ref가 동일한 element를 가리키도록 함
const combinedRef = (node: HTMLDivElement | null) => {
localRef.current = node;

if (ref) {
(ref as React.MutableRefObject<HTMLDivElement | null>).current = node;
}
};

useEffect(() => {
const element = localRef.current;

if (element) {
const preventScroll = (e: Event) => {
e.preventDefault();
e.stopPropagation();
};

// wheel 및 touchmove 이벤트 차단 (pc 및 모바일)
element.addEventListener('wheel', preventScroll, { passive: false });
element.addEventListener('touchmove', preventScroll, {
passive: false,
});

// 컴포넌트 언마운트 시 이벤트 제거
return () => {
element.removeEventListener('wheel', preventScroll);
element.removeEventListener('touchmove', preventScroll);
};
}
}, []);

return (
<div ref={combinedRef} {...props}>
{children}
</div>
);
}
);

MegaphoneScroller.displayName = 'MegaphoneScroller';

export default Megaphone;
10 changes: 8 additions & 2 deletions components/takgu/game/GameResultList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,21 @@ interface GameResultListProps {
radioMode?: SeasonMode;
}

type pageType = 'main' | 'game' | 'profile';

const pageTypeMap: Record<string, pageType> = {
'/takgu': 'main',
'/takgu/game': 'game',
};

export default function GameResultList({
path,
radioMode,
}: GameResultListProps) {
const { data, status, fetchNextPage, isLast, clickedGameItem, pathName } =
useGameResultList(path);

const page =
pathName === '/' ? 'main' : pathName === '/game' ? 'game' : 'profile';
const page: pageType = pageTypeMap[pathName] || 'profile';

if (status === 'loading') return <GameResultEmptyItem status={status} />;

Expand Down
2 changes: 1 addition & 1 deletion components/takgu/mode/modeWraps/GameModeWrap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export default function GameModeWrap({
setRadioMode(e.target.value as SeasonMode);
};

const isGamePage = useRouter().pathname === '/game';
const isGamePage = useRouter().pathname === '/takgu/game';

return (
<div>
Expand Down
6 changes: 0 additions & 6 deletions styles/takgu/Layout/MegaPhone.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,3 @@ $bannerHeight: 3rem;
justify-content: center;
align-items: center;
}

.virtuoso {
// NOTE : 라이브러리에서 인라인 스타일로 overflow-y: auto를 주고 있어 스크롤바가 생김
// 이를 상쇄하기 위해서 !important를 사용함.
overflow-y: hidden !important;
}
77 changes: 21 additions & 56 deletions utils/axios.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import axios, { AxiosError } from 'axios';
import axios, { AxiosError, AxiosRequestConfig } from 'axios';

const baseURL = `${process.env.NEXT_PUBLIC_SERVER_ENDPOINT}`;
const manageBaseURL = process.env.NEXT_PUBLIC_MANAGE_SERVER_ENDPOINT ?? '/';
Expand All @@ -13,61 +13,10 @@ const instanceInPartyManage = axios.create({ baseURL: managePartyBaseURL });
const instanceInAgenda = axios.create({ baseURL: agendaBaseURL });
const instanceInCalendar = axios.create({ baseURL: calendarBaseURL });

instance.interceptors.request.use(
function setConfig(config) {
config.headers = {
'Content-Type': 'application/json',
Authorization: `Bearer ${localStorage.getItem('42gg-token')}`,
};
config.withCredentials = true;
return config;
},
function getError(error) {
return Promise.reject(error);
}
);

instanceInManage.interceptors.request.use(
function setConfig(config) {
config.headers = {
'Content-Type': 'application/json',
Authorization: `Bearer ${localStorage.getItem('42gg-token')}`,
};
config.withCredentials = true;
return config;
},
function getError(error) {
return Promise.reject(error);
}
);

instanceInPartyManage.interceptors.request.use(
function setConfig(config) {
config.headers = {
'Content-Type': 'application/json',
Authorization: `Bearer ${localStorage.getItem('42gg-token')}`,
};
config.withCredentials = true;
return config;
},
function getError(error) {
return Promise.reject(error);
}
);

instanceInAgenda.interceptors.request.use(
function setConfig(config) {
config.headers = {
'Content-Type': 'application/json',
Authorization: `Bearer ${localStorage.getItem('42gg-token')}`,
};
config.withCredentials = true;
return config;
},
function getError(error) {
return Promise.reject(error);
}
);
instance.interceptors.request.use(setConfig, getError);
instanceInManage.interceptors.request.use(setConfig, getError);
instanceInPartyManage.interceptors.request.use(setConfig, getError);
instanceInAgenda.interceptors.request.use(setConfig, getError);

instanceInCalendar.interceptors.request.use(
function setConfig(config) {
Expand Down Expand Up @@ -97,3 +46,19 @@ export {
instanceInCalendar,
isAxiosError,
};

function setConfig<T>(config: AxiosRequestConfig<T>) {
return {
...config,
headers: {
...config.headers,
'Content-Type': 'application/json',
Authorization: `Bearer ${localStorage.getItem('42gg-token') ?? ''}`,
withCredentials: true,
},
};
}

function getError(error: unknown) {
return Promise.reject(error);
}

0 comments on commit 9e75ce0

Please sign in to comment.