Files
xo-cli/src/tui/screens/action-wizard/steps/RoleSelectStep.tsx

121 lines
3.7 KiB
TypeScript

/**
* Role Selection Step - Allows the user to choose which role they want
* to take for the selected action.
*/
import React from 'react';
import { Box, Text } from 'ink';
import { colors } from '../../../theme.js';
import type { XOTemplate } from '@xo-cash/types';
import type { FocusArea } from '../types.js';
interface RoleSelectStepProps {
/** The loaded template definition. */
template: XOTemplate;
/** The selected action identifier. */
actionIdentifier: string;
/** Role identifiers available for this action. */
availableRoles: string[];
/** The currently focused role index. */
selectedRoleIndex: number;
/** Whether the content area or button bar is focused. */
focusArea: FocusArea;
}
/**
* Displays the available roles for the selected action and
* lets the user navigate between them with arrow keys.
*/
export function RoleSelectStep({
template,
actionIdentifier,
availableRoles,
selectedRoleIndex,
focusArea,
}: RoleSelectStepProps): React.ReactElement {
const action = template.actions?.[actionIdentifier];
return (
<Box flexDirection="column">
<Text color={colors.text} bold>
Select your role for this action:
</Text>
{/* Action info */}
{action && (
<Box marginTop={1} flexDirection="column">
<Text color={colors.textMuted}>
{action.description || 'No description available'}
</Text>
</Box>
)}
{/* Role list */}
<Box
marginTop={1}
flexDirection="column"
borderStyle="single"
borderColor={colors.border}
paddingX={1}
>
{availableRoles.length === 0 ? (
<Text color={colors.textMuted}>No roles available</Text>
) : (
availableRoles.map((roleId, index) => {
const isCursor =
selectedRoleIndex === index && focusArea === 'content';
const roleDef = template.roles?.[roleId];
const actionRole = action?.roles?.[roleId];
const requirements = actionRole?.requirements;
return (
<Box key={roleId} flexDirection="column" marginY={0}>
<Text
color={isCursor ? colors.focus : colors.text}
bold={isCursor}
>
{isCursor ? '▸ ' : ' '}
{roleDef?.name || roleId}
</Text>
{/* Show role description indented below the name */}
{roleDef?.description && (
<Text color={colors.textMuted}>
{' '}
{roleDef.description}
</Text>
)}
{/* Show a brief summary of requirements */}
{requirements && (
<Box flexDirection="row" paddingLeft={4}>
{requirements.variables && requirements.variables.length > 0 && (
<Text color={colors.textMuted} dimColor>
{requirements.variables.length} variable
{requirements.variables.length !== 1 ? 's' : ''}
{' '}
</Text>
)}
{requirements.slots && requirements.slots.min > 0 && (
<Text color={colors.textMuted} dimColor>
{requirements.slots.min} input slot
{requirements.slots.min !== 1 ? 's' : ''}
</Text>
)}
</Box>
)}
</Box>
);
})
)}
</Box>
<Box marginTop={1}>
<Text color={colors.textMuted} dimColor>
: Navigate Next: Confirm selection
</Text>
</Box>
</Box>
);
}