211 lines
7.2 KiB
TypeScript
211 lines
7.2 KiB
TypeScript
import { ChangeEvent, useEffect, useState } from 'react';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { PATHS } from '@/shared/constants/paths';
|
|
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
|
|
import { useNoticeListMutation } from '@/entities/support/api/use-notice-list-mutation';
|
|
import { DEFAULT_PAGE_PARAM } from '@/entities/common/model/constant';
|
|
import { DetailData, InformCl, NoticeItem, NoticeListParams, NoticeListResponse, SearchCl } from '@/entities/support/model/types';
|
|
import { SupportNoticeItem } from '@/entities/support/ui/notice-item';
|
|
import { DefaultRequestPagination, HeaderType } from '@/entities/common/model/types';
|
|
import {
|
|
useSetHeaderTitle,
|
|
useSetHeaderType,
|
|
useSetFooterMode,
|
|
useSetOnBack
|
|
} from '@/widgets/sub-layout/use-sub-layout';
|
|
import useIntersectionObserver from '@/widgets/intersection-observer';
|
|
import { NoticeDetail } from '@/entities/support/ui/detail/notice-detail';
|
|
import { useParams } from 'react-router';
|
|
import { showAlert } from '@/widgets/show-alert';
|
|
import { snackBar } from '@/shared/lib';
|
|
import { useDetailOnStore } from '@/shared/model/store';
|
|
|
|
export const NoticeListPage = () => {
|
|
const { navigate } = useNavigate();
|
|
const { seq } = useParams();
|
|
const { t } = useTranslation();
|
|
|
|
const [onActionIntersect, setOnActionIntersect] = useState<boolean>(false);
|
|
const [pageParam, setPageParam] = useState<DefaultRequestPagination>(DEFAULT_PAGE_PARAM);
|
|
const [informCl, setInformCl] = useState<InformCl | string>('');
|
|
const [searchKeyword, setSearchKeyword] = useState<string>('');
|
|
const [resultList, setResultList] = useState<Array<NoticeItem>>([]);
|
|
const { detailOn, setDetailOn } = useDetailOnStore();
|
|
const [detailSeq, setDetailSeq] = useState<number | string>();
|
|
|
|
useSetHeaderTitle(t('support.notice.title'));
|
|
useSetHeaderType(HeaderType.LeftArrow);
|
|
useSetFooterMode(false);
|
|
useSetOnBack(() => {
|
|
navigate(PATHS.home);
|
|
});
|
|
|
|
const { mutateAsync: noticeList } = useNoticeListMutation();
|
|
|
|
const onIntersect: IntersectionObserverCallback = (entries: Array<IntersectionObserverEntry>) => {
|
|
entries.forEach((entry: IntersectionObserverEntry) => {
|
|
if(entry.isIntersecting){
|
|
if(onActionIntersect && !!pageParam.cursor){
|
|
setOnActionIntersect(false);
|
|
callList('page');
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
const { setTarget } = useIntersectionObserver({
|
|
threshold: 1,
|
|
onIntersect
|
|
});
|
|
|
|
const callList = (type?: string) => {
|
|
setOnActionIntersect(false);
|
|
let listParams: NoticeListParams = {
|
|
informCl: informCl,
|
|
searchCl: (!!searchKeyword)? SearchCl.HEAD: null,
|
|
searchKeyword: searchKeyword,
|
|
page: pageParam
|
|
};
|
|
if(type !== 'page' && listParams.page){
|
|
listParams.page.cursor = null;
|
|
}
|
|
|
|
noticeList(listParams).then((rs: NoticeListResponse) => {
|
|
if(type === 'page'){
|
|
setResultList([
|
|
...resultList,
|
|
...rs.content
|
|
]);
|
|
}
|
|
else{
|
|
setResultList(rs.content);
|
|
}
|
|
if(rs.hasNext
|
|
&& rs.nextCursor !== pageParam.cursor
|
|
&& rs.content.length === DEFAULT_PAGE_PARAM.size
|
|
){
|
|
setPageParam({
|
|
...pageParam,
|
|
...{ cursor: rs.nextCursor }
|
|
});
|
|
}
|
|
else{
|
|
setPageParam({
|
|
...pageParam,
|
|
...{ cursor: null }
|
|
});
|
|
}
|
|
setOnActionIntersect(
|
|
!!rs.hasNext
|
|
&& rs.nextCursor !== pageParam.cursor
|
|
&& rs.content.length === DEFAULT_PAGE_PARAM.size
|
|
);
|
|
}).catch((e: any) => {
|
|
if(e.response?.data?.error?.message){
|
|
snackBar(e.response?.data?.error?.message);
|
|
return;
|
|
}
|
|
});
|
|
};
|
|
|
|
const onClickToAction = () => {
|
|
// Remove focus from active element
|
|
if (document.activeElement instanceof HTMLElement) {
|
|
document.activeElement.blur();
|
|
}
|
|
callList();
|
|
};
|
|
|
|
const setDetailData = (detailData: DetailData) => {
|
|
setDetailOn(detailData.detailOn);
|
|
if(detailData?.seq){
|
|
setDetailSeq(detailData?.seq);
|
|
}
|
|
};
|
|
|
|
const getNoticeList = () => {
|
|
let rs = [];
|
|
for(let i=0;i<resultList.length;i++){
|
|
let noticeItem = resultList[i];
|
|
if(noticeItem){
|
|
rs.push(
|
|
<SupportNoticeItem
|
|
key={ `key-support-notice-item-${i}` }
|
|
noticeItem={ noticeItem }
|
|
setDetailData={ setDetailData }
|
|
></SupportNoticeItem>
|
|
);
|
|
}
|
|
}
|
|
return rs;
|
|
};
|
|
|
|
useEffect(() => {
|
|
callList();
|
|
}, [informCl]);
|
|
useEffect(() => {
|
|
if(seq){
|
|
setDetailOn(true);
|
|
setDetailSeq(parseInt(seq));
|
|
}
|
|
}, [seq]);
|
|
|
|
return (
|
|
<>
|
|
<main>
|
|
<div className="tab-content">
|
|
<div className="tab-pane sub active">
|
|
<div className="notice114">
|
|
<div className="notice-controls">
|
|
<div className="notice-search">
|
|
<span
|
|
className="ic16 search"
|
|
aria-hidden="true"
|
|
onClick={ () => onClickToAction() }
|
|
></span>
|
|
<input
|
|
type="text"
|
|
placeholder={ t('support.notice.searchPlaceholder') }
|
|
value={ searchKeyword }
|
|
onChange={ (e: ChangeEvent<HTMLInputElement>) => setSearchKeyword(e.target.value) }
|
|
onKeyDown={ (e: React.KeyboardEvent<HTMLInputElement>) => {
|
|
if (e.key === 'Enter' && !e.nativeEvent.isComposing) {
|
|
onClickToAction();
|
|
}
|
|
}}
|
|
/>
|
|
</div>
|
|
<div className="notice-filter">
|
|
<select
|
|
className="flex-1"
|
|
value={ informCl }
|
|
onChange={ (e: ChangeEvent<HTMLSelectElement>) => setInformCl(e.target.value) }
|
|
>
|
|
<option value="">{ t('support.notice.categories.all') }</option>
|
|
<option value="INTEREST_FREE_INSTALLMENT">{ t('support.notice.categories.INTEREST_FREE_INSTALLMENT') }</option>
|
|
<option value="NEWS">{ t('support.notice.categories.NEWS') }</option>
|
|
<option value="SERVICE_DISRUPTION_NOTICE">{ t('support.notice.categories.SERVICE_DISRUPTION_NOTICE') }</option>
|
|
<option value="MAINTENANCE_NOTICE">{ t('support.notice.categories.MAINTENANCE_NOTICE') }</option>
|
|
<option value="EVENT">{ t('support.notice.categories.EVENT') }</option>
|
|
<option value="SERVICE_CHANGE_OR_ADDITION">{ t('support.notice.categories.SERVICE_CHANGE_OR_ADDITION') }</option>
|
|
<option value="IMPORTANT_NOTICE">{ t('support.notice.categories.IMPORTANT_NOTICE') }</option>
|
|
<option value="ADDITIONAL_SERVICE">{ t('support.notice.categories.ADDITIONAL_SERVICE') }</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div className="notice-list-114">
|
|
{ getNoticeList() }
|
|
</div>
|
|
<div ref={ setTarget }></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<NoticeDetail
|
|
detailOn={ detailOn }
|
|
setDetailOn={ setDetailOn }
|
|
seq={ detailSeq }
|
|
></NoticeDetail>
|
|
</main>
|
|
</>
|
|
);
|
|
}; |