feat: implement API composables for authentication and data fetching
- Add useApiFetch composable for HTTP requests with auth token - Implement useAuth composable for authentication endpoints - Add useAdmin composable for admin operations - Add useOperator composable for operator management - Add useMembers composable for member data - Add usePublic composable for public reports - Add useReports composable for report operations Co-authored-by: Copilot <[email protected]>
This commit is contained in:
@@ -0,0 +1,61 @@
|
|||||||
|
import type {
|
||||||
|
AreaListResponse, CategoryListResponse, CreateAreaRequest, CreateCategoryRequest, CreateTeamRequest,
|
||||||
|
ModerationListResponse,
|
||||||
|
OkResponse,
|
||||||
|
OverviewStatsResponse, TeamListResponse, UpdateModerationRequest,
|
||||||
|
UpdateUserBanRequest, UpdateUserRolesRequest,
|
||||||
|
UserListResponse
|
||||||
|
} from "~/types/api";
|
||||||
|
|
||||||
|
export const useAdmin = () => {
|
||||||
|
const getOverviewStats = () =>
|
||||||
|
useApiFetch<OverviewStatsResponse>('/api/v1/admin/stats/overview', { method: 'GET' })
|
||||||
|
|
||||||
|
const getUsers = () =>
|
||||||
|
useApiFetch<UserListResponse>('/api/v1/admin/users', { method: 'GET' })
|
||||||
|
|
||||||
|
const updateUserBan = (id: number, body: UpdateUserBanRequest) =>
|
||||||
|
useApiFetch<OkResponse>(`/api/v1/admin/users/${id}/ban`, { method: 'PATCH', body })
|
||||||
|
|
||||||
|
const updateUserRoles = (id: number, body: UpdateUserRolesRequest) =>
|
||||||
|
useApiFetch<OkResponse>(`/api/v1/admin/users/${id}/roles`, { method: 'PATCH', body })
|
||||||
|
|
||||||
|
const getAreas = () =>
|
||||||
|
useApiFetch<AreaListResponse>('/api/v1/admin/areas', { method: 'GET' })
|
||||||
|
|
||||||
|
const createArea = (body: CreateAreaRequest) =>
|
||||||
|
useApiFetch<OkResponse>('/api/v1/admin/areas', { method: 'POST', body })
|
||||||
|
|
||||||
|
const getCategories = () =>
|
||||||
|
useApiFetch<CategoryListResponse>('/api/v1/admin/categories', { method: 'GET' })
|
||||||
|
|
||||||
|
const createCategory = (body: CreateCategoryRequest) =>
|
||||||
|
useApiFetch<OkResponse>('/api/v1/admin/categories', { method: 'POST', body })
|
||||||
|
|
||||||
|
const getTeams = () =>
|
||||||
|
useApiFetch<TeamListResponse>('/api/v1/admin/teams', { method: 'GET' })
|
||||||
|
|
||||||
|
const createTeam = (body: CreateTeamRequest) =>
|
||||||
|
useApiFetch<OkResponse>('/api/v1/admin/teams', { method: 'POST', body })
|
||||||
|
|
||||||
|
const getModerationFlags = (query?: { status?: string; page?: number; per_page?: number }) =>
|
||||||
|
useApiFetch<ModerationListResponse>('/api/v1/admin/moderation', { method: 'GET', query })
|
||||||
|
|
||||||
|
const updateModerationFlag = (id: number, body: UpdateModerationRequest) =>
|
||||||
|
useApiFetch<OkResponse>(`/api/v1/admin/moderation/${id}`, { method: 'PATCH', body })
|
||||||
|
|
||||||
|
return {
|
||||||
|
getOverviewStats,
|
||||||
|
getUsers,
|
||||||
|
updateUserBan,
|
||||||
|
updateUserRoles,
|
||||||
|
getAreas,
|
||||||
|
createArea,
|
||||||
|
getCategories,
|
||||||
|
createCategory,
|
||||||
|
getTeams,
|
||||||
|
createTeam,
|
||||||
|
getModerationFlags,
|
||||||
|
updateModerationFlag,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { defu } from 'defu'
|
||||||
|
|
||||||
|
export const useApiFetch = <T>(request: string, options: Parameters<typeof $fetch>[1] = {}) => {
|
||||||
|
const config = useRuntimeConfig()
|
||||||
|
const token = useCookie('auth_token') // Make sure this matches the cookie name you use on login
|
||||||
|
|
||||||
|
const defaults: Parameters<typeof $fetch>[1] = {
|
||||||
|
baseURL: config.public.api as string,
|
||||||
|
headers: token.value ? { Authorization: `Bearer ${token.value}` } : {},
|
||||||
|
}
|
||||||
|
|
||||||
|
const params = defu(options, defaults)
|
||||||
|
|
||||||
|
return $fetch<T>(request, params)
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import type {
|
||||||
|
ChangePasswordRequest,
|
||||||
|
CurrentUserResponse, EmailRequest, NotificationListResponse,
|
||||||
|
OkResponse,
|
||||||
|
OtpRequestResponse, PasswordLoginRequest, RegisterCitizenRequest,
|
||||||
|
RegisterCitizenResponse, RewardsResponse,
|
||||||
|
TokenResponse, VerifyOtpRequest
|
||||||
|
} from "~/types/api";
|
||||||
|
|
||||||
|
export const useAuth = () => {
|
||||||
|
const register = (body: RegisterCitizenRequest) =>
|
||||||
|
useApiFetch<RegisterCitizenResponse>('/api/v1/auth/register', { method: 'POST', body })
|
||||||
|
|
||||||
|
const requestOtp = (body: EmailRequest) =>
|
||||||
|
useApiFetch<OtpRequestResponse>('/api/v1/auth/otp/request', { method: 'POST', body })
|
||||||
|
|
||||||
|
const verifyOtp = (body: VerifyOtpRequest) =>
|
||||||
|
useApiFetch<TokenResponse>('/api/v1/auth/otp/verify', { method: 'POST', body })
|
||||||
|
|
||||||
|
const loginWithPassword = (body: PasswordLoginRequest) =>
|
||||||
|
useApiFetch<TokenResponse>('/api/v1/auth/login/password', { method: 'POST', body })
|
||||||
|
|
||||||
|
const changePassword = (body: ChangePasswordRequest) =>
|
||||||
|
useApiFetch<OkResponse>('/api/v1/auth/change-password', { method: 'POST', body })
|
||||||
|
|
||||||
|
const fetchCurrentUser = () =>
|
||||||
|
useApiFetch<CurrentUserResponse>('/api/v1/me', { method: 'GET' })
|
||||||
|
|
||||||
|
const fetchRewards = (query?: { page?: number; per_page?: number }) =>
|
||||||
|
useApiFetch<RewardsResponse>('/api/v1/me/rewards', { method: 'GET', query })
|
||||||
|
|
||||||
|
const fetchNotifications = (query?: { page?: number; per_page?: number }) =>
|
||||||
|
useApiFetch<NotificationListResponse>('/api/v1/notifications', { method: 'GET', query })
|
||||||
|
|
||||||
|
const markNotificationRead = (id: number) =>
|
||||||
|
useApiFetch<OkResponse>(`/api/v1/notifications/${id}/read`, { method: 'PATCH' })
|
||||||
|
|
||||||
|
return {
|
||||||
|
register,
|
||||||
|
requestOtp,
|
||||||
|
verifyOtp,
|
||||||
|
loginWithPassword,
|
||||||
|
changePassword,
|
||||||
|
fetchCurrentUser,
|
||||||
|
fetchRewards,
|
||||||
|
fetchNotifications,
|
||||||
|
markNotificationRead,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { computed } from 'vue';
|
||||||
|
|
||||||
|
export interface Member {
|
||||||
|
name: string;
|
||||||
|
image: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useMembers() {
|
||||||
|
const members: Member[] = [
|
||||||
|
{ name: "Renato Loiacono", image: "https://placehold.co/50x50" },
|
||||||
|
{ name: "Michelangelo Parisi", image: "https://placehold.co/50x50" },
|
||||||
|
{ name: "Gabriele Schiraldi", image: "https://placehold.co/50x50" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const sortedMembers = computed(() => {
|
||||||
|
return [...members].sort((a, b) => {
|
||||||
|
const aSurnameInitial = a.name.split(" ").pop()?.[0] ?? "";
|
||||||
|
const bSurnameInitial = b.name.split(" ").pop()?.[0] ?? "";
|
||||||
|
return aSurnameInitial.localeCompare(bSurnameInitial);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
members,
|
||||||
|
sortedMembers
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import type {
|
||||||
|
AssignTeamRequest,
|
||||||
|
InterventionSummaryResponse,
|
||||||
|
OkResponse,
|
||||||
|
PagedReportListResponse,
|
||||||
|
UpdateStatusRequest
|
||||||
|
} from "~/types/api";
|
||||||
|
|
||||||
|
export const useOperator = () => {
|
||||||
|
const getOpenReports = (query?: { page?: number; per_page?: number }) =>
|
||||||
|
useApiFetch<PagedReportListResponse>('/api/v1/operator/reports/open', { method: 'GET', query })
|
||||||
|
|
||||||
|
const getAssignedReports = (query?: { page?: number; per_page?: number }) =>
|
||||||
|
useApiFetch<PagedReportListResponse>('/api/v1/operator/reports/assigned', { method: 'GET', query })
|
||||||
|
|
||||||
|
const getOtherOperatorReports = (query?: { page?: number; per_page?: number }) =>
|
||||||
|
useApiFetch<PagedReportListResponse>('/api/v1/operator/reports/others', { method: 'GET', query })
|
||||||
|
|
||||||
|
const takeReport = (id: number) =>
|
||||||
|
useApiFetch<OkResponse>(`/api/v1/reports/${id}/take`, { method: 'POST' })
|
||||||
|
|
||||||
|
const updateReportStatus = (id: number, body: UpdateStatusRequest) =>
|
||||||
|
useApiFetch<OkResponse>(`/api/v1/reports/${id}/status`, { method: 'PATCH', body })
|
||||||
|
|
||||||
|
const assignTeam = (id: number, body: AssignTeamRequest) =>
|
||||||
|
useApiFetch<OkResponse>(`/api/v1/reports/${id}/assignments`, { method: 'POST', body })
|
||||||
|
|
||||||
|
const getInterventionSummary = (id: number) =>
|
||||||
|
useApiFetch<InterventionSummaryResponse>(`/api/v1/reports/${id}/intervention-summary`, { method: 'GET' })
|
||||||
|
|
||||||
|
return {
|
||||||
|
getOpenReports,
|
||||||
|
getAssignedReports,
|
||||||
|
getOtherOperatorReports,
|
||||||
|
takeReport,
|
||||||
|
updateReportStatus,
|
||||||
|
assignTeam,
|
||||||
|
getInterventionSummary,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import type { OpenDataReportListResponse } from "~/types/api";
|
||||||
|
|
||||||
|
export default function usePublic() {
|
||||||
|
const getOpenDataReports = (query?: { page?: number; per_page?: number }) =>
|
||||||
|
useApiFetch<OpenDataReportListResponse>('/api/v1/open-data/reports', { method: 'GET', query })
|
||||||
|
|
||||||
|
return { getOpenDataReports }
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import type {
|
||||||
|
CreateReportRequest,
|
||||||
|
CreateReportResponse, FeedbackRequest, FlagRequest, FlagResponse,
|
||||||
|
MediaUploadResponse,
|
||||||
|
MessageListResponse, MessageRequest, OkResponse,
|
||||||
|
ReportDetailResponse,
|
||||||
|
ReportListResponse
|
||||||
|
} from "~/types/api";
|
||||||
|
|
||||||
|
export const useReports = () => {
|
||||||
|
const getReports = (query?: { area_id?: number; category_id?: number; status?: string }) =>
|
||||||
|
useApiFetch<ReportListResponse>('/api/v1/reports', { method: 'GET', query })
|
||||||
|
|
||||||
|
const createReport = (body: CreateReportRequest) =>
|
||||||
|
useApiFetch<CreateReportResponse>('/api/v1/reports', { method: 'POST', body })
|
||||||
|
|
||||||
|
const getReportDetail = (id: number) =>
|
||||||
|
useApiFetch<ReportDetailResponse>(`/api/v1/reports/${id}`, { method: 'GET' })
|
||||||
|
|
||||||
|
const uploadMedia = (id: number, formData: FormData) =>
|
||||||
|
useApiFetch<MediaUploadResponse>(`/api/v1/reports/${id}/media`, { method: 'POST', body: formData })
|
||||||
|
|
||||||
|
const getMessages = (id: number) =>
|
||||||
|
useApiFetch<MessageListResponse>(`/api/v1/reports/${id}/messages`, { method: 'GET' })
|
||||||
|
|
||||||
|
const addMessage = (id: number, body: MessageRequest) =>
|
||||||
|
useApiFetch<OkResponse>(`/api/v1/reports/${id}/messages`, { method: 'POST', body })
|
||||||
|
|
||||||
|
const addFeedback = (id: number, body: FeedbackRequest) =>
|
||||||
|
useApiFetch<OkResponse>(`/api/v1/reports/${id}/feedback`, { method: 'POST', body })
|
||||||
|
|
||||||
|
const flagReport = (id: number, body: FlagRequest) =>
|
||||||
|
useApiFetch<FlagResponse>(`/api/v1/reports/${id}/flags`, { method: 'POST', body })
|
||||||
|
|
||||||
|
const flagMessage = (reportId: number, messageId: number, body: FlagRequest) =>
|
||||||
|
useApiFetch<FlagResponse>(`/api/v1/reports/${reportId}/messages/${messageId}/flags`, { method: 'POST', body })
|
||||||
|
|
||||||
|
return {
|
||||||
|
getReports,
|
||||||
|
createReport,
|
||||||
|
getReportDetail,
|
||||||
|
uploadMedia,
|
||||||
|
getMessages,
|
||||||
|
addMessage,
|
||||||
|
addFeedback,
|
||||||
|
flagReport,
|
||||||
|
flagMessage,
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user