Files
formbricks/packages/ee/multiLanguage/components/LocalizedEditor.tsx
Dhruwang Jariwala 8b5328aa74 feat: Multi language Surveys (#1630)
Co-authored-by: Johannes <johannes@formbricks.com>
Co-authored-by: Johannes <72809645+jobenjada@users.noreply.github.com>
Co-authored-by: Matthias Nannt <mail@matthiasnannt.com>
Co-authored-by: pandeymangg <anshuman.pandey9999@gmail.com>
2024-03-18 19:02:18 +00:00

110 lines
3.5 KiB
TypeScript

import DOMPurify from "dompurify";
import type { Dispatch, SetStateAction } from "react";
import { useMemo } from "react";
import { extractLanguageCodes, isLabelValidForAllLanguages } from "@formbricks/lib/i18n/utils";
import { md } from "@formbricks/lib/markdownIt";
import { recallToHeadline } from "@formbricks/lib/utils/recall";
import { TI18nString, TSurvey } from "@formbricks/types/surveys";
import { Editor } from "@formbricks/ui/Editor";
import { LanguageIndicator } from "./LanguageIndicator";
interface LocalizedEditorProps {
id: string;
value: TI18nString | undefined;
localSurvey: TSurvey;
isInvalid: boolean;
updateQuestion: any;
selectedLanguageCode: string;
setSelectedLanguageCode: (languageCode: string) => void;
questionIdx: number;
firstRender: boolean;
setFirstRender?: Dispatch<SetStateAction<boolean>>;
}
const checkIfValueIsIncomplete = (
id: string,
isInvalid: boolean,
surveyLanguageCodes: string[],
value?: TI18nString
) => {
const labelIds = ["subheader"];
if (value === undefined) return false;
const isDefaultIncomplete = labelIds.includes(id) ? value["default"]?.trim() !== "" : false;
return isInvalid && !isLabelValidForAllLanguages(value, surveyLanguageCodes) && isDefaultIncomplete;
};
export const LocalizedEditor = ({
id,
value,
localSurvey,
isInvalid,
updateQuestion,
selectedLanguageCode,
setSelectedLanguageCode,
questionIdx,
firstRender,
setFirstRender,
}: LocalizedEditorProps) => {
const surveyLanguageCodes = useMemo(
() => extractLanguageCodes(localSurvey.languages),
[localSurvey.languages]
);
const isInComplete = useMemo(
() => checkIfValueIsIncomplete(id, isInvalid, surveyLanguageCodes, value),
[id, isInvalid, surveyLanguageCodes, value, selectedLanguageCode]
);
return (
<div className="relative w-full">
<Editor
key={`${questionIdx}-${selectedLanguageCode}`}
getText={() => md.render(value ? value[selectedLanguageCode] ?? "" : "")}
setText={(v: string) => {
if (!value) return;
let translatedHtml = {
...value,
[selectedLanguageCode]: v,
};
if (questionIdx === -1) {
// welcome card
updateQuestion({ html: translatedHtml });
return;
}
updateQuestion(questionIdx, { html: translatedHtml });
}}
excludedToolbarItems={["blockType"]}
disableLists
firstRender={firstRender}
setFirstRender={setFirstRender}
/>
{localSurvey.languages?.length > 1 && (
<div>
<LanguageIndicator
selectedLanguageCode={selectedLanguageCode}
surveyLanguages={localSurvey.languages}
setSelectedLanguageCode={setSelectedLanguageCode}
setFirstRender={setFirstRender}
/>
{value && selectedLanguageCode !== "default" && value["default"] && (
<div className="mt-1 flex text-xs text-gray-500">
<strong>Translate:</strong>
<label
className="fb-htmlbody ml-1" // styles are in global.css
dangerouslySetInnerHTML={{
__html: DOMPurify.sanitize(
recallToHeadline(value, localSurvey, false, "default")["default"] ?? ""
),
}}></label>
</div>
)}
</div>
)}
{isInComplete && <div className="mt-1 text-xs text-red-400">Contains Incomplete translations</div>}
</div>
);
};