Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions frontend/src/lib/auth-api.ts
Original file line number Diff line number Diff line change
@@ -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<void> {
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})`);
}
}
59 changes: 59 additions & 0 deletions frontend/src/lib/profile-api.ts
Original file line number Diff line number Diff line change
@@ -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<UserProfile | null> {
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<T>(
fetchImpl: typeof fetch = fetch,
): Promise<T[]> {
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<T>(
reportId: string,
fetchImpl: typeof fetch = fetch,
): Promise<T | null> {
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;
}