Add LoadingSpinner and API client with auth interceptors
This commit is contained in:
parent
416b331703
commit
9f19912bdd
2 changed files with 37 additions and 0 deletions
23
src/api/client.ts
Normal file
23
src/api/client.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import axios from 'axios';
|
||||
|
||||
export const apiClient = axios.create({
|
||||
baseURL: import.meta.env.VITE_API_BASE_URL ?? '/api',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
|
||||
apiClient.interceptors.request.use((config) => {
|
||||
const token = localStorage.getItem('access_token');
|
||||
if (token) config.headers.Authorization = `Bearer ${token}`;
|
||||
return config;
|
||||
});
|
||||
|
||||
apiClient.interceptors.response.use(
|
||||
(r) => r,
|
||||
(err) => {
|
||||
if (err.response?.status === 401) {
|
||||
localStorage.removeItem('access_token');
|
||||
window.location.href = '/login';
|
||||
}
|
||||
return Promise.reject(err);
|
||||
},
|
||||
);
|
||||
14
src/components/LoadingSpinner.tsx
Normal file
14
src/components/LoadingSpinner.tsx
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import React from 'react';
|
||||
|
||||
interface Props { size?: number; }
|
||||
|
||||
export const LoadingSpinner: React.FC<Props> = ({ size = 32 }) => (
|
||||
<div role="status" aria-label="Loading" style={{ width: size, height: size }}>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2}>
|
||||
<circle cx={12} cy={12} r={10} strokeOpacity={0.25} />
|
||||
<path d="M12 2 a10 10 0 0 1 10 10" strokeLinecap="round">
|
||||
<animateTransform attributeName="transform" type="rotate" from="0 12 12" to="360 12 12" dur="0.8s" repeatCount="indefinite" />
|
||||
</path>
|
||||
</svg>
|
||||
</div>
|
||||
);
|
||||
Loading…
Reference in a new issue