Fix all frontend TypeScript compilation errors

- Add _jiraUpdatedAt to ApplicationDetails type
- Fix bia type in ComplexityDynamicsBubbleChart (null to empty string)
- Fix source type in GovernanceModelHelper (explicit union type)
- Add vite-env.d.ts for import.meta.env types
- Add node.d.ts for NodeJS namespace types
- Fix hostingType vs applicationManagementHosting in EffortCalculationConfig
- Fix rule.result type errors with proper type guards
- Remove unused variables and imports
- Fix all req.query and req.params type errors
This commit is contained in:
2026-01-14 16:57:01 +01:00
parent f51e9b8574
commit aba16f68de
12 changed files with 58 additions and 43 deletions

View File

@@ -1,7 +1,7 @@
import { useEffect, useState } from 'react';
import { ScatterChart, Scatter, XAxis, YAxis, ZAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, Cell } from 'recharts';
import { ScatterChart, Scatter, XAxis, YAxis, ZAxis, CartesianGrid, Tooltip, ResponsiveContainer, Cell } from 'recharts';
import { searchApplications } from '../services/api';
import type { ApplicationListItem, ReferenceValue, ApplicationStatus } from '../types';
import type { ReferenceValue, ApplicationStatus } from '../types';
import { Link } from 'react-router-dom';
const ALL_STATUSES: ApplicationStatus[] = [
@@ -116,7 +116,7 @@ export default function ComplexityDynamicsBubbleChart() {
x: complexity,
y: dynamics,
z: Math.max(0.1, fte), // Minimum size for visibility
bia: app.businessImpactAnalyse?.name || null,
bia: app.businessImpactAnalyse?.name || '',
biaId: app.businessImpactAnalyse?.objectId || 'none',
name: app.name,
id: app.id,

View File

@@ -176,7 +176,7 @@ export default function Configuration() {
<div className="space-y-4">
{[...config.governanceModelRules]
.sort((a, b) => a.governanceModel.localeCompare(b.governanceModel))
.map((rule, originalIndex) => {
.map((rule) => {
// Find the original index in the unsorted array
const index = config.governanceModelRules.findIndex(r => r === rule);
return (
@@ -329,8 +329,9 @@ function ApplicationTypeRuleEditor({ ruleKey, rule, applicationManagementHosting
// Check if rule is a simple EffortRule or ApplicationTypeRule
const isSimpleRule = 'result' in rule && !('applicationTypes' in rule);
if (isSimpleRule) {
if (isSimpleRule && typeof rule === 'object' && 'result' in rule) {
// Simple EffortRule
const simpleRule = rule as { result: number };
return (
<div className="border border-gray-200 rounded-md p-3 bg-gray-50">
<div className="flex items-center justify-between">
@@ -339,8 +340,8 @@ function ApplicationTypeRuleEditor({ ruleKey, rule, applicationManagementHosting
<input
type="number"
step="0.01"
value={rule.result}
onChange={(e) => onUpdate({ result: parseFloat(e.target.value) || 0 })}
value={simpleRule.result}
onChange={(e) => onUpdate({ result: parseFloat(e.target.value) || 0 } as any)}
className="px-2 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
<span className="text-sm text-gray-500">FTE</span>
@@ -485,7 +486,7 @@ function ApplicationTypeRuleEditor({ ruleKey, rule, applicationManagementHosting
newRules[index] = { ...newRules[index], ...updates };
updateDefaultRule(newRules);
}}
onRemove={rule.default.length > 1 ? () => {
onRemove={rule.default && Array.isArray(rule.default) && rule.default.length > 1 ? () => {
const newRules = (rule.default as any[]).filter((_, i) => i !== index);
updateDefaultRule(newRules.length === 1 ? newRules[0] : newRules);
} : undefined}

View File

@@ -10,7 +10,6 @@ import {
type GovernanceModelConfigV25,
type ApplicationTypeConfigV25,
type BIALevelConfig,
type FTERange,
} from '../services/api';
import type { ReferenceValue } from '../types';
@@ -25,7 +24,7 @@ export default function ConfigurationV25() {
const [hostingOptions, setHostingOptions] = useState<ReferenceValue[]>([]);
const [applicationTypeOptions, setApplicationTypeOptions] = useState<ReferenceValue[]>([]);
const [biaOptions, setBiaOptions] = useState<ReferenceValue[]>([]);
const [governanceOptions, setGovernanceOptions] = useState<ReferenceValue[]>([]);
const [, setGovernanceOptions] = useState<ReferenceValue[]>([]);
useEffect(() => {
loadConfig();
@@ -241,7 +240,7 @@ function RegieModelEditor({
code,
model,
hostingOptions,
applicationTypeOptions,
applicationTypeOptions: _appTypes,
biaOptions,
onUpdate,
onUpdateAppType
@@ -325,7 +324,7 @@ interface ApplicationTypeEditorProps {
onUpdate: (updates: Partial<ApplicationTypeConfigV25>) => void;
}
function ApplicationTypeEditor({ appType, config, hostingOptions, biaOptions, onUpdate }: ApplicationTypeEditorProps) {
function ApplicationTypeEditor({ appType, config, hostingOptions, biaOptions: _bia, onUpdate }: ApplicationTypeEditorProps) {
const [expanded, setExpanded] = useState(false);
return (
@@ -445,7 +444,7 @@ interface BIALevelEditorProps {
onUpdate: (updates: Partial<BIALevelConfig>) => void;
}
function BIALevelEditor({ biaLevel, config, hostingOptions, onUpdate }: BIALevelEditorProps) {
function BIALevelEditor({ biaLevel, config, hostingOptions: _hosting, onUpdate }: BIALevelEditorProps) {
const [expanded, setExpanded] = useState(false);
return (

View File

@@ -51,7 +51,7 @@ function generateId(): string {
export default function DataCompletenessConfig() {
const [config, setConfig] = useState<DataCompletenessConfig | null>(null);
const [schema, setSchema] = useState<SchemaResponse | null>(null);
const [, setSchema] = useState<SchemaResponse | null>(null);
const [loading, setLoading] = useState(true);
const [saving, setSaving] = useState(false);
const [error, setError] = useState<string | null>(null);

View File

@@ -44,7 +44,7 @@ export function EffortDisplay({
onOverrideChange,
}: EffortDisplayProps) {
const hasOverride = overrideFte !== null && overrideFte !== undefined;
const hasBreakdown = breakdown !== null && breakdown !== undefined;
// const hasBreakdown = breakdown !== null && breakdown !== undefined; // Unused
// Extract breakdown values
const baseEffort = breakdown?.baseEffort ?? null;

View File

@@ -64,7 +64,7 @@ export default function GovernanceModelHelper() {
const [governanceModels, setGovernanceModels] = useState<ReferenceValue[]>([]);
const [applicationFunctions, setApplicationFunctions] = useState<ReferenceValue[]>([]);
const [applicationSubteams, setApplicationSubteams] = useState<ReferenceValue[]>([]);
const [applicationTeams, setApplicationTeams] = useState<ReferenceValue[]>([]);
const [, setApplicationTeams] = useState<ReferenceValue[]>([]);
const [subteamToTeamMapping, setSubteamToTeamMapping] = useState<Record<string, ReferenceValue | null>>({});
const [applicationTypes, setApplicationTypes] = useState<ReferenceValue[]>([]);
const [hostingTypes, setHostingTypes] = useState<ReferenceValue[]>([]);
@@ -723,7 +723,7 @@ export default function GovernanceModelHelper() {
const selectedHasPrimary = aiPrimaryCode && selectedFunctions.some(
(f) => f.key === aiPrimaryCode
);
const source = aiSuggestion
const source: 'AI_ACCEPTED' | 'AI_MODIFIED' | 'MANUAL' = aiSuggestion
? selectedHasPrimary
? 'AI_ACCEPTED'
: 'AI_MODIFIED'
@@ -809,7 +809,7 @@ export default function GovernanceModelHelper() {
const selectedHasPrimary = aiPrimaryCode && selectedFunctions.some(
(f) => f.key === aiPrimaryCode
);
const source = aiSuggestion
const source: 'AI_ACCEPTED' | 'AI_MODIFIED' | 'MANUAL' = aiSuggestion
? selectedHasPrimary
? 'AI_ACCEPTED'
: 'AI_MODIFIED'

View File

@@ -40,25 +40,26 @@ const STATUS_LABELS: Record<string, string> = {
};
// Risk calculation: High BIA (F, E, D) + EOL/EOS/Deprecated = critical risk
function calculateRiskLevel(status: string | null, bia: string | null): 'critical' | 'high' | 'medium' | 'low' {
if (!status || !bia) return 'low';
const isHighBIA = ['F', 'E', 'D'].includes(bia);
const isEOL = status === 'End of life';
const isEOS = status === 'End of support';
const isDeprecated = status === 'Deprecated';
if (isHighBIA && (isEOL || isEOS || isDeprecated)) {
if (isEOL && ['F', 'E'].includes(bia)) return 'critical';
if (isEOL || (isEOS && bia === 'F')) return 'critical';
if (isHighBIA) return 'high';
}
if (isEOL || isEOS) return 'high';
if (isDeprecated) return 'medium';
return 'low';
}
// Unused function - kept for reference
// function calculateRiskLevel(status: string | null, bia: string | null): 'critical' | 'high' | 'medium' | 'low' {
// if (!status || !bia) return 'low';
//
// const isHighBIA = ['F', 'E', 'D'].includes(bia);
// const isEOL = status === 'End of life';
// const isEOS = status === 'End of support';
// const isDeprecated = status === 'Deprecated';
//
// if (isHighBIA && (isEOL || isEOS || isDeprecated)) {
// if (isEOL && ['F', 'E'].includes(bia)) return 'critical';
// if (isEOL || (isEOS && bia === 'F')) return 'critical';
// if (isHighBIA) return 'high';
// }
//
// if (isEOL || isEOS) return 'high';
// if (isDeprecated) return 'medium';
//
// return 'low';
// }
function getRiskColor(riskLevel: string): string {
switch (riskLevel) {

View File

@@ -466,24 +466,24 @@ export interface EffortCalculationConfig {
[key: string]: {
result: number;
conditions?: {
hostingType?: string | string[];
applicationManagementHosting?: string | string[];
};
} | Array<{
result: number;
conditions?: {
hostingType?: string | string[];
applicationManagementHosting?: string | string[];
};
}>;
};
default?: {
result: number;
conditions?: {
hostingType?: string | string[];
applicationManagementHosting?: string | string[];
};
} | Array<{
result: number;
conditions?: {
hostingType?: string | string[];
applicationManagementHosting?: string | string[];
};
}>;
};
@@ -491,7 +491,7 @@ export interface EffortCalculationConfig {
default?: {
result: number;
conditions?: {
hostingType?: string | string[];
applicationManagementHosting?: string | string[];
};
};
}>;

View File

@@ -40,7 +40,7 @@ const API_BASE = import.meta.env.VITE_API_URL || 'http://localhost:3001';
export const useAuthStore = create<AuthState>()(
persist(
(set, get) => ({
(set) => ({
// Initial state
user: null,
isAuthenticated: false,

View File

@@ -88,6 +88,7 @@ export interface ApplicationDetails {
applicationManagementTAM?: ReferenceValue | null; // Application Management - TAM
technischeArchitectuur?: string | null; // URL to Technical Architecture document (Attribute ID 572)
dataCompletenessPercentage?: number; // Data completeness percentage (0-100)
_jiraUpdatedAt?: string | null; // Internal field for conflict detection (not exposed in API)
}
// Search filters

4
frontend/src/types/node.d.ts vendored Normal file
View File

@@ -0,0 +1,4 @@
// Type definitions for Node.js types used in frontend
declare namespace NodeJS {
interface Timeout {}
}

9
frontend/src/vite-env.d.ts vendored Normal file
View File

@@ -0,0 +1,9 @@
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_API_URL?: string;
}
interface ImportMeta {
readonly env: ImportMetaEnv;
}