|
| 1 | +import { useForm } from 'react-hook-form' |
| 2 | +import { Form } from 'react-router-dom' |
| 3 | +import { |
| 4 | + Button, |
| 5 | + Flex, |
| 6 | + FormControl, |
| 7 | + FormErrorMessage, |
| 8 | + ModalBody, |
| 9 | + ModalFooter, |
| 10 | + ModalHeader, |
| 11 | + Text, |
| 12 | + Textarea, |
| 13 | +} from '@chakra-ui/react' |
| 14 | +import { zodResolver } from '@hookform/resolvers/zod' |
| 15 | +import { FormLabel, useIsMobile } from '@opengovsg/design-system-react' |
| 16 | + |
| 17 | +import pairLogo from '@/assets/pair-logo.svg' |
| 18 | +import { ImageBox } from '@/components/FlowStepConfigurationModal/ChooseAndAddConnection/ConfigureExcelConnection' |
| 19 | +import { AI_FORM_SCHEMA, AiFormData } from '@/pages/AiBuilder/schema' |
| 20 | +import { AI_FORM_FIELDS, AI_FORM_IDEAS } from '@/pages/Flows/constants' |
| 21 | + |
| 22 | +export const AIFormModalContent = ({ |
| 23 | + flowName, |
| 24 | + trigger, |
| 25 | + actions, |
| 26 | + type, |
| 27 | + onBack, |
| 28 | + onSubmit, |
| 29 | +}: { |
| 30 | + flowName?: string |
| 31 | + trigger?: string |
| 32 | + actions?: string |
| 33 | + type: 'create' | 'update' |
| 34 | + onBack: () => void |
| 35 | + onSubmit: (data: AiFormData) => void |
| 36 | +}) => { |
| 37 | + const isMobile = useIsMobile() |
| 38 | + const { |
| 39 | + register, |
| 40 | + handleSubmit, |
| 41 | + formState: { errors, isValid }, |
| 42 | + setValue, |
| 43 | + } = useForm<AiFormData>({ |
| 44 | + resolver: zodResolver(AI_FORM_SCHEMA), |
| 45 | + mode: 'onChange', |
| 46 | + defaultValues: { |
| 47 | + flowName: flowName || 'Name your Pipe', |
| 48 | + trigger: trigger || undefined, |
| 49 | + actions: actions || undefined, |
| 50 | + }, |
| 51 | + }) |
| 52 | + |
| 53 | + const handleIdeaClick = (idea: (typeof AI_FORM_IDEAS)[number]) => { |
| 54 | + setValue('trigger', idea.trigger, { shouldValidate: true }) |
| 55 | + setValue('actions', idea.actions, { shouldValidate: true }) |
| 56 | + } |
| 57 | + |
| 58 | + return ( |
| 59 | + <> |
| 60 | + <Form onSubmit={handleSubmit(onSubmit)}> |
| 61 | + <ModalHeader p="2.5rem 2rem 1.5rem"> |
| 62 | + <Text textStyle="h4">Build with AI</Text> |
| 63 | + </ModalHeader> |
| 64 | + <ModalBody> |
| 65 | + <Flex gap={4} flexDir="column"> |
| 66 | + {AI_FORM_FIELDS.map((field) => ( |
| 67 | + <FormControl |
| 68 | + isRequired |
| 69 | + isInvalid={!!errors[field.key]} |
| 70 | + key={field.key} |
| 71 | + > |
| 72 | + <FormLabel>{field.label}</FormLabel> |
| 73 | + <Textarea |
| 74 | + {...register(field.key)} |
| 75 | + placeholder={field.placeholder} |
| 76 | + resize={field.resize} |
| 77 | + minH={field.minH} |
| 78 | + maxH={field.maxH} |
| 79 | + required={field.required} |
| 80 | + /> |
| 81 | + {errors[field.key] && ( |
| 82 | + <FormErrorMessage> |
| 83 | + {errors[field.key]?.message} |
| 84 | + </FormErrorMessage> |
| 85 | + )} |
| 86 | + </FormControl> |
| 87 | + ))} |
| 88 | + <Flex flexDir="row" alignItems="center"> |
| 89 | + <FormLabel |
| 90 | + isRequired |
| 91 | + style={{ margin: 0, marginRight: '0.5rem' }} |
| 92 | + > |
| 93 | + {/* arbitrary isRequired to hide optional text */} |
| 94 | + Try: |
| 95 | + </FormLabel> |
| 96 | + <Flex |
| 97 | + flexDir="row" |
| 98 | + gap={2} |
| 99 | + justifyContent="space-between" |
| 100 | + flexWrap="wrap" |
| 101 | + > |
| 102 | + {AI_FORM_IDEAS.map((idea) => ( |
| 103 | + <Button |
| 104 | + key={idea.label} |
| 105 | + size="sm" |
| 106 | + bgColor="interaction.sub-subtle.default" |
| 107 | + color="#5D6785" |
| 108 | + variant="clear" |
| 109 | + _hover={{ |
| 110 | + bgColor: 'interaction.sub-subtle.hover', |
| 111 | + }} |
| 112 | + onClick={() => handleIdeaClick(idea)} |
| 113 | + px={3} |
| 114 | + minH={4} |
| 115 | + w={isMobile ? 'calc(50% - 4px)' : 'auto'} |
| 116 | + flexShrink={0} |
| 117 | + > |
| 118 | + <Text textStyle="caption-1">{idea.label}</Text> |
| 119 | + </Button> |
| 120 | + ))} |
| 121 | + </Flex> |
| 122 | + </Flex> |
| 123 | + </Flex> |
| 124 | + </ModalBody> |
| 125 | + <ModalFooter> |
| 126 | + <Flex justifyContent="space-between" alignItems="center" w="100%"> |
| 127 | + <Flex gap={1} alignItems="center"> |
| 128 | + <Text fontSize="xs" color="gray.500"> |
| 129 | + Powered by{' '} |
| 130 | + </Text> |
| 131 | + <ImageBox imageUrl={pairLogo} boxSize={6} /> |
| 132 | + </Flex> |
| 133 | + <Flex gap={4}> |
| 134 | + <Button variant="clear" colorScheme="secondary" onClick={onBack}> |
| 135 | + Back |
| 136 | + </Button> |
| 137 | + <Button type="submit" isDisabled={!isValid}> |
| 138 | + {type === 'update' ? 'Update workflow' : 'Create'} |
| 139 | + </Button> |
| 140 | + </Flex> |
| 141 | + </Flex> |
| 142 | + </ModalFooter> |
| 143 | + </Form> |
| 144 | + </> |
| 145 | + ) |
| 146 | +} |
0 commit comments