diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/EmbedSurveyModal.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/EmbedSurveyModal.tsx index 20a4945bc6..3228b43564 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/EmbedSurveyModal.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/EmbedSurveyModal.tsx @@ -1,6 +1,20 @@ "use client"; -import { Button, Dialog, DialogContent } from "@formbricks/ui"; +import toast from "react-hot-toast"; +import CodeBlock from "@/components/shared/CodeBlock"; +import { + Section, + Tailwind, + render, + Button as EmailButton, + Text, + Link, + Container, + Row, + Column, +} from "@react-email/components"; +import { useMemo, useRef, useState } from "react"; +import { Button, Dialog, DialogContent, Input } from "@formbricks/ui"; import { TSurvey } from "@formbricks/types/v1/surveys"; import { LinkIcon, @@ -9,16 +23,14 @@ import { DocumentDuplicateIcon, ArrowUpRightIcon, } from "@heroicons/react/24/outline"; -import { useMemo, useRef, useState } from "react"; import { cn } from "@formbricks/lib/cn"; -import CodeBlock from "@/components/shared/CodeBlock"; -import { SURVEY_BASE_URL } from "@formbricks/lib/constants"; -import toast from "react-hot-toast"; +import { QuestionType } from "@formbricks/types/questions"; interface EmbedSurveyModalProps { survey: TSurvey; open: boolean; setOpen: (open: boolean) => void; + surveyBaseUrl: string; } const tabs = [ @@ -27,15 +39,14 @@ const tabs = [ { id: "webpage", label: "Embed in a Web Page", icon: CodeBracketIcon }, ]; -export default function EmbedSurveyModal({ survey, open, setOpen }: EmbedSurveyModalProps) { +export default function EmbedSurveyModal({ survey, open, setOpen, surveyBaseUrl }: EmbedSurveyModalProps) { const [activeId, setActiveId] = useState(tabs[0].id); - const [showEmbed, setShowEmbed] = useState(false); - const surveyUrl = useMemo(() => SURVEY_BASE_URL + survey.id, [survey]); + const surveyUrl = useMemo(() => surveyBaseUrl + survey.id, [survey]); const componentMap = { link: , - email: , + email: , webpage: , }; @@ -54,7 +65,8 @@ export default function EmbedSurveyModal({ survey, open, setOpen }: EmbedSurveyM key={tab.id} onClick={() => setActiveId(tab.id)} className={cn( - "rounded-[4px] px-4 py-[6px] text-slate-600 focus:ring-0 focus:ring-offset-0", + "rounded-[4px] px-4 py-[6px] text-slate-600", + // "focus:ring-0 focus:ring-offset-0", // enable these classes to remove the focus rings on buttons tab.id === activeId ? " border border-gray-200 bg-slate-100 font-semibold text-slate-900" : "border-transparent text-slate-500 hover:text-slate-700" @@ -87,6 +99,7 @@ const LinkTab = ({ surveyUrl }) => { } } }; + return (
@@ -108,7 +121,7 @@ const LinkTab = ({ surveyUrl }) => { Copy URL
-
+
@@ -125,8 +140,102 @@ const LinkTab = ({ surveyUrl }) => { ); }; -const EmailTab = () => { - return <>Email; +const EmailTab = ({ survey, surveyUrl }: { survey: TSurvey; surveyUrl: string }) => { + const [email, setEmail] = useState(""); + const [showEmbed, setShowEmbed] = useState(false); + + console.log(survey); + const Email = ( + + {getEmailTemplate(survey, surveyUrl)} + + ); + + const confirmEmail = render(Email, { pretty: true }); + + return ( +
+
+ setEmail(e.target.value)} + /> + {showEmbed ? ( + + ) : ( + + )} + +
+
+ {showEmbed ? ( + <> + + {confirmEmail} + + + ) : ( +
+
+
+
+
+
+
+
+ To : {email || "user@mail.com"} +
+
+ Subject : Formbricks Email Survey Preview +
+
{Email}
+
+
+ )} +
+
+ ); }; const WebpageTab = ({ surveyUrl }) => { @@ -153,15 +262,152 @@ const WebpageTab = ({ surveyUrl }) => { Copy code
-
- {/* {iframeCode} */} - - {/* +
+ {iframeCode} - */} +
); }; + +const getEmailTemplate = (survey: TSurvey, surveyUrl: string) => { + const firstQuestion = survey.questions[0]; + console.log(firstQuestion); + switch (firstQuestion.type) { + case QuestionType.OpenText: + return ( + + + {firstQuestion.headline} + + + {firstQuestion.subheader} + +
+ + powered by + Formbricks + + + ); + case QuestionType.Consent: + return ( + +
+ + {firstQuestion.headline} + + + + + + + {firstQuestion.label} + + + {!firstQuestion.required && ( + + Reject + + )} + + Accept + + + + powered by + Formbricks + +
+ + ); + case QuestionType.NPS: + return ( + +
+ + {firstQuestion.headline} + + + {firstQuestion.subheader} + + +
+ {Array.from({ length: 11 }, (_, i) => ( + + {i} + + ))} +
+
+ + + {firstQuestion.lowerLabel} + + + {firstQuestion.upperLabel} + + +
+
+ + + powered by + Formbricks + +
+ + ); + case QuestionType.CTA: + return ( + +
+ + {firstQuestion.headline} + + + + + + + {!firstQuestion.required && ( + + {firstQuestion.dismissButtonLabel} + + )} + { + if (firstQuestion.buttonExternal && firstQuestion.buttonUrl) { + window?.open(firstQuestion.buttonUrl, "_blank")?.focus(); + } + }} + href={`${surveyUrl}?${firstQuestion.id}=clicked`} + className="ml-2 inline-flex cursor-pointer appearance-none rounded-md bg-slate-500 px-6 py-3 text-sm font-medium text-white"> + {firstQuestion.buttonLabel} + + + + powered by + Formbricks + +
+ + ); + } + return <>; +}; diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/LinkModalButton.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/LinkModalButton.tsx index b1acd10b5a..0f3a3e5cd0 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/LinkModalButton.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/LinkModalButton.tsx @@ -32,16 +32,22 @@ export default function LinkSurveyShareButton({ onClick={() => setShowLinkModal(true)}> - {/* {showLinkModal && } */} - {/* {showLinkModal && } */} {showLinkModal && ( - )} + {/* {showLinkModal && ( + + )} */} ); } diff --git a/apps/web/app/s/[surveyId]/prefilling.ts b/apps/web/app/s/[surveyId]/prefilling.ts index d5a9e597a3..da4ec65294 100644 --- a/apps/web/app/s/[surveyId]/prefilling.ts +++ b/apps/web/app/s/[surveyId]/prefilling.ts @@ -17,6 +17,11 @@ export function getPrefillResponseData( const answer = transformAnswer(question, firstQuestionPrefill || ""); const answerObj = { [firstQuestionId]: answer }; + + if (question.type === QuestionType.CTA && question.buttonExternal && question.buttonUrl) { + window?.open(question.buttonUrl, "blank"); + } + return answerObj; } } catch (error) { diff --git a/apps/web/components/shared/CodeBlock.tsx b/apps/web/components/shared/CodeBlock.tsx index 0eb89c76f8..e9698e91e9 100644 --- a/apps/web/components/shared/CodeBlock.tsx +++ b/apps/web/components/shared/CodeBlock.tsx @@ -11,23 +11,31 @@ interface CodeBlockProps { children: React.ReactNode; language: string; customCodeClass?: string; + showCopyToClipboard?: boolean; } -const CodeBlock: React.FC = ({ children, language, customCodeClass = "" }) => { +const CodeBlock: React.FC = ({ + children, + language, + customCodeClass = "", + showCopyToClipboard = true, +}) => { useEffect(() => { Prism.highlightAll(); }, [children]); return (
- { - const childText = children?.toString() || ""; - navigator.clipboard.writeText(childText); - toast.success("Copied to clipboard"); - }} - /> + {showCopyToClipboard && ( + { + const childText = children?.toString() || ""; + navigator.clipboard.writeText(childText); + toast.success("Copied to clipboard"); + }} + /> + )}
         {children}