diff --git a/src/features/tech-log/presentation/public/pages/project-activity-page.tsx b/src/features/tech-log/presentation/public/pages/project-activity-page.tsx index e65f205..c658311 100644 --- a/src/features/tech-log/presentation/public/pages/project-activity-page.tsx +++ b/src/features/tech-log/presentation/public/pages/project-activity-page.tsx @@ -1,5 +1,3 @@ -import { Link } from "react-router-dom"; - import { RegisteredNotFoundRoute, useRouteInput, @@ -21,28 +19,33 @@ export function ProjectActivityPage() { const { project, activity } = view.data; if (!project) return ; + /* + 활동은 로그다 — 언제 무엇을 올렸는지만 적는다. + + 예전에는 각 줄에 그 기록으로 가는 링크가 있었다. 그러면 같은 글에 닿는 길이 둘이 되고, + 읽는 사람은 "기록"과 "활동"이 어떻게 다른지 매번 다시 판단해야 한다. 글을 읽는 자리는 + 기록 화면 하나로 둔다. + */ return (
-
    - {activity.map((item) => ( -
  1. -
    -
    - {item.type} - -
    -

    {item.title}

    -

    {item.summary}

    - - {item.recordPath - ? "연결된 공개 기록 읽기" - : "이 활동 위치 열기"} - -
    -
  2. - ))} -
+ {activity.length === 0 ? ( +

아직 이 프로젝트에서 공개한 기록이 없습니다.

+ ) : ( +
    + {activity.map((item) => ( +
  1. +
    +
    + {item.type} + +
    +

    {item.title}

    +
    +
  2. + ))} +
+ )}
); } diff --git a/src/features/tech-log/presentation/studio/components/project-editor.tsx b/src/features/tech-log/presentation/studio/components/project-editor.tsx index 0e00910..fa6c8eb 100644 --- a/src/features/tech-log/presentation/studio/components/project-editor.tsx +++ b/src/features/tech-log/presentation/studio/components/project-editor.tsx @@ -114,14 +114,6 @@ export function ProjectEditor() { const [records, setRecords] = useState([]); const [activities, setActivities] = useState([]); const [draft, setDraft] = useState(null); - const [newActivity, setNewActivity] = useState({ - activityType: "MILESTONE_REACHED", - title: "", - summary: "", - visibility: "PUBLIC", - relatedId: "", - occurredAt: toLocalInput(new Date().toISOString()), - }); const [pending, setPending] = useState(false); const [error, setError] = useState(""); const [generation, setGeneration] = useState(0); @@ -218,88 +210,6 @@ export function ProjectEditor() { } }; - const addActivity = async (event: FormEvent) => { - event.preventDefault(); - if (pending || !project) return; - const title = newActivity.title.trim(); - if (!title) { - setError("활동에는 제목이 필요합니다."); - return; - } - setPending(true); - setError(""); - try { - const related = records.find((entry) => entry.id === newActivity.relatedId); - await managementGateway.createProjectActivity(project.id, { - expectedProjectVersion: project.version, - activityType: newActivity.activityType, - title, - summary: newActivity.summary, - visibility: newActivity.visibility === "PUBLIC" ? "PUBLIC" : "PRIVATE", - /* - 공개 화면의 "이 활동 위치 열기" 는 이 자리를 따라간다. 비워 두면 그 링크는 갈 곳이 없다 — - 예전에는 고를 방법 자체가 없어 모든 활동의 그 버튼이 눌리지 않았다. - */ - relatedResourceType: related?.kind ?? undefined, - relatedResourceId: related?.id ?? undefined, - occurredAt: fromLocalInput(newActivity.occurredAt), - }); - setNewActivity({ - activityType: "MILESTONE_REACHED", - title: "", - summary: "", - visibility: "PUBLIC", - relatedId: "", - occurredAt: toLocalInput(new Date().toISOString()), - }); - setRequestAnnouncement(`활동 ${title} 을(를) 추가했습니다.`); - reload(); - } catch (failure) { - setError(managementFailureMessage(failure, "활동을 추가하지 못했습니다.")); - } finally { - setPending(false); - } - }; - - const saveActivity = async ( - activity: ProjectActivityResponse, - changes: Partial>, - ) => { - if (pending || !project) return; - setPending(true); - setError(""); - try { - const saved = await managementGateway.updateProjectActivity(project.id, activity.id, { - expectedVersion: activity.version, - title: changes.title ?? activity.title, - summary: changes.summary ?? activity.summary ?? "", - visibility: (changes.visibility ?? activity.visibility) === "PUBLIC" ? "PUBLIC" : "PRIVATE", - occurredAt: changes.occurredAt ?? activity.occurredAt, - }); - setActivities((current) => current.map((item) => (item.id === saved.id ? saved : item))); - setRequestAnnouncement("활동을 저장했습니다."); - } catch (failure) { - setError(managementFailureMessage(failure, "활동을 저장하지 못했습니다.")); - } finally { - setPending(false); - } - }; - - const removeActivity = async (activity: ProjectActivityResponse) => { - if (pending || !project) return; - setPending(true); - setError(""); - try { - await managementGateway.deleteProjectActivity(project.id, activity.id, activity.version); - setActivities((current) => current.filter((item) => item.id !== activity.id)); - setRequestAnnouncement(`활동 ${activity.title} 을(를) 삭제했습니다.`); - } catch (failure) { - setError(managementFailureMessage(failure, "활동을 삭제하지 못했습니다.")); - } finally { - setPending(false); - } - }; - const published = project ? project.targetVisibility !== "PRIVATE" : false; return ( @@ -445,9 +355,19 @@ export function ProjectEditor() { >

NARRATIVE

-

맥락

-

프로젝트 상세 화면의 본문입니다. 마크다운을 씁니다.

+

목적

+

+ 프로젝트 화면의 “프로젝트가 지키는 기준”이 이 글을 그립니다. +

+ {/* + 경계와 시스템 개요 칸이 여기 함께 있었다. 저장은 되지만 공개 화면 어디에도 + 나오지 않는다 — 프로젝트 화면이 그리는 것은 목적 하나다. 쓰는 사람에게는 쓴 글이 + 어딘가 실릴 것처럼 보이는 칸이었고, 실제로는 아무도 읽지 않았다. + + 열의 데이터는 남겨 둔다(계약이 요구하고, 이미 적어 둔 글이 있을 수 있다). 저장할 + 때 서버가 가진 값을 그대로 돌려보내므로 지워지지 않는다. + */}
-