// The notes module's pages, as the one server component the web shell mounts under // `////notes` (apps/web's module mount reads it from `modules/index.ts`): // // /notes the list and the form that adds a note // /notes/ one note: edit it, attach files, delete it // // Every read is a procedure through the same caller the API uses (spec ยง6.2: one API path); every // write is a client component that calls a procedure through the shell's transport. import { type Container, notFound, type TransportCaller } from "@conusai-kit/core" import type { I18n } from "@conusai-kit/i18n" import type { ProjectPage } from "@conusai-kit/ui" import type { ReactElement } from "react" import { ATTACHMENT_CONTENT_TYPES, noteGet, noteList } from "../contract/index.js" import { FeedbackButton } from "../guides/feedback-button.js" // kit:guides import { feedbackLabels } from "../guides/feedback-labels.js" // kit:guides import { Attachments } from "./attachments.js" import { DeleteNote } from "./delete-note.js" import { attachmentLabels, createFormLabels, deleteLabels, editFormLabels, listLabels, sizeLabel } from "./labels.js" import { NoteForm } from "./note-form.js" import { NoteList } from "./note-list.js" export type NotesPage = ProjectPage export const notesPage: NotesPage = async ({ slugs, segments, caller, i18n }): Promise => { const t = (key: string, values?: Record) => i18n.message(`notes.${key}`, values) const failed = i18n.message("app.failed") const listHref = `/${slugs.org}/${slugs.workspace}/${slugs.project}/notes` if (segments.length === 0) { const { notes } = await caller.call(noteList, slugs) return ( <>

{t("title")}

{t("intro")}

{/* guide: The form that adds a note */}
`${listHref}/${noteId}`} labels={listLabels(t)} formatDate={(iso) => i18n.date(new Date(iso))} /> ) } const [noteId, ...rest] = segments if (noteId === undefined || rest.length > 0) throw notFound("no such page") const { note, attachments, attachmentsEnabled } = await caller.call(noteGet, { ...slugs, noteId }) return ( <>

{t("detail.back")}

{note.title}

{t("detail.changed", { date: i18n.date(new Date(note.updatedAt)) })}

({ attachmentId: attachment.attachmentId, fileId: attachment.fileId, filename: attachment.filename, contentType: attachment.contentType, size: sizeLabel(t, attachment.size), }))} enabled={attachmentsEnabled} accept={ATTACHMENT_CONTENT_TYPES} labels={attachmentLabels(t, failed, attachments.length)} /> ) }