338 lines
8.5 KiB
TypeScript
338 lines
8.5 KiB
TypeScript
import { api } from '@/core/services/api'
|
|
import type { PaginatedApiResponse } from '@/core/types/api'
|
|
import type {
|
|
ActivityDetail,
|
|
ActivityListItem,
|
|
ActivityReport,
|
|
ActivityType,
|
|
CreateActivityReportPayload,
|
|
CreateActivityPayload,
|
|
CreateActivityTypePayload,
|
|
ListActivitiesParams,
|
|
UpdateActivityFiles,
|
|
UpdateActivityPayload,
|
|
UpdateActivityReportPayload,
|
|
} from '../types/activity.types'
|
|
|
|
type ActivityApiResponse = {
|
|
success: boolean
|
|
data: ActivityDetail
|
|
message?: string
|
|
}
|
|
|
|
type ActivityReportApiResponse = {
|
|
success: boolean
|
|
data: ActivityReport
|
|
message?: string
|
|
}
|
|
|
|
function appendIfPresent(formData: FormData, key: string, value: string | null | undefined) {
|
|
if (value !== null && value !== undefined && value !== '') {
|
|
formData.append(key, value)
|
|
}
|
|
}
|
|
|
|
export function buildActivityFormData(
|
|
payload: UpdateActivityPayload,
|
|
files: UpdateActivityFiles = {},
|
|
options: { method?: 'PUT' } = {},
|
|
): FormData {
|
|
const formData = new FormData()
|
|
|
|
formData.append('activity_type_id', payload.activity_type_id)
|
|
formData.append('title', payload.title)
|
|
formData.append('is_active', payload.is_active ? '1' : '0')
|
|
appendIfPresent(formData, 'reference_number', payload.reference_number ?? undefined)
|
|
appendIfPresent(formData, 'description', payload.description ?? undefined)
|
|
appendIfPresent(formData, 'start_datetime', payload.start_datetime ?? undefined)
|
|
appendIfPresent(formData, 'end_datetime', payload.end_datetime ?? undefined)
|
|
appendIfPresent(formData, 'organizer', payload.organizer ?? undefined)
|
|
appendIfPresent(formData, 'location', payload.location ?? undefined)
|
|
|
|
files.documents?.forEach((file, index) => {
|
|
formData.append(`documents[${index}]`, file)
|
|
})
|
|
|
|
files.gallery?.forEach((file, index) => {
|
|
formData.append(`gallery[${index}]`, file)
|
|
})
|
|
|
|
if (options.method === 'PUT') {
|
|
formData.append('_method', 'PUT')
|
|
}
|
|
|
|
return formData
|
|
}
|
|
|
|
export async function listActivities(
|
|
params: ListActivitiesParams,
|
|
): Promise<PaginatedApiResponse<ActivityListItem>> {
|
|
const { data } = await api.get<PaginatedApiResponse<ActivityListItem>>('/v1/activities', {
|
|
params,
|
|
})
|
|
|
|
if (!data.success) {
|
|
throw new Error(data.message ?? 'Gagal memuatkan senarai aktiviti.')
|
|
}
|
|
|
|
return data
|
|
}
|
|
|
|
export async function listActivityTypes(): Promise<ActivityType[]> {
|
|
const { data } = await api.get<PaginatedApiResponse<ActivityType>>('/v1/activity-types', {
|
|
params: { per_page: 1000 },
|
|
})
|
|
|
|
if (!data.success) {
|
|
throw new Error(data.message ?? 'Gagal memuatkan jenis aktiviti.')
|
|
}
|
|
|
|
return data.data
|
|
}
|
|
|
|
type ActivityTypeApiResponse = {
|
|
success: boolean
|
|
data: ActivityType
|
|
message?: string
|
|
}
|
|
|
|
export async function createActivityType(
|
|
payload: CreateActivityTypePayload,
|
|
): Promise<ActivityType> {
|
|
const { data } = await api.post<ActivityTypeApiResponse>('/v1/activity-types', payload)
|
|
|
|
if (!data.success) {
|
|
throw new Error(data.message ?? 'Gagal menambah jenis aktiviti.')
|
|
}
|
|
|
|
return data.data
|
|
}
|
|
|
|
export async function getActivity(id: string): Promise<ActivityDetail> {
|
|
const { data } = await api.get<ActivityApiResponse>(`/v1/activities/${id}`)
|
|
|
|
if (!data.success) {
|
|
throw new Error(data.message ?? 'Gagal memuatkan butiran aktiviti.')
|
|
}
|
|
|
|
return data.data
|
|
}
|
|
|
|
export async function updateActivity(
|
|
id: string,
|
|
payload: UpdateActivityPayload,
|
|
files: UpdateActivityFiles = {},
|
|
): Promise<ActivityDetail> {
|
|
const formData = buildActivityFormData(payload, files, { method: 'PUT' })
|
|
|
|
const { data } = await api.post<ActivityApiResponse>(`/v1/activities/${id}`, formData, {
|
|
headers: {
|
|
'Content-Type': 'multipart/form-data',
|
|
},
|
|
})
|
|
|
|
if (!data.success) {
|
|
throw new Error(data.message ?? 'Gagal mengemaskini aktiviti.')
|
|
}
|
|
|
|
return data.data
|
|
}
|
|
|
|
export async function createActivity(
|
|
payload: CreateActivityPayload,
|
|
files: UpdateActivityFiles = {},
|
|
): Promise<ActivityDetail> {
|
|
const formData = buildActivityFormData(payload, files)
|
|
|
|
const { data } = await api.post<ActivityApiResponse>('/v1/activities', formData, {
|
|
headers: {
|
|
'Content-Type': 'multipart/form-data',
|
|
},
|
|
})
|
|
|
|
if (!data.success) {
|
|
throw new Error(data.message ?? 'Gagal mendaftar aktiviti.')
|
|
}
|
|
|
|
return data.data
|
|
}
|
|
|
|
export async function uploadActivityGalleryImage(
|
|
activityId: string,
|
|
file: File,
|
|
): Promise<ActivityDetail> {
|
|
const formData = new FormData()
|
|
formData.append('file', file)
|
|
|
|
const { data } = await api.post<ActivityApiResponse>(
|
|
`/v1/activities/${activityId}/gallery`,
|
|
formData,
|
|
{
|
|
headers: {
|
|
'Content-Type': 'multipart/form-data',
|
|
},
|
|
},
|
|
)
|
|
|
|
if (!data.success) {
|
|
throw new Error(data.message ?? 'Gagal memuat naik imej galeri.')
|
|
}
|
|
|
|
return data.data
|
|
}
|
|
|
|
export async function uploadActivityDocument(
|
|
activityId: string,
|
|
file: File,
|
|
): Promise<ActivityDetail> {
|
|
const formData = new FormData()
|
|
formData.append('file', file)
|
|
|
|
const { data } = await api.post<ActivityApiResponse>(
|
|
`/v1/activities/${activityId}/documents`,
|
|
formData,
|
|
{
|
|
headers: {
|
|
'Content-Type': 'multipart/form-data',
|
|
},
|
|
},
|
|
)
|
|
|
|
if (!data.success) {
|
|
throw new Error(data.message ?? 'Gagal memuat naik dokumen.')
|
|
}
|
|
|
|
return data.data
|
|
}
|
|
|
|
export async function deleteActivityGalleryImage(
|
|
activityId: string,
|
|
imageId: string,
|
|
): Promise<ActivityDetail> {
|
|
const { data } = await api.delete<ActivityApiResponse>(
|
|
`/v1/activities/${activityId}/gallery/${imageId}`,
|
|
)
|
|
|
|
if (!data.success) {
|
|
throw new Error(data.message ?? 'Gagal memadam imej galeri.')
|
|
}
|
|
|
|
return data.data
|
|
}
|
|
|
|
export async function deleteActivityDocument(
|
|
activityId: string,
|
|
documentId: string,
|
|
): Promise<ActivityDetail> {
|
|
const { data } = await api.delete<ActivityApiResponse>(
|
|
`/v1/activities/${activityId}/documents/${documentId}`,
|
|
)
|
|
|
|
if (!data.success) {
|
|
throw new Error(data.message ?? 'Gagal memadam dokumen.')
|
|
}
|
|
|
|
return data.data
|
|
}
|
|
|
|
export async function fetchActivityGalleryImage(
|
|
activityId: string,
|
|
imageId: string,
|
|
mimeType?: string | null,
|
|
): Promise<Blob> {
|
|
const response = await api.get(`/v1/activities/${activityId}/gallery/${imageId}`, {
|
|
responseType: 'blob',
|
|
})
|
|
|
|
const contentType =
|
|
mimeType ||
|
|
(typeof response.headers['content-type'] === 'string' ? response.headers['content-type'] : null) ||
|
|
'application/octet-stream'
|
|
|
|
return new Blob([response.data], { type: contentType })
|
|
}
|
|
|
|
export async function fetchActivityDocument(
|
|
activityId: string,
|
|
documentId: string,
|
|
mimeType?: string | null,
|
|
): Promise<Blob> {
|
|
const response = await api.get(
|
|
`/v1/activities/${activityId}/documents/${documentId}/download`,
|
|
{ responseType: 'blob' },
|
|
)
|
|
|
|
const contentType =
|
|
mimeType ||
|
|
(typeof response.headers['content-type'] === 'string' ? response.headers['content-type'] : null) ||
|
|
'application/octet-stream'
|
|
|
|
return new Blob([response.data], { type: contentType })
|
|
}
|
|
|
|
export async function downloadActivityDocument(
|
|
activityId: string,
|
|
documentId: string,
|
|
fileName: string,
|
|
mimeType?: string | null,
|
|
): Promise<void> {
|
|
const blob = await fetchActivityDocument(activityId, documentId, mimeType)
|
|
const url = window.URL.createObjectURL(blob)
|
|
const link = document.createElement('a')
|
|
link.href = url
|
|
link.download = fileName
|
|
link.click()
|
|
window.URL.revokeObjectURL(url)
|
|
}
|
|
|
|
export async function createActivityReport(
|
|
payload: CreateActivityReportPayload,
|
|
): Promise<ActivityReport> {
|
|
const { data } = await api.post<ActivityReportApiResponse>('/v1/activity-reports', payload)
|
|
|
|
if (!data.success) {
|
|
throw new Error(data.message ?? 'Gagal menambah laporan aktiviti.')
|
|
}
|
|
|
|
return data.data
|
|
}
|
|
|
|
export async function updateActivityReport(
|
|
id: string,
|
|
payload: UpdateActivityReportPayload,
|
|
): Promise<ActivityReport> {
|
|
const { data } = await api.put<ActivityReportApiResponse>(`/v1/activity-reports/${id}`, payload)
|
|
|
|
if (!data.success) {
|
|
throw new Error(data.message ?? 'Gagal mengemaskini laporan aktiviti.')
|
|
}
|
|
|
|
return data.data
|
|
}
|
|
|
|
type ActivityDeleteResponse = {
|
|
success: boolean
|
|
message?: string
|
|
}
|
|
|
|
export async function deleteActivity(id: string): Promise<void> {
|
|
const { data } = await api.delete<ActivityDeleteResponse>(`/v1/activities/${id}`)
|
|
|
|
if (!data.success) {
|
|
throw new Error(data.message ?? 'Gagal memadam aktiviti.')
|
|
}
|
|
}
|
|
|
|
type ActivityReportDeleteResponse = {
|
|
success: boolean
|
|
message?: string
|
|
}
|
|
|
|
export async function deleteActivityReport(id: string): Promise<void> {
|
|
const { data } = await api.delete<ActivityReportDeleteResponse>(`/v1/activity-reports/${id}`)
|
|
|
|
if (!data.success) {
|
|
throw new Error(data.message ?? 'Gagal memadam laporan aktiviti.')
|
|
}
|
|
}
|