mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 15:27:27 +00:00
feat: Secret reminder from date filter (#4289)
* feat: add fromDate in reminders * feat: update reminder form * fix: lint * chore: generate schema * fix: reminder logic * fix: update ui * fix: pr change --------- Co-authored-by: sidwebworks <[email protected]>
This commit is contained in:
@@ -0,0 +1,19 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
if (!(await knex.schema.hasColumn(TableName.Reminder, "fromDate"))) {
|
||||||
|
await knex.schema.alterTable(TableName.Reminder, (t) => {
|
||||||
|
t.timestamp("fromDate", { useTz: true }).nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
if (await knex.schema.hasColumn(TableName.Reminder, "fromDate")) {
|
||||||
|
await knex.schema.alterTable(TableName.Reminder, (t) => {
|
||||||
|
t.dropColumn("fromDate");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,7 +14,8 @@ export const RemindersSchema = z.object({
|
|||||||
repeatDays: z.number().nullable().optional(),
|
repeatDays: z.number().nullable().optional(),
|
||||||
nextReminderDate: z.date(),
|
nextReminderDate: z.date(),
|
||||||
createdAt: z.date(),
|
createdAt: z.date(),
|
||||||
updatedAt: z.date()
|
updatedAt: z.date(),
|
||||||
|
fromDate: z.date().nullable().optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
export type TReminders = z.infer<typeof RemindersSchema>;
|
export type TReminders = z.infer<typeof RemindersSchema>;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ export const registerSecretReminderRouter = async (server: FastifyZodProvider) =
|
|||||||
message: z.string().trim().max(1024).optional(),
|
message: z.string().trim().max(1024).optional(),
|
||||||
repeatDays: z.number().min(1).nullable().optional(),
|
repeatDays: z.number().min(1).nullable().optional(),
|
||||||
nextReminderDate: z.string().datetime().nullable().optional(),
|
nextReminderDate: z.string().datetime().nullable().optional(),
|
||||||
|
fromDate: z.string().datetime().nullable().optional(),
|
||||||
recipients: z.string().array().optional()
|
recipients: z.string().array().optional()
|
||||||
})
|
})
|
||||||
.refine((data) => {
|
.refine((data) => {
|
||||||
@@ -45,6 +46,7 @@ export const registerSecretReminderRouter = async (server: FastifyZodProvider) =
|
|||||||
message: req.body.message,
|
message: req.body.message,
|
||||||
repeatDays: req.body.repeatDays,
|
repeatDays: req.body.repeatDays,
|
||||||
nextReminderDate: req.body.nextReminderDate,
|
nextReminderDate: req.body.nextReminderDate,
|
||||||
|
fromDate: req.body.fromDate,
|
||||||
recipients: req.body.recipients
|
recipients: req.body.recipients
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -79,25 +79,33 @@ export const reminderServiceFactory = ({
|
|||||||
repeatDays,
|
repeatDays,
|
||||||
nextReminderDate: nextReminderDateInput,
|
nextReminderDate: nextReminderDateInput,
|
||||||
recipients,
|
recipients,
|
||||||
projectId
|
projectId,
|
||||||
|
fromDate: fromDateInput
|
||||||
}: {
|
}: {
|
||||||
secretId?: string;
|
secretId?: string;
|
||||||
message?: string | null;
|
message?: string | null;
|
||||||
repeatDays?: number | null;
|
repeatDays?: number | null;
|
||||||
nextReminderDate?: string | null;
|
nextReminderDate?: string | null;
|
||||||
recipients?: string[] | null;
|
recipients?: string[] | null;
|
||||||
|
fromDate?: string | null;
|
||||||
projectId: string;
|
projectId: string;
|
||||||
}) => {
|
}) => {
|
||||||
if (!secretId) {
|
if (!secretId) {
|
||||||
throw new BadRequestError({ message: "secretId is required" });
|
throw new BadRequestError({ message: "secretId is required" });
|
||||||
}
|
}
|
||||||
let nextReminderDate;
|
let nextReminderDate;
|
||||||
|
let fromDate;
|
||||||
if (nextReminderDateInput) {
|
if (nextReminderDateInput) {
|
||||||
nextReminderDate = new Date(nextReminderDateInput);
|
nextReminderDate = new Date(nextReminderDateInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (repeatDays && repeatDays > 0) {
|
if (repeatDays) {
|
||||||
nextReminderDate = $addDays(repeatDays);
|
if (fromDateInput) {
|
||||||
|
fromDate = new Date(fromDateInput);
|
||||||
|
nextReminderDate = fromDate;
|
||||||
|
} else {
|
||||||
|
nextReminderDate = $addDays(repeatDays);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!nextReminderDate) {
|
if (!nextReminderDate) {
|
||||||
@@ -112,7 +120,8 @@ export const reminderServiceFactory = ({
|
|||||||
await reminderDAL.updateById(existingReminder.id, {
|
await reminderDAL.updateById(existingReminder.id, {
|
||||||
message,
|
message,
|
||||||
repeatDays,
|
repeatDays,
|
||||||
nextReminderDate
|
nextReminderDate,
|
||||||
|
fromDate
|
||||||
});
|
});
|
||||||
reminderId = existingReminder.id;
|
reminderId = existingReminder.id;
|
||||||
} else {
|
} else {
|
||||||
@@ -121,7 +130,8 @@ export const reminderServiceFactory = ({
|
|||||||
secretId,
|
secretId,
|
||||||
message,
|
message,
|
||||||
repeatDays,
|
repeatDays,
|
||||||
nextReminderDate
|
nextReminderDate,
|
||||||
|
fromDate
|
||||||
});
|
});
|
||||||
reminderId = newReminder.id;
|
reminderId = newReminder.id;
|
||||||
}
|
}
|
||||||
@@ -280,14 +290,28 @@ export const reminderServiceFactory = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const processedReminders = remindersData.map(
|
const processedReminders = remindersData.map(
|
||||||
({ secretId, message, repeatDays, nextReminderDate: nextReminderDateInput, recipients, projectId }) => {
|
({
|
||||||
|
secretId,
|
||||||
|
message,
|
||||||
|
repeatDays,
|
||||||
|
nextReminderDate: nextReminderDateInput,
|
||||||
|
recipients,
|
||||||
|
projectId,
|
||||||
|
fromDate: fromDateInput
|
||||||
|
}) => {
|
||||||
let nextReminderDate;
|
let nextReminderDate;
|
||||||
|
let fromDate;
|
||||||
if (nextReminderDateInput) {
|
if (nextReminderDateInput) {
|
||||||
nextReminderDate = new Date(nextReminderDateInput);
|
nextReminderDate = new Date(nextReminderDateInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (repeatDays && repeatDays > 0 && !nextReminderDate) {
|
if (repeatDays && !nextReminderDate) {
|
||||||
nextReminderDate = $addDays(repeatDays);
|
if (fromDateInput) {
|
||||||
|
fromDate = new Date(fromDateInput);
|
||||||
|
nextReminderDate = fromDate;
|
||||||
|
} else {
|
||||||
|
nextReminderDate = $addDays(repeatDays);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!nextReminderDate) {
|
if (!nextReminderDate) {
|
||||||
@@ -302,17 +326,19 @@ export const reminderServiceFactory = ({
|
|||||||
repeatDays,
|
repeatDays,
|
||||||
nextReminderDate,
|
nextReminderDate,
|
||||||
recipients: recipients ? [...new Set(recipients)] : [],
|
recipients: recipients ? [...new Set(recipients)] : [],
|
||||||
projectId
|
projectId,
|
||||||
|
fromDate
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const newReminders = await reminderDAL.insertMany(
|
const newReminders = await reminderDAL.insertMany(
|
||||||
processedReminders.map(({ secretId, message, repeatDays, nextReminderDate }) => ({
|
processedReminders.map(({ secretId, message, repeatDays, nextReminderDate, fromDate }) => ({
|
||||||
secretId,
|
secretId,
|
||||||
message,
|
message,
|
||||||
repeatDays,
|
repeatDays,
|
||||||
nextReminderDate
|
nextReminderDate,
|
||||||
|
fromDate
|
||||||
})),
|
})),
|
||||||
tx
|
tx
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ export type TReminder = {
|
|||||||
message?: string | null;
|
message?: string | null;
|
||||||
repeatDays?: number | null;
|
repeatDays?: number | null;
|
||||||
nextReminderDate: Date;
|
nextReminderDate: Date;
|
||||||
|
fromDate?: Date | null;
|
||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
updatedAt: Date;
|
updatedAt: Date;
|
||||||
};
|
};
|
||||||
@@ -21,6 +22,7 @@ export type TCreateReminderDTO = {
|
|||||||
secretId?: string;
|
secretId?: string;
|
||||||
message?: string | null;
|
message?: string | null;
|
||||||
repeatDays?: number | null;
|
repeatDays?: number | null;
|
||||||
|
fromDate?: string | null;
|
||||||
nextReminderDate?: string | null;
|
nextReminderDate?: string | null;
|
||||||
recipients?: string[] | null;
|
recipients?: string[] | null;
|
||||||
};
|
};
|
||||||
@@ -31,6 +33,7 @@ export type TBatchCreateReminderDTO = {
|
|||||||
message?: string | null;
|
message?: string | null;
|
||||||
repeatDays?: number | null;
|
repeatDays?: number | null;
|
||||||
nextReminderDate?: string | Date | null;
|
nextReminderDate?: string | Date | null;
|
||||||
|
fromDate?: Date | null;
|
||||||
recipients?: string[] | null;
|
recipients?: string[] | null;
|
||||||
projectId?: string;
|
projectId?: string;
|
||||||
}[];
|
}[];
|
||||||
@@ -95,6 +98,7 @@ export interface TReminderServiceFactory {
|
|||||||
nextReminderDate?: string | null;
|
nextReminderDate?: string | null;
|
||||||
recipients?: string[] | null;
|
recipients?: string[] | null;
|
||||||
projectId: string;
|
projectId: string;
|
||||||
|
fromDate?: string | null;
|
||||||
}) => Promise<{
|
}) => Promise<{
|
||||||
id: string;
|
id: string;
|
||||||
created: boolean;
|
created: boolean;
|
||||||
|
|||||||
@@ -12,14 +12,15 @@ export const useCreateReminder = (secretId: string) => {
|
|||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
return useMutation<Reminder, object, CreateReminderDTO>({
|
return useMutation<Reminder, object, CreateReminderDTO>({
|
||||||
mutationFn: async ({ message, repeatDays, nextReminderDate, recipients }) => {
|
mutationFn: async ({ message, repeatDays, nextReminderDate, recipients, fromDate }) => {
|
||||||
const { data } = await apiRequest.post<{ reminder: Reminder }>(
|
const { data } = await apiRequest.post<{ reminder: Reminder }>(
|
||||||
`/api/v1/reminders/secrets/${secretId}`,
|
`/api/v1/reminders/secrets/${secretId}`,
|
||||||
{
|
{
|
||||||
message,
|
message,
|
||||||
repeatDays,
|
repeatDays,
|
||||||
nextReminderDate,
|
nextReminderDate,
|
||||||
recipients
|
recipients,
|
||||||
|
fromDate
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
return data.reminder;
|
return data.reminder;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ export type CreateReminderDTO = {
|
|||||||
message?: string | null;
|
message?: string | null;
|
||||||
repeatDays?: number | null;
|
repeatDays?: number | null;
|
||||||
nextReminderDate?: Date | null;
|
nextReminderDate?: Date | null;
|
||||||
|
fromDate?: Date | null;
|
||||||
secretId: string;
|
secretId: string;
|
||||||
recipients?: string[];
|
recipients?: string[];
|
||||||
};
|
};
|
||||||
|
|||||||
+79
-36
@@ -4,6 +4,7 @@ import { faClock, faTrash } from "@fortawesome/free-solid-svg-icons";
|
|||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { useQueryClient } from "@tanstack/react-query";
|
import { useQueryClient } from "@tanstack/react-query";
|
||||||
|
import { format } from "date-fns";
|
||||||
import { twMerge } from "tailwind-merge";
|
import { twMerge } from "tailwind-merge";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
@@ -33,6 +34,7 @@ const MIN_REPEAT_DAYS = 1;
|
|||||||
const MAX_REPEAT_DAYS = 365;
|
const MAX_REPEAT_DAYS = 365;
|
||||||
const DEFAULT_REPEAT_DAYS = 30;
|
const DEFAULT_REPEAT_DAYS = 30;
|
||||||
const DEFAULT_TEXTAREA_ROWS = 8;
|
const DEFAULT_TEXTAREA_ROWS = 8;
|
||||||
|
const ONE_DAY_IN_MILLIS = 86400000;
|
||||||
|
|
||||||
// Enums
|
// Enums
|
||||||
enum ReminderType {
|
enum ReminderType {
|
||||||
@@ -79,6 +81,11 @@ const ReminderFormSchema = z.object({
|
|||||||
.refine((data) => data > new Date(), { message: "Reminder date must be in the future" })
|
.refine((data) => data > new Date(), { message: "Reminder date must be in the future" })
|
||||||
.nullable()
|
.nullable()
|
||||||
.optional(),
|
.optional(),
|
||||||
|
fromDate: z.coerce
|
||||||
|
.date()
|
||||||
|
.refine((data) => data > new Date(), { message: "From date must be in the future" })
|
||||||
|
.nullable()
|
||||||
|
.optional(),
|
||||||
reminderType: z.enum(["Recurring", "One Time"])
|
reminderType: z.enum(["Recurring", "One Time"])
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -86,7 +93,7 @@ export type TReminderFormSchema = z.infer<typeof ReminderFormSchema>;
|
|||||||
|
|
||||||
// Custom hook for form state management
|
// Custom hook for form state management
|
||||||
const useReminderForm = (reminderData?: Reminder) => {
|
const useReminderForm = (reminderData?: Reminder) => {
|
||||||
const { repeatDays, message, nextReminderDate } = reminderData || {};
|
const { repeatDays, message, nextReminderDate, fromDate } = reminderData || {};
|
||||||
|
|
||||||
const isEditMode = Boolean(reminderData);
|
const isEditMode = Boolean(reminderData);
|
||||||
|
|
||||||
@@ -96,9 +103,10 @@ const useReminderForm = (reminderData?: Reminder) => {
|
|||||||
message: message || "",
|
message: message || "",
|
||||||
nextReminderDate: nextReminderDate || null,
|
nextReminderDate: nextReminderDate || null,
|
||||||
reminderType: repeatDays ? ReminderType.Recurring : ReminderType.OneTime,
|
reminderType: repeatDays ? ReminderType.Recurring : ReminderType.OneTime,
|
||||||
recipients: []
|
recipients: [],
|
||||||
|
fromDate
|
||||||
}),
|
}),
|
||||||
[repeatDays, message, nextReminderDate]
|
[repeatDays, message, nextReminderDate, fromDate]
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -153,7 +161,8 @@ export const CreateReminderForm = ({
|
|||||||
message: reminderData?.message || "",
|
message: reminderData?.message || "",
|
||||||
nextReminderDate: reminderData?.nextReminderDate || null,
|
nextReminderDate: reminderData?.nextReminderDate || null,
|
||||||
reminderType: reminderData?.repeatDays ? ReminderType.Recurring : ReminderType.OneTime,
|
reminderType: reminderData?.repeatDays ? ReminderType.Recurring : ReminderType.OneTime,
|
||||||
recipients: []
|
recipients: [],
|
||||||
|
fromDate: reminderData?.fromDate
|
||||||
},
|
},
|
||||||
resolver: zodResolver(ReminderFormSchema)
|
resolver: zodResolver(ReminderFormSchema)
|
||||||
});
|
});
|
||||||
@@ -170,6 +179,7 @@ export const CreateReminderForm = ({
|
|||||||
|
|
||||||
// Watch form values
|
// Watch form values
|
||||||
const reminderType = watch("reminderType");
|
const reminderType = watch("reminderType");
|
||||||
|
const fromDate = watch("fromDate");
|
||||||
|
|
||||||
// Invalidate queries helper
|
// Invalidate queries helper
|
||||||
const invalidateQueries = () => {
|
const invalidateQueries = () => {
|
||||||
@@ -195,7 +205,8 @@ export const CreateReminderForm = ({
|
|||||||
message: data.message,
|
message: data.message,
|
||||||
recipients: data.recipients?.map((r) => r.value) || [],
|
recipients: data.recipients?.map((r) => r.value) || [],
|
||||||
secretId,
|
secretId,
|
||||||
nextReminderDate: data.nextReminderDate
|
nextReminderDate: data.nextReminderDate,
|
||||||
|
fromDate: data.fromDate
|
||||||
});
|
});
|
||||||
|
|
||||||
invalidateQueries();
|
invalidateQueries();
|
||||||
@@ -243,6 +254,7 @@ export const CreateReminderForm = ({
|
|||||||
if (newType === ReminderType.Recurring) {
|
if (newType === ReminderType.Recurring) {
|
||||||
setValue("repeatDays", DEFAULT_REPEAT_DAYS);
|
setValue("repeatDays", DEFAULT_REPEAT_DAYS);
|
||||||
setValue("nextReminderDate", null);
|
setValue("nextReminderDate", null);
|
||||||
|
setValue("fromDate", null);
|
||||||
} else if (newType === ReminderType.OneTime) {
|
} else if (newType === ReminderType.OneTime) {
|
||||||
const tomorrow = new Date();
|
const tomorrow = new Date();
|
||||||
tomorrow.setDate(tomorrow.getDate() + 1);
|
tomorrow.setDate(tomorrow.getDate() + 1);
|
||||||
@@ -259,6 +271,7 @@ export const CreateReminderForm = ({
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
repeatDays: repeatDaysInitial,
|
repeatDays: repeatDaysInitial,
|
||||||
|
fromDate: fromDateInitial,
|
||||||
message,
|
message,
|
||||||
recipients,
|
recipients,
|
||||||
nextReminderDate: nextReminderDateInitial
|
nextReminderDate: nextReminderDateInitial
|
||||||
@@ -266,6 +279,7 @@ export const CreateReminderForm = ({
|
|||||||
|
|
||||||
if (repeatDaysInitial) {
|
if (repeatDaysInitial) {
|
||||||
setValue("repeatDays", repeatDaysInitial);
|
setValue("repeatDays", repeatDaysInitial);
|
||||||
|
setValue("fromDate", fromDateInitial);
|
||||||
setValue("reminderType", ReminderType.Recurring);
|
setValue("reminderType", ReminderType.Recurring);
|
||||||
} else {
|
} else {
|
||||||
setValue("reminderType", ReminderType.OneTime);
|
setValue("reminderType", ReminderType.OneTime);
|
||||||
@@ -323,44 +337,73 @@ export const CreateReminderForm = ({
|
|||||||
|
|
||||||
{/* Conditional Fields Based on Reminder Type */}
|
{/* Conditional Fields Based on Reminder Type */}
|
||||||
{reminderType === ReminderType.Recurring ? (
|
{reminderType === ReminderType.Recurring ? (
|
||||||
<Controller
|
<div className="grid grid-cols-[1fr,auto] gap-x-2">
|
||||||
control={control}
|
<Controller
|
||||||
name="repeatDays"
|
control={control}
|
||||||
render={({ field, fieldState }) => (
|
name="repeatDays"
|
||||||
<div>
|
render={({ field, fieldState }) => (
|
||||||
|
<div>
|
||||||
|
<FormControl
|
||||||
|
isRequired
|
||||||
|
className="mb-0"
|
||||||
|
label="Reminder Interval (in days)"
|
||||||
|
isError={Boolean(fieldState.error)}
|
||||||
|
errorText={fieldState.error?.message || ""}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
onChange={(el) => {
|
||||||
|
const value = parseInt(el.target.value, 10);
|
||||||
|
setValue("repeatDays", Number.isNaN(value) ? null : value);
|
||||||
|
}}
|
||||||
|
type="number"
|
||||||
|
placeholder={DEFAULT_REPEAT_DAYS.toString()}
|
||||||
|
value={field.value || ""}
|
||||||
|
min={MIN_REPEAT_DAYS}
|
||||||
|
max={MAX_REPEAT_DAYS}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
{/* Interval description */}
|
||||||
|
<div
|
||||||
|
className={twMerge(
|
||||||
|
"ml-1 mt-2 text-xs",
|
||||||
|
field.value ? "opacity-60" : "opacity-0"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
A reminder will be sent every{" "}
|
||||||
|
{field.value && field.value > 1 ? `${field.value} days` : "day"}
|
||||||
|
{fromDate ? ` starting from ${format(fromDate, "MM/dd/yy")}` : ""}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="fromDate"
|
||||||
|
render={({ field, fieldState }) => (
|
||||||
<FormControl
|
<FormControl
|
||||||
isRequired
|
|
||||||
className="mb-0"
|
className="mb-0"
|
||||||
label="Reminder Interval (in days)"
|
label="Start Date"
|
||||||
|
tooltipText="When enabled, this date will be used as the start date for the first reminder"
|
||||||
isError={Boolean(fieldState.error)}
|
isError={Boolean(fieldState.error)}
|
||||||
errorText={fieldState.error?.message || ""}
|
errorText={fieldState.error?.message || ""}
|
||||||
>
|
>
|
||||||
<Input
|
<DatePicker
|
||||||
onChange={(el) => {
|
value={field.value || undefined}
|
||||||
const value = parseInt(el.target.value, 10);
|
className="w-full"
|
||||||
setValue("repeatDays", Number.isNaN(value) ? null : value);
|
onChange={field.onChange}
|
||||||
|
dateFormat="P"
|
||||||
|
popUpProps={{
|
||||||
|
open: isDatePickerOpen,
|
||||||
|
onOpenChange: setIsDatePickerOpen
|
||||||
}}
|
}}
|
||||||
type="number"
|
popUpContentProps={{}}
|
||||||
placeholder={DEFAULT_REPEAT_DAYS.toString()}
|
hideTime
|
||||||
value={field.value || ""}
|
hidden={{ before: new Date(Date.now() + ONE_DAY_IN_MILLIS) }}
|
||||||
min={MIN_REPEAT_DAYS}
|
|
||||||
max={MAX_REPEAT_DAYS}
|
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
)}
|
||||||
{/* Interval description */}
|
/>
|
||||||
<div
|
</div>
|
||||||
className={twMerge(
|
|
||||||
"ml-1 mt-2 text-xs",
|
|
||||||
field.value ? "opacity-60" : "opacity-0"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
A reminder will be sent every{" "}
|
|
||||||
{field.value && field.value > 1 ? `${field.value} days` : "day"}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
) : (
|
) : (
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
@@ -385,7 +428,7 @@ export const CreateReminderForm = ({
|
|||||||
}}
|
}}
|
||||||
popUpContentProps={{}}
|
popUpContentProps={{}}
|
||||||
hideTime
|
hideTime
|
||||||
hidden={{ before: new Date(Date.now() + 86400000) }}
|
hidden={{ before: new Date(Date.now() + ONE_DAY_IN_MILLIS) }}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user