task-d.7.6

This commit is contained in:
phaichayon
2026-07-03 09:51:36 +07:00
parent b7589017ab
commit 110c2f9e7f
10 changed files with 1376 additions and 392 deletions

View File

@@ -1,10 +1,11 @@
import { queryOptions } from '@tanstack/react-query';
import { getSetupReadiness, verifySetup } from './service';
import { getSetupReadiness, getSetupTemplates, verifySetup } from './service';
import type { SetupVerificationPayload } from './types';
export const setupKeys = {
all: ['setup'] as const,
readiness: () => [...setupKeys.all, 'readiness'] as const,
templates: () => [...setupKeys.all, 'templates'] as const,
verification: (payload: SetupVerificationPayload = {}) =>
[...setupKeys.all, 'verification', payload] as const
};
@@ -15,6 +16,12 @@ export const setupReadinessQueryOptions = () =>
queryFn: () => getSetupReadiness()
});
export const setupTemplatesQueryOptions = () =>
queryOptions({
queryKey: setupKeys.templates(),
queryFn: () => getSetupTemplates()
});
export const setupVerificationQueryOptions = (payload: SetupVerificationPayload = {}) =>
queryOptions({
queryKey: setupKeys.verification(payload),

View File

@@ -1,14 +1,26 @@
import { apiClient } from '@/lib/api-client';
import { ApiClientError, apiClient } from '@/lib/api-client';
import type {
CsvPreviewResult,
ImportReport,
SetupReadinessReport,
SetupTemplatesResponse,
SetupVerificationPayload,
SetupVerificationReport
} from './types';
interface ApiErrorPayload {
message?: string;
error?: string;
}
export async function getSetupReadiness(): Promise<SetupReadinessReport> {
return apiClient<SetupReadinessReport>('/setup/readiness');
}
export async function getSetupTemplates(): Promise<SetupTemplatesResponse> {
return apiClient<SetupTemplatesResponse>('/setup/templates');
}
export async function verifySetup(
payload: SetupVerificationPayload = {}
): Promise<SetupVerificationReport> {
@@ -17,3 +29,50 @@ export async function verifySetup(
body: JSON.stringify(payload)
});
}
async function readUploadResponse<T>(response: Response): Promise<T> {
if (response.ok) {
return response.json() as Promise<T>;
}
const payload = (await response.json().catch(() => null)) as ApiErrorPayload | null;
const message = payload?.message ?? payload?.error ?? `API error: ${response.status}`;
throw new ApiClientError(message, {
status: response.status,
statusText: response.statusText,
payload
});
}
function buildCsvFormData(files: File[]): FormData {
const formData = new FormData();
files.forEach((file) => formData.append('files', file, file.name));
return formData;
}
export async function previewSetupCsvFiles(files: File[]): Promise<CsvPreviewResult> {
return readUploadResponse<CsvPreviewResult>(
await fetch('/api/setup/import/preview', {
method: 'POST',
body: buildCsvFormData(files)
})
);
}
export async function commitSetupCsvFiles(input: {
files: File[];
previewHash: string;
dryRun?: boolean;
}): Promise<ImportReport> {
const formData = buildCsvFormData(input.files);
formData.set('previewHash', input.previewHash);
formData.set('dryRun', String(Boolean(input.dryRun)));
return readUploadResponse<ImportReport>(
await fetch('/api/setup/import/commit', {
method: 'POST',
body: formData
})
);
}

View File

@@ -37,3 +37,36 @@ export interface SetupVerificationPayload {
export interface SetupVerificationReport extends SetupReadinessReport {
organizationId: string | null;
}
export interface SetupTemplateMetadataItem {
file: string;
seedType: string;
importOrder: number;
supported: boolean;
requiredColumns: string[];
description: string;
}
export interface SetupTemplatesResponse {
success: boolean;
time: string;
version: string;
generatedFrom: string;
templates: SetupTemplateMetadataItem[];
}
export type {
CsvPreviewError,
CsvPreviewFileResult,
CsvPreviewRow,
CsvPreviewResult,
CsvPreviewStatus,
CsvPreviewWarning
} from '@/features/setup/server/csv/types';
export type {
ImportFileReport,
ImportReport,
ImportRowReport,
ImportStatus
} from '@/features/setup/server/csv/import-report';

View File

@@ -0,0 +1,17 @@
'use client';
import { useMutation } from '@tanstack/react-query';
import { commitSetupCsvFiles, previewSetupCsvFiles } from './service';
export function useCsvPreview() {
return useMutation({
mutationFn: (files: File[]) => previewSetupCsvFiles(files)
});
}
export function useCsvCommit() {
return useMutation({
mutationFn: (input: { files: File[]; previewHash: string; dryRun?: boolean }) =>
commitSetupCsvFiles(input)
});
}

View File

@@ -0,0 +1,11 @@
'use client';
import { useMutation } from '@tanstack/react-query';
import { verifySetup } from './service';
import type { SetupVerificationPayload } from './types';
export function useSetupVerification() {
return useMutation({
mutationFn: (payload: SetupVerificationPayload = {}) => verifySetup(payload)
});
}

File diff suppressed because it is too large Load Diff