fix: comprehensive TypeScript/build fixes and modernization

- Update tsconfig to ES2024 target and bundler moduleResolution
- Add dynamic imports for chart.js and recharts (bundle optimization)
- Consolidate 17 useState into useReducer in sessions page
- Fix 18 .js extension imports across lib files
- Add type declarations for @rapideditor/country-coder
- Fix platform user types (PlatformUserRole enum)
- Fix Calendar component prop types
- Centralize next-auth type augmentation
- Add force-dynamic to all API routes (prevent build-time prerender)
- Fix Prisma JSON null handling with Prisma.DbNull
- Fix various type mismatches (SessionMessage, ImportRecord, etc.)
- Export ButtonProps from button component
- Update next-themes import path
- Replace JSX.Element with React.ReactElement
- Remove obsolete debug scripts and pnpm lockfile
- Downgrade eslint to v8 for next compatibility
This commit is contained in:
2026-01-20 07:28:10 +01:00
parent 8b3846539f
commit 5bfd762e55
161 changed files with 14655 additions and 11682 deletions

View File

@@ -1,41 +1,29 @@
// SessionImport to Session processor
import type { Prisma, SessionImport } from "@prisma/client";
import { ProcessingStage, SentimentCategory } from "@prisma/client";
import cron from "node-cron";
import { withRetry } from "./database-retry.js";
import { withRetry } from "./database-retry";
import { getSchedulerConfig } from "./env";
import { prisma } from "./prisma.js";
import { prisma } from "./prisma";
import {
completeStage,
failStage,
initializeSession,
skipStage,
startStage,
} from "./processingStatusManager.js";
} from "./processingStatusManager";
import {
fetchTranscriptContent,
isValidTranscriptUrl,
} from "./transcriptFetcher";
interface ImportRecord {
id: string;
companyId: string;
startTimeRaw: string;
endTimeRaw: string;
externalSessionId: string;
sessionId?: string;
userId?: string;
category?: string;
language?: string;
sentiment?: string;
escalated?: boolean;
forwardedHr?: boolean;
avgResponseTime?: number;
messagesSent?: number;
fullTranscriptUrl?: string;
rawTranscriptContent?: string;
aiSummary?: string;
initialMsg?: string;
}
type ImportRecord = SessionImport & {
company: {
id: string;
csvUsername: string | null;
csvPassword: string | null;
};
};
/**
* Parse European date format (DD.MM.YYYY HH:mm:ss) to JavaScript Date
@@ -245,7 +233,7 @@ async function handleTranscriptFetching(
);
if (transcriptResult.success) {
transcriptContent = transcriptResult.content;
transcriptContent = transcriptResult.content ?? null;
console.log(
`[Import Processor] ✓ Fetched transcript for ${importRecord.externalSessionId} (${transcriptContent?.length} chars)`
);
@@ -397,6 +385,15 @@ async function processQueuedImportsInternal(batchSize = 50): Promise<void> {
status: "ACTIVE", // Only process imports from active companies
},
},
include: {
company: {
select: {
id: true,
csvUsername: true,
csvPassword: true,
},
},
},
take: batchSize,
orderBy: {
createdAt: "asc", // Process oldest first
@@ -429,7 +426,10 @@ async function processQueuedImportsInternal(batchSize = 50): Promise<void> {
// Process with concurrency limit to avoid overwhelming the database
const concurrencyLimit = 5;
const results = [];
const results: Array<{
importRecord: ImportRecord;
result: { success: boolean; error?: string };
}> = [];
for (let i = 0; i < batchPromises.length; i += concurrencyLimit) {
const chunk = batchPromises.slice(i, i + concurrencyLimit);