From 18702e130ec2d8ae4d41752c4e599e17439aea07 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Fri, 6 Feb 2026 04:47:23 -0800 Subject: [PATCH] Decompose BoardPage into individual components and remove debug logging. Extract BoardRow, BoardColumn, BoardViewHeader, BoardEditHeader, and boardConstants into separate files. Remove 9 console.log statements from BoardBody and BoardProvider. Co-Authored-By: Claude Opus 4.6 --- src/app/(main)/boards/BoardProvider.tsx | 2 - src/app/(main)/boards/[boardId]/BoardBody.tsx | 194 +----------------- .../(main)/boards/[boardId]/BoardColumn.tsx | 52 +++++ .../boards/[boardId]/BoardEditHeader.tsx | 99 +++++++++ .../(main)/boards/[boardId]/BoardHeader.tsx | 122 +---------- src/app/(main)/boards/[boardId]/BoardRow.tsx | 125 +++++++++++ .../boards/[boardId]/BoardViewHeader.tsx | 22 ++ .../(main)/boards/[boardId]/boardConstants.ts | 5 + 8 files changed, 311 insertions(+), 310 deletions(-) create mode 100644 src/app/(main)/boards/[boardId]/BoardColumn.tsx create mode 100644 src/app/(main)/boards/[boardId]/BoardEditHeader.tsx create mode 100644 src/app/(main)/boards/[boardId]/BoardRow.tsx create mode 100644 src/app/(main)/boards/[boardId]/BoardViewHeader.tsx create mode 100644 src/app/(main)/boards/[boardId]/boardConstants.ts diff --git a/src/app/(main)/boards/BoardProvider.tsx b/src/app/(main)/boards/BoardProvider.tsx index 1b248e7e8..f96a13ab2 100644 --- a/src/app/(main)/boards/BoardProvider.tsx +++ b/src/app/(main)/boards/BoardProvider.tsx @@ -74,9 +74,7 @@ export function BoardProvider({ // Get current layout sizes from BoardBody if registered const layoutData = layoutGetterRef.current?.(); - console.log('layoutData from getter:', layoutData); const parameters = layoutData ? { ...board.parameters, ...layoutData } : board.parameters; - console.log('parameters to save:', parameters); const result = await mutateAsync({ ...board, diff --git a/src/app/(main)/boards/[boardId]/BoardBody.tsx b/src/app/(main)/boards/[boardId]/BoardBody.tsx index d9133b8fc..5e2c32264 100644 --- a/src/app/(main)/boards/[boardId]/BoardBody.tsx +++ b/src/app/(main)/boards/[boardId]/BoardBody.tsx @@ -1,24 +1,12 @@ -import { Box, Button, Column, Icon, Row, Tooltip, TooltipTrigger } from '@umami/react-zen'; +import { Button, Icon, Row, Tooltip, TooltipTrigger } from '@umami/react-zen'; import { produce } from 'immer'; -import { Fragment, type ReactElement, useEffect, useRef } from 'react'; +import { Fragment, useEffect, useRef } from 'react'; import { Group, type GroupImperativeHandle, Panel, Separator } from 'react-resizable-panels'; import { v4 as uuid } from 'uuid'; import { useBoard } from '@/components/hooks'; -import { ChevronDown, Minus, Plus, X } from '@/components/icons'; -import type { BoardColumn as BoardColumnType } from '@/lib/types'; - -const CATALOG = { - text: { - label: 'Text', - component: BoardColumn, - }, -}; - -const MIN_ROW_HEIGHT = 300; -const MAX_ROW_HEIGHT = 600; -const MIN_COLUMN_WIDTH = 300; -const BUTTON_ROW_HEIGHT = 60; -const MAX_COLUMNS = 4; +import { Plus } from '@/components/icons'; +import { BoardRow } from './BoardRow'; +import { BUTTON_ROW_HEIGHT, MAX_ROW_HEIGHT, MIN_ROW_HEIGHT } from './boardConstants'; export function BoardBody() { const { board, editing, updateBoard, saveBoard, isPending, registerLayoutGetter } = useBoard(); @@ -29,19 +17,14 @@ export function BoardBody() { useEffect(() => { registerLayoutGetter(() => { const rows = board?.parameters?.rows; - console.log('Layout getter called, rows:', rows); - console.log('rowGroupRef.current:', rowGroupRef.current); - console.log('columnGroupRefs.current:', columnGroupRefs.current); if (!rows?.length) return null; const rowLayout = rowGroupRef.current?.getLayout(); - console.log('rowLayout:', rowLayout); const updatedRows = rows.map(row => { const columnGroupRef = columnGroupRefs.current.get(row.id); const columnLayout = columnGroupRef?.getLayout(); - console.log(`Row ${row.id} columnLayout:`, columnLayout); const updatedColumns = row.columns.map(col => ({ ...col, @@ -55,7 +38,6 @@ export function BoardBody() { }; }); - console.log('updatedRows:', updatedRows); return { rows: updatedRows }; }); }, [registerLayoutGetter, board?.parameters?.rows]); @@ -68,8 +50,6 @@ export function BoardBody() { } }; - console.log({ board }); - const handleAddRow = () => { updateBoard({ parameters: produce(board.parameters, draft => { @@ -168,167 +148,3 @@ export function BoardBody() { ); } - -function BoardRow({ - rowId, - rowIndex, - rowCount, - columns, - editing = false, - onRemove, - onMoveUp, - onMoveDown, - onRegisterRef, -}: { - rowId: string; - rowIndex: number; - rowCount: number; - columns: BoardColumnType[]; - editing?: boolean; - onRemove?: (id: string) => void; - onMoveUp?: (id: string) => void; - onMoveDown?: (id: string) => void; - onRegisterRef?: (rowId: string, ref: GroupImperativeHandle | null) => void; -}) { - const { board, updateBoard } = useBoard(); - - const handleGroupRef = (ref: GroupImperativeHandle | null) => { - onRegisterRef?.(rowId, ref); - }; - - const handleAddColumn = () => { - updateBoard({ - parameters: produce(board.parameters, draft => { - const rowIndex = draft.rows.findIndex(row => row.id === rowId); - const row = draft.rows[rowIndex]; - - if (!row) { - draft.rows[rowIndex] = { id: uuid(), columns: [] }; - } - row.columns.push({ id: uuid(), component: null }); - }), - }); - }; - - const handleRemoveColumn = (columnId: string) => { - updateBoard({ - parameters: produce(board.parameters, draft => { - const row = draft.rows.find(row => row.id === rowId); - if (row) { - row.columns = row.columns.filter(col => col.id !== columnId); - } - }), - }); - }; - - return ( - - {columns?.map((column, index) => ( - - - 1} - /> - - {index < columns?.length - 1 && } - - ))} - {editing && ( - - - - Move row up - - - - Add column - - - - Remove row - - - - Move row down - - - )} - - ); -} - -function BoardColumn({ - id, - component, - editing = false, - onRemove, - canRemove = true, -}: { - id: string; - component?: ReactElement; - editing?: boolean; - onRemove?: (id: string) => void; - canRemove?: boolean; -}) { - const handleAddComponent = () => {}; - - return ( - - {editing && canRemove && ( - - - - Remove column - - - )} - {editing && ( - - )} - - ); -} diff --git a/src/app/(main)/boards/[boardId]/BoardColumn.tsx b/src/app/(main)/boards/[boardId]/BoardColumn.tsx new file mode 100644 index 000000000..bfaf22fc9 --- /dev/null +++ b/src/app/(main)/boards/[boardId]/BoardColumn.tsx @@ -0,0 +1,52 @@ +import { Box, Button, Column, Icon, Tooltip, TooltipTrigger } from '@umami/react-zen'; +import type { ReactElement } from 'react'; +import { Plus, X } from '@/components/icons'; + +export function BoardColumn({ + id, + component, + editing = false, + onRemove, + canRemove = true, +}: { + id: string; + component?: ReactElement; + editing?: boolean; + onRemove?: (id: string) => void; + canRemove?: boolean; +}) { + const handleAddComponent = () => {}; + + return ( + + {editing && canRemove && ( + + + + Remove column + + + )} + {editing && ( + + )} + + ); +} diff --git a/src/app/(main)/boards/[boardId]/BoardEditHeader.tsx b/src/app/(main)/boards/[boardId]/BoardEditHeader.tsx new file mode 100644 index 000000000..e49449166 --- /dev/null +++ b/src/app/(main)/boards/[boardId]/BoardEditHeader.tsx @@ -0,0 +1,99 @@ +import { + Button, + Column, + Grid, + Heading, + LoadingButton, + Row, + Text, + TextField, +} from '@umami/react-zen'; +import { useBoard, useMessages, useNavigation } from '@/components/hooks'; +import { WebsiteSelect } from '@/components/input/WebsiteSelect'; + +export function BoardEditHeader() { + const { board, updateBoard, saveBoard, isPending } = useBoard(); + const { formatMessage, labels } = useMessages(); + const { router, renderUrl } = useNavigation(); + const defaultName = formatMessage(labels.untitled); + + const handleNameChange = (value: string) => { + updateBoard({ name: value }); + }; + + const handleDescriptionChange = (value: string) => { + updateBoard({ description: value }); + }; + + const handleWebsiteChange = (websiteId: string) => { + updateBoard({ parameters: { ...board.parameters, websiteId } }); + }; + + const handleSave = async () => { + await saveBoard(); + if (board.id) { + router.push(renderUrl(`/boards/${board.id}`)); + } + }; + + const handleCancel = () => { + if (board.id) { + router.push(renderUrl(`/boards/${board.id}`)); + } else { + router.push(renderUrl('/boards')); + } + }; + + return ( + + + + + {board?.name} + + + + + {board?.description} + + + + {formatMessage(labels.website)} + + + + + + + + {formatMessage(labels.save)} + + + + + ); +} diff --git a/src/app/(main)/boards/[boardId]/BoardHeader.tsx b/src/app/(main)/boards/[boardId]/BoardHeader.tsx index 345da086d..ed2e11970 100644 --- a/src/app/(main)/boards/[boardId]/BoardHeader.tsx +++ b/src/app/(main)/boards/[boardId]/BoardHeader.tsx @@ -1,19 +1,6 @@ -import { - Button, - Column, - Grid, - Heading, - LoadingButton, - Row, - Text, - TextField, -} from '@umami/react-zen'; -import { IconLabel } from '@/components/common/IconLabel'; -import { LinkButton } from '@/components/common/LinkButton'; -import { PageHeader } from '@/components/common/PageHeader'; -import { useBoard, useMessages, useNavigation, useWebsiteQuery } from '@/components/hooks'; -import { Edit } from '@/components/icons'; -import { WebsiteSelect } from '@/components/input/WebsiteSelect'; +import { useBoard } from '@/components/hooks'; +import { BoardEditHeader } from './BoardEditHeader'; +import { BoardViewHeader } from './BoardViewHeader'; export function BoardHeader() { const { board, editing } = useBoard(); @@ -24,106 +11,3 @@ export function BoardHeader() { return ; } - -function BoardViewHeader() { - const { board } = useBoard(); - const { renderUrl } = useNavigation(); - const { formatMessage, labels } = useMessages(); - const { data: website } = useWebsiteQuery(board?.parameters?.websiteId); - - return ( - - {website?.name && {website.name}} - - }>{formatMessage(labels.edit)} - - - ); -} - -function BoardEditHeader() { - const { board, updateBoard, saveBoard, isPending } = useBoard(); - const { formatMessage, labels } = useMessages(); - const { router, renderUrl } = useNavigation(); - const defaultName = formatMessage(labels.untitled); - - const handleNameChange = (value: string) => { - updateBoard({ name: value }); - }; - - const handleDescriptionChange = (value: string) => { - updateBoard({ description: value }); - }; - - const handleWebsiteChange = (websiteId: string) => { - updateBoard({ parameters: { ...board.parameters, websiteId } }); - }; - - const handleSave = async () => { - await saveBoard(); - if (board.id) { - router.push(renderUrl(`/boards/${board.id}`)); - } - }; - - const handleCancel = () => { - if (board.id) { - router.push(renderUrl(`/boards/${board.id}`)); - } else { - router.push(renderUrl('/boards')); - } - }; - - return ( - - - - - {board?.name} - - - - - {board?.description} - - - - {formatMessage(labels.website)} - - - - - - - - {formatMessage(labels.save)} - - - - - ); -} diff --git a/src/app/(main)/boards/[boardId]/BoardRow.tsx b/src/app/(main)/boards/[boardId]/BoardRow.tsx new file mode 100644 index 000000000..7c5ee47ef --- /dev/null +++ b/src/app/(main)/boards/[boardId]/BoardRow.tsx @@ -0,0 +1,125 @@ +import { Button, Column, Icon, Tooltip, TooltipTrigger } from '@umami/react-zen'; +import { produce } from 'immer'; +import { Fragment } from 'react'; +import { Group, type GroupImperativeHandle, Panel, Separator } from 'react-resizable-panels'; +import { v4 as uuid } from 'uuid'; +import { useBoard } from '@/components/hooks'; +import { ChevronDown, Minus, Plus } from '@/components/icons'; +import type { BoardColumn as BoardColumnType } from '@/lib/types'; +import { BoardColumn } from './BoardColumn'; +import { MAX_COLUMNS, MIN_COLUMN_WIDTH } from './boardConstants'; + +export function BoardRow({ + rowId, + rowIndex, + rowCount, + columns, + editing = false, + onRemove, + onMoveUp, + onMoveDown, + onRegisterRef, +}: { + rowId: string; + rowIndex: number; + rowCount: number; + columns: BoardColumnType[]; + editing?: boolean; + onRemove?: (id: string) => void; + onMoveUp?: (id: string) => void; + onMoveDown?: (id: string) => void; + onRegisterRef?: (rowId: string, ref: GroupImperativeHandle | null) => void; +}) { + const { board, updateBoard } = useBoard(); + + const handleGroupRef = (ref: GroupImperativeHandle | null) => { + onRegisterRef?.(rowId, ref); + }; + + const handleAddColumn = () => { + updateBoard({ + parameters: produce(board.parameters, draft => { + const rowIndex = draft.rows.findIndex(row => row.id === rowId); + const row = draft.rows[rowIndex]; + + if (!row) { + draft.rows[rowIndex] = { id: uuid(), columns: [] }; + } + row.columns.push({ id: uuid(), component: null }); + }), + }); + }; + + const handleRemoveColumn = (columnId: string) => { + updateBoard({ + parameters: produce(board.parameters, draft => { + const row = draft.rows.find(row => row.id === rowId); + if (row) { + row.columns = row.columns.filter(col => col.id !== columnId); + } + }), + }); + }; + + return ( + + {columns?.map((column, index) => ( + + + 1} + /> + + {index < columns?.length - 1 && } + + ))} + {editing && ( + + + + Move row up + + + + Add column + + + + Remove row + + + + Move row down + + + )} + + ); +} diff --git a/src/app/(main)/boards/[boardId]/BoardViewHeader.tsx b/src/app/(main)/boards/[boardId]/BoardViewHeader.tsx new file mode 100644 index 000000000..756f39d28 --- /dev/null +++ b/src/app/(main)/boards/[boardId]/BoardViewHeader.tsx @@ -0,0 +1,22 @@ +import { Text } from '@umami/react-zen'; +import { IconLabel } from '@/components/common/IconLabel'; +import { LinkButton } from '@/components/common/LinkButton'; +import { PageHeader } from '@/components/common/PageHeader'; +import { useBoard, useMessages, useNavigation, useWebsiteQuery } from '@/components/hooks'; +import { Edit } from '@/components/icons'; + +export function BoardViewHeader() { + const { board } = useBoard(); + const { renderUrl } = useNavigation(); + const { formatMessage, labels } = useMessages(); + const { data: website } = useWebsiteQuery(board?.parameters?.websiteId); + + return ( + + {website?.name && {website.name}} + + }>{formatMessage(labels.edit)} + + + ); +} diff --git a/src/app/(main)/boards/[boardId]/boardConstants.ts b/src/app/(main)/boards/[boardId]/boardConstants.ts new file mode 100644 index 000000000..91dabd536 --- /dev/null +++ b/src/app/(main)/boards/[boardId]/boardConstants.ts @@ -0,0 +1,5 @@ +export const MIN_ROW_HEIGHT = 300; +export const MAX_ROW_HEIGHT = 600; +export const MIN_COLUMN_WIDTH = 300; +export const BUTTON_ROW_HEIGHT = 60; +export const MAX_COLUMNS = 4;