diff --git a/frontend/src/lib/auth-api.ts b/frontend/src/lib/auth-api.ts new file mode 100644 index 0000000..cbc89f7 --- /dev/null +++ b/frontend/src/lib/auth-api.ts @@ -0,0 +1,27 @@ +/** + * Auth API calls (#1507). + * + * The security settings "Change password" form reported success without calling + * any API. This provides the missing call so the UI reflects the real result. + */ +import { apiUrl } from "./api-version"; + +export interface ChangePasswordPayload { + currentPassword: string; + newPassword: string; +} + +export async function changePassword( + payload: ChangePasswordPayload, + fetchImpl: typeof fetch = fetch, +): Promise { + const response = await fetchImpl(apiUrl("/auth/change-password"), { + method: "POST", + headers: { "Content-Type": "application/json" }, + credentials: "include", + body: JSON.stringify(payload), + }); + if (!response.ok) { + throw new Error(`Failed to change password (${response.status})`); + } +} diff --git a/frontend/src/lib/profile-api.ts b/frontend/src/lib/profile-api.ts new file mode 100644 index 0000000..b350cc4 --- /dev/null +++ b/frontend/src/lib/profile-api.ts @@ -0,0 +1,59 @@ +/** + * Profile and admin activity loaders (#1506, #1505, #1504). + * + * The profile page showed a hard-coded "Jane Doe" and faked saving with a + * timeout; the admin activity page fell back to MOCK_ACTIVITY; the report page + * silently showed a fake "Sample Land Title". These loaders return the real API + * result and never substitute fake data — callers are expected to render an + * empty/error state instead. + */ +import { apiUrl } from "./api-version"; + +export interface UserProfile { + id: string; + name: string; + email: string; +} + +export async function loadProfile( + fetchImpl: typeof fetch = fetch, +): Promise { + const response = await fetchImpl(apiUrl("/users/me"), { + credentials: "include", + }); + if (response.status === 401) { + return null; + } + if (!response.ok) { + throw new Error(`Failed to load profile (${response.status})`); + } + return (await response.json()) as UserProfile; +} + +export async function loadAdminActivity( + fetchImpl: typeof fetch = fetch, +): Promise { + const response = await fetchImpl(apiUrl("/admin/activity"), { + credentials: "include", + }); + if (!response.ok) { + throw new Error(`Failed to load activity (${response.status})`); + } + return (await response.json()) as T[]; +} + +export async function loadReport( + reportId: string, + fetchImpl: typeof fetch = fetch, +): Promise { + const response = await fetchImpl(apiUrl(`/reports/${reportId}`), { + credentials: "include", + }); + if (response.status === 404) { + return null; + } + if (!response.ok) { + throw new Error(`Failed to load report (${response.status})`); + } + return (await response.json()) as T; +}