fix: PostbackInput

This commit is contained in:
yassinedorbozgithub 2024-11-27 17:56:32 +01:00
parent eb7d6ebe3c
commit 3be6006380

View File

@ -9,6 +9,7 @@
import { import {
Autocomplete, Autocomplete,
Box, Box,
Chip,
CircularProgress, CircularProgress,
InputAdornment, InputAdornment,
Skeleton, Skeleton,
@ -26,6 +27,7 @@ import {
ButtonType, ButtonType,
PayloadType, PayloadType,
PostBackButton, PostBackButton,
QuickReplyType,
StdOutgoingButtonsMessage, StdOutgoingButtonsMessage,
StdOutgoingQuickRepliesMessage, StdOutgoingQuickRepliesMessage,
StdQuickReply, StdQuickReply,
@ -37,9 +39,8 @@ type PayloadOption = PayloadPattern & {
group: string; group: string;
}; };
const isSamePostback = <T extends PayloadPattern>(a: T, b: T) => { const isSamePostback = <T extends PayloadPattern>(a: T, b: T) =>
return a.label === b.label && a.value === b.value; a.label === b.label && a.value === b.value;
};
type PostbackInputProps = { type PostbackInputProps = {
defaultValue?: PayloadPattern; defaultValue?: PayloadPattern;
@ -89,28 +90,24 @@ export const PostbackInput = ({
() => () =>
(block?.previousBlocks || []) (block?.previousBlocks || [])
.map((b) => getBlockFromCache(b)) .map((b) => getBlockFromCache(b))
.filter((b) => { .filter(
return b && typeof b.message === "object" && "buttons" in b.message; (b) => b && typeof b.message === "object" && "buttons" in b.message,
}) )
.map((b) => b as IBlock) .map((b) => b as IBlock)
.reduce((acc, b) => { .reduce((acc, b) => {
const postbackButtons = ( const postbackButtons = (
(b.message as StdOutgoingButtonsMessage)?.buttons || [] (b.message as StdOutgoingButtonsMessage)?.buttons || []
) )
.filter((btn) => btn.type === ButtonType.postback) .filter((btn) => btn.type === ButtonType.postback)
.map((btn) => { .map((btn) => ({ ...btn, group: b.name }));
return { ...btn, group: b.name };
});
return acc.concat(postbackButtons); return acc.concat(postbackButtons);
}, [] as (PostBackButton & { group: string })[]) }, [] as (PostBackButton & { group: string })[])
.map((btn) => { .map((btn) => ({
return { label: btn.title,
label: btn.title, value: btn.payload,
value: btn.payload, group: "buttons",
group: btn.group, })),
};
}),
[block?.previousBlocks, getBlockFromCache], [block?.previousBlocks, getBlockFromCache],
); );
// Gather previous blocks quick replies // Gather previous blocks quick replies
@ -118,32 +115,27 @@ export const PostbackInput = ({
() => () =>
(block?.previousBlocks || []) (block?.previousBlocks || [])
.map((b) => getBlockFromCache(b)) .map((b) => getBlockFromCache(b))
.filter((b) => { .filter(
return ( (b) =>
b && typeof b.message === "object" && "quickReplies" in b.message b && typeof b.message === "object" && "quickReplies" in b.message,
); )
})
.map((b) => b as IBlock) .map((b) => b as IBlock)
.reduce((acc, b) => { .reduce((acc, b) => {
const postbackQuickReplies = ( const postbackQuickReplies = (
(b.message as StdOutgoingQuickRepliesMessage)?.quickReplies || [] (b.message as StdOutgoingQuickRepliesMessage)?.quickReplies || []
) )
.filter((btn) => btn.content_type === "text") .filter(({ content_type }) => content_type === QuickReplyType.text)
.map((btn) => { .map((btn) => ({ ...btn, group: b.name }));
return { ...btn, group: b.name };
});
return acc.concat(postbackQuickReplies); return acc.concat(postbackQuickReplies);
}, [] as (StdQuickReply & { group: string })[]) }, [] as (StdQuickReply & { group: string })[])
.map((btn) => { .map((btn) => ({
return { id: btn.payload as string,
id: btn.payload as string, label: btn.title as string,
label: btn.title as string, value: btn.payload as string,
value: btn.payload as string, type: PayloadType.menu,
type: PayloadType.menu, group: "quick_replies",
group: btn.group, })),
};
}),
[block?.previousBlocks], [block?.previousBlocks],
); );
const menuOptions = menu const menuOptions = menu
@ -158,15 +150,13 @@ export const PostbackInput = ({
const contentOptions = useMemo( const contentOptions = useMemo(
() => () =>
(block?.previousBlocks || []) (block?.previousBlocks || [])
.map((bId) => getBlockFromCache(bId)) .map((bId) => getBlockFromCache(bId) as IBlock)
.filter((b) => { .filter(
return ( (b) =>
b && b &&
b.options?.content?.entity && b.options?.content?.entity &&
b.options.content.buttons.length > 0 b.options.content.buttons.length > 0,
); )
})
.map((b) => b as IBlock)
.map((b) => { .map((b) => {
const availableContents = (contents || []).filter( const availableContents = (contents || []).filter(
({ entity, status }) => ({ entity, status }) =>
@ -214,60 +204,66 @@ export const PostbackInput = ({
); );
} }
const selected = defaultValue const selected = defaultValue
? options.find((o) => { ? options.find((o) => isSamePostback(o, defaultValue))
return isSamePostback(o, defaultValue);
})
: undefined; : undefined;
return ( return (
<Autocomplete<PayloadOption> <Autocomplete
size="small" size="small"
defaultValue={selected} defaultValue={selected}
options={options} options={options}
// label={t("label.postback")}
multiple={false} multiple={false}
onChange={(_e, value) => { onChange={(_e, value) => {
setSelectedValue(value); setSelectedValue(value);
if (value) { if (value) {
const { group: _g, ...payloadPattern } = value; const { group: _g, ...payloadPattern } = value;
onChange(payloadPattern); onChange(payloadPattern);
} else { } else {
onChange(null); onChange(null);
} }
}} }}
groupBy={(option) => { groupBy={({ group }) => group ?? t("label.other")}
return option.group ?? t("label.other");
}}
getOptionLabel={({ label }) => label} getOptionLabel={({ label }) => label}
renderGroup={(params) => ( renderGroup={({ key, group, children }) => (
<li key={params.key}> <li key={key}>
<Typography component="h4" p={2} fontWeight={700} color="primary"> <Typography component="h4" p={2} fontWeight={700} color="primary">
{t(`label.${params.group}`)} {t(`label.${group}`)}
</Typography> </Typography>
<Box>{params.children}</Box> <Box>{children}</Box>
</li> </li>
)} )}
renderInput={(props) => { renderInput={(props) => (
return ( <Input
<Input {...props}
{...props} label={t("label.postback")}
label={t("label.postback")} InputProps={{
InputProps={{ ...props.InputProps,
...props.InputProps, startAdornment: (
startAdornment: ( <InputAdornment position="start">
<InputAdornment position="start"> <Chip
{selectedValue?.type || t("label.postback")} sx={{
</InputAdornment> p: "0",
), m: "0 ",
endAdornment: fontSize: "12px",
isLoadingMenu || isLoadingContent ? ( minWidth: "75px",
<CircularProgress color="inherit" size={20} /> maxHeight: "30px",
) : null, borderRadius: "16px 0 0 16px",
}} }}
/> style={{ padding: 0, margin: 0 }}
); color="primary"
}} label={selectedValue?.type || t("label.postback")}
variant="role"
/>
</InputAdornment>
),
endAdornment:
isLoadingMenu || isLoadingContent ? (
<CircularProgress color="inherit" size={20} />
) : null,
}}
/>
)}
/> />
); );
}; };