@ -1,6 +1,6 @@
import { Tooltip } from "@mui/joy" ;
import { Button, Tooltip } from "@mui/joy" ;
import { ClientError } from "nice-grpc-web" ;
import { ClientError } from "nice-grpc-web" ;
import { useEffect , use State } from "react" ;
import { useEffect , use Ref, use State } from "react" ;
import toast from "react-hot-toast" ;
import toast from "react-hot-toast" ;
import { showCommonDialog } from "@/components/Dialog/CommonDialog" ;
import { showCommonDialog } from "@/components/Dialog/CommonDialog" ;
import Empty from "@/components/Empty" ;
import Empty from "@/components/Empty" ;
@ -9,28 +9,36 @@ import MemoContent from "@/components/MemoContent";
import MemoFilter from "@/components/MemoFilter" ;
import MemoFilter from "@/components/MemoFilter" ;
import MobileHeader from "@/components/MobileHeader" ;
import MobileHeader from "@/components/MobileHeader" ;
import SearchBar from "@/components/SearchBar" ;
import SearchBar from "@/components/SearchBar" ;
import { memoServiceClient } from "@/grpcweb" ;
import { DEFAULT_MEMO_LIMIT } from "@/helpers/consts" ;
import { getTimeStampByDate } from "@/helpers/datetime" ;
import { getDateTimeString } from "@/helpers/datetime" ;
import { getDateTimeString } from "@/helpers/datetime" ;
import useCurrentUser from "@/hooks/useCurrentUser" ;
import useCurrentUser from "@/hooks/useCurrentUser" ;
import useFilterWithUrlParams from "@/hooks/useFilterWithUrlParams" ;
import useFilterWithUrlParams from "@/hooks/useFilterWithUrlParams" ;
import useLoading from "@/hooks/useLoading" ;
import { useMemoList , useMemoStore } from "@/store/v1" ;
import { useMemoStore } from "@/store/v1" ;
import { RowStatus } from "@/types/proto/api/v2/common" ;
import { RowStatus } from "@/types/proto/api/v2/common" ;
import { Memo } from "@/types/proto/api/v2/memo_service" ;
import { Memo } from "@/types/proto/api/v2/memo_service" ;
import { useTranslate } from "@/utils/i18n" ;
import { useTranslate } from "@/utils/i18n" ;
const Archived = ( ) = > {
const Archived = ( ) = > {
const t = useTranslate ( ) ;
const t = useTranslate ( ) ;
const loadingState = useLoading ( ) ;
const user = useCurrentUser ( ) ;
const user = useCurrentUser ( ) ;
const memoStore = useMemoStore ( ) ;
const memoStore = useMemoStore ( ) ;
const [ archivedMemos , setArchivedMemos ] = useState < Memo [ ] > ( [ ] ) ;
const memoList = useMemoList ( ) ;
const [ isRequesting , setIsRequesting ] = useState ( true ) ;
const nextPageTokenRef = useRef < string | undefined > ( undefined ) ;
const { tag : tagQuery , text : textQuery } = useFilterWithUrlParams ( ) ;
const { tag : tagQuery , text : textQuery } = useFilterWithUrlParams ( ) ;
const sortedMemos = memoList . value
. filter ( ( memo ) = > memo . rowStatus === RowStatus . ARCHIVED )
. sort ( ( a , b ) = > getTimeStampByDate ( b . displayTime ) - getTimeStampByDate ( a . displayTime ) ) ;
useEffect ( ( ) = > {
useEffect ( ( ) = > {
( async ( ) = > {
nextPageTokenRef . current = undefined ;
try {
memoList . reset ( ) ;
const filters = [ ` creator == " ${ user . name } " ` , "row_status == 'ARCHIVED'" ] ;
fetchMemos ( ) ;
} , [ tagQuery , textQuery ] ) ;
const fetchMemos = async ( ) = > {
const filters = [ ` creator == " ${ user . name } " ` , ` row_status == "ARCHIVED" ` ] ;
const contentSearch : string [ ] = [ ] ;
const contentSearch : string [ ] = [ ] ;
if ( tagQuery ) {
if ( tagQuery ) {
contentSearch . push ( JSON . stringify ( ` # ${ tagQuery } ` ) ) ;
contentSearch . push ( JSON . stringify ( ` # ${ tagQuery } ` ) ) ;
@ -41,16 +49,15 @@ const Archived = () => {
if ( contentSearch . length > 0 ) {
if ( contentSearch . length > 0 ) {
filters . push ( ` content_search == [ ${ contentSearch . join ( ", " ) } ] ` ) ;
filters . push ( ` content_search == [ ${ contentSearch . join ( ", " ) } ] ` ) ;
}
}
const { memos } = await memoServiceClient . listMemos ( {
setIsRequesting ( true ) ;
const data = await memoStore . fetchMemos ( {
pageSize : DEFAULT_MEMO_LIMIT ,
filter : filters.join ( " && " ) ,
filter : filters.join ( " && " ) ,
pageToken : nextPageTokenRef.current ,
} ) ;
} ) ;
setArchivedMemos ( memos ) ;
setIsRequesting ( false ) ;
} catch ( error : unknown ) {
nextPageTokenRef . current = data . nextPageToken ;
toast . error ( ( error as ClientError ) . details ) ;
} ;
}
loadingState . setFinish ( ) ;
} ) ( ) ;
} , [ tagQuery , textQuery ] ) ;
const handleDeleteMemoClick = async ( memo : Memo ) = > {
const handleDeleteMemoClick = async ( memo : Memo ) = > {
showCommonDialog ( {
showCommonDialog ( {
@ -60,7 +67,6 @@ const Archived = () => {
dialogName : "delete-memo-dialog" ,
dialogName : "delete-memo-dialog" ,
onConfirm : async ( ) = > {
onConfirm : async ( ) = > {
await memoStore . deleteMemo ( memo . id ) ;
await memoStore . deleteMemo ( memo . id ) ;
setArchivedMemos ( ( prev ) = > prev . filter ( ( m ) = > m . id !== memo . id ) ) ;
} ,
} ,
} ) ;
} ) ;
} ;
} ;
@ -74,7 +80,6 @@ const Archived = () => {
} ,
} ,
[ "row_status" ] ,
[ "row_status" ] ,
) ;
) ;
setArchivedMemos ( ( prev ) = > prev . filter ( ( m ) = > m . id !== memo . id ) ) ;
toast ( t ( "message.restored-successfully" ) ) ;
toast ( t ( "message.restored-successfully" ) ) ;
} catch ( error : unknown ) {
} catch ( error : unknown ) {
console . error ( error ) ;
console . error ( error ) ;
@ -83,7 +88,7 @@ const Archived = () => {
} ;
} ;
return (
return (
< section className = "@container w-full max-w-5xl min-h-full flex flex-col justify-start items- start sm:pt-3 md:pt-6 pb-8">
< section className = "@container w-full max-w-5xl min-h-full flex flex-col justify-start items- center sm:pt-3 md:pt-6 pb-8">
< MobileHeader / >
< MobileHeader / >
< div className = "w-full px-4 sm:px-6" >
< div className = "w-full px-4 sm:px-6" >
< div className = "w-full flex flex-col justify-start items-start" >
< div className = "w-full flex flex-col justify-start items-start" >
@ -93,24 +98,14 @@ const Archived = () => {
< / div >
< / div >
< / div >
< / div >
< MemoFilter className = "px-2 pb-2" / >
< MemoFilter className = "px-2 pb-2" / >
{ loadingState . isLoading ? (
{ sortedMemos . map ( ( memo ) = > (
< div className = "w-full h-32 flex flex-col justify-center items-center" >
< p className = "opacity-70" > { t ( "memo.fetching-data" ) } < / p >
< / div >
) : archivedMemos . length === 0 ? (
< div className = "w-full mt-16 mb-8 flex flex-col justify-center items-center italic" >
< Empty / >
< p className = "mt-4 text-gray-600 dark:text-gray-400" > { t ( "message.no-data" ) } < / p >
< / div >
) : (
archivedMemos . map ( ( memo ) = > (
< div
< div
key = { memo . id }
key = { memo . id }
className = "relative flex flex-col justify-start items-start w-full p-4 pt-3 mb-2 bg-white dark:bg-zinc-800 rounded-lg"
className = "relative flex flex-col justify-start items-start w-full p-4 pt-3 mb-2 bg-white dark:bg-zinc-800 rounded-lg"
>
>
< div className = "w-full mb-1 flex flex-row justify-between items-center" >
< div className = "w-full mb-1 flex flex-row justify-between items-center" >
< div className = "w-full max-w-[calc(100%-20px)] flex flex-row justify-start items-center mr-1" >
< div className = "w-full max-w-[calc(100%-20px)] flex flex-row justify-start items-center mr-1" >
< span className = "text-sm text-gray-400 select-none" > { getDateTimeString ( memo . update Time) } < / span >
< span className = "text-sm text-gray-400 select-none" > { getDateTimeString ( memo . displayTime ) } < / span >
< / div >
< / div >
< div className = "flex flex-row justify-end items-center gap-x-2" >
< div className = "flex flex-row justify-end items-center gap-x-2" >
< Tooltip title = { t ( "common.restore" ) } placement = "top" >
< Tooltip title = { t ( "common.restore" ) } placement = "top" >
@ -125,9 +120,27 @@ const Archived = () => {
< / Tooltip >
< / Tooltip >
< / div >
< / div >
< / div >
< / div >
< MemoContent key = { ` ${ memo . id } - ${ memo . updateTime } ` } memoId = { memo . id } content = { memo . content } readonly = { true } / >
< MemoContent key = { ` ${ memo . id } - ${ memo . displayTime } ` } memoId = { memo . id } content = { memo . content } readonly = { true } / >
< / div >
) ) }
{ isRequesting ? (
< div className = "flex flex-row justify-center items-center w-full my-4 text-gray-400" >
< Icon.Loader className = "w-4 h-auto animate-spin mr-1" / >
< p className = "text-sm italic" > { t ( "memo.fetching-data" ) } < / p >
< / div >
) : ! nextPageTokenRef . current ? (
sortedMemos . length === 0 && (
< div className = "w-full mt-16 mb-8 flex flex-col justify-center items-center italic" >
< Empty / >
< p className = "mt-4 text-gray-600 dark:text-gray-400" > { t ( "message.no-data" ) } < / p >
< / div >
)
) : (
< div className = "w-full flex flex-row justify-center items-center my-4" >
< Button variant = "plain" endDecorator = { < Icon.ArrowDown className = "w-5 h-auto" / > } onClick = { fetchMemos } >
{ t ( "memo.fetch-more" ) }
< / Button >
< / div >
< / div >
) )
) }
) }
< / div >
< / div >
< / div >
< / div >