
- Introduced CreateExpenseForm.vue for creating new expenses with fields for description, total amount, split type, and date. - Integrated the CreateExpenseForm into ListDetailPage.vue, allowing users to add expenses directly from the list view. - Enhanced UI with a modal for the expense creation form and added validation for required fields. - Updated styles for consistency across the application. - Implemented logic to refresh the expense list upon successful creation of a new expense.
108 lines
2.8 KiB
TypeScript
108 lines
2.8 KiB
TypeScript
import { API_ENDPOINTS } from '@/config/api-config'
|
|
import { apiClient } from '@/services/api'
|
|
import { defineStore } from 'pinia'
|
|
import { ref, computed } from 'vue'
|
|
import router from '@/router'
|
|
|
|
interface AuthState {
|
|
accessToken: string | null
|
|
refreshToken: string | null
|
|
user: {
|
|
email: string
|
|
name: string
|
|
id?: string | number
|
|
} | null
|
|
}
|
|
|
|
export const useAuthStore = defineStore('auth', () => {
|
|
// State
|
|
const accessToken = ref<string | null>(localStorage.getItem('token'))
|
|
const refreshToken = ref<string | null>(localStorage.getItem('refreshToken'))
|
|
const user = ref<AuthState['user']>(null)
|
|
|
|
// Getters
|
|
const isAuthenticated = computed(() => !!accessToken.value)
|
|
const getUser = computed(() => user.value)
|
|
|
|
// Actions
|
|
const setTokens = (tokens: { access_token: string; refresh_token?: string }) => {
|
|
accessToken.value = tokens.access_token
|
|
localStorage.setItem('token', tokens.access_token)
|
|
if (tokens.refresh_token) {
|
|
refreshToken.value = tokens.refresh_token
|
|
localStorage.setItem('refreshToken', tokens.refresh_token)
|
|
}
|
|
}
|
|
|
|
const clearTokens = () => {
|
|
accessToken.value = null
|
|
refreshToken.value = null
|
|
user.value = null
|
|
localStorage.removeItem('token')
|
|
localStorage.removeItem('refreshToken')
|
|
}
|
|
|
|
const setUser = (userData: AuthState['user']) => {
|
|
user.value = userData
|
|
}
|
|
|
|
const fetchCurrentUser = async () => {
|
|
if (!accessToken.value) {
|
|
clearTokens()
|
|
return null
|
|
}
|
|
try {
|
|
const response = await apiClient.get(API_ENDPOINTS.USERS.PROFILE)
|
|
setUser(response.data)
|
|
return response.data
|
|
} catch (error: any) {
|
|
console.error('AuthStore: Failed to fetch current user:', error)
|
|
clearTokens()
|
|
return null
|
|
}
|
|
}
|
|
|
|
const login = async (email: string, password: string) => {
|
|
const formData = new FormData()
|
|
formData.append('username', email)
|
|
formData.append('password', password)
|
|
|
|
const response = await apiClient.post(API_ENDPOINTS.AUTH.LOGIN, formData, {
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
},
|
|
})
|
|
|
|
const { access_token, refresh_token } = response.data
|
|
setTokens({ access_token, refresh_token })
|
|
// Skip fetching profile data
|
|
// await fetchCurrentUser();
|
|
return response.data
|
|
}
|
|
|
|
const signup = async (userData: { name: string; email: string; password: string }) => {
|
|
const response = await apiClient.post(API_ENDPOINTS.AUTH.SIGNUP, userData)
|
|
return response.data
|
|
}
|
|
|
|
const logout = async () => {
|
|
clearTokens()
|
|
await router.push('/auth/login')
|
|
}
|
|
|
|
return {
|
|
accessToken,
|
|
user,
|
|
refreshToken,
|
|
isAuthenticated,
|
|
getUser,
|
|
setTokens,
|
|
clearTokens,
|
|
setUser,
|
|
fetchCurrentUser,
|
|
login,
|
|
signup,
|
|
logout,
|
|
}
|
|
})
|