metis-desk/packages/rdx-ui/src/components/option-selection-field.tsx
David 94ddc5cf16 feat: enhance work profile management with new components and functionality
- Updated WorkstationDetailPage to replace BriefcaseIcon with MonitorIcon.
- Modified package.json to include new test files.
- Refactored FormStepActions to improve button state management.
- Introduced profile-creation helper functions for better profile management.
- Added WorkProfileAccountField and WorkProfileAuthorizationNotice components for account handling.
- Created WorkProfileComputerSummary and WorkProfileSummary for displaying profile details.
- Implemented WorkProfileFormFields to consolidate form fields for work profiles.
- Developed WorkProfileIdentityFields for managing identity-related inputs.
- Added WorkProfileSelectionField for selecting accounts, workstations, and persons.
- Created OptionPickerDialog and OptionPickerList for enhanced option selection.
- Introduced OptionSelectionField for visual selection with actions.
- Added tests for selection components to ensure functionality and reliability.
2026-10-16 13:11:52 +02:00

118 lines
3.0 KiB
TypeScript

import { Button } from "@repo/shadcn-ui/components/button";
import type { ReactNode } from "react";
import { useState } from "react";
import { EmptyState } from "./empty-state";
import type { PickerOption } from "./option-picker-dialog";
import { OptionPickerDialog } from "./option-picker-dialog";
import { SelectionSummaryCard } from "./selection-summary-card";
/** Selección visual con estado vacío, ficha y listado; no conoce consultas ni entidades. */
export function OptionSelectionField({
title,
description,
icon,
options,
value,
onChange,
labels,
locale,
disabled = false,
locked = false,
loading = false,
createAction,
clearLabel,
}: {
title: string;
description: string;
icon: ReactNode;
options: readonly PickerOption[];
value: string;
onChange: (id: string) => void;
labels: {
select: string;
change: string;
selection: string;
name: string;
description: string;
confirm: string;
cancel: string;
search: string;
};
locale: string;
disabled?: boolean;
locked?: boolean;
loading?: boolean;
createAction?: { label: string; onClick: () => void; disabled?: boolean } | undefined;
clearLabel?: string | undefined;
}) {
const [open, setOpen] = useState(false);
const selected = options.find((option) => option.id === value);
const actions = (
<>
<Button
aria-haspopup="dialog"
disabled={disabled || locked || loading}
onClick={() => setOpen(true)}
type="button"
>
{selected ? labels.change : labels.select}
</Button>
{createAction && !locked && (
<Button
aria-haspopup="dialog"
disabled={disabled || loading || createAction.disabled}
onClick={createAction.onClick}
type="button"
variant="outline"
>
{createAction.label}
</Button>
)}
{selected && clearLabel && (
<Button
disabled={disabled || locked}
onClick={() => onChange("")}
type="button"
variant="ghost"
>
{clearLabel}
</Button>
)}
</>
);
return (
<>
{selected ? (
<div className="space-y-3">
<ul className="grid items-stretch gap-3">
<li className="min-w-0">
<SelectionSummaryCard
description={selected.description || "—"}
icon={icon}
title={selected.label}
/>
</li>
</ul>
<div className="flex flex-wrap gap-3">{actions}</div>
</div>
) : (
<EmptyState actions={actions} description={description} icon={icon} title={title} />
)}
{open && (
<OptionPickerDialog
labels={labels}
loading={loading}
locale={locale}
onClose={() => setOpen(false)}
onSelect={onChange}
options={options}
title={labels.select}
value={value}
/>
)}
</>
);
}