mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-08-21 19:59:24 +00:00
simplify search results & tool picker
This commit is contained in:
parent
19d2b72f65
commit
f2b5a4a1f8
@ -3,6 +3,8 @@ import { Box, Stack, Text } from '@mantine/core';
|
||||
import { type ToolRegistryEntry } from '../../data/toolRegistry';
|
||||
import ToolButton from './toolPicker/ToolButton';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useToolSections } from '../../hooks/useToolSections';
|
||||
import SubcategoryHeader from './shared/SubcategoryHeader';
|
||||
|
||||
interface SearchResultsProps {
|
||||
filteredTools: [string, ToolRegistryEntry][];
|
||||
@ -11,38 +13,9 @@ interface SearchResultsProps {
|
||||
|
||||
const SearchResults: React.FC<SearchResultsProps> = ({ filteredTools, onSelect }) => {
|
||||
const { t } = useTranslation();
|
||||
// Group tools by subcategory and remove duplicates
|
||||
const groupedToolsByCategory = useMemo(() => {
|
||||
const categoryToToolsMap: Record<string, Array<{ id: string; tool: ToolRegistryEntry }>> = {};
|
||||
const processedToolIds = new Set<string>();
|
||||
const { searchGroups } = useToolSections(filteredTools);
|
||||
|
||||
// Process each tool, skipping duplicates and grouping by subcategory
|
||||
filteredTools.forEach(([toolId, toolEntry]) => {
|
||||
// Skip if we've already processed this tool ID (deduplication)
|
||||
if (processedToolIds.has(toolId)) return;
|
||||
processedToolIds.add(toolId);
|
||||
|
||||
// Use subcategory or default to 'General' if not specified
|
||||
const categoryName = toolEntry?.subcategory || 'General';
|
||||
|
||||
// Initialize category array if it doesn't exist
|
||||
if (!categoryToToolsMap[categoryName]) {
|
||||
categoryToToolsMap[categoryName] = [];
|
||||
}
|
||||
|
||||
categoryToToolsMap[categoryName].push({ id: toolId, tool: toolEntry });
|
||||
});
|
||||
|
||||
// Convert to sorted array format for rendering
|
||||
return Object.entries(categoryToToolsMap)
|
||||
.sort(([categoryA], [categoryB]) => categoryA.localeCompare(categoryB))
|
||||
.map(([categoryName, toolsInCategory]) => ({
|
||||
categoryName,
|
||||
toolsInCategory
|
||||
}));
|
||||
}, [filteredTools]);
|
||||
|
||||
if (groupedToolsByCategory.length === 0) {
|
||||
if (searchGroups.length === 0) {
|
||||
return (
|
||||
<Text c="dimmed" size="sm" p="sm">
|
||||
{t('toolPicker.noToolsFound', 'No tools found')}
|
||||
@ -52,13 +25,11 @@ const SearchResults: React.FC<SearchResultsProps> = ({ filteredTools, onSelect }
|
||||
|
||||
return (
|
||||
<Stack p="sm" gap="xs">
|
||||
{groupedToolsByCategory.map(categoryGroup => (
|
||||
<Box key={categoryGroup.categoryName} w="100%">
|
||||
<Text size="sm" fw={500} mb="0.25rem" mt="1rem" className="tool-subcategory-title">
|
||||
{t(`toolPicker.subcategories.${categoryGroup.categoryName}`, categoryGroup.categoryName)}
|
||||
</Text>
|
||||
{searchGroups.map(group => (
|
||||
<Box key={group.subcategory} w="100%">
|
||||
<SubcategoryHeader label={t(`toolPicker.subcategories.${group.subcategory}`, group.subcategory)} />
|
||||
<Stack gap="xs">
|
||||
{categoryGroup.toolsInCategory.map(({ id, tool }) => (
|
||||
{group.tools.map(({ id, tool }) => (
|
||||
<ToolButton
|
||||
key={id}
|
||||
id={id}
|
||||
@ -68,7 +39,6 @@ const SearchResults: React.FC<SearchResultsProps> = ({ filteredTools, onSelect }
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
{/* bottom spacer within each group not strictly required, outer list can add a spacer if needed */}
|
||||
</Box>
|
||||
))}
|
||||
{/* global spacer to allow scrolling past last row in search mode */}
|
||||
|
@ -5,6 +5,7 @@ import { type ToolRegistryEntry } from "../../data/toolRegistry";
|
||||
import ToolButton from "./toolPicker/ToolButton";
|
||||
import "./toolPicker/ToolPicker.css";
|
||||
import { useToolSections } from "../../hooks/useToolSections";
|
||||
import SubcategoryHeader from "./shared/SubcategoryHeader";
|
||||
|
||||
interface ToolPickerProps {
|
||||
selectedToolKey: string | null;
|
||||
@ -13,12 +14,6 @@ interface ToolPickerProps {
|
||||
isSearching?: boolean;
|
||||
}
|
||||
|
||||
interface GroupedTools {
|
||||
[category: string]: {
|
||||
[subcategory: string]: Array<{ id: string; tool: ToolRegistryEntry }>;
|
||||
};
|
||||
}
|
||||
|
||||
const ToolPicker = ({ selectedToolKey, onSelect, filteredTools, isSearching = false }: ToolPickerProps) => {
|
||||
const { t } = useTranslation();
|
||||
const [quickHeaderHeight, setQuickHeaderHeight] = useState(0);
|
||||
@ -45,15 +40,6 @@ const ToolPicker = ({ selectedToolKey, onSelect, filteredTools, isSearching = fa
|
||||
return () => window.removeEventListener("resize", update);
|
||||
}, []);
|
||||
|
||||
// Lightweight inline component to avoid an extra file
|
||||
const SubcategoryHeader: React.FC<{ label: string; mt?: string | number; mb?: string | number }> = ({ label, mt = "1rem", mb = "0.25rem" }) => (
|
||||
<div className="tool-subcategory-row" style={{ marginLeft: "1rem", marginRight: "1rem", marginTop: mt, marginBottom: mb }}>
|
||||
<div className="tool-subcategory-row-rule" />
|
||||
<span className="tool-subcategory-row-title">{label}</span>
|
||||
<div className="tool-subcategory-row-rule" />
|
||||
</div>
|
||||
);
|
||||
|
||||
const { sections: visibleSections } = useToolSections(filteredTools);
|
||||
|
||||
const quickSection = useMemo(
|
||||
|
17
frontend/src/components/tools/shared/SubcategoryHeader.tsx
Normal file
17
frontend/src/components/tools/shared/SubcategoryHeader.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
import React from 'react';
|
||||
|
||||
interface SubcategoryHeaderProps {
|
||||
label: string;
|
||||
mt?: string | number;
|
||||
mb?: string | number;
|
||||
}
|
||||
|
||||
export const SubcategoryHeader: React.FC<SubcategoryHeaderProps> = ({ label, mt = '1rem', mb = '0.25rem' }) => (
|
||||
<div className="tool-subcategory-row" style={{ marginLeft: '1rem', marginRight: '1rem', marginTop: mt, marginBottom: mb }}>
|
||||
<div className="tool-subcategory-row-rule" />
|
||||
<span className="tool-subcategory-row-title">{label}</span>
|
||||
<div className="tool-subcategory-row-rule" />
|
||||
</div>
|
||||
);
|
||||
|
||||
export default SubcategoryHeader;
|
Loading…
x
Reference in New Issue
Block a user