diff --git a/shared b/shared index e33f2b8..e8ecaca 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit e33f2b8fb41afa8dbeab22570c0039cb53c1af45 +Subproject commit e8ecaca674a221dd27d4d2ede26a6a90ac0fb9ad diff --git a/src/api/services/auth.ts b/src/api/services/auth.ts index 26db7b0..a4b60be 100644 --- a/src/api/services/auth.ts +++ b/src/api/services/auth.ts @@ -2,63 +2,20 @@ import axios from 'axios'; import api from '../api'; import { SafeUser, UserLogInInput, UserSignUpInput } from 'models/user.model'; -export interface MeResponse { - message: string; - user: SafeUser; -} - -export type FieldErrors = Partial<{ - username: string; - password: string; - name_first: string; - name_last: string; - email: string; -}>; - -export type LoginErrorDetails = - | { - type: 'dbError'; - message: string; - } - | { - type: 'fieldErrors'; - fieldErrors: FieldErrors; - }; - -export type LoginResponse = { - token: string | null; - errors: LoginErrorDetails | null; -}; - -export type SignupFieldErrors = Partial<{ - email: string; - username: string; - password: string; -}>; - -export type SignupErrorDetails = - | { - type: 'dbError'; - message: string; - } - | { - type: 'fieldErrors'; - fieldErrors: SignupFieldErrors; - }; - -export type SignupResponse = - | { - insertedId: string; - errors: null; - } - | { - insertedId: null; - errors: SignupErrorDetails; - }; +import { + MeSuccessResponse, + LoginSuccessResponse, + LoginErrorResponse, + LoginResponse, + SignupSuccessResponse, + SignupErrorResponse, + SignupResponse, +} from 'services/auth.service.ts'; +import { ErrorResponse } from 'services/general.service.ts'; export const getMe = async (): Promise => { try { - const { data } = await api.get('/auth/me'); + const { data } = await api.get('/auth/me'); return data.user; } catch (error) { if (axios.isAxiosError(error) && error.response?.status === 401) { @@ -72,40 +29,18 @@ export const login = async ( credentials: UserLogInInput, ): Promise => { try { - const { data } = await api.post<{ token: string }>( + const { data } = await api.post( '/auth/login', credentials, ); - return { - token: data.token, - errors: null, - }; + return data; } catch (error) { - if ( - axios.isAxiosError(error) && - error.response?.data?.errors?.fieldErrors - ) { - const fieldErrors = error.response.data.errors.fieldErrors; - - return { - token: null, - errors: { - type: 'fieldErrors', - fieldErrors: { - username: fieldErrors.username, - password: fieldErrors.password, - }, - }, - }; + if (axios.isAxiosError(error) && error.response?.data?.errors) { + return error.response.data as LoginErrorResponse; } + if (axios.isAxiosError(error) && error.response?.data?.error) { - return { - token: null, - errors: { - type: 'dbError', - message: error.response.data.error, - }, - }; + return error.response.data as ErrorResponse; } throw error; @@ -126,42 +61,18 @@ export const signup = async ( credentials: UserSignUpInput, ): Promise => { try { - const { data } = await api.post<{ insertedId: string }>( + const { data } = await api.post( '/auth/signup', credentials, ); - return { - insertedId: data.insertedId, - errors: null, - }; + return data as SignupSuccessResponse; } catch (error) { - if ( - axios.isAxiosError(error) && - error.response?.data?.errors?.fieldErrors - ) { - const fieldErrors = error.response.data.errors.fieldErrors; - - return { - insertedId: null, - errors: { - type: 'fieldErrors', - fieldErrors: { - email: fieldErrors.email, - username: fieldErrors.username, - password: fieldErrors.password, - }, - }, - }; + if (axios.isAxiosError(error) && error.response?.data?.errors) { + return error.response.data as SignupErrorResponse; } if (axios.isAxiosError(error) && error.response?.data?.error) { - return { - insertedId: null, - errors: { - type: 'dbError', - message: error.response.data.error, - }, - }; + return error.response.data as ErrorResponse; } throw error; diff --git a/src/api/services/events.ts b/src/api/services/events.ts index c9a2986..2749bca 100644 --- a/src/api/services/events.ts +++ b/src/api/services/events.ts @@ -2,6 +2,11 @@ import axios from 'axios'; import api from '../api'; import { Event } from 'models/event.model'; +import { + GeneralResponse, + MessageResponse, + ErrorResponse, +} from 'services/general.service'; export const getEventByMode = async (modes: string[]) => { console.log('getting events by mode...'); @@ -31,38 +36,28 @@ export const getEventById = async (id: string) => { return events; }; -export interface UpdateEventResponse { - message: string; -} - export const updateEventById = async ( id: string, event: Event, -): Promise => { +): Promise => { try { - const { data } = await api.put('/events/' + id, event); - return data; + const { data } = await api.put('/events/' + id, event); + return data as MessageResponse; } catch (error) { if (axios.isAxiosError(error) && error.response?.status === 401) { - return null; + return error.response.data as ErrorResponse; } throw error; } }; -export interface DeleteEventResponse { - message: string; -} - -export const deleteEventById = async ( - id: string, -): Promise => { +export const deleteEventById = async (id: string): Promise => { try { - const { data } = await api.delete('/events/' + id); - return data; + const { data } = await api.delete('/events/' + id); + return data as MessageResponse; } catch (error) { if (axios.isAxiosError(error) && error.response?.status === 401) { - return null; + return error.response.data as ErrorResponse; } throw error; } diff --git a/src/pages/EditEvent.tsx b/src/pages/EditEvent.tsx index 13f0656..4f8cd6f 100644 --- a/src/pages/EditEvent.tsx +++ b/src/pages/EditEvent.tsx @@ -8,6 +8,7 @@ import NavBar from '../components/major/nav-bar'; import FormInput from '../components/minor/FormInput'; import { Event } from 'models/event.model.ts'; +import { GeneralResponse } from 'services/general.service.ts'; export default function EditEvent() { let { id } = useParams(); @@ -47,8 +48,8 @@ export default function EditEvent() { e.preventDefault(); if (!formData) return; - const result = await updateEventById(eventId, formData); - if (result && result.message) setMessage(result.message); + const result: GeneralResponse = await updateEventById(eventId, formData); + if (result && 'message' in result) setMessage(result.message); } return ( diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx index 9e4769d..9234548 100644 --- a/src/pages/Login.tsx +++ b/src/pages/Login.tsx @@ -3,9 +3,10 @@ import DirectButton from '../components/minor/DirectButton'; import FormInput from '../components/minor/FormInput'; import { useState } from 'react'; import { useNavigate } from 'react-router'; -import { FieldErrors, login } from '../api/services/auth.ts'; +import { login } from '../api/services/auth.ts'; import { useAuth } from '../auth/useAuth.tsx'; import { UserLogInInput } from 'models/user.model.ts'; +import { LoginErrorDetails, LoginResponse } from 'services/auth.service.ts'; export default function Login() { const [formData, setFormData] = useState({ @@ -26,12 +27,12 @@ export default function Login() { setFormData((prevState) => ({ ...prevState, [name]: value })); }; - const displayErrors = (error: string | FieldErrors) => { + const displayErrors = (error: string | LoginErrorDetails) => { if (typeof error === 'string') { setFieldErrorStates({ username: false, password: false }); setErrorMessage(error); } else { - const { username, password } = error; + const { username, password } = error.fieldErrors; const messages = [ username && `Username too short`, password && `Password too short`, @@ -52,24 +53,18 @@ export default function Login() { async function handleLogin(e: React.FormEvent) { e.preventDefault(); - const { token, errors } = await login(formData); + const result: LoginResponse = await login(formData); - if (token) { - localStorage.setItem('token', token); + if ('token' in result) { + localStorage.setItem('token', result.token); await refreshUser(); navigate('/userhome'); - } else if (errors) { - switch (errors.type) { - case 'dbError': - displayErrors(errors.message); - break; - case 'fieldErrors': - displayErrors(errors.fieldErrors); - break; - default: - displayErrors('An unknown error occurred.'); - break; - } + } else if ('errors' in result) { + displayErrors(result.errors); + } else if ('error' in result) { + displayErrors(result.error); + } else { + displayErrors('An unknown error occurred.'); } } diff --git a/src/pages/SignUp.tsx b/src/pages/SignUp.tsx index d95657e..37873af 100644 --- a/src/pages/SignUp.tsx +++ b/src/pages/SignUp.tsx @@ -3,7 +3,12 @@ import FormInput from '../components/minor/FormInput'; import { useState } from 'react'; import { useNavigate } from 'react-router'; -import { FieldErrors, login, signup } from '../api/services/auth.ts'; +import { login, signup } from '../api/services/auth.ts'; +import { + LoginResponse, + SignupErrorDetails, + SignupResponse, +} from 'services/auth.service.ts'; import '../styles/login.css'; import { useAuth } from '../auth/useAuth.tsx'; @@ -31,7 +36,7 @@ export default function SignUp() { setFormData((prevState) => ({ ...prevState, [name]: value })); }; - const displayErrors = (error: string | FieldErrors) => { + const displayErrors = (error: string | SignupErrorDetails) => { if (typeof error === 'string') { if (error.includes('email')) { setFieldErrorStates({ @@ -50,7 +55,7 @@ export default function SignUp() { setErrorMessage(error); } } else { - const { username, password } = error; + const { username, password } = error.fieldErrors; const messages = [ username && `Username too short`, password && `Password too short`, @@ -73,42 +78,31 @@ export default function SignUp() { async function handleSignup(e: React.FormEvent) { e.preventDefault(); - const signupResult = await signup(formData); + const signupResult: SignupResponse = await signup(formData); - if (signupResult.insertedId) { - const loginResult = await login({ + if ('insertedId' in signupResult) { + const loginResult: LoginResponse = await login({ username: formData.username, password: formData.password, }); - if (loginResult.token) { + if ('token' in loginResult) { localStorage.setItem('token', loginResult.token); await refreshUser(); navigate('/userhome'); - } else if (loginResult.errors) { - switch (loginResult.errors.type) { - case 'dbError': - displayErrors(loginResult.errors.message); - break; - case 'fieldErrors': - displayErrors(loginResult.errors.fieldErrors); - break; - default: - displayErrors('An unknown error occurred.'); - } - } - } else if (signupResult.errors) { - switch (signupResult.errors.type) { - case 'dbError': - displayErrors(signupResult.errors.message); - break; - case 'fieldErrors': - displayErrors(signupResult.errors.fieldErrors); - break; - default: - displayErrors('An unknown error occurred during signup.'); - break; + } else if ('errors' in loginResult) { + displayErrors(loginResult.errors); + } else if ('error' in loginResult) { + displayErrors(loginResult.error); + } else { + displayErrors('An unknown error occurred.'); } + } else if ('errors' in signupResult) { + displayErrors(signupResult.errors); + } else if ('error' in signupResult) { + displayErrors(signupResult.error); + } else { + displayErrors('An unknown error occurred during signup.'); } } diff --git a/tsconfig.app.json b/tsconfig.app.json index e0d5f51..8108a0a 100644 --- a/tsconfig.app.json +++ b/tsconfig.app.json @@ -24,8 +24,9 @@ "baseUrl": ".", "paths": { - "models/*": ["shared/src/models/*"] + "models/*": ["shared/src/models/*"], + "services/*": ["shared/src/services/*"], } }, - "include": ["src", "shared/src/models"] + "include": ["src", "shared/src"] }