diff --git a/.github/workflows/cron-reportUsageToStripe.yml b/.github/workflows/cron-reportUsageToStripe.yml
index 62a50b5fae..15892818a2 100644
--- a/.github/workflows/cron-reportUsageToStripe.yml
+++ b/.github/workflows/cron-reportUsageToStripe.yml
@@ -1,4 +1,4 @@
-name: Cron - reportUsageToStripe
+name: Cron - Report usage to Stripe
on:
# "Scheduled workflows run on the latest commit on the default or base branch."
diff --git a/.github/workflows/cron-closeOnDate.yml b/.github/workflows/cron-surveyStatusUpdate.yml
similarity index 87%
rename from .github/workflows/cron-closeOnDate.yml
rename to .github/workflows/cron-surveyStatusUpdate.yml
index dadfda8e01..95d40fb894 100644
--- a/.github/workflows/cron-closeOnDate.yml
+++ b/.github/workflows/cron-surveyStatusUpdate.yml
@@ -1,4 +1,4 @@
-name: Cron - closeOnDate
+name: Cron - Survey status update
on:
# "Scheduled workflows run on the latest commit on the default or base branch."
@@ -16,7 +16,7 @@ jobs:
- name: cURL request
if: ${{ env.APP_URL && env.CRON_SECRET }}
run: |
- curl ${{ env.APP_URL }}/api/cron/close_surveys \
+ curl ${{ env.APP_URL }}/api/cron/survey-status \
-X POST \
-H 'content-type: application/json' \
-H 'x-api-key: ${{ env.CRON_SECRET }}' \
diff --git a/.github/workflows/cron-weeklySummary.yml b/.github/workflows/cron-weeklySummary.yml
index 0014ff40b2..975128849a 100644
--- a/.github/workflows/cron-weeklySummary.yml
+++ b/.github/workflows/cron-weeklySummary.yml
@@ -1,4 +1,4 @@
-name: Cron - weeklySummary
+name: Cron - Weekly summary
on:
# "Scheduled workflows run on the latest commit on the default or base branch."
@@ -16,7 +16,7 @@ jobs:
- name: cURL request
if: ${{ env.APP_URL && env.CRON_SECRET }}
run: |
- curl ${{ env.APP_URL }}/api/cron/weekly_summary \
+ curl ${{ env.APP_URL }}/api/cron/weekly-summary \
-X POST \
-H 'content-type: application/json' \
-H 'x-api-key: ${{ env.CRON_SECRET }}' \
diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/SummaryHeader.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/SummaryHeader.tsx
index 6fb88a08d8..74957fd8e4 100644
--- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/SummaryHeader.tsx
+++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/SummaryHeader.tsx
@@ -119,6 +119,7 @@ const SummaryHeader = ({
)}
+ {survey.status === "scheduled" && "Scheduled"}
{survey.status === "inProgress" && "In-progress"}
{survey.status === "paused" && "Paused"}
{survey.status === "completed" && "Completed"}
diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/SurveyStatusDropdown.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/SurveyStatusDropdown.tsx
index 002b82893c..eb24167eb1 100644
--- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/SurveyStatusDropdown.tsx
+++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/SurveyStatusDropdown.tsx
@@ -10,18 +10,22 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@
import { SurveyStatusIndicator } from "@formbricks/ui/SurveyStatusIndicator";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@formbricks/ui/Tooltip";
+interface SurveyStatusDropdownProps {
+ environment: TEnvironment;
+ updateLocalSurveyStatus?: (status: TSurvey["status"]) => void;
+ survey: TSurvey;
+}
+
export default function SurveyStatusDropdown({
environment,
updateLocalSurveyStatus,
survey,
-}: {
- environment: TEnvironment;
- updateLocalSurveyStatus?: (status: "draft" | "inProgress" | "paused" | "completed" | "archived") => void;
- survey: TSurvey;
-}) {
+}: SurveyStatusDropdownProps) {
const isCloseOnDateEnabled = survey.closeOnDate !== null;
const closeOnDate = survey.closeOnDate ? new Date(survey.closeOnDate) : null;
- const isStatusChangeDisabled = (isCloseOnDateEnabled && closeOnDate && closeOnDate < new Date()) ?? false;
+ const isStatusChangeDisabled =
+ (survey.status === "scheduled" || (isCloseOnDateEnabled && closeOnDate && closeOnDate < new Date())) ??
+ false;
return (
<>
@@ -34,7 +38,7 @@ export default function SurveyStatusDropdown({
value={survey.status}
disabled={isStatusChangeDisabled}
onValueChange={(value) => {
- const castedValue = value as "draft" | "inProgress" | "paused" | "completed";
+ const castedValue = value as TSurvey["status"];
updateSurveyAction({ ...survey, status: castedValue })
.then(() => {
toast.success(
@@ -51,8 +55,7 @@ export default function SurveyStatusDropdown({
toast.error(`Error: ${error.message}`);
});
- if (updateLocalSurveyStatus)
- updateLocalSurveyStatus(value as "draft" | "inProgress" | "paused" | "completed" | "archived");
+ if (updateLocalSurveyStatus) updateLocalSurveyStatus(value as TSurvey["status"]);
}}>
@@ -64,6 +67,7 @@ export default function SurveyStatusDropdown({
)}
+ {survey.status === "scheduled" && "Scheduled"}
{survey.status === "inProgress" && "In-progress"}
{survey.status === "paused" && "Paused"}
{survey.status === "completed" && "Completed"}
@@ -88,8 +92,8 @@ export default function SurveyStatusDropdown({
- To update the survey status, update the “Close
- survey on date” setting in the Response Options.
+ To update the survey status, update the schedule and close setting in the survey response
+ options.
diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/edit/components/ResponseOptionsCard.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/edit/components/ResponseOptionsCard.tsx
index 364fa3746d..c3e57f2dff 100644
--- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/edit/components/ResponseOptionsCard.tsx
+++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/edit/components/ResponseOptionsCard.tsx
@@ -1,7 +1,8 @@
"use client";
import * as Collapsible from "@radix-ui/react-collapsible";
-import { CheckIcon } from "lucide-react";
+import { ArrowUpRight, CheckIcon } from "lucide-react";
+import Link from "next/link";
import { KeyboardEventHandler, useEffect, useState } from "react";
import toast from "react-hot-toast";
@@ -27,7 +28,8 @@ export default function ResponseOptionsCard({
const [open, setOpen] = useState(localSurvey.type === "link" ? true : false);
const autoComplete = localSurvey.autoComplete !== null;
const [redirectToggle, setRedirectToggle] = useState(false);
- const [surveyCloseOnDateToggle, setSurveyCloseOnDateToggle] = useState(false);
+ const [runOnDateToggle, setRunOnDateToggle] = useState(false);
+ const [closeOnDateToggle, setCloseOnDateToggle] = useState(false);
useState;
const [redirectUrl, setRedirectUrl] = useState("");
const [surveyClosedMessageToggle, setSurveyClosedMessageToggle] = useState(false);
@@ -48,7 +50,8 @@ export default function ResponseOptionsCard({
name: "",
subheading: "",
});
- const [closeOnDate, setCloseOnDate] = useState();
+ const [runOnDate, setRunOnDate] = useState(null);
+ const [closeOnDate, setCloseOnDate] = useState(null);
const isPinProtectionEnabled = localSurvey.pin !== null;
@@ -63,19 +66,28 @@ export default function ResponseOptionsCard({
}
};
- const handleSurveyCloseOnDateToggle = () => {
- if (surveyCloseOnDateToggle && localSurvey.closeOnDate) {
- setSurveyCloseOnDateToggle(false);
- setCloseOnDate(undefined);
- setLocalSurvey({ ...localSurvey, closeOnDate: null });
- return;
+ const handleRunOnDateToggle = () => {
+ if (runOnDateToggle) {
+ setRunOnDateToggle(false);
+ if (localSurvey.runOnDate) {
+ setRunOnDate(null);
+ setLocalSurvey({ ...localSurvey, runOnDate: null });
+ }
+ } else {
+ setRunOnDateToggle(true);
}
+ };
- if (surveyCloseOnDateToggle) {
- setSurveyCloseOnDateToggle(false);
- return;
+ const handleCloseOnDateToggle = () => {
+ if (closeOnDateToggle) {
+ setCloseOnDateToggle(false);
+ if (localSurvey.closeOnDate) {
+ setCloseOnDate(null);
+ setLocalSurvey({ ...localSurvey, closeOnDate: null });
+ }
+ } else {
+ setCloseOnDateToggle(true);
}
- setSurveyCloseOnDateToggle(true);
};
const handleProtectSurveyWithPinToggle = () => {
@@ -126,6 +138,15 @@ export default function ResponseOptionsCard({
}
};
+ const handleRunOnDateChange = (date: Date) => {
+ const equivalentDate = date?.getDate();
+ date?.setUTCHours(0, 0, 0, 0);
+ date?.setDate(equivalentDate);
+
+ setRunOnDate(date);
+ setLocalSurvey({ ...localSurvey, runOnDate: date ?? null });
+ };
+
const handleCloseOnDateChange = (date: Date) => {
const equivalentDate = date?.getDate();
date?.setUTCHours(0, 0, 0, 0);
@@ -143,7 +164,7 @@ export default function ResponseOptionsCard({
subheading?: string;
}) => {
const message = {
- enabled: surveyCloseOnDateToggle,
+ enabled: closeOnDateToggle,
heading: heading ?? surveyClosedMessage.heading,
subheading: subheading ?? surveyClosedMessage.subheading,
};
@@ -245,9 +266,14 @@ export default function ResponseOptionsCard({
setVerifyEmailToggle(true);
}
+ if (localSurvey.runOnDate) {
+ setRunOnDate(localSurvey.runOnDate);
+ setRunOnDateToggle(true);
+ }
+
if (localSurvey.closeOnDate) {
setCloseOnDate(localSurvey.closeOnDate);
- setSurveyCloseOnDateToggle(true);
+ setCloseOnDateToggle(true);
}
}, [
localSurvey,
@@ -318,7 +344,7 @@ export default function ResponseOptionsCard({
description="Automatically close the survey after a certain number of responses."
childBorder={true}>
+ {/* Run Survey on Date */}
+
+
+
+
+
{/* Close Survey on Date */}
-
-
- Automatically mark survey as complete on:
-
+
@@ -356,22 +391,17 @@ export default function ResponseOptionsCard({
isChecked={redirectToggle}
onToggle={handleRedirectCheckMark}
title="Redirect on completion"
- description="Redirect user to specified link on survey completion"
+ description="Redirect user to link destination when they completed the survey"
childBorder={true}>
-
-
- Redirect respondents here:
-
- handleRedirectUrlChange(e.target.value)}
- />
-
+ handleRedirectUrlChange(e.target.value)}
+ />
@@ -427,7 +457,15 @@ export default function ResponseOptionsCard({
Blocks survey if the survey URL has no Single Use Id (suId).
- Blocks survey if a submission with the Single Use Id (suId) in the URL exists already.
+ Blocks survey if a submission with the Single Use Id (suId) exists already.
+
+
+
+ Docs
+
@@ -479,7 +517,7 @@ export default function ResponseOptionsCard({
childBorder={true}>
-
How it works
+
Respondants will receive the survey link via email.
@@ -513,25 +551,25 @@ export default function ResponseOptionsCard({
title="Protect survey with a PIN"
description="Only users who have the PIN can access the survey."
childBorder={true}>
-