Tristan Yu commited on
Commit
a02bcda
Β·
1 Parent(s): 4632a1e

Fix client directory API URL and authentication - update all client files to use HF backend

Browse files
client/src/contexts/AuthContext.tsx CHANGED
@@ -5,7 +5,7 @@ interface User {
5
  id: string;
6
  username: string;
7
  email: string;
8
- role: 'student' | 'instructor' | 'admin';
9
  targetCultures: string[];
10
  nativeLanguage?: string;
11
  }
@@ -53,10 +53,39 @@ export const AuthProvider: React.FC<AuthProviderProps> = ({ children }) => {
53
  api.defaults.headers.common['Authorization'] = `Bearer ${token}`;
54
  fetchUser();
55
  } else {
56
- setLoading(false);
 
57
  }
58
  }, []);
59
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  const fetchUser = async () => {
61
  try {
62
  const response = await api.get('/api/auth/profile');
@@ -65,6 +94,9 @@ export const AuthProvider: React.FC<AuthProviderProps> = ({ children }) => {
65
  console.error('Failed to fetch user:', error);
66
  localStorage.removeItem('token');
67
  delete api.defaults.headers.common['Authorization'];
 
 
 
68
  } finally {
69
  setLoading(false);
70
  }
@@ -100,28 +132,28 @@ export const AuthProvider: React.FC<AuthProviderProps> = ({ children }) => {
100
  localStorage.removeItem('token');
101
  delete api.defaults.headers.common['Authorization'];
102
  setUser(null);
 
 
103
  };
104
 
105
  const updateProfile = async (data: Partial<User>) => {
106
  try {
107
  const response = await api.put('/api/auth/profile', data);
108
- setUser(response.data.user);
109
  } catch (error: any) {
110
  throw new Error(error.response?.data?.error || 'Profile update failed');
111
  }
112
  };
113
 
114
- const value: AuthContextType = {
115
- user,
116
- loading,
117
- login,
118
- register,
119
- logout,
120
- updateProfile,
121
- };
122
-
123
  return (
124
- <AuthContext.Provider value={value}>
 
 
 
 
 
 
 
125
  {children}
126
  </AuthContext.Provider>
127
  );
 
5
  id: string;
6
  username: string;
7
  email: string;
8
+ role: 'student' | 'instructor' | 'admin' | 'visitor';
9
  targetCultures: string[];
10
  nativeLanguage?: string;
11
  }
 
53
  api.defaults.headers.common['Authorization'] = `Bearer ${token}`;
54
  fetchUser();
55
  } else {
56
+ // Auto-setup visitor authentication
57
+ setupVisitorAuth();
58
  }
59
  }, []);
60
 
61
+ const setupVisitorAuth = async () => {
62
+ try {
63
+ const response = await api.post('/api/auth/login', {
64
+ email: 'visitor@example.com'
65
+ });
66
+ const { token, user } = response.data;
67
+
68
+ localStorage.setItem('token', token);
69
+ api.defaults.headers.common['Authorization'] = `Bearer ${token}`;
70
+ setUser(user);
71
+ } catch (error) {
72
+ console.error('Failed to setup visitor auth:', error);
73
+ // Set a fallback visitor token
74
+ const fallbackToken = `visitor_${Date.now()}`;
75
+ localStorage.setItem('token', fallbackToken);
76
+ api.defaults.headers.common['Authorization'] = `Bearer ${fallbackToken}`;
77
+ setUser({
78
+ id: 'visitor',
79
+ username: 'Visitor',
80
+ email: 'visitor@example.com',
81
+ role: 'visitor',
82
+ targetCultures: []
83
+ });
84
+ } finally {
85
+ setLoading(false);
86
+ }
87
+ };
88
+
89
  const fetchUser = async () => {
90
  try {
91
  const response = await api.get('/api/auth/profile');
 
94
  console.error('Failed to fetch user:', error);
95
  localStorage.removeItem('token');
96
  delete api.defaults.headers.common['Authorization'];
97
+ // Try to setup visitor auth as fallback
98
+ setupVisitorAuth();
99
+ return;
100
  } finally {
101
  setLoading(false);
102
  }
 
132
  localStorage.removeItem('token');
133
  delete api.defaults.headers.common['Authorization'];
134
  setUser(null);
135
+ // Setup visitor auth after logout
136
+ setupVisitorAuth();
137
  };
138
 
139
  const updateProfile = async (data: Partial<User>) => {
140
  try {
141
  const response = await api.put('/api/auth/profile', data);
142
+ setUser(response.data);
143
  } catch (error: any) {
144
  throw new Error(error.response?.data?.error || 'Profile update failed');
145
  }
146
  };
147
 
 
 
 
 
 
 
 
 
 
148
  return (
149
+ <AuthContext.Provider value={{
150
+ user,
151
+ loading,
152
+ login,
153
+ register,
154
+ logout,
155
+ updateProfile
156
+ }}>
157
  {children}
158
  </AuthContext.Provider>
159
  );
