// src/utils/toolRendering.ts - Consolidated tool rendering utilities
import { Tool, escapeHtml, sanitizeText, truncateText, getConfidenceColor } from './uiHelpers.js';
// TOOL CLASSIFICATION UTILITIES (consolidates repeated logic across components)
export interface ToolClassification {
isMethod: boolean;
isConcept: boolean;
isHosted: boolean;
isOpenSource: boolean;
hasKnowledgebase: boolean;
}
export function classifyTool(tool: Tool): ToolClassification {
const isMethod = tool.type === 'method';
const isConcept = tool.type === 'concept';
const isHosted = tool.projectUrl !== undefined &&
tool.projectUrl !== null &&
tool.projectUrl !== "" &&
tool.projectUrl.trim() !== "";
const isOpenSource = tool.license !== 'Proprietary';
const hasKnowledgebase = tool.knowledgebase === true;
return { isMethod, isConcept, isHosted, isOpenSource, hasKnowledgebase };
}
export function getToolCardClass(tool: Tool): string {
const { isMethod, isConcept, isHosted, isOpenSource } = classifyTool(tool);
if (isConcept) return 'card card-concept tool-card cursor-pointer';
if (isMethod) return 'card card-method tool-card cursor-pointer';
if (isHosted) return 'card card-hosted tool-card cursor-pointer';
if (isOpenSource) return 'card card-oss tool-card cursor-pointer';
return 'card tool-card cursor-pointer';
}
export function getToolChipClass(tool: Tool): string {
const { isMethod, isHosted, isOpenSource } = classifyTool(tool);
if (isMethod) return 'tool-chip tool-chip-method';
if (isHosted) return 'tool-chip tool-chip-hosted';
if (isOpenSource) return 'tool-chip tool-chip-oss';
return 'tool-chip';
}
export function getRecommendationClass(tool: Tool): string {
const { isMethod, isHosted, isOpenSource } = classifyTool(tool);
if (isMethod) return 'method';
if (isHosted) return 'hosted';
if (isOpenSource) return 'oss';
return '';
}
// BADGE RENDERING UTILITIES (consolidates badge logic across components)
export function renderToolBadges(tool: Tool): string {
const { isMethod, isConcept, isHosted, hasKnowledgebase } = classifyTool(tool);
let badges = '';
if (isConcept) {
badges += 'Konzept';
} else if (isMethod) {
badges += 'Methode';
} else if (isHosted) {
badges += 'CC24-Server';
}
if (hasKnowledgebase) {
badges += 'đź“–';
}
return badges;
}
export function renderInlineBadges(tool: Tool): string {
const { isMethod, isHosted, hasKnowledgebase } = classifyTool(tool);
let badges = '';
if (isMethod) {
badges += 'Methode';
} else if (isHosted) {
badges += 'CC24-Server';
}
if (hasKnowledgebase) {
badges += 'đź“–';
}
return badges;
}
// METADATA RENDERING UTILITIES (consolidates metadata display logic)
export function renderToolMetadata(tool: Tool, compact: boolean = false): string {
const { isMethod, isConcept } = classifyTool(tool);
const domains = tool.domains || [];
const phases = tool.phases || [];
const domainsText = domains.length > 0 ? domains.join(', ') : 'Domain-agnostic';
const phasesText = phases.join(', ');
if (compact) {
return `
${isMethod ? 'Methode' : isConcept ? 'Konzept' : tool.platforms?.slice(0, 2).join(', ')}
•
${tool.skillLevel}
`;
}
let metadataHTML = ``;
if (!isConcept) {
metadataHTML += `
Betriebssystem: ${(tool.platforms || []).join(', ')}
Skill Level: ${tool.skillLevel}
Lizenzmodell: ${tool.license}
Deployment: ${tool.accessType}
`;
} else {
metadataHTML += `
Skill Level: ${tool.skillLevel}
`;
}
metadataHTML += `
Einsatzgebiete: ${domainsText}
Ermittlungsphasen: ${phasesText}
`;
return metadataHTML;
}
// BUTTON RENDERING UTILITIES (consolidates button logic across components)
export function renderToolButtons(tool: Tool, stopPropagation: boolean = true): string {
const { isMethod, isConcept, isHosted } = classifyTool(tool);
const onClickAttr = stopPropagation ? 'onclick="event.stopPropagation();"' : '';
if (isConcept) {
return `
Mehr erfahren
`;
}
if (isMethod) {
return `
Zur Methode
`;
}
if (isHosted) {
return `
`;
}
return `
Software-Homepage
`;
}
export function renderExtendedToolLinks(tool: Tool): string {
const { hasKnowledgebase } = classifyTool(tool);
let linksHTML = renderToolButtons(tool, false);
if (hasKnowledgebase) {
const kbId = tool.name.toLowerCase()
.replace(/[^a-z0-9\s-]/g, '')
.replace(/\s+/g, '-')
.replace(/-+/g, '-')
.replace(/^-|-$/g, '');
linksHTML += `
Knowledgebase anzeigen
`;
}
return linksHTML;
}
// TAG RENDERING UTILITIES (consolidates tag display logic)
export function renderTagCloud(tool: Tool, maxTags: number = 8): string {
const tags = tool.tags || [];
return tags.slice(0, maxTags).map(tag =>
`${escapeHtml(tag)}`
).join('');
}
export function renderRelatedItems(
tool: Tool,
allTools: Tool[],
modalType: string = 'primary'
): string {
const relatedConcepts = tool.related_concepts || [];
const relatedSoftware = tool.related_software || [];
let html = '';
if (relatedConcepts.length > 0 && modalType === 'primary') {
const conceptLinks = relatedConcepts.map(conceptName => {
const concept = allTools.find(t => t.name === conceptName && t.type === 'concept');
if (concept) {
return `
`;
}
return `${conceptName}`;
}).join('');
const isMobile = window.innerWidth <= 768;
const collapseOnMobile = isMobile && relatedConcepts.length > 2;
html += `
Verwandte Konzepte:
${collapseOnMobile ? `
` : ''}
${conceptLinks}
`;
}
if (relatedSoftware.length > 0 && modalType === 'primary') {
const softwareLinks = relatedSoftware.map(softwareName => {
const software = allTools.find(t => t.name === softwareName && (t.type === 'software' || t.type === 'method'));
if (software) {
const { isHosted, isMethod } = classifyTool(software);
const bgColor = isMethod ? 'var(--color-method-bg)' :
isHosted ? 'var(--color-hosted-bg)' : 'var(--color-oss-bg)';
const borderColor = isMethod ? 'var(--color-method)' :
isHosted ? 'var(--color-hosted)' : 'var(--color-oss)';
return `
`;
}
return `${softwareName}`;
}).join('');
const isMobile = window.innerWidth <= 768;
const collapseOnMobile = isMobile && relatedSoftware.length > 2;
html += `
Verwandte Software:
${collapseOnMobile ? `
` : ''}
${softwareLinks}
`;
}
return html;
}
// CONFIDENCE RENDERING UTILITIES (consolidates AI confidence display logic)
export interface ConfidenceData {
overall: number;
semanticRelevance: number;
taskSuitability: number;
uncertaintyFactors: string[];
strengthIndicators: string[];
}
export function renderConfidenceTooltip(confidence: ConfidenceData): string {
const confidenceColor = getConfidenceColor(confidence.overall);
const tooltipId = `tooltip-${Math.random().toString(36).substr(2, 9)}`;
return `
${confidence.overall}%
`;
}
// SUITABILITY UTILITIES (consolidates suitability display logic)
export function getSuitabilityText(score: string): string {
const texts = {
high: 'GUT GEEIGNET',
medium: 'GEEIGNET',
low: 'VIELLEICHT GEEIGNET'
};
return texts[score] || 'GEEIGNET';
}
export function getSuitabilityColor(score: string): string {
const colors = {
high: 'var(--color-accent)',
medium: 'var(--color-warning)',
low: 'var(--color-text-secondary)'
};
return colors[score] || 'var(--color-warning)';
}