Files
ef_front/app/usr/4_noticeboard/page.tsx

140 lines
4.7 KiB
TypeScript
Raw Normal View History

2025-09-07 22:57:43 +00:00
'use client'
import { useEffect, useState } from "react";
import NoticeModal from "@/app/components/ModelNotice";
import { MilkdownViewer } from "@/app/components/MilkdownViewer";
import { MilkdownProvider } from "@milkdown/react";
import { Crepe } from "@milkdown/crepe";
import { useRef } from "react";
export default function Page() {
const crepeRef = useRef<Crepe>(null!);
const [noticeList, setNoticeList] = useState<{
id: string;
title: string;
pubDate: Date;
content: string;
tag: string;
}[]>([]);
const [currentNotice, setCurrentNotice] = useState<{
id: string;
title: string;
content: string;
tag:string
pubDate: Date;
}>({
id: "",
tag: "",
title: "",
content: "",
pubDate: new Date("0"),
});
const [isNoticeModalOpen, setIsNoticeModalOpen] = useState(false);
const openHandler = (id: string) => {
const notice = noticeList.find((notice) => notice.id === id);
if (notice) {
setCurrentNotice({
id: notice.id,
title: notice.title,
content: notice.content,
tag: notice.tag,
pubDate: notice.pubDate,
});
}
setIsNoticeModalOpen(true);
}
const fetchNotices = async () => {
const response = await fetch('/api/notice');
const data = await response.json();
setNoticeList(data);
}
useEffect(() => {
fetchNotices();
}, []);
return (
<div className="bg-white h-full w-[100vw] lg:w-[calc(100vw-360px)]">
<div className="h-[calc(100%-80px)] max-w-[800px] mx-auto overflow-y-auto p-4 flex flex-col">
{noticeList.length === 0 ? (
<div className="text-center text-gray-500"> .</div>
) : (
noticeList.map((notice) => (
<div
key={notice.id}
className="h-[75px] border-[#d5d5d5] border-1 rounded-lg p-4 my-2 flex flex-row justify-between hover:border-[#F94B37] cursor-pointer min-w-[100px] shrink-0 basis-0 grow-0"
onClick={() => openHandler(notice.id)}
>
{/* 여기 min-w-0 추가해서 자식을 제한함 부모와 이 위치 관계 다시 확인 */}
<div className="flex flex-col justify-between min-w-0">
<div className="flex flex-row justify-start">
{
notice.tag === "중요" && (
<div className="mr-2 flex items-center justify-center">
<div className="w-[33px] h-[20px] bg-[#FEDBD7] text-[#F94B37] font-semibold text-xs rounded-lg text-center flex items-center justify-center"></div>
</div>
)
}
<div className="text-normal font-semibold truncate">
{notice.title}
</div>
</div>
<div className="text-xs text-[#848484]">
{notice.pubDate.toLocaleString('ko-KR', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', hour12: false })}
</div>
</div>
<div className="flex items-center justify-center">
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7.5 15L12.5 10L7.5 5" stroke="#848484" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
</svg>
</div>
</div>
))
)}
</div>
<NoticeModal isOpen={isNoticeModalOpen} onClose={() => setIsNoticeModalOpen(false)}>
<div className="flex flex-col h-full bg-white rounded-lg p-6">
<div className="flex justify-end mb-4">
<button
className="bg-gray-500 text-white px-4 py-2 rounded hover:bg-gray-600"
onClick={() => setIsNoticeModalOpen(false)}
>
</button>
</div>
<div className="flex flex-col border-b border-gray-200 pb-4 mb-4">
<h1 className="text-2xl font-bold text-gray-800">{currentNotice.title}</h1>
<p className="text-sm text-gray-400 mt-1">
{currentNotice.pubDate.toLocaleString('ko-KR', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
hour12: false,
})}
</p>
</div>
<div className="flex-1 overflow-y-auto">
<MilkdownProvider>
<MilkdownViewer value={currentNotice.content} editorRef={crepeRef} />
</MilkdownProvider>
</div>
</div>
</NoticeModal>
</div>
);
}