metis-desk/packages/rdx-ui/src/components/remote-option-picker.tsx
David 0a34ddf752 feat: add local identity management features and UI components
- Implement folder account options helper for filtering access items based on person ID and date.
- Create FolderAccessAccountField component for selecting accounts with profile integration.
- Develop AssetLocalIdentities component for managing local identities associated with assets.
- Introduce LocalIdentityOwner component to display and manage local identity ownership.
- Add LocalIdentityEditor for creating, associating, and retiring local identities.
- Implement local identity API for fetching and executing local identity commands.
- Create tests for local identity UI components to ensure functionality and correctness.
- Add NetworkShareOptions class for structured and paginated SMB selection.
- Introduce NetworkShareAddress component for displaying and copying network share addresses.
- Create RemoteOptionList and RemoteOptionPicker components for remote option selection with pagination and search.
- Add tests for RemoteOptionList to validate rendering and behavior under various states.
2026-10-21 12:37:59 +02:00

118 lines
2.9 KiB
TypeScript

import { Button } from "@repo/shadcn-ui/components/button";
import { Input } from "@repo/shadcn-ui/components/input";
import type { ReactNode } from "react";
import { useId, useState } from "react";
import { FormActions, FormBody, FormDialog } from "./form-dialog";
import type { RemotePickerOption } from "./remote-option-list";
import { RemoteOptionList } from "./remote-option-list";
export type { RemotePickerOption } from "./remote-option-list";
/** Presenta exclusivamente la página recibida; el consumidor controla consulta, filtros y paginación remota. */
export function RemoteOptionPicker({
title,
items,
pending,
error,
search,
onSearch,
onRetry,
onSelect,
onClose,
pagination,
labels,
}: {
title: string;
items: readonly RemotePickerOption[];
pending: boolean;
error: string | undefined;
search: string;
onSearch: (search: string) => void;
onRetry: () => Promise<unknown>;
onSelect: (option: RemotePickerOption) => void;
onClose: () => void;
pagination: ReactNode;
labels: {
search: string;
selection: string;
name: string;
description: string;
empty: string;
loading: string;
confirm: string;
cancel: string;
retry: string;
};
}) {
const id = useId();
const [selected, setSelected] = useState<RemotePickerOption>();
return (
<FormDialog
cancelLabel={labels.cancel}
formActions
layout="picker"
onOpenChange={(open) => {
if (!open) {
onClose();
}
}}
open
size="medium"
title={title}
>
<FormBody contentLayout="fill">
<label className="sr-only" htmlFor={id}>
{labels.search}
</label>
<Input
data-quick-search=""
id={id}
maxLength={100}
onChange={(event) => onSearch(event.target.value)}
placeholder={labels.search}
value={search}
/>
{pending && <p role="status">{labels.loading}</p>}
{error && (
<div role="alert">
<p>{error}</p>
<Button
onClick={async () => {
await onRetry();
}}
variant="outline"
>
{labels.retry}
</Button>
</div>
)}
<RemoteOptionList
error={error}
items={items}
labels={labels}
onSelect={setSelected}
pending={pending}
title={title}
value={selected?.id ?? ""}
/>
{pagination}
</FormBody>
<FormActions>
<Button
disabled={!selected || pending || !!error || selected.disabled}
onClick={() => {
if (selected && !selected.disabled) {
onSelect(selected);
onClose();
}
}}
>
{labels.confirm}
</Button>
</FormActions>
</FormDialog>
);
}