import { useState, useEffect, useCallback } from "react"; import { IMAGE_URL_REG, MEMO_LINK_REG, UNKNOWN_ID } from "../helpers/consts"; import utils from "../helpers/utils"; import { editorStateService, memoService } from "../services"; import { parseHtmlToRawText } from "../helpers/marked"; import { formatMemoContent } from "./Memo"; import toastHelper from "./Toast"; import { showDialog } from "./Dialog"; import Only from "./common/OnlyWhen"; import Image from "./Image"; import "../less/memo-card-dialog.less"; import "../less/memo-content.less"; interface LinkedMemo extends Memo { createdAtStr: string; dateStr: string; } interface Props extends DialogProps { memo: Memo; } const MemoCardDialog: React.FC = (props: Props) => { const [memo, setMemo] = useState({ ...props.memo, }); const [linkMemos, setLinkMemos] = useState([]); const [linkedMemos, setLinkedMemos] = useState([]); const imageUrls = Array.from(memo.content.match(IMAGE_URL_REG) ?? []); useEffect(() => { const fetchLinkedMemos = async () => { try { const linkMemos: LinkedMemo[] = []; const matchedArr = [...memo.content.matchAll(MEMO_LINK_REG)]; for (const matchRes of matchedArr) { if (matchRes && matchRes.length === 3) { const id = matchRes[2]; const memoTemp = memoService.getMemoById(Number(id)); if (memoTemp) { linkMemos.push({ ...memoTemp, createdAtStr: utils.getDateTimeString(memoTemp.createdTs), dateStr: utils.getDateString(memoTemp.createdTs), }); } } } setLinkMemos([...linkMemos]); const linkedMemos = await memoService.getLinkedMemos(memo.id); setLinkedMemos( linkedMemos .sort((a, b) => utils.getTimeStampByDate(b.createdTs) - utils.getTimeStampByDate(a.createdTs)) .map((m) => ({ ...m, createdAtStr: utils.getDateTimeString(m.createdTs), dateStr: utils.getDateString(m.createdTs), })) ); } catch (error) { // do nth } }; fetchLinkedMemos(); }, [memo.id]); const handleMemoContentClick = useCallback(async (e: React.MouseEvent) => { const targetEl = e.target as HTMLElement; if (targetEl.className === "memo-link-text") { const nextMemoId = targetEl.dataset?.value; const memoTemp = memoService.getMemoById(Number(nextMemoId) ?? UNKNOWN_ID); if (memoTemp) { const nextMemo = { ...memoTemp, createdAtStr: utils.getDateTimeString(memoTemp.createdTs), }; setLinkMemos([]); setLinkedMemos([]); setMemo(nextMemo); } else { toastHelper.error("MEMO Not Found"); targetEl.classList.remove("memo-link-text"); } } }, []); const handleLinkedMemoClick = useCallback((memo: Memo) => { setLinkMemos([]); setLinkedMemos([]); setMemo(memo); }, []); const handleEditMemoBtnClick = useCallback(() => { props.destroy(); editorStateService.setEditMemoWithId(memo.id); }, [memo.id]); return ( <>

{utils.getDateTimeString(memo.createdTs)}

0}>
{imageUrls.map((imgUrl, idx) => ( ))}
{linkMemos.map((_, idx) => { if (idx < 4) { return (
); } else { return null; } })}
{linkMemos.length > 0 ? (

{linkMemos.length} related MEMO

{linkMemos.map((m) => { const rawtext = parseHtmlToRawText(formatMemoContent(m.content)).replaceAll("\n", " "); return (
handleLinkedMemoClick(m)}> {m.dateStr} {rawtext}
); })}
) : null} {linkedMemos.length > 0 ? (

{linkedMemos.length} linked MEMO

{linkedMemos.map((m) => { const rawtext = parseHtmlToRawText(formatMemoContent(m.content)).replaceAll("\n", " "); return (
handleLinkedMemoClick(m)}> {m.dateStr} {rawtext}
); })}
) : null} ); }; export default function showMemoCardDialog(memo: Memo): void { showDialog( { className: "memo-card-dialog", }, MemoCardDialog, { memo } ); }