Refactored into generic cardSelector

This commit is contained in:
Connor Yoh 2025-09-16 12:40:14 +01:00
parent 55f3c97f2a
commit 0a8d763f5c
3 changed files with 72 additions and 78 deletions

View File

@ -1,39 +1,50 @@
import { Stack, Card, Text, Flex } from '@mantine/core'; import { Stack, Card, Text, Flex } from '@mantine/core';
import { Tooltip } from '../../shared/Tooltip'; import { Tooltip } from './Tooltip';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { type SplitMethod, METHOD_OPTIONS } from '../../../constants/splitConstants';
import { useSplitSettingsTips } from '../../tooltips/useSplitSettingsTips';
export interface SplitMethodSelectorProps { export interface CardOption<T = string> {
onMethodSelect: (method: SplitMethod) => void; value: T;
disabled?: boolean; prefixKey: string;
nameKey: string;
tooltipKey?: string;
tooltipContent?: any[];
} }
const SplitMethodSelector = ({ export interface CardSelectorProps<T, K extends CardOption<T>> {
onMethodSelect, options: K[];
disabled = false onSelect: (value: T) => void;
}: SplitMethodSelectorProps) => { disabled?: boolean;
getTooltipContent?: (option: K) => any[];
}
const CardSelector = <T, K extends CardOption<T>>({
options,
onSelect,
disabled = false,
getTooltipContent
}: CardSelectorProps<T, K>) => {
const { t } = useTranslation(); const { t } = useTranslation();
// Get tooltip content for a specific method const handleOptionClick = (value: T) => {
const getMethodTooltip = (method: SplitMethod) => { if (!disabled) {
const tooltipContent = useSplitSettingsTips(method); onSelect(value);
return tooltipContent?.tips || []; }
}; };
const handleMethodClick = (method: SplitMethod) => { const getTooltips = (option: K) => {
if (!disabled) { if (getTooltipContent) {
onMethodSelect(method); return getTooltipContent(option);
} }
return [];
}; };
return ( return (
<Stack gap="sm"> <Stack gap="sm">
{METHOD_OPTIONS.map((option) => ( {options.map((option) => (
<Tooltip <Tooltip
key={option.method} key={option.value as string}
sidebarTooltip sidebarTooltip
tips={getMethodTooltip(option.method)} tips={getTooltips(option)}
> >
<Card <Card
radius="md" radius="md"
@ -62,11 +73,11 @@ const SplitMethodSelector = ({
e.currentTarget.style.boxShadow = 'none'; e.currentTarget.style.boxShadow = 'none';
} }
}} }}
onClick={() => handleMethodClick(option.method)} onClick={() => handleOptionClick(option.value)}
> >
<Flex align={'center'} w="100%" > <Flex align={'center'} pl="sm" w="100%">
<Text size="sm" c="dimmed" ta="center" fw={350} > <Text size="sm" c="dimmed" ta="center" fw={350}>
{t(option.prefixKey, "Split by")} {t(option.prefixKey, "Prefix")}
</Text> </Text>
<Text <Text
fw={600} fw={600}
@ -74,8 +85,8 @@ const SplitMethodSelector = ({
c={undefined} c={undefined}
ta="center" ta="center"
style={{ marginLeft: '0.25rem' }} style={{ marginLeft: '0.25rem' }}
> >
{t(option.nameKey, "Method Name")} {t(option.nameKey, "Option Name")}
</Text> </Text>
</Flex> </Flex>
</Card> </Card>
@ -85,4 +96,4 @@ const SplitMethodSelector = ({
); );
}; };
export default SplitMethodSelector; export default CardSelector;

View File

@ -24,52 +24,51 @@ export const isSplitMethod = (value: string | null): value is SplitMethod => {
return Object.values(SPLIT_METHODS).includes(value as SplitMethod); return Object.values(SPLIT_METHODS).includes(value as SplitMethod);
} }
export interface MethodOption { import { CardOption } from '../components/shared/CardSelector';
method: SplitMethod;
prefixKey: string; export interface MethodOption extends CardOption<SplitMethod> {
nameKey: string;
tooltipKey: string; tooltipKey: string;
} }
export const METHOD_OPTIONS: MethodOption[] = [ export const METHOD_OPTIONS: MethodOption[] = [
{ {
method: SPLIT_METHODS.BY_PAGES, value: SPLIT_METHODS.BY_PAGES,
prefixKey: "split.methods.prefix.splitAt", prefixKey: "split.methods.prefix.splitAt",
nameKey: "split.methods.byPages.name", nameKey: "split.methods.byPages.name",
tooltipKey: "split.methods.byPages.tooltip" tooltipKey: "split.methods.byPages.tooltip"
}, },
{ {
method: SPLIT_METHODS.BY_CHAPTERS, value: SPLIT_METHODS.BY_CHAPTERS,
prefixKey: "split.methods.prefix.splitBy", prefixKey: "split.methods.prefix.splitBy",
nameKey: "split.methods.byChapters.name", nameKey: "split.methods.byChapters.name",
tooltipKey: "split.methods.byChapters.tooltip" tooltipKey: "split.methods.byChapters.tooltip"
}, },
{ {
method: SPLIT_METHODS.BY_SECTIONS, value: SPLIT_METHODS.BY_SECTIONS,
prefixKey: "split.methods.prefix.splitBy", prefixKey: "split.methods.prefix.splitBy",
nameKey: "split.methods.bySections.name", nameKey: "split.methods.bySections.name",
tooltipKey: "split.methods.bySections.tooltip" tooltipKey: "split.methods.bySections.tooltip"
}, },
{ {
method: SPLIT_METHODS.BY_SIZE, value: SPLIT_METHODS.BY_SIZE,
prefixKey: "split.methods.prefix.splitBy", prefixKey: "split.methods.prefix.splitBy",
nameKey: "split.methods.bySize.name", nameKey: "split.methods.bySize.name",
tooltipKey: "split.methods.bySize.tooltip" tooltipKey: "split.methods.bySize.tooltip"
}, },
{ {
method: SPLIT_METHODS.BY_PAGE_COUNT, value: SPLIT_METHODS.BY_PAGE_COUNT,
prefixKey: "split.methods.prefix.splitBy", prefixKey: "split.methods.prefix.splitBy",
nameKey: "split.methods.byPageCount.name", nameKey: "split.methods.byPageCount.name",
tooltipKey: "split.methods.byPageCount.tooltip" tooltipKey: "split.methods.byPageCount.tooltip"
}, },
{ {
method: SPLIT_METHODS.BY_DOC_COUNT, value: SPLIT_METHODS.BY_DOC_COUNT,
prefixKey: "split.methods.prefix.splitBy", prefixKey: "split.methods.prefix.splitBy",
nameKey: "split.methods.byDocCount.name", nameKey: "split.methods.byDocCount.name",
tooltipKey: "split.methods.byDocCount.tooltip" tooltipKey: "split.methods.byDocCount.tooltip"
}, },
{ {
method: SPLIT_METHODS.BY_PAGE_DIVIDER, value: SPLIT_METHODS.BY_PAGE_DIVIDER,
prefixKey: "split.methods.prefix.splitBy", prefixKey: "split.methods.prefix.splitBy",
nameKey: "split.methods.byPageDivider.name", nameKey: "split.methods.byPageDivider.name",
tooltipKey: "split.methods.byPageDivider.tooltip" tooltipKey: "split.methods.byPageDivider.tooltip"

View File

@ -1,6 +1,6 @@
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { createToolFlow } from "../components/tools/shared/createToolFlow"; import { createToolFlow } from "../components/tools/shared/createToolFlow";
import SplitMethodSelector from "../components/tools/split/SplitMethodSelector"; import CardSelector from "../components/shared/CardSelector";
import SplitSettings from "../components/tools/split/SplitSettings"; import SplitSettings from "../components/tools/split/SplitSettings";
import { useSplitParameters } from "../hooks/tools/split/useSplitParameters"; import { useSplitParameters } from "../hooks/tools/split/useSplitParameters";
import { useSplitOperation } from "../hooks/tools/split/useSplitOperation"; import { useSplitOperation } from "../hooks/tools/split/useSplitOperation";
@ -8,6 +8,7 @@ import { useBaseTool } from "../hooks/tools/shared/useBaseTool";
import { useSplitMethodTips } from "../components/tooltips/useSplitMethodTips"; import { useSplitMethodTips } from "../components/tooltips/useSplitMethodTips";
import { useSplitSettingsTips } from "../components/tooltips/useSplitSettingsTips"; import { useSplitSettingsTips } from "../components/tooltips/useSplitSettingsTips";
import { BaseToolProps, ToolComponent } from "../types/tool"; import { BaseToolProps, ToolComponent } from "../types/tool";
import { type SplitMethod, METHOD_OPTIONS, type MethodOption } from "../constants/splitConstants";
const Split = (props: BaseToolProps) => { const Split = (props: BaseToolProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
@ -22,43 +23,26 @@ const Split = (props: BaseToolProps) => {
const methodTips = useSplitMethodTips(); const methodTips = useSplitMethodTips();
const settingsTips = useSplitSettingsTips(base.params.parameters.method); const settingsTips = useSplitSettingsTips(base.params.parameters.method);
// Get tooltip content for a specific method
const getMethodTooltip = (option: MethodOption) => {
const tooltipContent = useSplitSettingsTips(option.value);
return tooltipContent?.tips || [];
};
// Typed parameter updaters
const clearMethod = () => base.params.updateParameter('method', '' as const);
const setMethod = (method: SplitMethod) => base.params.updateParameter('method', method);
// Get the method name for the settings step title // Get the method name for the settings step title
const getSettingsTitle = () => { const getSettingsTitle = () => {
if (!base.params.parameters.method) return t("split.steps.settings", "Settings"); if (!base.params.parameters.method) return t("split.steps.settings", "Settings");
const methodTitleMap = { const methodOption = METHOD_OPTIONS.find(option => option.value === base.params.parameters.method);
'byPages': { if (!methodOption) return t("split.steps.settings", "Settings");
prefix: t("split.methods.prefix.splitAt", "Split at"),
name: t("split.methods.byPages.name", "Page Numbers")
},
'bySections': {
prefix: t("split.methods.prefix.splitBy", "Split by"),
name: t("split.methods.bySections.name", "Sections")
},
'bySize': {
prefix: t("split.methods.prefix.splitBy", "Split by"),
name: t("split.methods.bySize.name", "File Size")
},
'byPageCount': {
prefix: t("split.methods.prefix.splitBy", "Split by"),
name: t("split.methods.byPageCount.name", "Page Count")
},
'byDocCount': {
prefix: t("split.methods.prefix.splitBy", "Split by"),
name: t("split.methods.byDocCount.name", "Document Count")
},
'byChapters': {
prefix: t("split.methods.prefix.splitBy", "Split by"),
name: t("split.methods.byChapters.name", "Chapters")
},
'byPageDivider': {
prefix: t("split.methods.prefix.splitBy", "Split by"),
name: t("split.methods.byPageDivider.name", "Page Divider")
},
};
const method = methodTitleMap[base.params.parameters.method as keyof typeof methodTitleMap]; const prefix = t(methodOption.prefixKey, "Split by");
return method ? `${method.prefix} ${method.name}` : t("split.steps.settings", "Settings"); const name = t(methodOption.nameKey, "Method Name");
return `${prefix} ${name}`;
}; };
return createToolFlow({ return createToolFlow({
@ -70,15 +54,15 @@ const Split = (props: BaseToolProps) => {
{ {
title: t("split.steps.chooseMethod", "Choose Method"), title: t("split.steps.chooseMethod", "Choose Method"),
isCollapsed: !!base.params.parameters.method, // Collapse when method is selected isCollapsed: !!base.params.parameters.method, // Collapse when method is selected
onCollapsedClick: () => { onCollapsedClick: () => base.params.updateParameter('method', '')
// Clear the selected method to expand the method selection step ,
base.params.updateParameter('method', '');
},
tooltip: methodTips, tooltip: methodTips,
content: ( content: (
<SplitMethodSelector <CardSelector<SplitMethod, MethodOption>
onMethodSelect={(method) => base.params.updateParameter('method', method)} options={METHOD_OPTIONS}
onSelect={(method) => base.params.updateParameter('method', method)}
disabled={base.endpointLoading} disabled={base.endpointLoading}
getTooltipContent={getMethodTooltip}
/> />
), ),
}, },