client/src/index.tsx CHANGED
@@ -1,6 +1,7 @@
1
  import React from 'react';
2
  import ReactDOM from 'react-dom/client';
3
  import { BrowserRouter } from 'react-router-dom';
 
4
  import './index.css';
5
  import App from './App';
6
 
@@ -11,7 +12,9 @@ const root = ReactDOM.createRoot(
11
  root.render(
12
  <React.StrictMode>
13
  <BrowserRouter>
14
- <App />
 
 
15
  </BrowserRouter>
16
  </React.StrictMode>
17
  );
 
1
  import React from 'react';
2
  import ReactDOM from 'react-dom/client';
3
  import { BrowserRouter } from 'react-router-dom';
4
+ import { AuthProvider } from './contexts/AuthContext';
5
  import './index.css';
6
  import App from './App';
7
 
 
12
  root.render(
13
  <React.StrictMode>
14
  <BrowserRouter>
15
+ <AuthProvider>
16
+ <App />
17
+ </AuthProvider>
18
  </BrowserRouter>
19
  </React.StrictMode>
20
  );
client/src/services/api.ts CHANGED
@@ -1,14 +1,24 @@
1
  import axios from 'axios';
2
 
3
  // Create axios instance with base configuration
 
4
  const api = axios.create({
5
- baseURL: process.env.REACT_APP_API_URL || 'http://localhost:5000/api',
6
  headers: {
7
  'Content-Type': 'application/json',
8
  },
9
  timeout: 10000, // 10 second timeout
10
  });
11
 
 
 
 
 
 
 
 
 
 
12
  // Request interceptor to add auth token and user role
13
  api.interceptors.request.use(
14
  (config) => {
@@ -28,6 +38,10 @@ api.interceptors.request.use(
28
  }
29
  }
30
 
 
 
 
 
31
  return config;
32
  },
33
  (error) => {
@@ -38,14 +52,24 @@ api.interceptors.request.use(
38
  // Response interceptor to handle errors
39
  api.interceptors.response.use(
40
  (response) => {
 
41
  return response;
42
  },
43
  (error) => {
 
44
  if (error.response?.status === 401) {
45
  // Token expired or invalid
46
  localStorage.removeItem('token');
47
  localStorage.removeItem('user');
48
  window.location.href = '/login';
 
 
 
 
 
 
 
 
49
  } else if (error.response?.status === 500) {
50
  console.error('Server error:', error.response.data);
51
  } else if (error.code === 'ECONNABORTED') {
 
1
  import axios from 'axios';
2
 
3
  // Create axios instance with base configuration
4
+ // FORCE REBUILD: Updated API URL to fix production build
5
  const api = axios.create({
6
+ baseURL: 'https://linguabot-transcreation-backend.hf.space/api',
7
  headers: {
8
  'Content-Type': 'application/json',
9
  },
10
  timeout: 10000, // 10 second timeout
11
  });
12
 
13
+ // Debug: Log the API URL being used
14
+ console.log('πŸ”§ API CONFIGURATION DEBUG - CLIENT BUILD:');
15
+ console.log('API Base URL: https://linguabot-transcreation-backend.hf.space/api');
16
+ console.log('Environment variables:', {
17
+ REACT_APP_API_URL: process.env.REACT_APP_API_URL,
18
+ NODE_ENV: process.env.NODE_ENV
19
+ });
20
+ console.log('Build timestamp:', new Date().toISOString()); // Force rebuild - Updated for data restoration
21
+
22
  // Request interceptor to add auth token and user role
23
  api.interceptors.request.use(
24
  (config) => {
 
38
  }
39
  }
40
 
41
+ // Debug: Log the actual request URL
42
+ console.log('πŸš€ Making API request to:', (config.baseURL || '') + (config.url || ''));
43
+ console.log('πŸ”‘ Auth token:', token ? 'Present' : 'Missing');
44
+
45
  return config;
46
  },
47
  (error) => {
 
52
  // Response interceptor to handle errors
53
  api.interceptors.response.use(
54
  (response) => {
55
+ console.log('βœ… API response received:', response.config.url);
56
  return response;
57
  },
58
  (error) => {
59
+ console.error('❌ API request failed:', error.config?.url, error.message);
60
  if (error.response?.status === 401) {
61
  // Token expired or invalid
62
  localStorage.removeItem('token');
63
  localStorage.removeItem('user');
64
  window.location.href = '/login';
65
+ } else if (error.response?.status === 429) {
66
+ // Rate limit exceeded - retry after delay
67
+ console.warn('Rate limit exceeded, retrying after delay...');
68
+ return new Promise(resolve => {
69
+ setTimeout(() => {
70
+ resolve(api.request(error.config));
71
+ }, 2000); // Wait 2 seconds before retry
72
+ });
73
  } else if (error.response?.status === 500) {
74
  console.error('Server error:', error.response.data);
75
  } else if (error.code === 'ECONNABORTED') {