mirror of
https://github.com/formbricks/formbricks.git
synced 2025-12-30 10:19:51 -06:00
Compare commits
1 Commits
stable
...
feat/resta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1475b7429d |
2864
apps/web/locales/ro-RO.json
Normal file
2864
apps/web/locales/ro-RO.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,9 @@ import { ResponseOptionsCard } from "@/modules/survey/editor/components/response
|
||||
import { SurveyPlacementCard } from "@/modules/survey/editor/components/survey-placement-card";
|
||||
import { TargetingLockedCard } from "@/modules/survey/editor/components/targeting-locked-card";
|
||||
import { WhenToSendCard } from "@/modules/survey/editor/components/when-to-send-card";
|
||||
import { PreviewSurveyRef } from "@/modules/ui/components/preview-survey";
|
||||
import { ActionClass, Environment, OrganizationRole } from "@prisma/client";
|
||||
import { RefObject } from "react";
|
||||
import { TContactAttributeKey } from "@formbricks/types/contact-attribute-key";
|
||||
import { TSegment } from "@formbricks/types/segment";
|
||||
import { TSurvey } from "@formbricks/types/surveys/types";
|
||||
@@ -24,6 +26,7 @@ interface SettingsViewProps {
|
||||
isSpamProtectionAllowed: boolean;
|
||||
projectPermission: TTeamPermission | null;
|
||||
isFormbricksCloud: boolean;
|
||||
previewSurveyRef: RefObject<PreviewSurveyRef | null>;
|
||||
}
|
||||
|
||||
export const SettingsView = ({
|
||||
@@ -39,6 +42,7 @@ export const SettingsView = ({
|
||||
isSpamProtectionAllowed,
|
||||
projectPermission,
|
||||
isFormbricksCloud,
|
||||
previewSurveyRef,
|
||||
}: SettingsViewProps) => {
|
||||
const isAppSurvey = localSurvey.type === "app";
|
||||
|
||||
@@ -75,6 +79,7 @@ export const SettingsView = ({
|
||||
propActionClasses={actionClasses}
|
||||
membershipRole={membershipRole}
|
||||
projectPermission={projectPermission}
|
||||
previewSurveyRef={previewSurveyRef}
|
||||
/>
|
||||
|
||||
<ResponseOptionsCard
|
||||
|
||||
@@ -13,7 +13,7 @@ import { SurveyEditorTabs } from "@/modules/survey/editor/components/survey-edit
|
||||
import { SurveyMenuBar } from "@/modules/survey/editor/components/survey-menu-bar";
|
||||
import { TFollowUpEmailToUser } from "@/modules/survey/editor/types/survey-follow-up";
|
||||
import { FollowUpsView } from "@/modules/survey/follow-ups/components/follow-ups-view";
|
||||
import { PreviewSurvey } from "@/modules/ui/components/preview-survey";
|
||||
import { PreviewSurvey, PreviewSurveyRef } from "@/modules/ui/components/preview-survey";
|
||||
import { ActionClass, Environment, Language, OrganizationRole, Project } from "@prisma/client";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { TContactAttributeKey } from "@formbricks/types/contact-attribute-key";
|
||||
@@ -84,6 +84,7 @@ export const SurveyEditor = ({
|
||||
|
||||
const [styling, setStyling] = useState(localSurvey?.styling);
|
||||
const [localStylingChanges, setLocalStylingChanges] = useState<TSurveyStyling | null>(null);
|
||||
const previewSurveyRef = useRef<PreviewSurveyRef | null>(null);
|
||||
|
||||
const fetchLatestProject = useCallback(async () => {
|
||||
const refetchProjectResponse = await refetchProjectAction({ projectId: localProject.id });
|
||||
@@ -231,6 +232,7 @@ export const SurveyEditor = ({
|
||||
isSpamProtectionAllowed={isSpamProtectionAllowed}
|
||||
projectPermission={projectPermission}
|
||||
isFormbricksCloud={isFormbricksCloud}
|
||||
previewSurveyRef={previewSurveyRef}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -250,6 +252,7 @@ export const SurveyEditor = ({
|
||||
|
||||
<aside className="group hidden flex-1 flex-shrink-0 items-center justify-center overflow-hidden border-l border-slate-200 bg-slate-100 shadow-inner md:flex md:flex-col">
|
||||
<PreviewSurvey
|
||||
ref={previewSurveyRef}
|
||||
survey={localSurvey}
|
||||
questionId={activeQuestionId}
|
||||
project={localProject}
|
||||
|
||||
@@ -9,12 +9,13 @@ import { ActionClassInfo } from "@/modules/ui/components/action-class-info";
|
||||
import { AdvancedOptionToggle } from "@/modules/ui/components/advanced-option-toggle";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { Input } from "@/modules/ui/components/input";
|
||||
import { PreviewSurveyRef } from "@/modules/ui/components/preview-survey";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { ActionClass, OrganizationRole } from "@prisma/client";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
import { useTranslate } from "@tolgee/react";
|
||||
import { CheckIcon, PlusIcon, Trash2Icon } from "lucide-react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { RefObject, useEffect, useMemo, useState } from "react";
|
||||
import { TSurvey } from "@formbricks/types/surveys/types";
|
||||
|
||||
interface WhenToSendCardProps {
|
||||
@@ -24,6 +25,7 @@ interface WhenToSendCardProps {
|
||||
propActionClasses: ActionClass[];
|
||||
membershipRole?: OrganizationRole;
|
||||
projectPermission: TTeamPermission | null;
|
||||
previewSurveyRef: RefObject<PreviewSurveyRef>;
|
||||
}
|
||||
|
||||
export const WhenToSendCard = ({
|
||||
@@ -33,6 +35,7 @@ export const WhenToSendCard = ({
|
||||
propActionClasses,
|
||||
membershipRole,
|
||||
projectPermission,
|
||||
previewSurveyRef,
|
||||
}: WhenToSendCardProps) => {
|
||||
const { t } = useTranslate();
|
||||
const [open, setOpen] = useState(localSurvey.type === "app" ? true : false);
|
||||
@@ -62,6 +65,9 @@ export const WhenToSendCard = ({
|
||||
const updatedSurvey = { ...localSurvey, autoClose: 10 };
|
||||
setLocalSurvey(updatedSurvey);
|
||||
}
|
||||
if (previewSurveyRef.current) {
|
||||
previewSurveyRef.current.resetProgress();
|
||||
}
|
||||
};
|
||||
|
||||
const handleDelayToggle = () => {
|
||||
|
||||
@@ -8,7 +8,7 @@ import { Environment, Project } from "@prisma/client";
|
||||
import { useTranslate } from "@tolgee/react";
|
||||
import { Variants, motion } from "framer-motion";
|
||||
import { ExpandIcon, MonitorIcon, ShrinkIcon, SmartphoneIcon } from "lucide-react";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
|
||||
import { TProjectStyling } from "@formbricks/types/project";
|
||||
import { TSurvey, TSurveyQuestionId, TSurveyStyling } from "@formbricks/types/surveys/types";
|
||||
import { Modal } from "./components/modal";
|
||||
@@ -26,6 +26,10 @@ interface PreviewSurveyProps {
|
||||
isSpamProtectionAllowed: boolean;
|
||||
}
|
||||
|
||||
export interface PreviewSurveyRef {
|
||||
resetProgress: () => void;
|
||||
}
|
||||
|
||||
let surveyNameTemp: string;
|
||||
|
||||
const previewParentContainerVariant: Variants = {
|
||||
@@ -57,215 +61,317 @@ const previewParentContainerVariant: Variants = {
|
||||
|
||||
let setQuestionId = (_: string) => {};
|
||||
|
||||
export const PreviewSurvey = ({
|
||||
questionId,
|
||||
survey,
|
||||
previewType,
|
||||
project,
|
||||
environment,
|
||||
languageCode,
|
||||
isSpamProtectionAllowed,
|
||||
}: PreviewSurveyProps) => {
|
||||
const [isModalOpen, setIsModalOpen] = useState(true);
|
||||
const [isFullScreenPreview, setIsFullScreenPreview] = useState(false);
|
||||
const { t } = useTranslate();
|
||||
const [appSetupCompleted, setAppSetupCompleted] = useState(false);
|
||||
export const PreviewSurvey = forwardRef<PreviewSurveyRef, PreviewSurveyProps>(
|
||||
({ questionId, survey, previewType, project, environment, languageCode, isSpamProtectionAllowed }, ref) => {
|
||||
const [isModalOpen, setIsModalOpen] = useState(true);
|
||||
const [isFullScreenPreview, setIsFullScreenPreview] = useState(false);
|
||||
const { t } = useTranslate();
|
||||
const [appSetupCompleted, setAppSetupCompleted] = useState(false);
|
||||
|
||||
const [previewMode, setPreviewMode] = useState("desktop");
|
||||
const [previewPosition, setPreviewPosition] = useState("relative");
|
||||
const ContentRef = useRef<HTMLDivElement | null>(null);
|
||||
const [shrink, setShrink] = useState(false);
|
||||
const { projectOverwrites } = survey || {};
|
||||
const previewScreenVariants: Variants = {
|
||||
expanded: {
|
||||
right: "5%",
|
||||
bottom: "10%",
|
||||
top: "12%",
|
||||
width: "40%",
|
||||
position: "fixed",
|
||||
height: "80%",
|
||||
zIndex: 1050,
|
||||
boxShadow: "0px 4px 5px 4px rgba(169, 169, 169, 0.25)",
|
||||
transition: {
|
||||
ease: "easeInOut",
|
||||
duration: shrink ? 0.3 : 0,
|
||||
const [previewMode, setPreviewMode] = useState("desktop");
|
||||
const [previewPosition, setPreviewPosition] = useState("relative");
|
||||
const ContentRef = useRef<HTMLDivElement | null>(null);
|
||||
const [shrink, setShrink] = useState(false);
|
||||
const { projectOverwrites } = survey || {};
|
||||
const previewScreenVariants: Variants = {
|
||||
expanded: {
|
||||
right: "5%",
|
||||
bottom: "10%",
|
||||
top: "12%",
|
||||
width: "40%",
|
||||
position: "fixed",
|
||||
height: "80%",
|
||||
zIndex: 1050,
|
||||
boxShadow: "0px 4px 5px 4px rgba(169, 169, 169, 0.25)",
|
||||
transition: {
|
||||
ease: "easeInOut",
|
||||
duration: shrink ? 0.3 : 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
expanded_with_fixed_positioning: {
|
||||
zIndex: 1050,
|
||||
position: "fixed",
|
||||
top: "5%",
|
||||
right: "5%",
|
||||
bottom: "10%",
|
||||
width: "90%",
|
||||
height: "90%",
|
||||
transition: {
|
||||
ease: "easeOut",
|
||||
duration: 0.4,
|
||||
expanded_with_fixed_positioning: {
|
||||
zIndex: 1050,
|
||||
position: "fixed",
|
||||
top: "5%",
|
||||
right: "5%",
|
||||
bottom: "10%",
|
||||
width: "90%",
|
||||
height: "90%",
|
||||
transition: {
|
||||
ease: "easeOut",
|
||||
duration: 0.4,
|
||||
},
|
||||
},
|
||||
},
|
||||
shrink: {
|
||||
display: "relative",
|
||||
width: ["95%"],
|
||||
height: ["95%"],
|
||||
},
|
||||
};
|
||||
shrink: {
|
||||
display: "relative",
|
||||
width: ["95%"],
|
||||
height: ["95%"],
|
||||
},
|
||||
};
|
||||
|
||||
const { placement: surveyPlacement } = projectOverwrites || {};
|
||||
const { darkOverlay: surveyDarkOverlay } = projectOverwrites || {};
|
||||
const { clickOutsideClose: surveyClickOutsideClose } = projectOverwrites || {};
|
||||
const { placement: surveyPlacement } = projectOverwrites || {};
|
||||
const { darkOverlay: surveyDarkOverlay } = projectOverwrites || {};
|
||||
const { clickOutsideClose: surveyClickOutsideClose } = projectOverwrites || {};
|
||||
|
||||
const placement = surveyPlacement || project.placement;
|
||||
const darkOverlay = surveyDarkOverlay ?? project.darkOverlay;
|
||||
const clickOutsideClose = surveyClickOutsideClose ?? project.clickOutsideClose;
|
||||
const placement = surveyPlacement || project.placement;
|
||||
const darkOverlay = surveyDarkOverlay ?? project.darkOverlay;
|
||||
const clickOutsideClose = surveyClickOutsideClose ?? project.clickOutsideClose;
|
||||
|
||||
const widgetSetupCompleted = appSetupCompleted;
|
||||
const widgetSetupCompleted = appSetupCompleted;
|
||||
|
||||
const styling: TSurveyStyling | TProjectStyling = useMemo(() => {
|
||||
// allow style overwrite is disabled from the project
|
||||
if (!project.styling.allowStyleOverwrite) {
|
||||
return project.styling;
|
||||
}
|
||||
|
||||
// allow style overwrite is enabled from the project
|
||||
if (project.styling.allowStyleOverwrite) {
|
||||
// survey style overwrite is disabled
|
||||
if (!survey.styling?.overwriteThemeStyling) {
|
||||
const styling: TSurveyStyling | TProjectStyling = useMemo(() => {
|
||||
// allow style overwrite is disabled from the project
|
||||
if (!project.styling.allowStyleOverwrite) {
|
||||
return project.styling;
|
||||
}
|
||||
|
||||
// survey style overwrite is enabled
|
||||
return survey.styling;
|
||||
}
|
||||
// allow style overwrite is enabled from the project
|
||||
if (project.styling.allowStyleOverwrite) {
|
||||
// survey style overwrite is disabled
|
||||
if (!survey.styling?.overwriteThemeStyling) {
|
||||
return project.styling;
|
||||
}
|
||||
|
||||
return project.styling;
|
||||
}, [project.styling, survey.styling]);
|
||||
// survey style overwrite is enabled
|
||||
return survey.styling;
|
||||
}
|
||||
|
||||
const updateQuestionId = useCallback(
|
||||
(newQuestionId: TSurveyQuestionId) => {
|
||||
if (
|
||||
!newQuestionId ||
|
||||
newQuestionId === "hidden" ||
|
||||
newQuestionId === "multiLanguage" ||
|
||||
newQuestionId.includes("fb-variables-")
|
||||
)
|
||||
return;
|
||||
if (newQuestionId === "start" && !survey.welcomeCard.enabled) return;
|
||||
setQuestionId(newQuestionId);
|
||||
},
|
||||
[survey.welcomeCard.enabled]
|
||||
);
|
||||
return project.styling;
|
||||
}, [project.styling, survey.styling]);
|
||||
|
||||
useEffect(() => {
|
||||
if (questionId) {
|
||||
updateQuestionId(questionId);
|
||||
}
|
||||
}, [questionId, updateQuestionId]);
|
||||
const updateQuestionId = useCallback(
|
||||
(newQuestionId: TSurveyQuestionId) => {
|
||||
if (
|
||||
!newQuestionId ||
|
||||
newQuestionId === "hidden" ||
|
||||
newQuestionId === "multiLanguage" ||
|
||||
newQuestionId.includes("fb-variables-")
|
||||
)
|
||||
return;
|
||||
if (newQuestionId === "start" && !survey.welcomeCard.enabled) return;
|
||||
setQuestionId(newQuestionId);
|
||||
},
|
||||
[survey.welcomeCard.enabled]
|
||||
);
|
||||
|
||||
const onFinished = () => {
|
||||
// close modal if there are no questions left
|
||||
if (survey.type === "app" && survey.endings.length === 0) {
|
||||
useEffect(() => {
|
||||
if (questionId) {
|
||||
updateQuestionId(questionId);
|
||||
}
|
||||
}, [questionId, updateQuestionId]);
|
||||
|
||||
const onFinished = () => {
|
||||
// close modal if there are no questions left
|
||||
if (survey.type === "app" && survey.endings.length === 0) {
|
||||
setIsModalOpen(false);
|
||||
setTimeout(() => {
|
||||
setQuestionId(survey.questions[0]?.id);
|
||||
setIsModalOpen(true);
|
||||
}, 500);
|
||||
}
|
||||
};
|
||||
|
||||
// this useEffect is for refreshing the survey preview only if user is switching between templates on survey templates page and hence we are checking for survey.id === "someUniqeId1" which is a common Id for all templates
|
||||
useEffect(() => {
|
||||
if (survey.name !== surveyNameTemp && survey.id === "someUniqueId1") {
|
||||
resetQuestionProgress();
|
||||
surveyNameTemp = survey.name;
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [survey]);
|
||||
|
||||
const resetQuestionProgress = () => {
|
||||
let storePreviewMode = previewMode;
|
||||
setPreviewMode("null");
|
||||
setTimeout(() => {
|
||||
setPreviewMode(storePreviewMode);
|
||||
}, 10);
|
||||
|
||||
setQuestionId(survey.welcomeCard.enabled ? "start" : survey?.questions[0]?.id);
|
||||
};
|
||||
|
||||
// Expose the reset function via ref
|
||||
useImperativeHandle(ref, () => ({
|
||||
resetProgress: resetQuestionProgress,
|
||||
}));
|
||||
|
||||
useEffect(() => {
|
||||
if (environment) {
|
||||
setAppSetupCompleted(environment.appSetupCompleted);
|
||||
}
|
||||
}, [environment]);
|
||||
|
||||
const isSpamProtectionEnabled = useMemo(() => {
|
||||
return isSpamProtectionAllowed && survey.recaptcha?.enabled;
|
||||
}, [survey.recaptcha?.enabled, isSpamProtectionAllowed]);
|
||||
|
||||
const handlePreviewModalClose = () => {
|
||||
setIsModalOpen(false);
|
||||
setTimeout(() => {
|
||||
setQuestionId(survey.questions[0]?.id);
|
||||
setIsModalOpen(true);
|
||||
}, 500);
|
||||
}
|
||||
};
|
||||
resetQuestionProgress();
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
// this useEffect is for refreshing the survey preview only if user is switching between templates on survey templates page and hence we are checking for survey.id === "someUniqeId1" which is a common Id for all templates
|
||||
useEffect(() => {
|
||||
if (survey.name !== surveyNameTemp && survey.id === "someUniqueId1") {
|
||||
resetQuestionProgress();
|
||||
surveyNameTemp = survey.name;
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [survey]);
|
||||
if (!previewType) {
|
||||
previewType = widgetSetupCompleted ? "modal" : "fullwidth";
|
||||
|
||||
const resetQuestionProgress = () => {
|
||||
let storePreviewMode = previewMode;
|
||||
setPreviewMode("null");
|
||||
setTimeout(() => {
|
||||
setPreviewMode(storePreviewMode);
|
||||
}, 10);
|
||||
|
||||
setQuestionId(survey.welcomeCard.enabled ? "start" : survey?.questions[0]?.id);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (environment) {
|
||||
setAppSetupCompleted(environment.appSetupCompleted);
|
||||
}
|
||||
}, [environment]);
|
||||
|
||||
const isSpamProtectionEnabled = useMemo(() => {
|
||||
return isSpamProtectionAllowed && survey.recaptcha?.enabled;
|
||||
}, [survey.recaptcha?.enabled, isSpamProtectionAllowed]);
|
||||
|
||||
const handlePreviewModalClose = () => {
|
||||
setIsModalOpen(false);
|
||||
setTimeout(() => {
|
||||
setIsModalOpen(true);
|
||||
resetQuestionProgress();
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
if (!previewType) {
|
||||
previewType = widgetSetupCompleted ? "modal" : "fullwidth";
|
||||
|
||||
if (!questionId) {
|
||||
return <></>;
|
||||
}
|
||||
}
|
||||
|
||||
const handlePreviewModeChange = (mode: "mobile" | "desktop") => {
|
||||
setPreviewMode(mode);
|
||||
requestAnimationFrame(() => {
|
||||
if (questionId) {
|
||||
setQuestionId(questionId);
|
||||
if (!questionId) {
|
||||
return <></>;
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex h-full w-full flex-col items-center justify-items-center py-4" id="survey-preview">
|
||||
<motion.div
|
||||
variants={previewParentContainerVariant}
|
||||
animate={isFullScreenPreview ? "expanded" : "shrink"}
|
||||
/>
|
||||
<motion.div
|
||||
layout
|
||||
variants={previewScreenVariants}
|
||||
animate={
|
||||
isFullScreenPreview
|
||||
? previewPosition === "relative"
|
||||
? "expanded"
|
||||
: "expanded_with_fixed_positioning"
|
||||
: "shrink"
|
||||
const handlePreviewModeChange = (mode: "mobile" | "desktop") => {
|
||||
setPreviewMode(mode);
|
||||
requestAnimationFrame(() => {
|
||||
if (questionId) {
|
||||
setQuestionId(questionId);
|
||||
}
|
||||
className="relative flex h-full w-[95%] items-center justify-center rounded-lg border border-slate-300 bg-slate-200">
|
||||
{previewMode === "mobile" && (
|
||||
<>
|
||||
<p className="absolute left-0 top-0 m-2 rounded bg-slate-100 px-2 py-1 text-xs text-slate-400">
|
||||
Preview
|
||||
</p>
|
||||
<div className="absolute right-0 top-0 m-2">
|
||||
<ResetProgressButton onClick={resetQuestionProgress} />
|
||||
</div>
|
||||
<MediaBackground
|
||||
surveyType={survey.type}
|
||||
styling={styling}
|
||||
ContentRef={ContentRef as React.RefObject<HTMLDivElement>}
|
||||
isMobilePreview>
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex h-full w-full flex-col items-center justify-items-center py-4" id="survey-preview">
|
||||
<motion.div
|
||||
variants={previewParentContainerVariant}
|
||||
animate={isFullScreenPreview ? "expanded" : "shrink"}
|
||||
/>
|
||||
<motion.div
|
||||
layout
|
||||
variants={previewScreenVariants}
|
||||
animate={
|
||||
isFullScreenPreview
|
||||
? previewPosition === "relative"
|
||||
? "expanded"
|
||||
: "expanded_with_fixed_positioning"
|
||||
: "shrink"
|
||||
}
|
||||
className="relative flex h-full w-[95%] items-center justify-center rounded-lg border border-slate-300 bg-slate-200">
|
||||
{previewMode === "mobile" && (
|
||||
<>
|
||||
<p className="absolute left-0 top-0 m-2 rounded bg-slate-100 px-2 py-1 text-xs text-slate-400">
|
||||
Preview
|
||||
</p>
|
||||
<div className="absolute right-0 top-0 m-2">
|
||||
<ResetProgressButton onClick={resetQuestionProgress} />
|
||||
</div>
|
||||
<MediaBackground
|
||||
surveyType={survey.type}
|
||||
styling={styling}
|
||||
ContentRef={ContentRef as React.RefObject<HTMLDivElement>}
|
||||
isMobilePreview>
|
||||
{previewType === "modal" ? (
|
||||
<Modal
|
||||
isOpen={isModalOpen}
|
||||
placement={placement}
|
||||
previewMode="mobile"
|
||||
darkOverlay={darkOverlay}
|
||||
clickOutsideClose={clickOutsideClose}
|
||||
borderRadius={styling?.roundness ?? 8}
|
||||
background={styling?.cardBackgroundColor?.light}>
|
||||
<SurveyInline
|
||||
isPreviewMode={true}
|
||||
survey={survey}
|
||||
isBrandingEnabled={project.inAppSurveyBranding}
|
||||
isRedirectDisabled={true}
|
||||
languageCode={languageCode}
|
||||
styling={styling}
|
||||
isCardBorderVisible={!styling.highlightBorderColor?.light}
|
||||
onClose={handlePreviewModalClose}
|
||||
getSetQuestionId={(f: (value: string) => void) => {
|
||||
setQuestionId = f;
|
||||
}}
|
||||
onFinished={onFinished}
|
||||
isSpamProtectionEnabled={isSpamProtectionEnabled}
|
||||
/>
|
||||
</Modal>
|
||||
) : (
|
||||
<div className="flex h-full w-full flex-col justify-center px-1">
|
||||
<div className="absolute left-5 top-5">
|
||||
{!styling.isLogoHidden && (
|
||||
<ClientLogo environmentId={environment.id} projectLogo={project.logo} previewSurvey />
|
||||
)}
|
||||
</div>
|
||||
<div className="z-10 w-full max-w-md rounded-lg border border-transparent">
|
||||
<SurveyInline
|
||||
isPreviewMode={true}
|
||||
survey={{ ...survey, type: "link" }}
|
||||
isBrandingEnabled={project.linkSurveyBranding}
|
||||
languageCode={languageCode}
|
||||
responseCount={42}
|
||||
styling={styling}
|
||||
getSetQuestionId={(f: (value: string) => void) => {
|
||||
setQuestionId = f;
|
||||
}}
|
||||
isSpamProtectionEnabled={isSpamProtectionEnabled}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</MediaBackground>
|
||||
</>
|
||||
)}
|
||||
{previewMode === "desktop" && (
|
||||
<div className="flex h-full flex-1 flex-col">
|
||||
<div className="flex h-8 w-full items-center rounded-t-lg bg-slate-100">
|
||||
<div className="ml-6 flex space-x-2">
|
||||
<div className="h-3 w-3 rounded-full bg-red-500"></div>
|
||||
<div className="h-3 w-3 rounded-full bg-amber-500"></div>
|
||||
<button
|
||||
className="h-3 w-3 cursor-pointer rounded-full bg-emerald-500"
|
||||
onClick={() => {
|
||||
if (isFullScreenPreview) {
|
||||
setShrink(true);
|
||||
setPreviewPosition("relative");
|
||||
setTimeout(() => setIsFullScreenPreview(false), 300);
|
||||
} else {
|
||||
setShrink(false);
|
||||
setIsFullScreenPreview(true);
|
||||
setTimeout(() => setPreviewPosition("fixed"), 300);
|
||||
}
|
||||
}}
|
||||
aria-label={isFullScreenPreview ? "Shrink Preview" : "Expand Preview"}></button>
|
||||
</div>
|
||||
<div className="ml-4 flex w-full justify-between font-mono text-sm text-slate-400">
|
||||
<p>
|
||||
{previewType === "modal"
|
||||
? t("environments.surveys.edit.your_web_app")
|
||||
: t("common.preview")}
|
||||
</p>
|
||||
|
||||
<div className="flex items-center">
|
||||
{isFullScreenPreview ? (
|
||||
<ShrinkIcon
|
||||
className="mr-1 h-[22px] w-[22px] cursor-pointer rounded-md bg-white p-1 text-slate-500 hover:text-slate-700"
|
||||
onClick={() => {
|
||||
setShrink(true);
|
||||
setPreviewPosition("relative");
|
||||
setTimeout(() => setIsFullScreenPreview(false), 300);
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<ExpandIcon
|
||||
className="mr-1 h-[22px] w-[22px] cursor-pointer rounded-md bg-white p-1 text-slate-500 hover:text-slate-700"
|
||||
onClick={() => {
|
||||
setShrink(false);
|
||||
setIsFullScreenPreview(true);
|
||||
setTimeout(() => setPreviewPosition("fixed"), 300);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<ResetProgressButton onClick={resetQuestionProgress} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{previewType === "modal" ? (
|
||||
<Modal
|
||||
isOpen={isModalOpen}
|
||||
placement={placement}
|
||||
previewMode="mobile"
|
||||
darkOverlay={darkOverlay}
|
||||
clickOutsideClose={clickOutsideClose}
|
||||
borderRadius={styling?.roundness ?? 8}
|
||||
background={styling?.cardBackgroundColor?.light}>
|
||||
darkOverlay={darkOverlay}
|
||||
previewMode="desktop"
|
||||
borderRadius={styling.roundness ?? 8}
|
||||
background={styling.cardBackgroundColor?.light}>
|
||||
<SurveyInline
|
||||
isPreviewMode={true}
|
||||
survey={survey}
|
||||
@@ -283,17 +389,22 @@ export const PreviewSurvey = ({
|
||||
/>
|
||||
</Modal>
|
||||
) : (
|
||||
<div className="flex h-full w-full flex-col justify-center px-1">
|
||||
<MediaBackground
|
||||
surveyType={survey.type}
|
||||
styling={styling}
|
||||
ContentRef={ContentRef as React.RefObject<HTMLDivElement>}
|
||||
isEditorView>
|
||||
<div className="absolute left-5 top-5">
|
||||
{!styling.isLogoHidden && (
|
||||
<ClientLogo environmentId={environment.id} projectLogo={project.logo} previewSurvey />
|
||||
)}
|
||||
</div>
|
||||
<div className="z-10 w-full max-w-md rounded-lg border border-transparent">
|
||||
<div className="z-0 w-full max-w-4xl rounded-lg border-transparent">
|
||||
<SurveyInline
|
||||
isPreviewMode={true}
|
||||
survey={{ ...survey, type: "link" }}
|
||||
isBrandingEnabled={project.linkSurveyBranding}
|
||||
isRedirectDisabled={true}
|
||||
languageCode={languageCode}
|
||||
responseCount={42}
|
||||
styling={styling}
|
||||
@@ -303,136 +414,30 @@ export const PreviewSurvey = ({
|
||||
isSpamProtectionEnabled={isSpamProtectionEnabled}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</MediaBackground>
|
||||
)}
|
||||
</MediaBackground>
|
||||
</>
|
||||
)}
|
||||
{previewMode === "desktop" && (
|
||||
<div className="flex h-full flex-1 flex-col">
|
||||
<div className="flex h-8 w-full items-center rounded-t-lg bg-slate-100">
|
||||
<div className="ml-6 flex space-x-2">
|
||||
<div className="h-3 w-3 rounded-full bg-red-500"></div>
|
||||
<div className="h-3 w-3 rounded-full bg-amber-500"></div>
|
||||
<button
|
||||
className="h-3 w-3 cursor-pointer rounded-full bg-emerald-500"
|
||||
onClick={() => {
|
||||
if (isFullScreenPreview) {
|
||||
setShrink(true);
|
||||
setPreviewPosition("relative");
|
||||
setTimeout(() => setIsFullScreenPreview(false), 300);
|
||||
} else {
|
||||
setShrink(false);
|
||||
setIsFullScreenPreview(true);
|
||||
setTimeout(() => setPreviewPosition("fixed"), 300);
|
||||
}
|
||||
}}
|
||||
aria-label={isFullScreenPreview ? "Shrink Preview" : "Expand Preview"}></button>
|
||||
</div>
|
||||
<div className="ml-4 flex w-full justify-between font-mono text-sm text-slate-400">
|
||||
<p>
|
||||
{previewType === "modal"
|
||||
? t("environments.surveys.edit.your_web_app")
|
||||
: t("common.preview")}
|
||||
</p>
|
||||
|
||||
<div className="flex items-center">
|
||||
{isFullScreenPreview ? (
|
||||
<ShrinkIcon
|
||||
className="mr-1 h-[22px] w-[22px] cursor-pointer rounded-md bg-white p-1 text-slate-500 hover:text-slate-700"
|
||||
onClick={() => {
|
||||
setShrink(true);
|
||||
setPreviewPosition("relative");
|
||||
setTimeout(() => setIsFullScreenPreview(false), 300);
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<ExpandIcon
|
||||
className="mr-1 h-[22px] w-[22px] cursor-pointer rounded-md bg-white p-1 text-slate-500 hover:text-slate-700"
|
||||
onClick={() => {
|
||||
setShrink(false);
|
||||
setIsFullScreenPreview(true);
|
||||
setTimeout(() => setPreviewPosition("fixed"), 300);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<ResetProgressButton onClick={resetQuestionProgress} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</motion.div>
|
||||
|
||||
{previewType === "modal" ? (
|
||||
<Modal
|
||||
isOpen={isModalOpen}
|
||||
placement={placement}
|
||||
clickOutsideClose={clickOutsideClose}
|
||||
darkOverlay={darkOverlay}
|
||||
previewMode="desktop"
|
||||
borderRadius={styling.roundness ?? 8}
|
||||
background={styling.cardBackgroundColor?.light}>
|
||||
<SurveyInline
|
||||
isPreviewMode={true}
|
||||
survey={survey}
|
||||
isBrandingEnabled={project.inAppSurveyBranding}
|
||||
isRedirectDisabled={true}
|
||||
languageCode={languageCode}
|
||||
styling={styling}
|
||||
isCardBorderVisible={!styling.highlightBorderColor?.light}
|
||||
onClose={handlePreviewModalClose}
|
||||
getSetQuestionId={(f: (value: string) => void) => {
|
||||
setQuestionId = f;
|
||||
}}
|
||||
onFinished={onFinished}
|
||||
isSpamProtectionEnabled={isSpamProtectionEnabled}
|
||||
/>
|
||||
</Modal>
|
||||
) : (
|
||||
<MediaBackground
|
||||
surveyType={survey.type}
|
||||
styling={styling}
|
||||
ContentRef={ContentRef as React.RefObject<HTMLDivElement>}
|
||||
isEditorView>
|
||||
<div className="absolute left-5 top-5">
|
||||
{!styling.isLogoHidden && (
|
||||
<ClientLogo environmentId={environment.id} projectLogo={project.logo} previewSurvey />
|
||||
)}
|
||||
</div>
|
||||
<div className="z-0 w-full max-w-4xl rounded-lg border-transparent">
|
||||
<SurveyInline
|
||||
isPreviewMode={true}
|
||||
survey={{ ...survey, type: "link" }}
|
||||
isBrandingEnabled={project.linkSurveyBranding}
|
||||
isRedirectDisabled={true}
|
||||
languageCode={languageCode}
|
||||
responseCount={42}
|
||||
styling={styling}
|
||||
getSetQuestionId={(f: (value: string) => void) => {
|
||||
setQuestionId = f;
|
||||
}}
|
||||
isSpamProtectionEnabled={isSpamProtectionEnabled}
|
||||
/>
|
||||
</div>
|
||||
</MediaBackground>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</motion.div>
|
||||
|
||||
{/* for toggling between mobile and desktop mode */}
|
||||
<div className="mt-2 flex rounded-full border-2 border-slate-300 p-1">
|
||||
<TabOption
|
||||
active={previewMode === "mobile"}
|
||||
icon={<SmartphoneIcon className="mx-4 my-2 h-4 w-4 text-slate-700" />}
|
||||
onClick={() => handlePreviewModeChange("mobile")}
|
||||
/>
|
||||
<TabOption
|
||||
active={previewMode === "desktop"}
|
||||
icon={<MonitorIcon className="mx-4 my-2 h-4 w-4 text-slate-700" />}
|
||||
onClick={() => handlePreviewModeChange("desktop")}
|
||||
/>
|
||||
{/* for toggling between mobile and desktop mode */}
|
||||
<div className="mt-2 flex rounded-full border-2 border-slate-300 p-1">
|
||||
<TabOption
|
||||
active={previewMode === "mobile"}
|
||||
icon={<SmartphoneIcon className="mx-4 my-2 h-4 w-4 text-slate-700" />}
|
||||
onClick={() => handlePreviewModeChange("mobile")}
|
||||
/>
|
||||
<TabOption
|
||||
active={previewMode === "desktop"}
|
||||
icon={<MonitorIcon className="mx-4 my-2 h-4 w-4 text-slate-700" />}
|
||||
onClick={() => handlePreviewModeChange("desktop")}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
PreviewSurvey.displayName = "PreviewSurvey";
|
||||
|
||||
export { getPlacementStyle } from "./lib/utils";
|
||||
|
||||
Reference in New Issue
Block a user