P4N Favorites Management
Relevant source files
The following files were used as context for generating this wiki page:
P4N Favorites Management is a core system within the P4N Map application that allows users to organize, view, and manage their bookmarked locations from Park4Night. It provides a bridge between the application's planning capabilities and the user's Park4Night account, enabling CRUD operations on bookmark folders and individual location entries. Sources: README.md, src/components/Planner.tsx:162-175
The system is designed as a client-server architecture where the frontend manages local state and UI interactions, while a dedicated Node.js backend proxies requests to private Park4Night endpoints using the user's PHPSESSID. Sources: README.md, src/lib/p4n.ts:5-10
Architecture and Components
Frontend Module: FavouritesBoard
The primary user interface for managing bookmarks is the FavouritesBoard component. It implements a dual-pane layout: a "Folder rail" on the left for navigation and folder management, and a "Places list" on the right for displaying bookmarks within the selected folder. Sources: src/components/FavouritesBoard.tsx:112-115, src/components/FavouritesBoard.tsx:210-213
Key UI features include:
- Drag-and-Drop: Users can move places between folders by dragging them from the list onto a folder icon in the rail. Sources: src/components/FavouritesBoard.tsx:88-109
- Inbox Logic: The system identifies a specific "Unclassified" folder, which typically maps to the main Park4Night favorites inbox (limited to 200 items). Sources: src/components/FavouritesBoard.tsx:16-24
- Folder Operations: Supports creating new folders with custom icons and deleting existing folders. Sources: src/components/FavouritesBoard.tsx:64-74, src/components/FavouritesBoard.tsx:140-184
Data Structures
The favorites system relies on standardized TypeScript interfaces to ensure consistency between the API and the UI.
| Type | Description | Key Fields |
|---|---|---|
BookmarkFolder | Represents a Park4Night folder. | id, name, icon, bookmarks[], max_size |
P4nPlace | The core location data object. | id, name, lat, lng, services[], rating |
P4nUser | User profile containing account-level data. | id, uuid, isPremium, bookmarksFolders[] |
Sources: src/lib/types.ts:79-85, src/lib/types.ts:88-97, src/lib/types.ts:34-56
Backend API and Data Flow
The backend handles session authentication and executes requests against Park4Night's internal API. It uses a fetchWithRetry mechanism and decodes responses that are often base64-encoded JSON. Sources: src/lib/p4n.ts:32-45, src/lib/p4n.ts:56-65
Sequence: Moving a Bookmark
Moving a bookmark is an atomic operation on the frontend but requires a two-step process on the backend (add then remove) to prevent data loss in case of partial failure. Sources: src/lib/p4n.ts:167-175
The logic for moving a bookmark ensures the destination folder receives the item before it is purged from the source. Sources: src/app/api/bookmarks/move/route.ts:28-36, src/lib/p4n.ts:173-174
API Endpoints
| Endpoint | Method | Purpose |
|---|---|---|
/api/bookmarks | POST | Adds a place to favorites (or specific folder). |
/api/bookmarks | DELETE | Removes a place from favorites. |
/api/bookmarks/move | POST | Relocates a place between two folders. |
/api/bookmarks/{id} | GET | Fetches all full place objects in a folder. |
/api/folders | POST | Creates a new user folder. |
/api/folders/{id} | DELETE | Deletes an existing folder. |
Sources: src/app/api/bookmarks/route.ts:14-25, src/app/api/bookmarks/route.ts:38-50, src/app/api/bookmarks/move/route.ts:17-26, src/lib/client.ts:58-95
Logic and Utility Functions
Folder Resolution
Because Park4Night uses different endpoints for the "Main" inbox versus custom folders, the system employs resolution logic to determine if a UI action should target the inbox (sentinel UNCLASSIFIED_ID = -1) or a specific folder ID. Sources: src/components/FavouritesBoard.tsx:13-14, src/components/FavouritesBoard.tsx:32-37
Server-side Implementation: addBookmark
The server-side implementation in lib/p4n.ts distinguishes between adding to the default favorites list and adding to a specific folder by switching between POST and PUT methods. Sources: src/lib/p4n.ts:133-149
export async function addBookmark(placeId: number, folderId?: number): Promise<void> {
if (folderId != null) {
const res = await fetchWithRetry(`${BASE}/api/user/folder/${folderId}/bookmarks`, {
method: "PUT",
headers: await baseHeaders({ "Content-Type": "application/json" }),
body: JSON.stringify({ id: placeId }),
});
if (!res.ok) throw new Error(`Could not add favourite (${res.status}).`);
return;
}
// ... fallback to default inbox via POST ...
}
Sources: src/lib/p4n.ts:134-143
Summary
The P4N Favorites Management system provides a robust interface for organizing Park4Night data. By abstracting the complexities of the Park4Night private API—such as base64 encoding and inconsistent folder behaviors—into a clean React interface and a set of Node.js route handlers, the system enables users to seamlessly transition between high-level trip planning and granular organization of their saved locations. Sources: src/lib/p4n.ts:5-10, src/components/Planner.tsx:162-175