A very performant and light (2mb in memory) link shortener and tracker. Written in Rust and React and uses Postgres/SQLite.
1import { createContext, useContext, useEffect, useState } from 'react';
2import { User } from '../types/api';
3import * as api from '../api/client';
4
5interface AuthContextType {
6 user: User | null;
7 login: (email: string, password: string) => Promise<void>;
8 register: (email: string, password: string, adminToken: string) => Promise<void>;
9 logout: () => void;
10 isLoading: boolean;
11}
12
13const AuthContext = createContext<AuthContextType | undefined>(undefined);
14
15export function AuthProvider({ children }: { children: React.ReactNode }) {
16 const [user, setUser] = useState<User | null>(null);
17 const [isLoading, setIsLoading] = useState(true);
18
19 useEffect(() => {
20 const token = localStorage.getItem('token');
21 if (token) {
22 const userData = JSON.parse(localStorage.getItem('user') || 'null');
23 setUser(userData);
24 }
25 setIsLoading(false);
26
27 const handleUnauthorized = () => {
28 setUser(null);
29 };
30
31 window.addEventListener('unauthorized', handleUnauthorized);
32
33 return () => {
34 window.removeEventListener('unauthorized', handleUnauthorized);
35 };
36 }, []);
37
38 const login = async (email: string, password: string) => {
39 const response = await api.login(email, password);
40 const { token, user } = response;
41 localStorage.setItem('token', token);
42 localStorage.setItem('user', JSON.stringify(user));
43 setUser(user);
44 };
45
46 const register = async (email: string, password: string, adminToken: string) => {
47 const response = await api.register(email, password, adminToken);
48 const { token, user } = response;
49 localStorage.setItem('token', token);
50 localStorage.setItem('user', JSON.stringify(user));
51 setUser(user);
52 };
53
54 const logout = () => {
55 localStorage.removeItem('token');
56 localStorage.removeItem('user');
57 setUser(null);
58 };
59
60 return (
61 <AuthContext.Provider value={{ user, login, register, logout, isLoading }}>
62 {children}
63 </AuthContext.Provider>
64 );
65}
66
67export function useAuth() {
68 const context = useContext(AuthContext);
69 if (context === undefined) {
70 throw new Error('useAuth must be used within an AuthProvider');
71 }
72 return context;
73}