feat(portal): auth persistence, shift visibility, profile page, and UI polish

- Fix session persistence: add loading state to App.vue, hydrate portal store
  in router guards so page refresh preserves auth + event context
- Fix shift visibility for festivals: query child event time slots so shifts
  on sub-events appear in the portal
- Add profile page with editable personal info and password change
- Add backend endpoints: PUT /portal/profile and PUT /portal/password
- Fix registration form: make first_name/last_name editable for logged-in users
- Restyle login page: remove Vuexy illustration, center form with Crewli branding
- Improve dashboard StatusCard with action cards, icons, and upcoming shift count
- Enhance shift cards with status border colors and availability progress bars

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-13 10:19:14 +02:00
parent 838bee4d60
commit 59ad09fad2
17 changed files with 1145 additions and 254 deletions

View File

@@ -0,0 +1,47 @@
import { useMutation } from '@tanstack/vue-query'
import { apiClient } from '@/lib/axios'
interface ApiResponse<T> {
data: T
}
export interface ProfileUpdatePayload {
event_id: string
first_name?: string
last_name?: string
phone?: string | null
date_of_birth?: string | null
remarks?: string | null
}
export interface PasswordUpdatePayload {
current_password: string
password: string
password_confirmation: string
}
export function useUpdateProfile() {
return useMutation({
mutationFn: async (payload: ProfileUpdatePayload) => {
const { data } = await apiClient.put<ApiResponse<{ message: string }>>(
'/portal/profile',
payload,
)
return data.data
},
})
}
export function useUpdatePassword() {
return useMutation({
mutationFn: async (payload: PasswordUpdatePayload) => {
const { data } = await apiClient.put<ApiResponse<{ message: string }>>(
'/portal/password',
payload,
)
return data.data
},
})
}