aboutsummaryrefslogtreecommitdiffstats
path: root/frontend/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/src/lib')
-rw-r--r--frontend/src/lib/api/auth.js90
-rw-r--r--frontend/src/lib/api/index.js40
-rw-r--r--frontend/src/lib/utils.js6
3 files changed, 136 insertions, 0 deletions
diff --git a/frontend/src/lib/api/auth.js b/frontend/src/lib/api/auth.js
new file mode 100644
index 0000000..85ed28f
--- /dev/null
+++ b/frontend/src/lib/api/auth.js
@@ -0,0 +1,90 @@
+import api from './index';
+
+/**
+ * Register a new user
+ * @param {Object} userData - User registration data
+ * @returns {Promise} - Promise with registration response
+ */
+export const register = async (userData) => {
+ try {
+ const response = await api.post('/auth/register', userData);
+ return response.data;
+ } catch (error) {
+ throw error.response?.data || { message: 'Registration failed' };
+ }
+};
+
+/**
+ * Login a user
+ * @param {Object} credentials - User login credentials
+ * @returns {Promise} - Promise with login response
+ */
+export const login = async (credentials) => {
+ try {
+ const response = await api.post('/auth/login', credentials);
+
+ // Store token and user data
+ if (response.data.token) {
+ localStorage.setItem('token', response.data.token);
+ localStorage.setItem('user', JSON.stringify(response.data.user));
+ }
+
+ return response.data;
+ } catch (error) {
+ throw error.response?.data || { message: 'Login failed' };
+ }
+};
+
+/**
+ * Get current user profile
+ * @returns {Promise} - Promise with user profile data
+ */
+export const getProfile = async () => {
+ try {
+ const response = await api.get('/auth/profile');
+ return response.data;
+ } catch (error) {
+ throw error.response?.data || { message: 'Failed to get profile' };
+ }
+};
+
+/**
+ * Logout current user
+ */
+export const logout = () => {
+ localStorage.removeItem('token');
+ localStorage.removeItem('user');
+
+ // Force reload to clear any state
+ if (typeof window !== 'undefined') {
+ window.location.href = '/login';
+ }
+};
+
+/**
+ * Check if user is authenticated
+ * @returns {Boolean} - True if user is authenticated
+ */
+export const isAuthenticated = () => {
+ if (typeof window === 'undefined') return false;
+
+ const token = localStorage.getItem('token');
+ return !!token;
+};
+
+/**
+ * Get current user data
+ * @returns {Object|null} - User data or null if not authenticated
+ */
+export const getCurrentUser = () => {
+ if (typeof window === 'undefined') return null;
+
+ const userStr = localStorage.getItem('user');
+ if (!userStr) return null;
+
+ try {
+ return JSON.parse(userStr);
+ } catch (e) {
+ return null;
+ }
+}; \ No newline at end of file
diff --git a/frontend/src/lib/api/index.js b/frontend/src/lib/api/index.js
new file mode 100644
index 0000000..dca56e3
--- /dev/null
+++ b/frontend/src/lib/api/index.js
@@ -0,0 +1,40 @@
+import axios from 'axios';
+
+const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:5000/api';
+
+const api = axios.create({
+ baseURL: API_URL,
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+});
+
+// Request interceptor to add authorization header
+api.interceptors.request.use(
+ (config) => {
+ const token = localStorage.getItem('token');
+ if (token) {
+ config.headers.Authorization = `Bearer ${token}`;
+ }
+ return config;
+ },
+ (error) => Promise.reject(error)
+);
+
+// Response interceptor to handle errors
+api.interceptors.response.use(
+ (response) => response,
+ (error) => {
+ // Handle 401 unauthorized errors
+ if (error.response && error.response.status === 401) {
+ localStorage.removeItem('token');
+ localStorage.removeItem('user');
+ if (typeof window !== 'undefined') {
+ window.location.href = '/login';
+ }
+ }
+ return Promise.reject(error);
+ }
+);
+
+export default api; \ No newline at end of file
diff --git a/frontend/src/lib/utils.js b/frontend/src/lib/utils.js
new file mode 100644
index 0000000..b20bf01
--- /dev/null
+++ b/frontend/src/lib/utils.js
@@ -0,0 +1,6 @@
+import { clsx } from "clsx";
+import { twMerge } from "tailwind-merge"
+
+export function cn(...inputs) {
+ return twMerge(clsx(inputs));
+}