Repository navigation
Feature/t227 account profile UI #66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b986442
12e2168
f614837
7dcf58b
c42bf18
f98b0a9
5a2c634
43e7662
682ff3f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| import axios from "axios" | ||
| import { clearAuth, getAuthorizationHeader } from "./authService" | ||
|
|
||
| const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || "http://localhost:8080" | ||
| const API_TIMEOUT_MS = 15000 | ||
|
|
||
| const dashboardClient = axios.create({ | ||
| baseURL: API_BASE_URL, | ||
| timeout: API_TIMEOUT_MS, | ||
| headers: { "Content-Type": "application/json" }, | ||
| }) | ||
|
|
||
| const request = async (config, fallback) => { | ||
| try { | ||
| const { data } = await dashboardClient.request({ | ||
| ...config, | ||
| headers: getAuthorizationHeader(), | ||
| }) | ||
| return data | ||
| } catch (error) { | ||
| if (error.response?.status === 401) clearAuth() | ||
| throw { | ||
| status: error.response?.status || 0, | ||
| message: error.response?.data?.message || fallback, | ||
| errors: error.response?.data?.errors || {}, | ||
| } | ||
| } | ||
| } | ||
|
|
||
| export const getDashboardOverview = () => request( | ||
| { method: "get", url: "/api/dashboard/overview" }, | ||
| "Không thể tải dữ liệu dashboard.", | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| import axios from 'axios' | ||
| import { clearAuth, getAuthorizationHeader, getCurrentUser } from './authService' | ||
|
|
||
| const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8080' | ||
| const API_TIMEOUT_MS = 15000 | ||
|
|
||
| const profileClient = axios.create({ | ||
| baseURL: API_BASE_URL, | ||
| timeout: API_TIMEOUT_MS, | ||
| headers: { | ||
| 'Content-Type': 'application/json', | ||
| }, | ||
| }) | ||
|
|
||
| export async function getCurrentProfile() { | ||
| const fallbackProfile = normalizeProfile(getCurrentUser()) | ||
|
|
||
| let lastError = null | ||
|
|
||
| try { | ||
| const endpoints = ['/api/auth/me', '/api/auth/profile'] | ||
| const currentUser = getCurrentUser() | ||
|
|
||
| if (currentUser?.employeeId) { | ||
| endpoints.unshift(`/api/employees/${currentUser.employeeId}`) | ||
| } | ||
|
|
||
| for (const endpoint of endpoints) { | ||
| try { | ||
| const { data } = await profileClient.get(endpoint, { | ||
| headers: getAuthorizationHeader(), | ||
| }) | ||
|
|
||
| const normalized = normalizeProfile(data, fallbackProfile) | ||
| if (hasProfileData(normalized)) { | ||
| return normalized | ||
| } | ||
| } catch (error) { | ||
| const normalizedError = normalizeProfileError(error, 'Phiên đăng nhập đã hết hạn.') | ||
|
|
||
| if (normalizedError.status === 401) { | ||
| clearAuth() | ||
| throw normalizedError | ||
| } | ||
|
|
||
| lastError = normalizedError | ||
|
|
||
| if (error.response?.status === 404) { | ||
| continue | ||
|
Comment on lines
+46
to
+49
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Không lưu lỗi Line 46 lưu Chỉ gán Đề xuất sửa- lastError = normalizedError
-
if (error.response?.status === 404) {
continue
}
+ lastError = normalizedError
+
if (error.response?.status && error.response.status < 500) {🤖 Prompt for AI AgentsSource: Path instructions |
||
| } | ||
|
|
||
| if (error.response?.status && error.response.status < 500) { | ||
| break | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (hasProfileData(fallbackProfile)) { | ||
| return fallbackProfile | ||
| } | ||
|
|
||
| if (lastError) { | ||
| throw lastError | ||
| } | ||
|
|
||
| return null | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| } catch (error) { | ||
| const normalizedError = normalizeProfileError(error, 'Không thể tải thông tin hồ sơ.') | ||
|
|
||
| if (normalizedError.status === 401) { | ||
| throw normalizedError | ||
| } | ||
|
|
||
| if (hasProfileData(fallbackProfile)) { | ||
| return fallbackProfile | ||
| } | ||
|
|
||
| throw normalizedError | ||
| } | ||
| } | ||
|
|
||
| function normalizeProfile(data = {}, fallback = {}) { | ||
| return { | ||
| id: data?.id ?? data?.employeeId ?? fallback?.id ?? fallback?.employeeId ?? null, | ||
| employeeId: data?.employeeId ?? data?.id ?? fallback?.employeeId ?? fallback?.id ?? null, | ||
| fullName: data?.fullName ?? fallback?.fullName ?? '', | ||
| email: data?.email ?? fallback?.email ?? '', | ||
| role: data?.roleName ?? data?.role ?? data?.roleCode ?? fallback?.roleName ?? fallback?.role ?? fallback?.roleCode ?? '', | ||
| roleCode: data?.roleCode ?? fallback?.roleCode ?? '', | ||
| status: data?.status ?? fallback?.status ?? '', | ||
| } | ||
| } | ||
|
|
||
| function hasProfileData(profile) { | ||
| return Boolean(profile?.fullName || profile?.email || profile?.role || profile?.status || profile?.employeeId) | ||
| } | ||
|
|
||
| function normalizeProfileError(error, fallbackMessage) { | ||
| if (error?.response?.status === 401) { | ||
| clearAuth() | ||
| } | ||
|
|
||
| if (error?.response?.data) { | ||
| return { | ||
| status: error.response.status, | ||
| message: error.response.data.message || fallbackMessage, | ||
| } | ||
| } | ||
|
|
||
| return { | ||
| status: error?.status || 0, | ||
| message: error?.message || fallbackMessage, | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.