Skip to content

Commit

Permalink
feat: Custom closed message (#4389)
Browse files Browse the repository at this point in the history
*remove api endpoint

* add closed component ui

* server action to pull from DB

* update front facing form

* move closed page out of preview

* update strings

Co-authored-by: Anik Brazeau <38330843+anikbrazeau@users.noreply.github.com>
  • Loading branch information
timarney and anikbrazeau authored Oct 16, 2024
1 parent 9768159 commit 2670aa8
Show file tree
Hide file tree
Showing 29 changed files with 362 additions and 174 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useTemplateStore } from "@lib/store/useTemplateStore";
import { Language, LocalizedElementProperties } from "@lib/types/form-builder-types";
import { useTranslation } from "@i18n/client";
import { FormElement } from "@lib/types";
import { LanguageLabel } from "./LanguageLabel";
import { LanguageLabel } from "@formBuilder/components/shared/LanguageLabel";
import { FieldsetLegend } from "./FieldsetLegend";

export const Description = ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import React from "react";
import { useTemplateStore } from "@lib/store/useTemplateStore";
import { Language } from "@lib/types/form-builder-types";
import { FieldsetLegend } from "./FieldsetLegend";
import { LanguageLabel } from "./LanguageLabel";
import { LanguageLabel } from "@formBuilder/components/shared/LanguageLabel";

export const Options = ({
element,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import React from "react";
import { RichTextEditor } from "../../components/elements/lexical-editor/RichTextEditor";
import { useTemplateStore } from "@lib/store/useTemplateStore";
import { Language, LocalizedElementProperties } from "@lib/types/form-builder-types";
import { LanguageLabel } from "./LanguageLabel";
import { LanguageLabel } from "@formBuilder/components/shared/LanguageLabel";
import { FieldsetLegend } from "./FieldsetLegend";

export const RichText = ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useTemplateStore } from "@lib/store/useTemplateStore";
import { Language, LocalizedElementProperties } from "@lib/types/form-builder-types";
import { useTranslation } from "@i18n/client";
import { FormElement } from "@lib/types";
import { LanguageLabel } from "./LanguageLabel";
import { LanguageLabel } from "@formBuilder/components/shared/LanguageLabel";
import { FieldsetLegend } from ".";

export const Title = ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
} from "@lib/types/form-builder-types";
import { DownloadCSV } from "./DownloadCSV";
import { RichTextEditor } from "../../components/elements/lexical-editor/RichTextEditor";
import { LanguageLabel } from "./LanguageLabel";
import { LanguageLabel } from "@formBuilder/components/shared/LanguageLabel";
import { FieldsetLegend, SectionTitle } from ".";
import { SaveButton } from "@formBuilder/components/shared/SaveButton";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Language } from "@lib/types/form-builder-types";
import { FieldsetLegend } from ".";
import { LanguageLabel } from "./LanguageLabel";
import { LanguageLabel } from "@formBuilder/components/shared/LanguageLabel";
import { useTranslation } from "@i18n/client";
import { useTemplateStore } from "@lib/store/useTemplateStore";
import { FormElement } from "@lib/types";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
Language,
} from "@lib/types/form-builder-types";
import { RichTextEditor } from "../../components/elements/lexical-editor/RichTextEditor";
import { LanguageLabel } from "./LanguageLabel";
import { LanguageLabel } from "@formBuilder/components/shared/LanguageLabel";
import { FieldsetLegend, SectionTitle } from ".";
import { SaveButton } from "@formBuilder/components/shared/SaveButton";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Markdown from "markdown-to-jsx";
import { PreviewNavigation } from "./PreviewNavigation";
import { getRenderedForm } from "@lib/formBuilder";
import { FormProperties, PublicFormRecord } from "@lib/types";
import { RichText, ClosedPage } from "@clientComponents/forms";
import { RichText } from "@clientComponents/forms";
import { Button } from "@clientComponents/globals";
import { NextButton } from "@clientComponents/forms/NextButton/NextButton";

