Add form-select.tsx with reset to default button used in settings

This commit is contained in:
2026-02-07 10:47:36 +00:00
parent f76cb81108
commit 765f7d6d35
2 changed files with 101 additions and 32 deletions

View File

@@ -18,6 +18,7 @@ import { Button } from './ui/button';
import { Tooltip, TooltipContent, TooltipTrigger } from './ui/tooltip'; import { Tooltip, TooltipContent, TooltipTrigger } from './ui/tooltip';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select';
import { FormNumericInput } from './ui/form-numeric-input'; import { FormNumericInput } from './ui/form-numeric-input';
import { FormSelect } from './ui/form-select';
import CollapsibleCardHeader from './ui/collapsible-card-header'; import CollapsibleCardHeader from './ui/collapsible-card-header';
import { Info } from 'lucide-react'; import { Info } from 'lucide-react';
import { getDefaultState } from '../constants/defaults'; import { getDefaultState } from '../constants/defaults';
@@ -37,6 +38,7 @@ const getDefaultsForTranslation = (pkParams: any, therapeuticRange: any, uiSetti
yAxisMax: defaults.uiSettings.yAxisMax, yAxisMax: defaults.uiSettings.yAxisMax,
therapeuticRangeMin: defaults.therapeuticRange.min, therapeuticRangeMin: defaults.therapeuticRange.min,
therapeuticRangeMax: defaults.therapeuticRange.max, therapeuticRangeMax: defaults.therapeuticRange.max,
showDayTimeOnXAxis: defaults.uiSettings.showDayTimeOnXAxis,
// PK Parameters // PK Parameters
damphHalfLife: defaults.pkParams.damph.halfLife, damphHalfLife: defaults.pkParams.damph.halfLife,
@@ -52,6 +54,9 @@ const getDefaultsForTranslation = (pkParams: any, therapeuticRange: any, uiSetti
fOral: defaults.pkParams.advanced.fOral, fOral: defaults.pkParams.advanced.fOral,
fOralPercent: String((parseFloat(defaults.pkParams.advanced.fOral) * 100).toFixed(1)), fOralPercent: String((parseFloat(defaults.pkParams.advanced.fOral) * 100).toFixed(1)),
steadyStateDays: defaults.pkParams.advanced.steadyStateDays, steadyStateDays: defaults.pkParams.advanced.steadyStateDays,
urinePh: defaults.pkParams.advanced.urinePh.mode,
ageGroup: defaults.pkParams.advanced.ageGroup?.preset || 'adult',
renalFunctionSeverity: defaults.pkParams.advanced.renalFunction?.severity || 'normal',
}; };
}; };
@@ -525,13 +530,13 @@ const Settings = ({
<div className="space-y-2"> <div className="space-y-2">
<Label className="font-medium">{t('xAxisTimeFormat')}</Label> <Label className="font-medium">{t('xAxisTimeFormat')}</Label>
<Select <FormSelect
value={showDayTimeOnXAxis} value={showDayTimeOnXAxis}
onValueChange={value => onUpdateUiSetting('showDayTimeOnXAxis', value)} onValueChange={value => onUpdateUiSetting('showDayTimeOnXAxis', value)}
showResetButton={true}
defaultValue={defaultsForT.showDayTimeOnXAxis}
triggerClassName="w-[360px]"
> >
<SelectTrigger className="w-[360px]">
<SelectValue />
</SelectTrigger>
<SelectContent> <SelectContent>
<Tooltip> <Tooltip>
<TooltipTrigger asChild> <TooltipTrigger asChild>
@@ -564,7 +569,7 @@ const Settings = ({
</TooltipContent> </TooltipContent>
</Tooltip> </Tooltip>
</SelectContent> </SelectContent>
</Select> </FormSelect>
</div> </div>
</CardContent> </CardContent>
)} )}
@@ -834,20 +839,20 @@ const Settings = ({
</TooltipContent> </TooltipContent>
</Tooltip> </Tooltip>
</div> </div>
<Select <FormSelect
value={pkParams.advanced.standardVd?.preset || 'adult'} value={pkParams.advanced.standardVd?.preset || 'adult'}
onValueChange={(value: 'adult' | 'child' | 'custom' | 'weight-based') => updateAdvanced('standardVd', 'preset', value)} onValueChange={(value) => updateAdvanced('standardVd', 'preset', value as 'adult' | 'child' | 'custom' | 'weight-based')}
showResetButton={true}
defaultValue={defaultsForT.standardVdPreset}
triggerClassName="w-[360px]"
> >
<SelectTrigger className="w-[360px]">
<SelectValue />
</SelectTrigger>
<SelectContent> <SelectContent>
<SelectItem value="adult">{t('standardVdPresetAdult')}</SelectItem> <SelectItem value="adult">{t('standardVdPresetAdult')}</SelectItem>
<SelectItem value="child">{t('standardVdPresetChild')}</SelectItem> <SelectItem value="child">{t('standardVdPresetChild')}</SelectItem>
<SelectItem value="custom">{t('standardVdPresetCustom')}</SelectItem> <SelectItem value="custom">{t('standardVdPresetCustom')}</SelectItem>
<SelectItem value="weight-based">{t('standardVdPresetWeightBased')}</SelectItem> <SelectItem value="weight-based">{t('standardVdPresetWeightBased')}</SelectItem>
</SelectContent> </SelectContent>
</Select> </FormSelect>
{pkParams.advanced.standardVd?.preset === 'weight-based' && ( {pkParams.advanced.standardVd?.preset === 'weight-based' && (
<div className="ml-0 mt-2 p-2 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded text-xs text-blue-800 dark:text-blue-200"> <div className="ml-0 mt-2 p-2 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded text-xs text-blue-800 dark:text-blue-200">
{t('weightBasedVdInfo')} {t('weightBasedVdInfo')}
@@ -967,21 +972,21 @@ const Settings = ({
</Tooltip> </Tooltip>
</div> </div>
<div> <div>
<Select <FormSelect
value={pkParams.advanced.urinePh.mode} value={pkParams.advanced.urinePh.mode}
onValueChange={(value: 'normal' | 'acidic' | 'alkaline') => onValueChange={(value) =>
updateAdvanced('urinePh', 'mode', value) updateAdvanced('urinePh', 'mode', value as 'normal' | 'acidic' | 'alkaline')
} }
showResetButton={true}
defaultValue={defaultsForT.urinePh}
triggerClassName="w-[360px]"
> >
<SelectTrigger id="urinePHMode" className="w-[360px]">
<SelectValue />
</SelectTrigger>
<SelectContent> <SelectContent>
<SelectItem value="normal">{t('urinePHModeNormal')}</SelectItem> <SelectItem value="normal">{t('urinePHModeNormal')}</SelectItem>
<SelectItem value="acidic">{t('urinePHModeAcidic')}</SelectItem> <SelectItem value="acidic">{t('urinePHModeAcidic')}</SelectItem>
<SelectItem value="alkaline">{t('urinePHModeAlkaline')}</SelectItem> <SelectItem value="alkaline">{t('urinePHModeAlkaline')}</SelectItem>
</SelectContent> </SelectContent>
</Select> </FormSelect>
</div> </div>
</div> </div>
@@ -1008,21 +1013,21 @@ const Settings = ({
</TooltipContent> </TooltipContent>
</Tooltip> </Tooltip>
</div> </div>
<Select <FormSelect
value={pkParams.advanced.ageGroup?.preset || 'adult'} value={pkParams.advanced.ageGroup?.preset || 'adult'}
onValueChange={(value: 'child' | 'adult' | 'custom') => { onValueChange={(value) => {
updateAdvancedDirect('ageGroup', { preset: value }); updateAdvancedDirect('ageGroup', { preset: value as 'child' | 'adult' | 'custom' });
}} }}
showResetButton={true}
defaultValue={defaultsForT.ageGroup}
triggerClassName="w-[360px]"
> >
<SelectTrigger className="w-[360px]">
<SelectValue />
</SelectTrigger>
<SelectContent> <SelectContent>
<SelectItem value="adult">{t('ageGroupAdult')}</SelectItem> <SelectItem value="adult">{t('ageGroupAdult')}</SelectItem>
<SelectItem value="child">{t('ageGroupChild')}</SelectItem> <SelectItem value="child">{t('ageGroupChild')}</SelectItem>
<SelectItem value="custom">{t('ageGroupCustom')}</SelectItem> <SelectItem value="custom">{t('ageGroupCustom')}</SelectItem>
</SelectContent> </SelectContent>
</Select> </FormSelect>
</div> </div>
<Separator className="my-4" /> <Separator className="my-4" />
@@ -1065,24 +1070,24 @@ const Settings = ({
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Label className="text-sm font-medium">{t('renalFunctionSeverity')}</Label> <Label className="text-sm font-medium">{t('renalFunctionSeverity')}</Label>
</div> </div>
<Select <FormSelect
value={pkParams.advanced.renalFunction?.severity || 'normal'} value={pkParams.advanced.renalFunction?.severity || 'normal'}
onValueChange={(value: 'normal' | 'mild' | 'severe') => { onValueChange={(value) => {
updateAdvancedDirect('renalFunction', { updateAdvancedDirect('renalFunction', {
enabled: true, enabled: true,
severity: value severity: value as 'normal' | 'mild' | 'severe'
}); });
}} }}
showResetButton={true}
defaultValue={defaultsForT.renalFunctionSeverity}
triggerClassName="w-full"
> >
<SelectTrigger className="w-full">
<SelectValue />
</SelectTrigger>
<SelectContent> <SelectContent>
<SelectItem value="normal">{t('renalFunctionNormal')}</SelectItem> <SelectItem value="normal">{t('renalFunctionNormal')}</SelectItem>
<SelectItem value="mild">{t('renalFunctionMild')}</SelectItem> <SelectItem value="mild">{t('renalFunctionMild')}</SelectItem>
<SelectItem value="severe">{t('renalFunctionSevere')}</SelectItem> <SelectItem value="severe">{t('renalFunctionSevere')}</SelectItem>
</SelectContent> </SelectContent>
</Select> </FormSelect>
</div> </div>
)} )}
</div> </div>

View File

@@ -0,0 +1,64 @@
/**
* Custom Form Component: Select with Reset Button
*
* A select/combobox field with an optional reset to default button.
* Built on top of shadcn/ui Select component.
*
* @author Andreas Weyer
* @license MIT
*/
import * as React from "react"
import { RotateCcw } from "lucide-react"
import { IconButtonWithTooltip } from "./icon-button-with-tooltip"
import { Select, SelectTrigger, SelectValue, SelectContent } from "./select"
import { cn } from "../../lib/utils"
import { useTranslation } from "react-i18next"
interface FormSelectProps {
value: string
onValueChange: (value: string) => void
showResetButton?: boolean
defaultValue?: string
children: React.ReactNode
triggerClassName?: string
placeholder?: string
}
export const FormSelect: React.FC<FormSelectProps> = ({
value,
onValueChange,
showResetButton = false,
defaultValue,
children,
triggerClassName,
placeholder,
}) => {
const { t } = useTranslation()
return (
<div className="flex items-center gap-0">
<Select value={value} onValueChange={onValueChange}>
<SelectTrigger className={cn(
showResetButton && "rounded-r-none border-r-0 z-10",
triggerClassName
)}>
<SelectValue placeholder={placeholder} />
</SelectTrigger>
{children}
</Select>
{showResetButton && (
<IconButtonWithTooltip
type="button"
icon={<RotateCcw className="h-4 w-4" />}
tooltip={t('buttonResetToDefault')}
variant="outline"
size="icon"
className="h-9 w-9 rounded-l-none border-l-0"
onClick={() => onValueChange(defaultValue || '')}
tabIndex={-1}
/>
)}
</div>
)
}