Skip to content

Commit

Permalink
feat: add form message UI
Browse files Browse the repository at this point in the history
  • Loading branch information
AhyoungRyu committed Sep 20, 2023
1 parent 428f33d commit 528324b
Show file tree
Hide file tree
Showing 6 changed files with 353 additions and 6 deletions.
9 changes: 6 additions & 3 deletions src/components/BotMessageWithBodyInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ type Props = {
zIndex?: number;
bodyStyle?: object;
isBotWelcomeMessage?: boolean;
isFormMessage?: boolean;
};

const ImageContainer = styled.div``;
Expand All @@ -82,6 +83,7 @@ export default function BotMessageWithBodyInput(props: Props) {
chainTop,
chainBottom,
isBotWelcomeMessage,
isFormMessage = false,
} = props;

const nonChainedMessage = chainTop == null && chainBottom == null;
Expand Down Expand Up @@ -114,9 +116,10 @@ export default function BotMessageWithBodyInput(props: Props) {
</Sender>
)}
{bodyComponent}
{enableEmojiFeedback && displayProfileImage && !isBotWelcomeMessage && (
<ReactionContainer message={message} />
)}
{enableEmojiFeedback &&
displayProfileImage &&
!isBotWelcomeMessage &&
!isFormMessage && <ReactionContainer message={message} />}
</BodyContainer>
<SentTime>{formatCreatedAtToAMPM(message.createdAt)}</SentTime>
</Root>
Expand Down
4 changes: 2 additions & 2 deletions src/components/Chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ const SBComponent = () => {
appId={applicationId}
userId={userId}
nickname={userNickName}
customApiHost={`https://api-${applicationId}.sendbird.com`}
customWebSocketHost={`wss://ws-${applicationId}.sendbird.com`}
customApiHost={`https://api-${applicationId}.sendbirdtest.com`}
customWebSocketHost={`wss://ws-${applicationId}.sendbirdtest.com`}
sdkInitParams={sdkInitParams}
configureSession={configureSession}
customExtensionParams={userAgentCustomParams.current}
Expand Down
42 changes: 42 additions & 0 deletions src/components/CustomMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import AdminMessage from './AdminMessage';
import BotMessageWithBodyInput from './BotMessageWithBodyInput';
import CurrentUserMessage from './CurrentUserMessage';
import CustomMessageBody from './CustomMessageBody';
import FormMessage from './FormMessage';
import ParsedBotMessageBody from './ParsedBotMessageBody';
import PendingMessage from './PendingMessage';
import SuggestedReplyMessageBody from './SuggestedReplyMessageBody';
Expand All @@ -31,6 +32,30 @@ type Props = {
isBotWelcomeMessage: boolean;
};

// const mockForms = [
// {
// key: 'personal_info',
// fields: [
// {
// key: 'company_name',
// title: 'Company Name',
// input_type: 'text',
// required: true,
// regex: /^(?!\s*$).+/,
// placeholder: 'Enter company name',
// },
// {
// key: 'phone_number',
// title: 'Phone Number',
// input_type: 'text',
// required: true,
// regex: /^(?!\s*$).+/,
// placeholder: 'Enter phone number',
// },
// ],
// },
// ];

export default function CustomMessage(props: Props) {
const {
message,
Expand All @@ -52,6 +77,23 @@ export default function CustomMessage(props: Props) {
return <div>{<AdminMessage message={message} />}</div>;
}

if (message.extendedMessage.forms) {
const forms = JSON.parse(message.extendedMessage.forms);
return (
<BotMessageWithBodyInput
botUser={botUser}
message={message as UserMessage}
bodyComponent={<FormMessage form={forms[0]} message={message} />}
bodyStyle={{ maxWidth: '320px', width: 'calc(100% - 98px)' }}
messageCount={allMessages.length}
chainTop={chainTop}
chainBottom={chainBottom}
isBotWelcomeMessage={isBotWelcomeMessage}
isFormMessage={true}
/>
);
}

// Sent by current user
if ((message as UserMessage).sender.userId !== botUser.userId) {
return (
Expand Down
133 changes: 133 additions & 0 deletions src/components/FormInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import Icon, { IconTypes, IconColors } from '@sendbird/uikit-react/ui/Icon';
import {
default as UIKitLabel,
LabelTypography,
LabelColors,
} from '@sendbird/uikit-react/ui/Label';
import { ReactElement, ChangeEvent, ReactNode } from 'react';
import styled, { css } from 'styled-components';

export interface InputLabelProps {
children: ReactNode;
}

const Label = styled(UIKitLabel)`
font-size: 11px;
position: relative;
bottom: 4px;
`;

export const InputLabel = ({ children }: InputLabelProps): ReactElement => (
<Label
className="sendbird-input-label"
style={css`
margin-bottom: 8px;
`}
type={LabelTypography.CAPTION_2}
color={LabelColors.ONBACKGROUND_2}
>
{children}
</Label>
);

const Root = styled.div<Pick<InputProps, 'hasError'>>`
padding-bottom: 12px;
width: 100%;
.sendbird-input .sendbird-input__input {
background-color: #fff;
border: ${({ hasError }) =>
`solid 1px ${hasError ? '#DE360B' : 'rgba(0, 0, 0, 0.12)'}`};
&:focus {
border: ${({ hasError }) => (hasError ? 'solid 1px #DE360B' : 'none')};
box-shadow: none;
}
&:disabled {
pointer-events: none;
background-color: #fff;
}
}
`;

const Input = styled.input`
::placeholder {
color: rgba(0, 0, 0, 0.38);
}
`;

const ErrorLabel = styled(Label)`
position: relative;
top: 0;
color: #de360b;
`;

const CheckIcon = styled(Icon)`
position: absolute;
right: 8px;
top: 50%;
transform: translateY(-50%);
`;

const InputContainer = styled.div`
position: relative;
`;
export interface InputProps {
name: string;
type: string;
required?: boolean;
disabled?: boolean;
isValid?: boolean;
hasError?: boolean;
value?: string;
placeHolder?: string;
onChange?: (event: ChangeEvent<HTMLInputElement>) => void;
}
const FormInput = (props: InputProps) => {
const {
name,
required,
disabled,
hasError,
isValid,
value,
type,
onChange,
placeHolder,
} = props;

return (
<Root hasError={hasError}>
<div className="sendbird-input">
<InputLabel>{required ? `${name} *` : name}</InputLabel>
<InputContainer>
<Input
type={type}
className="sendbird-input__input"
name={name}
required={required}
disabled={disabled}
value={value}
onChange={(event) => {
onChange?.(event);
}}
placeholder={!disabled ? placeHolder : ''}
/>
{isValid && (
<CheckIcon
type={IconTypes.DONE}
fillColor={IconColors.SECONDARY}
width="24px"
height="24px"
/>
)}
</InputContainer>
{hasError && (
<ErrorLabel type={LabelTypography.CAPTION_4}>
Please check the value
</ErrorLabel>
)}
</div>
</Root>
);
};

export default FormInput;
Loading

0 comments on commit 528324b

Please sign in to comment.