();
for (const p of properties) map.set(p.id, p);
return map;
}, [properties]);
return (
{headerGroups[0]?.headers.map((header) => (
))}
...
```
Make sure `useMemo` is imported from react (it already imports `memo`; add `useMemo` alongside).
- [ ] **Step 2: Build**
```bash
pnpm nx run client:build
```
Still expected to fail — `GridContainer` doesn't yet pass `properties`. Next task.
---
## Task 3: `GridContainer` — accept and forward `properties`
**Files:**
- Modify: `apps/client/src/features/base/components/grid/grid-container.tsx`
- [ ] **Step 1: Add `properties` to props**
Near the existing `GridContainerProps` type (look near the top of the file), add:
```tsx
properties: IBaseProperty[];
```
Add `IBaseProperty` to the existing `@/features/base/types/base.types` import at the top of the file if it's not already imported.
Destructure it in the component signature.
- [ ] **Step 2: Pass it to ``**
Find the `` JSX at roughly line 239-245 and add:
```tsx
```
- [ ] **Step 3: Build**
Still expected to fail — `BaseTable` doesn't yet pass `properties` to `GridContainer`. Next task.
---
## Task 4: `BaseTable` — pass `base.properties` to `GridContainer`
**Files:**
- Modify: `apps/client/src/features/base/components/base-table.tsx`
- [ ] **Step 1: Add the prop**
Find the `` JSX at line 187. Add:
```tsx
```
`base` is already guaranteed non-null at this point — line 174 has `if (!base) return null;`.
- [ ] **Step 2: Build**
```bash
pnpm nx run client:build
```
Should succeed now — grid path is complete.
- [ ] **Step 3: Commit the grid-side changes as one unit**
```bash
git add \
apps/client/src/features/base/components/grid/grid-header-cell.tsx \
apps/client/src/features/base/components/grid/grid-header.tsx \
apps/client/src/features/base/components/grid/grid-container.tsx \
apps/client/src/features/base/components/base-table.tsx
git commit -m "fix(base): refresh grid headers when a property is renamed"
```
The four files have to land together or the build is broken — one commit.
---
## Task 5: `ViewFieldVisibility` — accept `properties` and include it in the memo
**Files:**
- Modify: `apps/client/src/features/base/components/views/view-field-visibility.tsx`
- [ ] **Step 1: Add `properties` to the props type**
```tsx
type ViewFieldVisibilityProps = {
opened: boolean;
onClose: () => void;
table: Table;
properties: IBaseProperty[];
onPersist: () => void;
children: React.ReactNode;
};
```
- [ ] **Step 2: Add `properties` to the `useMemo` dep list**
Change:
```tsx
const columns = useMemo(() => {
return table
.getAllLeafColumns()
.filter((col) => col.id !== "__row_number");
}, [table]);
```
To:
```tsx
const columns = useMemo(() => {
return table
.getAllLeafColumns()
.filter((col) => col.id !== "__row_number");
}, [table, properties]);
```
We still derive columns from `table` (that's where `col.getIsVisible()` / `col.getCanHide()` live), but `properties` is added as a dep so the memo invalidates whenever properties change — forcing a re-read of `table.getAllLeafColumns()` which by then reflects the renamed metadata.
Also destructure `properties` in the function signature.
- [ ] **Step 3: Build**
Expected to fail until the toolbar passes `properties`.
---
## Task 6: `BaseToolbar` — pass `base.properties` to `ViewFieldVisibility`
**Files:**
- Modify: `apps/client/src/features/base/components/base-toolbar.tsx`
- [ ] **Step 1: Pass the prop**
Find `` (near the bottom of the file). Add:
```tsx
setFieldsOpened(false)}
table={table}
properties={base.properties}
onPersist={onPersistViewConfig}
>
```
`base` is already a prop on `BaseToolbar` — no other plumbing needed.
- [ ] **Step 2: Build**
```bash
pnpm nx run client:build
```
Should succeed.
- [ ] **Step 3: Commit the popover-side changes**
```bash
git add \
apps/client/src/features/base/components/views/view-field-visibility.tsx \
apps/client/src/features/base/components/base-toolbar.tsx
git commit -m "fix(base): refresh hide-fields popover when a property is renamed"
```
---
## Task 7: USER smoke test
> ⚠️ **Do not run `pnpm dev` as an agent.** Hand off to the user.
Ask the user to run through:
- [ ] **Local rename updates the grid header instantly.**
1. Open a base.
2. Click a column header → Rename → type a new name → press Enter.
3. The column header text updates immediately — no reload.
- [ ] **Local rename updates the hide-fields popover instantly.**
1. After renaming, open the Hide fields popover.
2. The property's entry in the list shows the new name.
- [ ] **Remote rename (other client) updates without reload.**
1. Open the same base in two browsers / tabs (A and B).
2. In A, rename a property.
3. In B, within a second, the header text (and hide-fields popover) show the new name.
- [ ] **Regression: column resize, reorder, hide, sort, filter all still work.**
If all pass, the fix is complete. Otherwise report back with which case failed.
---
## Out of scope
- `ViewSortConfigPopover` / `ViewFilterConfigPopover` also show property names, but they read from `base.properties` directly (they already get `base` as a prop and re-render when it changes), so they weren't broken by this bug. Not touching them.
- Property icons (`property.type` change). A type change already bumps `schemaVersion` on the base, which invalidates and refetches — that path works. Out of scope here.
- Server-side — rename already persists + broadcasts correctly.