-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
[Feat] left pages #1484
- Loading branch information
Showing
21 changed files
with
737 additions
and
130 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import Link from 'next/link'; | ||
import { instanceInAgenda } from 'utils/axios'; | ||
import useFetchGet from 'hooks/agenda/useFetchGet'; | ||
import styles from 'styles/agenda/Ticket/Ticket.module.scss'; | ||
interface TicketProps { | ||
ticketCount: number; | ||
setupTicket: boolean; | ||
} | ||
|
||
const Ticket = ({ type }: { type: string }) => { | ||
const { data } = useFetchGet<TicketProps>('/ticket'); | ||
return type === 'page' ? ( | ||
<div className={styles.container}> | ||
<h1 className={styles.h1}>내 티켓</h1> | ||
<div className={styles.ticketSection}> | ||
<div className={styles.ticketFrame}> | ||
<h1>{data && data.ticketCount}</h1> | ||
</div> | ||
<h1>개</h1> | ||
</div> | ||
<div className={styles.section}> | ||
<h3>발급 방법</h3> | ||
<div className={styles.line} /> | ||
<p>발급 시작 누르기</p> | ||
<div className={styles.arrowDown} /> | ||
<p> | ||
평가 포인트 기부하기 | ||
<br /> | ||
{`(최대 2개까지 반영)`} | ||
</p> | ||
<div className={styles.arrowDown} /> | ||
<p>현재 페이지로 돌아와 발급완료 누르기</p> | ||
</div> | ||
{data && data.setupTicket ? ( | ||
<button | ||
className={styles.submitButton} | ||
onClick={() => { | ||
instanceInAgenda.patch('/ticket').then((res) => { | ||
console.log(res); | ||
}); | ||
}} | ||
> | ||
발급 완료 | ||
</button> | ||
) : ( | ||
<button | ||
className={styles.submitButton} | ||
onClick={() => { | ||
instanceInAgenda.post('/ticket').then(() => { | ||
alert('티켓 발급 시작'); | ||
location.href = 'https://profile.intra.42.fr/'; | ||
}); | ||
}} | ||
> | ||
발급 시작 | ||
</button> | ||
)} | ||
<Link href='/agenda/ticket/history' style={{ width: '100%' }}> | ||
<button className={styles.logButton}>내역 보기</button> | ||
</Link> | ||
</div> | ||
) : ( | ||
<div className={styles.container}> | ||
<h1 className={styles.h1}>내 티켓</h1> | ||
<div | ||
className={styles.ticketSection} | ||
style={{ gap: '2rem', alignItems: 'center' }} | ||
> | ||
<Link href='/agenda/ticket'> | ||
<button className={styles.submitButton}>발급하러가기</button> | ||
</Link> | ||
<div className={styles.ticketSection}> | ||
<div className={styles.ticketFrame}> | ||
<h1>{data && data.ticketCount}</h1> | ||
</div> | ||
<h1>개</h1> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default Ticket; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { | ||
TableCell, | ||
TableRow, | ||
Table, | ||
TableHead, | ||
TableBody, | ||
} from '@mui/material'; | ||
import { TicketHistoryProps } from 'types/aganda/ticketTypes'; | ||
import styles from 'styles/agenda/Ticket/Ticket.module.scss'; | ||
|
||
const TicketHistory = ({ data }: { data: TicketHistoryProps[] | null }) => { | ||
return ( | ||
<div className={styles.container}> | ||
<h1 className={styles.h1}>티켓 발급 내역</h1> | ||
<Table sx={{ minWidth: 340 }} aria-label='simple table'> | ||
<TableHead> | ||
<TableRow> | ||
<TableCell>idx</TableCell> | ||
<TableCell align='center'>발급요청일</TableCell> | ||
<TableCell align='center'>승인여부</TableCell> | ||
<TableCell align='center'>승인일</TableCell> | ||
<TableCell align='center'>사용여부</TableCell> | ||
<TableCell align='center'>사용처</TableCell> | ||
</TableRow> | ||
</TableHead> | ||
<TableBody> | ||
{data && | ||
data.map((d, index) => { | ||
return ( | ||
<TableRow | ||
key={index} | ||
sx={{ '&:last-child td, &:last-child th': { border: 0 } }} | ||
> | ||
<TableCell component='th' scope='row'> | ||
{d.idx} | ||
</TableCell> | ||
<TableCell align='center'>{d.createdAt}</TableCell> | ||
<TableCell align='center'> | ||
{d.approved ? '✔︎' : '✕'} | ||
</TableCell> | ||
<TableCell align='center'>{d.approvedAt}</TableCell> | ||
<TableCell align='center'>{d.isUsed ? '✔︎' : '✕'}</TableCell> | ||
<TableCell align='center'> | ||
{d.usedAt ? d.usedAt : ''} | ||
</TableCell> | ||
</TableRow> | ||
); | ||
})} | ||
</TableBody> | ||
</Table> | ||
</div> | ||
); | ||
}; | ||
|
||
export default TicketHistory; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
import { useEffect, useState } from 'react'; | ||
import { AgendaDataProps } from 'types/agenda/agendaDetail/agendaTypes'; | ||
import { instanceInAgenda } from 'utils/axios'; | ||
import styles from 'styles/agenda/utils/PageController.module.scss'; | ||
import AgendaInfo from '../Home/AgendaInfo'; | ||
|
||
interface PageControllerNavigatorProps { | ||
currentPage: number; | ||
maxPage: number; | ||
onClick: (page: number) => void; | ||
} | ||
|
||
const PageControllerNavigator = ({ | ||
currentPage, | ||
maxPage, | ||
onClick, | ||
}: PageControllerNavigatorProps) => { | ||
const buttons = []; | ||
for (let i = 0; i < maxPage; i++) { | ||
if (i === currentPage) | ||
buttons.push( | ||
<button key={i} onClick={() => onClick(i)} className={styles.current} /> | ||
); | ||
else | ||
buttons.push( | ||
<button key={i} onClick={() => onClick(i)} className={styles.rest} /> | ||
); | ||
} | ||
return ( | ||
<div className={styles.navContainer}>{buttons.map((button) => button)}</div> | ||
); | ||
}; | ||
|
||
const PageController = ({ | ||
handleNavigation, | ||
}: { | ||
handleNavigation: (path: string) => void; | ||
}) => { | ||
const [current, setCurrent] = useState(0); | ||
const [data, setData] = useState<AgendaDataProps[]>([]); | ||
const max = data.length; | ||
|
||
const fetchAgendaList = async () => { | ||
const url = '/list'; | ||
const data = await instanceInAgenda | ||
.get(url) | ||
.then((res) => { | ||
return res.data; | ||
}) | ||
.catch((error) => { | ||
if (error.view === 403) return []; | ||
else return []; // 에러처리 필요 ERROR | ||
}); | ||
return data; | ||
}; | ||
|
||
useEffect(() => { | ||
fetchAgendaList().then((data) => { | ||
setData(data); | ||
}); | ||
}, []); | ||
useEffect(() => { | ||
const interval = setInterval(moveNext, 2000); | ||
return () => clearInterval(interval); | ||
}); | ||
|
||
function moveNext() { | ||
setCurrent(current + 1 < max ? current + 1 : 0); | ||
} | ||
function movePrev() { | ||
setCurrent(current - 1 >= 0 ? current - 1 : max - 1); | ||
} | ||
|
||
return ( | ||
<div className={styles.container}> | ||
<button | ||
className={styles.agendaInfoContainer} | ||
onClick={(e) => { | ||
const target = e.target as HTMLElement; | ||
console.log(target); | ||
if ( | ||
target.className.includes(styles.moveButton) || | ||
target.closest(styles.moveButton) | ||
) | ||
return; | ||
data.length && data[current] | ||
? handleNavigation('/agenda/' + data[current].agendaKey) | ||
: null; | ||
}} | ||
> | ||
<button | ||
onClick={movePrev} | ||
className={`${styles.moveButton} ${styles.moveButtonPrev}`} | ||
> | ||
<div className={styles.prev} /> | ||
</button> | ||
<button | ||
className={`${styles.moveButton} ${styles.moveButtonNext}`} | ||
onClick={moveNext} | ||
> | ||
<div className={styles.next} /> | ||
</button> | ||
<AgendaInfo agendaInfo={data[current]} key={current || 0} /> | ||
</button> | ||
<PageControllerNavigator | ||
currentPage={current} | ||
maxPage={data.length} | ||
onClick={setCurrent} | ||
/> | ||
</div> | ||
); | ||
}; | ||
|
||
export default PageController; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { useEffect, useRef, useState } from 'react'; | ||
import { instanceInAgenda } from 'utils/axios'; | ||
|
||
const usePageNation = <T>({ | ||
url, | ||
size, | ||
useIdx, | ||
}: { | ||
url: string; | ||
size?: number; // 페이지 사이즈 | ||
useIdx?: boolean; // 인덱싱 추가 여부 : 해당 데이터 타입에 idx?: number; 추가 필요 | ||
}) => { | ||
if (!size) size = 20; | ||
const getData = async (page: number) => { | ||
const res = await instanceInAgenda.get(`${url}?page=${page}&size=${size}`); | ||
res.data.totalSize ? res.data.totalSize : 0; | ||
res.data.content ? res.data.content : []; | ||
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; | ||
}); | ||
} | ||
return res.data as { totalSize: number; content: T[] }; | ||
}; | ||
// const data = getData(0); | ||
const [currentPage, setCurrentPage] = useState<number>(1); | ||
const [content, setContent] = useState<T[] | null>(null); | ||
const totalPages = useRef(1); | ||
|
||
const pageChangeHandler = async (pageNumber: number) => { | ||
if (pageNumber < 1 || pageNumber > totalPages.current) return; | ||
await getData(pageNumber).then((res) => { | ||
setCurrentPage(pageNumber); | ||
setContent(res.content); | ||
}); | ||
}; | ||
|
||
useEffect(() => { | ||
const fetchData = async () => { | ||
const data = await getData(currentPage); | ||
totalPages.current = Math.ceil(data.totalSize / size); | ||
setContent(data.content); | ||
}; | ||
fetchData(); | ||
}); | ||
|
||
const PagaNationElementProps = { | ||
curPage: currentPage, | ||
totalPages: totalPages.current, | ||
pageChangeHandler: pageChangeHandler, | ||
}; | ||
|
||
return { content, PagaNationElementProps }; | ||
}; | ||
|
||
export default usePageNation; |
Oops, something went wrong.