эмоджи выбирается и отправляется на бек

This commit is contained in:
Nastya 2025-06-20 16:37:04 +03:00
parent 522d8f14a4
commit 2e8325bf00
4 changed files with 65 additions and 53 deletions

@ -107,41 +107,46 @@ export const EmojiVariant = ({
ownPlaceholder, ownPlaceholder,
}: EmojiVariantProps) => { }: EmojiVariantProps) => {
const { settings } = useQuizStore(); const { settings } = useQuizStore();
const answers = useQuizViewStore((state) => state.answers); const { updateAnswer, deleteAnswer, updateOwnVariant, ownVariants } = useQuizViewStore();
const { updateAnswer, deleteAnswer } = useQuizViewStore((state) => state);
const theme = useTheme(); const theme = useTheme();
const { t } = useTranslation(); const { t } = useTranslation();
const customEmoji = ownVariants.find((v) => v.id === variant.id)?.variant.extendedText || "";
const onVariantClick = async (event: MouseEvent<HTMLDivElement>) => { const onVariantClick = async (event: MouseEvent<HTMLDivElement>) => {
event.preventDefault(); event.preventDefault();
const variantId = variant.id; const variantId = variant.id;
if (isMulti) { if (isMulti) {
const currentAnswer = typeof answer !== "string" ? answer || [] : []; const currentAnswer = Array.isArray(answer) ? answer : [];
const newAnswer = currentAnswer.includes(variantId)
return updateAnswer( ? currentAnswer.filter((item) => item !== variantId)
questionId, : [...currentAnswer, variantId];
currentAnswer.includes(variantId) updateAnswer(questionId, newAnswer, variant.points || 0);
? currentAnswer?.filter((item) => item !== variantId) } else {
: [...currentAnswer, variantId], if (answer === variant.id) {
variant.points || 0 deleteAnswer(questionId);
); } else {
} updateAnswer(questionId, variant.id, variant.points || 0);
}
updateAnswer(questionId, variant.id, variant.points || 0);
if (answer === variant.id) {
deleteAnswer(questionId);
} }
}; };
const handleEmojiSelect = (emoji: string) => {
// We store custom emoji in ownVariants store, with a specific field to differentiate
const currentOwnAnswer = ownVariants.find((v) => v.id === variant.id)?.variant.answer || "";
updateOwnVariant(variant.id, currentOwnAnswer, emoji);
};
const isSelected = isMulti ? Array.isArray(answer) && answer.includes(variant.id) : answer === variant.id;
return ( return (
<FormControl <FormControl
key={index} key={index}
sx={{ sx={{
borderRadius: "12px", borderRadius: "12px",
border: `1px solid`, border: `1px solid`,
borderColor: answer?.includes(variant.id) ? theme.palette.primary.main : "#9A9AAF", borderColor: isSelected ? theme.palette.primary.main : "#9A9AAF",
overflow: "hidden", overflow: "hidden",
maxWidth: "317px", maxWidth: "317px",
width: "100%", width: "100%",
@ -154,7 +159,6 @@ export const EmojiVariant = ({
: "transparent", : "transparent",
"&:hover": { borderColor: theme.palette.primary.main }, "&:hover": { borderColor: theme.palette.primary.main },
}} }}
// value={index}
onClick={onVariantClick} onClick={onVariantClick}
> >
<Box <Box
@ -167,7 +171,10 @@ export const EmojiVariant = ({
}} }}
> >
{own ? ( {own ? (
<OwnEmojiPicker emoji={variant.extendedText} /> <OwnEmojiPicker
emoji={customEmoji || variant.extendedText}
onEmojiSelect={handleEmojiSelect}
/>
) : ( ) : (
<Box <Box
sx={{ sx={{
@ -222,13 +229,14 @@ export const EmojiVariant = ({
control={ control={
isMulti ? ( isMulti ? (
<Checkbox <Checkbox
checked={!!answer?.includes(variant.id)} checked={isSelected}
checkedIcon={<RadioCheck color={theme.palette.primary.main} />} checkedIcon={<RadioCheck color={theme.palette.primary.main} />}
icon={<RadioIcon />} icon={<RadioIcon />}
sx={{ position: "absolute", top: "-162px", right: "12px" }} sx={{ position: "absolute", top: "-162px", right: "12px" }}
/> />
) : ( ) : (
<Radio <Radio
checked={isSelected}
checkedIcon={<RadioCheck color={theme.palette.primary.main} />} checkedIcon={<RadioCheck color={theme.palette.primary.main} />}
icon={<RadioIcon />} icon={<RadioIcon />}
sx={{ position: "absolute", top: "-162px", right: "12px" }} sx={{ position: "absolute", top: "-162px", right: "12px" }}

@ -13,10 +13,11 @@ type EmojiProps = {
export const Emoji = ({ currentQuestion }: EmojiProps) => { export const Emoji = ({ currentQuestion }: EmojiProps) => {
const answers = useQuizViewStore((state) => state.answers); const answers = useQuizViewStore((state) => state.answers);
const { updateAnswer } = useQuizViewStore((state) => state);
const theme = useTheme(); const theme = useTheme();
const { answer } = answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {}; const { answer } = answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
const selectedVariantId = Array.isArray(answer) ? answer[0] : answer;
if (moment.isMoment(answer)) throw new Error("Answer is Moment in Variant question"); if (moment.isMoment(answer)) throw new Error("Answer is Moment in Variant question");
return ( return (
@ -30,14 +31,7 @@ export const Emoji = ({ currentQuestion }: EmojiProps) => {
</Typography> </Typography>
<RadioGroup <RadioGroup
name={currentQuestion.id} name={currentQuestion.id}
value={currentQuestion.content.variants.findIndex(({ id }) => answer === id)} value={selectedVariantId}
onChange={({ target }) =>
updateAnswer(
currentQuestion.id,
currentQuestion.content.variants[Number(target.value)].answer,
currentQuestion.content.variants[Number(target.value)].points || 0
)
}
sx={{ sx={{
display: "flex", display: "flex",
flexWrap: "wrap", flexWrap: "wrap",

@ -30,7 +30,7 @@ interface QuizViewStore {
interface QuizViewActions { interface QuizViewActions {
updateAnswer: (questionId: string, answer: string | string[] | Moment, points: number) => void; updateAnswer: (questionId: string, answer: string | string[] | Moment, points: number) => void;
deleteAnswer: (questionId: string) => void; deleteAnswer: (questionId: string) => void;
updateOwnVariant: (id: string, answer: string) => void; updateOwnVariant: (id: string, answer: string, extendedText?: string) => void;
deleteOwnVariant: (id: string) => void; deleteOwnVariant: (id: string) => void;
setCurrentQuizStep: (step: QuizStep) => void; setCurrentQuizStep: (step: QuizStep) => void;
} }
@ -90,7 +90,7 @@ export const createQuizViewStore = () =>
} }
); );
}, },
updateOwnVariant(id, answer) { updateOwnVariant(id, answer, extendedText) {
set( set(
(state) => { (state) => {
const index = state.ownVariants.findIndex((variant) => variant.id === id); const index = state.ownVariants.findIndex((variant) => variant.id === id);
@ -101,13 +101,16 @@ export const createQuizViewStore = () =>
variant: { variant: {
id: id, id: id,
answer, answer,
extendedText: "", extendedText: extendedText || "",
hints: "", hints: "",
originalImageUrl: "", originalImageUrl: "",
}, },
}); });
} else { } else {
state.ownVariants[index].variant.answer = answer; state.ownVariants[index].variant.answer = answer;
if (extendedText) {
state.ownVariants[index].variant.extendedText = extendedText;
}
} }
}, },
false, false,

@ -50,25 +50,17 @@ export async function sendQuestionAnswer(
} }
case "emoji": { case "emoji": {
if (question.content.multi) { if (question.content.multi) {
const answer = questionAnswer.answer; const answer = questionAnswer.answer as string[];
const ownVariant = Array.isArray(answer) let answerString = ``;
? ownVariants[ownVariants.findIndex((variant) => answer.some((a: string) => a === variant.id))]?.variant || ""
: ownVariants[ownVariants.findIndex((variant) => variant.id === questionAnswer.answer)]?.variant || "";
if (moment.isMoment(answer)) throw new Error("Answer is Moment in Variant question");
//Оставляем только выбранные варианты
const selectedVariants = question.content.variants.filter((v) => answer.includes(v.id)); const selectedVariants = question.content.variants.filter((v) => answer.includes(v.id));
let answerString = ``; selectedVariants.forEach((variant) => {
selectedVariants.forEach((e) => { const ownVariantData = ownVariants.find((v) => v.id === variant.id)?.variant;
if (e.isOwn) { const customEmoji = ownVariantData?.extendedText || "";
if (question.content.own && selectedVariants.some((v) => v.isOwn)) { const emojiToSend = customEmoji || variant.extendedText;
answerString += `\`${e.extendedText} ${ownVariant?.answer ?? ""}\`,`; const textToSend = variant.isOwn ? ownVariantData?.answer || "" : variant.answer;
} answerString += `\`${emojiToSend} ${textToSend}\`,`;
} else {
answerString += `\`${e.extendedText} ${e.answer ?? ""}\`,`;
}
}); });
answerString = answerString.slice(0, -1); answerString = answerString.slice(0, -1);
@ -80,12 +72,27 @@ export async function sendQuestionAnswer(
}); });
} }
const variant = question.content.variants.find((v) => v.id === questionAnswer.answer); // Fallback for old string format for single choice
if (!variant) throw new Error(`Cannot find variant with id ${questionAnswer.answer} in question ${question.id}`); const answer = questionAnswer.answer as string;
const variant = question.content.variants.find((v) => v.id === answer);
if (!variant) {
// This can happen if the answer is not set, so we don't throw an error, just send empty
return sendAnswer({
questionId: question.id,
body: "",
qid: quizId,
});
}
const ownVariantData = ownVariants.find((v) => v.id === variant.id)?.variant;
const customEmoji = ownVariantData?.extendedText || "";
const emojiToSend = customEmoji || variant.extendedText;
const textToSend = variant.isOwn ? ownVariantData?.answer || "" : variant.answer;
const body = `${emojiToSend} ${textToSend}`.trim();
return sendAnswer({ return sendAnswer({
questionId: question.id, questionId: question.id,
body: variant.extendedText + " " + variant.answer, body: body,
qid: quizId, qid: quizId,
}); });
} }