Expand All @@ -18,7 +18,6 @@ import {
import { useRehydrate, useTemplateStore } from "@lib/store/useTemplateStore";
import { BackArrowIcon } from "@serverComponents/icons";
import Brand from "@clientComponents/globals/Brand";
import { useIsFormClosed } from "@lib/hooks/useIsFormClosed";
import { GCFormsProvider } from "@lib/hooks/useGCFormContext";
import Skeleton from "react-loading-skeleton";
import { Form } from "@clientComponents/forms/Form/Form";
Expand All @@ -29,6 +28,7 @@ import { toast } from "@formBuilder/components/shared";
import { defaultForm } from "@lib/store/defaults";
import { showReviewPage } from "@lib/utils/form-builder/showReviewPage";
import { focusElement } from "@lib/client/clientHelpers";
import { useIsFormClosed } from "@lib/hooks/useIsFormClosed";

export const Preview = ({
disableSubmit = true,
Expand All @@ -46,6 +46,8 @@ export const Preview = ({
getSecurityAttribute: s.getSecurityAttribute,
}));

const isPastClosingDate = useIsFormClosed();

const formParsed = safeJSONParse<FormProperties>(getSchema());
if (!formParsed) {
toast.error(<ErrorSaving errorCode={FormServerErrorCodes.JSON_PARSE} />, "wide");
Expand All @@ -69,7 +71,7 @@ export const Preview = ({
email: s.deliveryOption?.emailAddress,
}));

const { t } = useTranslation(["common", "form-builder"]);
const { t } = useTranslation(["common", "form-builder", "form-closed"]);
const language = translationLanguagePriority;
const currentForm = getRenderedForm(formRecord, language);

Expand All @@ -88,31 +90,18 @@ export const Preview = ({

const brand = formRecord?.form ? formRecord.form.brand : null;

const isPastClosingDate = useIsFormClosed();

const hasHydrated = useRehydrate();

const isShowReviewPage = showReviewPage(formRecord.form);

if (isPastClosingDate) {
// Force a hard refresh to the preview page to show the closed message
const refreshContent = `0;url=/${i18n.language}/form-builder/${id}/preview`;
return (
<div className="max-w-4xl">
<PreviewNavigation />
<div className="h-12"></div>
<div
className={`mb-8 border-3 border-dashed border-blue-focus bg-white p-4 ${
status !== "authenticated" && ""
}`}
{...getLocalizationAttribute()}
>
<div className="gc-formview">
<div className="mb-20 mt-0 border-b-4 border-blue-dark py-9">
<Brand brand={brand} lang={language} className="max-w-[360px]" />
</div>
<ClosedPage language={language} formRecord={formRecord} />
</div>
</div>
</div>
<>
<meta httpEquiv="refresh" content={refreshContent} />
<Skeleton count={4} height={40} className="mb-4" />
</>
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"use client";

import Brand from "@clientComponents/globals/Brand";
import { PreviewNavigation } from "./PreviewNavigation";
import { useTemplateStore } from "@lib/store/useTemplateStore";
import { defaultForm } from "@lib/store/defaults";
import { ClosedPage } from "@clientComponents/forms";
import { ClosedDetails, PublicFormRecord } from "@lib/types";
import { useSession } from "next-auth/react";
import { useTranslation } from "@i18n/client";
import { useIsFormClosed } from "@lib/hooks/useIsFormClosed";
import Skeleton from "react-loading-skeleton";

export const PreviewClosed = ({ closedDetails }: { closedDetails: ClosedDetails }) => {
const { i18n } = useTranslation(["common", "confirmation"]);
const { status } = useSession();
const { id, getIsPublished, getSecurityAttribute } = useTemplateStore((s) => ({
id: s.id,
getIsPublished: s.getIsPublished,
getSecurityAttribute: s.getSecurityAttribute,
}));

const { translationLanguagePriority, getLocalizationAttribute } = useTemplateStore((s) => ({
localizeField: s.localizeField,
translationLanguagePriority: s.translationLanguagePriority,
getLocalizationAttribute: s.getLocalizationAttribute,
}));

const language = translationLanguagePriority;

const formRecord: PublicFormRecord = {
id: id || "test0form00000id000asdf11",
form: defaultForm,
isPublished: getIsPublished(),
securityAttribute: getSecurityAttribute(),
closedDetails: closedDetails,
};

const brand = formRecord?.form ? formRecord.form.brand : null;

const isPastClosingDate = useIsFormClosed();

if (!isPastClosingDate) {
// Force a hard refresh to the preview page if the form is not closed
const refreshContent = `0;url=/${i18n.language}/form-builder/${id}/preview`;
return (
<>
<meta httpEquiv="refresh" content={refreshContent} />
<Skeleton count={4} height={40} className="mb-4" />
</>
);
}

return (
<div className="max-w-4xl">
<PreviewNavigation />
<div className="h-12"></div>
<div
className={`mb-8 border-3 border-dashed border-blue-focus bg-white p-4 ${
status !== "authenticated" && ""
}`}
{...getLocalizationAttribute()}
>
<div className="gc-formview">
<div className="mb-20 mt-0 border-b-4 border-blue-dark py-9">
<Brand brand={brand} lang={language} className="max-w-[360px]" />
</div>
<ClosedPage language={language} formRecord={formRecord} />
</div>
</div>
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import { notFound } from "next/navigation";
import { Preview } from "./Preview";
import { allowGrouping } from "@formBuilder/components/shared/right-panel/treeview/util/allowGrouping";
import { ClientContainer } from "./ClientContainer";
import { checkIfClosed } from "@lib/actions/checkIfClosed";
import { ClosedDetails } from "@lib/types";
import { PreviewClosed } from "./PreviewClosed";

export async function generateMetadata({
params: { locale },
Expand All @@ -31,6 +34,13 @@ export default async function Page({ params: { id } }: { params: { id: string }
if (!session?.user && formID !== "0000") {
return notFound();
}

const closedDetails = await checkIfClosed(id);

if (closedDetails && closedDetails.isPastClosingDate) {
return <PreviewClosed closedDetails={closedDetails.closedDetails as ClosedDetails} />;
}

return (
<ClientContainer>
<Preview disableSubmit={disableSubmit} allowGrouping={isAllowGrouping} />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"use client";

import { FormRecord } from "@lib/types";
import { FormRecord, ClosedDetails } from "@lib/types";
import { DownloadForm } from "./DownloadForm";
import { SetClosingDate } from "./SetClosingDate";
import { SetClosingDate } from "./close/SetClosingDate";
import { FormOwnership } from "./FormOwnership";
import { ErrorPanel } from "@clientComponents/globals/ErrorPanel";

Expand All @@ -20,6 +20,7 @@ interface ManageFormProps {
usersAssignedToFormRecord?: User[];
allUsers?: User[];
id: string;
closedDetails?: ClosedDetails;
}

export const ManageForm = (props: ManageFormProps) => {
Expand All @@ -31,12 +32,13 @@ export const ManageForm = (props: ManageFormProps) => {
canManageOwnership,
canSetClosingDate,
id,
closedDetails,
} = props;

if (!canManageOwnership) {
return (
<>
{canSetClosingDate && <SetClosingDate formID={id} />}
{canSetClosingDate && <SetClosingDate formId={id} closedDetails={closedDetails} />}
<DownloadForm />
</>
);
Expand All @@ -48,7 +50,7 @@ export const ManageForm = (props: ManageFormProps) => {

return (
<>
{canSetClosingDate && <SetClosingDate formID={id} />}
{canSetClosingDate && <SetClosingDate formId={id} closedDetails={closedDetails} />}
<FormOwnership
nonce={nonce}
formRecord={formRecord}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { useTranslation } from "@i18n/client";
import { ClosedDetails } from "@lib/types";
import { Editor } from "@formBuilder/[id]/edit/components/elements/lexical-editor/Editor";
import { LanguageLabel } from "@formBuilder/components/shared/LanguageLabel";
import { useRehydrate } from "@lib/store/useTemplateStore";
import Skeleton from "react-loading-skeleton";
import React from "react";

type ClosedMessageProps = {
closedDetails?: ClosedDetails;
setClosedDetails: (details: ClosedDetails) => void;
};

export const ClosedMessage = ({ closedDetails, setClosedDetails }: ClosedMessageProps) => {
const { t } = useTranslation("form-builder");
const hasHydrated = useRehydrate();

if (!hasHydrated) {
// Don't show the rich text editor until the form has been hydrated
return (
<div className="flex">
<div className="relative w-1/2 border-1 border-r-4 border-gray-100 border-r-black">
<div className="p-8">
<Skeleton className="w-full" count={3} />
</div>
</div>
<div className="relative w-1/2 border-1 border-gray-100">
<div className="p-8">
<Skeleton className="w-full" count={3} />
</div>
</div>
</div>
);
}

return (
<>
<p className="mb-2 font-bold">{t("closingDate.message.title")}</p>
<p className="mb-4">{t("closingDate.message.text1")}</p>
<div className="flex">
<div className="relative w-1/2 border-1 border-r-4 border-gray-100 border-r-black">
<label className="sr-only" htmlFor={`closed-en`}>
{t("english")}
</label>
<LanguageLabel id="form-introduction-english-language" lang={"en"}>
<>{t("english")}</>
</LanguageLabel>
<Editor
id="closed-en"
lang="en"
content={closedDetails && closedDetails.messageEn ? closedDetails.messageEn : ""}
onChange={(value: string) => {
setClosedDetails({ ...closedDetails, messageEn: value });
}}
/>
</div>

<div className="relative w-1/2 border-1 border-gray-100">
<label className="sr-only" htmlFor={`closed-fr`}>
{t("french")}
</label>

<LanguageLabel id="form-introduction-english-language" lang={"fr"}>
<>{t("french")}</>
</LanguageLabel>
<Editor
id="closed-fr"
lang="fr"
content={closedDetails && closedDetails.messageFr ? closedDetails.messageFr : ""}
onChange={(value: string) => setClosedDetails({ ...closedDetails, messageFr: value })}
/>
</div>
</div>
</>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { useTranslation } from "@i18n/client";

export const ClosedSuccess = () => {
const { t } = useTranslation("form-builder");
return (
<div className="w-full">
<h3 className="!mb-0 pb-0 text-xl font-semibold">
{t("closingDate.formClosedSuccessMessage.title")}
</h3>
<p className="mb-2 text-black">{t("closingDate.formClosedSuccessMessage.body")}</p>
</div>
);
};
Loading

0 comments on commit 2670aa8

Please sign in to comment.