690514:2019 204-rfa-approval-refactor #01
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
// File: hooks/use-distribution-matrices.ts
|
||||
// Change Log
|
||||
// - 2026-05-14: Add TanStack Query hooks for Distribution Matrix admin UI.
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import { toast } from 'sonner';
|
||||
import apiClient from '@/lib/api/client';
|
||||
import { getApiErrorMessage } from '@/types/api-error';
|
||||
|
||||
export type DistributionRecipientType = 'USER' | 'ORGANIZATION' | 'TEAM' | 'ROLE';
|
||||
export type DistributionDeliveryMethod = 'EMAIL' | 'IN_APP' | 'BOTH';
|
||||
|
||||
export interface DistributionConditions {
|
||||
codes?: string[];
|
||||
excludeCodes?: string[];
|
||||
}
|
||||
|
||||
export interface DistributionRecipient {
|
||||
publicId: string;
|
||||
recipientType: DistributionRecipientType;
|
||||
recipientPublicId: string;
|
||||
deliveryMethod: DistributionDeliveryMethod;
|
||||
sequence?: number;
|
||||
}
|
||||
|
||||
export interface DistributionMatrix {
|
||||
publicId: string;
|
||||
name: string;
|
||||
documentTypeId: number;
|
||||
conditions?: DistributionConditions;
|
||||
isActive: boolean;
|
||||
recipients?: DistributionRecipient[];
|
||||
responseCode?: {
|
||||
publicId: string;
|
||||
code: string;
|
||||
descriptionEn?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface CreateDistributionMatrixDto {
|
||||
name: string;
|
||||
projectPublicId?: string;
|
||||
documentTypeId: number;
|
||||
responseCodePublicId?: string;
|
||||
conditions?: DistributionConditions;
|
||||
}
|
||||
|
||||
const extractArrayData = <T>(value: unknown): T[] => {
|
||||
if (Array.isArray(value)) return value as T[];
|
||||
if (value && typeof value === 'object' && 'data' in value) {
|
||||
const nested = (value as { data?: unknown }).data;
|
||||
return Array.isArray(nested) ? (nested as T[]) : extractArrayData<T>(nested);
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
export const distributionMatrixKeys = {
|
||||
all: ['distribution-matrices'] as const,
|
||||
byProject: (projectPublicId?: string) => [...distributionMatrixKeys.all, { projectPublicId }] as const,
|
||||
};
|
||||
|
||||
export function useDistributionMatrices(projectPublicId?: string) {
|
||||
return useQuery({
|
||||
queryKey: distributionMatrixKeys.byProject(projectPublicId),
|
||||
queryFn: async (): Promise<DistributionMatrix[]> => {
|
||||
const res = await apiClient.get('/admin/distribution-matrices', {
|
||||
params: { projectPublicId },
|
||||
});
|
||||
return extractArrayData<DistributionMatrix>(res.data);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useCreateDistributionMatrix() {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (data: CreateDistributionMatrixDto) => apiClient.post('/admin/distribution-matrices', data),
|
||||
onSuccess: () => {
|
||||
toast.success('Distribution Matrix created');
|
||||
queryClient.invalidateQueries({ queryKey: distributionMatrixKeys.all });
|
||||
},
|
||||
onError: (error: unknown) => {
|
||||
toast.error('Failed to create Distribution Matrix', {
|
||||
description: getApiErrorMessage(error, 'Something went wrong'),
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useDeleteDistributionMatrix() {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (publicId: string) => apiClient.delete(`/admin/distribution-matrices/${publicId}`),
|
||||
onSuccess: () => {
|
||||
toast.success('Distribution Matrix deactivated');
|
||||
queryClient.invalidateQueries({ queryKey: distributionMatrixKeys.all });
|
||||
},
|
||||
onError: (error: unknown) => {
|
||||
toast.error('Failed to deactivate Distribution Matrix', {
|
||||
description: getApiErrorMessage(error, 'Something went wrong'),
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
// File: hooks/use-reminder.ts
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { toast } from 'sonner';
|
||||
import apiClient from '@/lib/api/client';
|
||||
import { getApiErrorMessage } from '@/types/api-error';
|
||||
import { ReminderType } from '@/types/workflow';
|
||||
|
||||
export interface ReminderRule {
|
||||
publicId: string;
|
||||
projectId?: number;
|
||||
name: string;
|
||||
documentTypeCode?: string;
|
||||
reminderType: ReminderType;
|
||||
daysBeforeDue: number;
|
||||
escalationLevel: number;
|
||||
notifyRoles?: string[];
|
||||
messageTemplate?: string;
|
||||
isActive: boolean;
|
||||
}
|
||||
|
||||
export interface ReminderHistory {
|
||||
publicId: string;
|
||||
taskId: number;
|
||||
userId: number;
|
||||
reminderType: ReminderType;
|
||||
escalationLevel: number;
|
||||
sentAt: string;
|
||||
user?: {
|
||||
fullName: string;
|
||||
email: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface CreateReminderRuleDto {
|
||||
projectId?: number;
|
||||
name: string;
|
||||
documentTypeCode?: string;
|
||||
reminderType: ReminderType;
|
||||
daysBeforeDue: number;
|
||||
escalationLevel?: number;
|
||||
notifyRoles?: string[];
|
||||
messageTemplate?: string;
|
||||
}
|
||||
|
||||
export const reminderKeys = {
|
||||
all: ['reminder-rules'] as const,
|
||||
byProject: (projectId?: string) => [...reminderKeys.all, { projectId }] as const,
|
||||
history: (taskPublicId: string) => ['reminder-history', taskPublicId] as const,
|
||||
};
|
||||
|
||||
export function useReminderRules(projectPublicId?: string) {
|
||||
return useQuery({
|
||||
queryKey: reminderKeys.byProject(projectPublicId),
|
||||
queryFn: async (): Promise<ReminderRule[]> => {
|
||||
const res = await apiClient.get('/admin/reminder-rules', {
|
||||
params: { projectPublicId },
|
||||
});
|
||||
return res.data;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useReminderHistory(taskPublicId: string) {
|
||||
return useQuery({
|
||||
queryKey: reminderKeys.history(taskPublicId),
|
||||
queryFn: async (): Promise<ReminderHistory[]> => {
|
||||
const res = await apiClient.get(`/admin/reminder-rules/history/${taskPublicId}`);
|
||||
return res.data;
|
||||
},
|
||||
enabled: !!taskPublicId,
|
||||
});
|
||||
}
|
||||
|
||||
export function useCreateReminderRule() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: (data: CreateReminderRuleDto) =>
|
||||
apiClient.post('/admin/reminder-rules', data),
|
||||
onSuccess: () => {
|
||||
toast.success('Reminder rule created successfully');
|
||||
queryClient.invalidateQueries({ queryKey: reminderKeys.all });
|
||||
},
|
||||
onError: (error: unknown) => {
|
||||
toast.error('Failed to create reminder rule', {
|
||||
description: getApiErrorMessage(error, 'Something went wrong'),
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useUpdateReminderRule() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: ({
|
||||
publicId,
|
||||
data,
|
||||
}: {
|
||||
publicId: string;
|
||||
data: Partial<CreateReminderRuleDto>;
|
||||
}) => apiClient.patch(`/admin/reminder-rules/${publicId}`, data),
|
||||
onSuccess: () => {
|
||||
toast.success('Reminder rule updated');
|
||||
queryClient.invalidateQueries({ queryKey: reminderKeys.all });
|
||||
},
|
||||
onError: (error: unknown) => {
|
||||
toast.error('Failed to update reminder rule', {
|
||||
description: getApiErrorMessage(error, 'Something went wrong'),
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useDeleteReminderRule() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: (publicId: string) =>
|
||||
apiClient.delete(`/admin/reminder-rules/${publicId}`),
|
||||
onSuccess: () => {
|
||||
toast.success('Reminder rule deleted');
|
||||
queryClient.invalidateQueries({ queryKey: reminderKeys.all });
|
||||
},
|
||||
onError: (error: unknown) => {
|
||||
toast.error('Failed to delete reminder rule', {
|
||||
description: getApiErrorMessage(error, 'Something went wrong'),
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { rfaService } from '@/lib/services/rfa.service';
|
||||
import { rfaService, SubmitRfaDto } from '@/lib/services/rfa.service';
|
||||
import { SearchRfaDto, CreateRfaDto, UpdateRfaDto } from '@/types/dto/rfa/rfa.dto';
|
||||
import { WorkflowActionDto } from '@/lib/services/rfa.service';
|
||||
import { toast } from 'sonner';
|
||||
@@ -41,8 +41,8 @@ export function useSubmitRFA() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: ({ uuid, templateId }: { uuid: string; templateId: number }) =>
|
||||
rfaService.submit(uuid, templateId),
|
||||
mutationFn: ({ uuid, data }: { uuid: string; data: SubmitRfaDto }) =>
|
||||
rfaService.submit(uuid, data),
|
||||
onSuccess: (_, { uuid }) => {
|
||||
toast.success('RFA submitted successfully');
|
||||
queryClient.invalidateQueries({ queryKey: rfaKeys.detail(uuid) });
|
||||
|
||||
Reference in New Issue
Block a user