|
|
@@ -1,5 +1,17 @@
|
|
|
<!-- --------------------------------------------------------------------------- -->
|
|
|
|
|
|
+<!-- --------------------------------------------------------------------------- -->
|
|
|
+
|
|
|
+<!-- Ordner: Docs -->
|
|
|
+
|
|
|
+<!-- Datei: frontend-api-usage.md -->
|
|
|
+
|
|
|
+<!-- Relativer Pfad: Docs/frontend-api-usage.md -->
|
|
|
+
|
|
|
+<!-- --------------------------------------------------------------------------- -->
|
|
|
+
|
|
|
+<!-- --------------------------------------------------------------------------- -->
|
|
|
+
|
|
|
<!-- Folder: Docs -->
|
|
|
|
|
|
<!-- File: frontend-api-usage.md -->
|
|
|
@@ -60,6 +72,10 @@ The core UI flow is a simple drill-down:
|
|
|
7. `getFiles(branch, year, month, day)`
|
|
|
8. Open a PDF via the binary endpoint (see section 4.3)
|
|
|
|
|
|
+Optional (admin/dev):
|
|
|
+
|
|
|
+- use the search endpoint (`GET /api/search`) to implement a global search UI (see section 4.4)
|
|
|
+
|
|
|
### 1.3 Example usage (client-side)
|
|
|
|
|
|
```js
|
|
|
@@ -415,6 +431,97 @@ const href = buildPdfDownloadUrl({ branch, year, month, day, filename });
|
|
|
- If you are logged in on `http://localhost:3000`, also open the PDF on `http://localhost:3000`.
|
|
|
- Switching to `http://127.0.0.1:3000` will not send the cookie (different host) and results in `401`.
|
|
|
|
|
|
+### 4.4 Search
|
|
|
+
|
|
|
+#### `GET /api/search`
|
|
|
+
|
|
|
+This is a **JSON** endpoint.
|
|
|
+
|
|
|
+You can call it via `apiFetch(...)` (or add a small convenience wrapper in `apiClient` when implementing the Search UI).
|
|
|
+
|
|
|
+Query params:
|
|
|
+
|
|
|
+- `q` (required)
|
|
|
+
|
|
|
+Optional filters:
|
|
|
+
|
|
|
+- `scope`: `branch | all | multi`
|
|
|
+- `branch`: single branch
|
|
|
+- `branches`: comma-separated branch list (for `scope=multi`)
|
|
|
+- `from`, `to`: `YYYY-MM-DD`
|
|
|
+- `limit`: page size
|
|
|
+- `cursor`: pagination cursor returned by the previous response
|
|
|
+
|
|
|
+Response shape:
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "items": [
|
|
|
+ {
|
|
|
+ "branch": "NL20",
|
|
|
+ "date": "2025-12-18",
|
|
|
+ "year": "2025",
|
|
|
+ "month": "12",
|
|
|
+ "day": "18",
|
|
|
+ "filename": "...pdf",
|
|
|
+ "relativePath": "NL20/2025/12/18/...pdf",
|
|
|
+ "snippet": "..."
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "nextCursor": "<opaque>"
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+Recommended usage (client-side):
|
|
|
+
|
|
|
+```js
|
|
|
+import { apiFetch } from "@/lib/frontend/apiClient";
|
|
|
+
|
|
|
+export async function searchDeliveryNotes({
|
|
|
+ q,
|
|
|
+ scope,
|
|
|
+ branch,
|
|
|
+ branches,
|
|
|
+ from,
|
|
|
+ to,
|
|
|
+ limit,
|
|
|
+ cursor,
|
|
|
+}) {
|
|
|
+ const params = new URLSearchParams();
|
|
|
+ params.set("q", q);
|
|
|
+ if (scope) params.set("scope", scope);
|
|
|
+ if (branch) params.set("branch", branch);
|
|
|
+ if (branches?.length) params.set("branches", branches.join(","));
|
|
|
+ if (from) params.set("from", from);
|
|
|
+ if (to) params.set("to", to);
|
|
|
+ if (limit) params.set("limit", String(limit));
|
|
|
+ if (cursor) params.set("cursor", cursor);
|
|
|
+
|
|
|
+ return apiFetch(`/api/search?${params.toString()}`);
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+Using a hit to navigate/open:
|
|
|
+
|
|
|
+- Navigate to the day folder:
|
|
|
+
|
|
|
+ - `dayPath(hit.branch, hit.year, hit.month, hit.day)`
|
|
|
+
|
|
|
+- Open the PDF:
|
|
|
+
|
|
|
+ - `buildPdfUrl({ branch: hit.branch, year: hit.year, month: hit.month, day: hit.day, filename: hit.filename })`
|
|
|
+
|
|
|
+Pagination:
|
|
|
+
|
|
|
+- Store `nextCursor` from the response.
|
|
|
+- Pass it back as `cursor=` for the next page.
|
|
|
+- Treat the cursor as opaque.
|
|
|
+
|
|
|
+RBAC note:
|
|
|
+
|
|
|
+- Branch users will only get results for their own branch.
|
|
|
+- Admin/dev users can use `scope=all` or `scope=multi` for cross-branch search.
|
|
|
+
|
|
|
---
|
|
|
|
|
|
## 5. Error handling
|
|
|
@@ -534,7 +641,13 @@ Rules:
|
|
|
## 9. Out of scope / planned additions
|
|
|
|
|
|
- Search UI and filters (route exists as placeholder: `/:branch/search`).
|
|
|
+
|
|
|
+ - Backend support exists via `GET /api/search`.
|
|
|
+ - The UI is still considered a planned addition.
|
|
|
+
|
|
|
- Optional Explorer UX polish:
|
|
|
|
|
|
- add a dedicated “Herunterladen” UI action (download variant)
|
|
|
- optional in-app PDF viewer experience (instead of a new tab)
|
|
|
+
|
|
|
+<!-- --------------------------------------------------------------------------- -->
|