577b052c05
User Profile (US-004): - Add authenticated profile endpoints (GET/PUT /users/me) - Add avatar upload with file validation (PNG/JPEG, max 2MB) - Create frontend profile page with edit form and avatar upload - Update app shell to link to profile page OAuth/Traefik Integration: - Externalize all Authentik URLs to environment variables - Add domain configuration (API_DOMAIN, WEB_DOMAIN, AUTHENTIK_DOMAIN) - Create docker-compose.traefik.yml for reverse proxy deployment - Update OAuth redirect/callback URLs to use configured domains - Add VITE_APP_URL for frontend public URL configuration Quality gates: pytest (50 passed), ruff, mypy, npm test (12 passed), typecheck, lint, build
31 lines
880 B
TypeScript
31 lines
880 B
TypeScript
import { apiClient } from "./client";
|
|
import type { SessionUser } from "../types";
|
|
|
|
export type UserProfile = SessionUser;
|
|
|
|
export type ProfileUpdatePayload = {
|
|
name?: string;
|
|
email?: string;
|
|
};
|
|
|
|
export const getProfile = async (): Promise<UserProfile> => {
|
|
const response = await apiClient.get<UserProfile>("/users/me");
|
|
return response.data;
|
|
};
|
|
|
|
export const updateProfile = async (payload: ProfileUpdatePayload): Promise<UserProfile> => {
|
|
const response = await apiClient.put<UserProfile>("/users/me", payload);
|
|
return response.data;
|
|
};
|
|
|
|
export const uploadAvatar = async (file: File): Promise<UserProfile> => {
|
|
const formData = new FormData();
|
|
formData.append("file", file);
|
|
const response = await apiClient.post<UserProfile>("/users/me/avatar", formData, {
|
|
headers: {
|
|
"Content-Type": "multipart/form-data",
|
|
},
|
|
});
|
|
return response.data;
|
|
};
|