mirror of
https://github.com/formbricks/formbricks.git
synced 2026-01-01 16:36:18 -06:00
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>
110 lines
3.5 KiB
TypeScript
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>
|
|
);
|
|
};
|