diff --git a/src/api/client.ts b/src/api/client.ts new file mode 100644 index 0000000..408e66f --- /dev/null +++ b/src/api/client.ts @@ -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); + }, +); diff --git a/src/components/LoadingSpinner.tsx b/src/components/LoadingSpinner.tsx new file mode 100644 index 0000000..4a54c47 --- /dev/null +++ b/src/components/LoadingSpinner.tsx @@ -0,0 +1,14 @@ +import React from 'react'; + +interface Props { size?: number; } + +export const LoadingSpinner: React.FC = ({ size = 32 }) => ( +
+ + + + + + +
+);