-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'staging' into admin-panel/manage-members
- Loading branch information
Showing
49 changed files
with
1,715 additions
and
506 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
## Summary of Changes | ||
|
||
<!-- | ||
Provide a brief summary of the changes introduced in this pull request. | ||
For example: | ||
- Implemented user authentication using JWT. | ||
- Refactored the data processing module for better performance. | ||
- Updated the dashboard UI to enhance user experience. | ||
--> | ||
|
||
## Splash Damage | ||
|
||
<!-- | ||
Describe any potential side effects or impacts these changes might have on other parts of the project. | ||
For example: | ||
- The new authentication system may require updating API endpoints. | ||
- Refactoring may affect existing unit tests; ensure all tests pass. | ||
- UI changes might require adjustments in mobile responsiveness. | ||
--> | ||
|
||
## Manual Test Steps | ||
|
||
<!-- | ||
Outline the steps required to manually test and verify the changes made in this pull request. | ||
For example: | ||
1. **Setup:** | ||
- Clone the repository and check out the feature branch. | ||
- Run `npm install` to install dependencies. | ||
2. **UI Verification:** | ||
- Navigate to `http://localhost:3000/dashboard` and review the updated UI elements. | ||
- Test responsiveness on different screen sizes. | ||
3. **New Feature Access:** | ||
- Go to `http://localhost:3000/new-feature` to access the newly implemented feature. | ||
- Verify that all functionalities of the new feature work as expected. | ||
- Check for any UI inconsistencies or errors. | ||
--> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
/* eslint-disable no-unused-vars */ | ||
|
||
import { MutationStatus, QueryStatus } from '@tanstack/react-query'; | ||
import { HTMLProps } from 'react'; | ||
|
||
export enum Role { | ||
admin = 'admin', | ||
content_manager = 'content_manager', | ||
content = 'content', | ||
member = 'member', | ||
} | ||
|
||
export type UserType = { | ||
id: number | string; | ||
is_verified: boolean; | ||
email: string; | ||
role: Role; | ||
}; | ||
|
||
export interface LoginParams { | ||
email: string; | ||
password: string; | ||
cfTurnstileResponse: string; | ||
role?: string; | ||
remember: boolean; | ||
} | ||
|
||
export interface AuthContextType { | ||
user: UserType | null; | ||
login: (params: LoginParams & { userType: string; redirectUrl: string }) => void; | ||
logout: () => void; | ||
userQuery: { | ||
status: QueryStatus; | ||
error: Error | null; | ||
isLoading: boolean; | ||
}; | ||
loginMutation: { | ||
isLoading: boolean; | ||
status: MutationStatus; | ||
error: Error | null; | ||
}; | ||
logoutMutation: { | ||
isLoading: boolean; | ||
status: MutationStatus; | ||
error: Error | null; | ||
}; | ||
loginStatus: MutationStatus; | ||
} | ||
|
||
export interface LoginResponse { | ||
data: { | ||
user: UserType; | ||
access_token: string; | ||
}; | ||
} | ||
|
||
export interface Session { | ||
token: string; | ||
} | ||
|
||
export interface LoginFormProps { | ||
onSubmit: (values: LoginParams) => Promise<void>; | ||
isLoading?: boolean; | ||
turnstileToken?: string | null; | ||
setTurnstileToken?: (token: string) => void; | ||
} | ||
|
||
export interface FormField { | ||
name: string; | ||
type: string; | ||
label: string; | ||
placeholder: string; | ||
} | ||
|
||
export interface SocialLink { | ||
id: string; | ||
icon: string; | ||
url: string; | ||
alt: string; | ||
} | ||
|
||
export interface ReusableFormProps { | ||
title: string; | ||
fields: FormField[]; | ||
initialValues: any; | ||
validationSchema: any; | ||
onSubmit: (values: any) => Promise<void>; | ||
submitButtonText: string; | ||
socialLinks?: SocialLink[]; | ||
alternativeActionText?: string; | ||
alternativeActionLink?: string; | ||
alternativeActionLinkText?: string; | ||
} | ||
|
||
export interface InputProps extends HTMLProps<HTMLInputElement> { | ||
placeholder: string; | ||
label: string; | ||
name: string; | ||
type: string; | ||
field: string; | ||
formik: any; | ||
isRequired?: boolean; | ||
isFooter?: boolean; | ||
inputClass?: string[]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/* eslint-disable */ | ||
/* tslint:disable */ | ||
/* eslint-disable @typescript-eslint/no-unused-vars */ | ||
|
||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
import NextAuth from 'next-auth'; | ||
import { JWT } from 'next-auth/jwt'; | ||
|
||
declare module 'next-auth' { | ||
interface Session { | ||
accessToken: string | unknown; | ||
expires: string; | ||
user: { | ||
id: string | unknown; | ||
name?: string | unknown; | ||
email?: string | unknown; | ||
image?: string | unknown; | ||
}; | ||
} | ||
} | ||
|
||
declare module 'next-auth' { | ||
interface JWT { | ||
accessToken?: string; | ||
id: string; | ||
name?: string; | ||
email?: string; | ||
exp?: number; | ||
} | ||
} | ||
declare module 'next-auth' { | ||
interface User { | ||
id: string; | ||
name?: string; | ||
email?: string; | ||
image?: string; | ||
accessToken?: string; | ||
remember?: boolean; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
import { LoginParams, LoginResponse, Role, UserType } from '../Types'; | ||
import { | ||
getFromLocalStorage, | ||
removeFromLocalStorage, | ||
saveToLocalStorage, | ||
} from './utils/localStorageUtils'; | ||
|
||
const baseUrl = process.env.NEXT_PUBLIC_API_BASE_URL || ''; | ||
|
||
export const getUser = async (): Promise<UserType | null> => { | ||
const session = getFromLocalStorage('session'); | ||
if (!session?.token) { | ||
console.log('No session token found, user is not authenticated'); | ||
return null; | ||
} | ||
|
||
try { | ||
const response = await fetch(`${baseUrl}/content/user`, { | ||
headers: { | ||
Accept: 'application/json', | ||
Authorization: `Bearer ${session.token}`, | ||
}, | ||
}); | ||
|
||
if (!response.ok) { | ||
if (response.status === 401) { | ||
console.log('Unauthorized access, clearing session'); | ||
removeFromLocalStorage('session'); | ||
removeFromLocalStorage('user'); | ||
} | ||
throw new Error(response.statusText || 'An error occurred while fetching the user'); | ||
} | ||
|
||
const data = await response.json(); | ||
console.log('User data fetched successfully:', data.data); | ||
return data.data; | ||
} catch (error) { | ||
console.error('Error fetching user:', error); | ||
return null; | ||
} | ||
}; | ||
|
||
export const login = async ({ | ||
email, | ||
password, | ||
cfTurnstileResponse, | ||
}: LoginParams): Promise<LoginResponse> => { | ||
console.log('Login attempt for email:', email); | ||
|
||
try { | ||
const response = await fetch(`${baseUrl}/content/login`, { | ||
method: 'POST', | ||
headers: { | ||
Accept: 'application/json', | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify({ email, password, cfTurnstileResponse }), | ||
}); | ||
|
||
const data = await response.json(); | ||
|
||
if (!response.ok) { | ||
console.error('Login error:', data); | ||
if (response.status === 422) { | ||
const errorMessage = data.message || 'Validation failed'; | ||
const errors = data.errors || {}; | ||
throw new Error(JSON.stringify({ message: errorMessage, errors })); | ||
} | ||
throw new Error(data.message || 'An error occurred while logging in'); | ||
} | ||
|
||
console.log('Login successful'); | ||
|
||
if (data.data && data.data.access_token && data.data.user) { | ||
console.log('Setting session and user data'); | ||
saveToLocalStorage('session', { | ||
token: data.data.access_token, | ||
role: Role.content, | ||
}); | ||
saveToLocalStorage('user', data.data.user); | ||
} else { | ||
console.error('Login response is missing expected data'); | ||
throw new Error('Invalid login response data'); | ||
} | ||
|
||
return data; | ||
} catch (error) { | ||
console.error('Login process failed:', error); | ||
throw error; | ||
} | ||
}; | ||
|
||
export const logout = async (): Promise<void> => { | ||
const session = getFromLocalStorage('session'); | ||
if (!session?.token) { | ||
console.log('No session found, user is already logged out'); | ||
return; | ||
} | ||
|
||
try { | ||
const response = await fetch(`${baseUrl}/content/logout`, { | ||
method: 'POST', | ||
headers: { | ||
Accept: 'application/json', | ||
Authorization: `Bearer ${session.token}`, | ||
}, | ||
}); | ||
|
||
if (!response.ok) { | ||
const errorData = await response.json(); | ||
throw new Error(errorData.message || 'An error occurred while logging out'); | ||
} | ||
|
||
console.log('Logout successful'); | ||
} catch (error) { | ||
console.error('Logout process failed:', error); | ||
throw error; | ||
} finally { | ||
console.log('Clearing session'); | ||
removeFromLocalStorage('session'); | ||
removeFromLocalStorage('user'); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { Session, UserType } from '../../../Types'; | ||
|
||
export const setSession = async (sessionData: Session | null): Promise<void> => { | ||
console.log('setSession called with:', sessionData); | ||
if (sessionData === null) { | ||
localStorage.removeItem('session'); | ||
console.log('Session removed from localStorage'); | ||
} else { | ||
localStorage.setItem('session', JSON.stringify(sessionData)); | ||
console.log('Session saved to localStorage', localStorage.getItem('session')); | ||
} | ||
}; | ||
|
||
export const getSession = async (): Promise<Session | null> => { | ||
const sessionData = localStorage.getItem('session'); | ||
return sessionData ? JSON.parse(sessionData) : null; | ||
}; | ||
|
||
export const clearSession = async (): Promise<void> => { | ||
localStorage.removeItem('session'); | ||
localStorage.removeItem('user'); | ||
}; | ||
|
||
export const setUser = async (user: UserType | null): Promise<void> => { | ||
console.log('setUser called with:', user); | ||
if (user === null) { | ||
localStorage.removeItem('user'); | ||
console.log('User removed from localStorage'); | ||
} else { | ||
localStorage.setItem('user', JSON.stringify(user)); | ||
console.log('User saved to localStorage'); | ||
} | ||
}; | ||
|
||
export const getUserFromStorage = async (): Promise<UserType | null> => { | ||
const userData = localStorage.getItem('user'); | ||
return userData ? JSON.parse(userData) : null; | ||
}; |
Oops, something went wrong.