Anton Tranelis 649efe551d
refactor(lib): implement server-response-first pattern (#322)
* use server response for local state updates

* fix formatting

* refactor: comprehensive server-response-first pattern implementation

## Major Changes

### LayerProps ID Required
- Made `LayerProps.id` required (was optional)
- All layers now guaranteed to have server-provided UUID
- Enables reliable layer ID mapping from server responses

### useSelectPosition Hook Refactored
- Added reusable `handleApiOperation` helper function
- Refactored `itemUpdatePosition`, `itemUpdateParent`, `linkItem`
- All functions now use server response + layer ID mapping
- Consistent error handling and toast management

### itemFunctions.ts Complete Refactor
- **submitNewItem**: Server response with layer mapping
- **linkItem**: Server response preserves layer object
- **unlinkItem**: Same pattern as linkItem
- **handleDelete**: Simplified error handling
- **onUpdateItem**: Complex function refactored for both update/create branches

### Benefits
-  Eliminates race conditions from manual state construction
-  Server response as single source of truth for all updates
-  Consistent error handling across all API operations
-  Items no longer disappear from map after updates
-  Type-safe layer ID mapping

### Testing
- Updated ItemFunctions.spec.tsx with new toast patterns
- Added required layer IDs to test objects
- All 19 tests passing (3 skipped)
- ESLint clean

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix linting

* fix: resolve TypeScript undefined data errors

- Add non-null assertions for result.data in conditional blocks
- TypeScript now properly recognizes data is defined after success check
- All linting and TypeScript errors resolved

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fixed examples

* remove unneccessary uuid generation

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-20 15:03:30 +02:00

76 lines
1.6 KiB
TypeScript

import { UtopiaMap, Layer } from "utopia-ui"
import { events, places } from "./sample-data"
const itemTypeEvent = {
id: "a6dbf1a7-adf2-4ff5-8e20-d3aad66635fb",
name: "event",
show_name_input: false,
show_profile_button: false,
show_start_end: false,
show_start_end_input: false,
show_text: false,
show_text_input: false,
custom_text: "",
profileTemplate: [],
offers_and_needs: false,
icon_as_labels: null,
relations: false,
template: "TODO",
questlog: false,
}
const itemTypePlace = {
name: "event",
show_name_input: false,
show_profile_button: false,
show_start_end: false,
show_start_end_input: false,
show_text: false,
show_text_input: false,
custom_text: "",
profileTemplate: [],
offers_and_needs: false,
icon_as_labels: null,
relations: false,
template: "TODO",
questlog: false,
}
function App() {
return (
<UtopiaMap center={[50.6, 15.5]} zoom={5} height='100dvh' width="100dvw">
<Layer
id="8b6892ea-4ca3-4b86-8060-b0371a8dd375"
name='events'
markerIcon={
{image: "calendar.svg",
size: 13
}
}
markerShape='square'
markerDefaultColor='#700'
data={events}
menuIcon="calendar"
menuColor="#700"
menuText="events"
itemType={itemTypeEvent}
/>
<Layer
id="eea49637-1232-42f9-aec9-77b3187d5d7c"
name='places'
markerIcon={
{image: "point.svg"}
}
markerShape='circle'
markerDefaultColor='#007'
data={places}
menuIcon="point"
menuColor="#007"
menuText="places"
itemType={itemTypePlace}
/>
</UtopiaMap>
)
}
export default App