= ({
type="number"
/>
+
+ ),
+ })}
+ disabled={isSubmitting}
+ fullWidth
+ inputProps={{ min: 0, step: 1 }}
+ label="Autostop reminder (hours)"
+ type="number"
+ />
+
{
+ const canvas = within(canvasElement);
+ const user = userEvent.setup();
+
+ const reminderField = await canvas.findByLabelText(
+ "Autostop reminder (hours)",
+ );
+
+ await user.clear(reminderField);
+ await user.type(reminderField, "2");
+
+ const submitButton = canvas.getByRole("button", { name: /save/i });
+ await user.click(submitButton);
+
+ await waitFor(() => {
+ expect(args.onSubmit).toHaveBeenCalledWith(
+ expect.objectContaining({
+ time_til_autostop_notify_ms: 2 * 60 * 60 * 1000,
+ }),
+ );
+ });
+ },
+};
+
+export const SubmitClearsAutostopReminder: Story = {
+ args: {
+ ...defaultArgs,
+ template: {
+ ...MockTemplate,
+ // Start with a non-zero autostop reminder so we can verify
+ // it gets cleared to 0 when the field is emptied.
+ time_til_autostop_notify_ms: 2 * 60 * 60 * 1000,
+ },
+ onSubmit: fn(),
+ },
+ play: async ({ canvasElement, args }) => {
+ const canvas = within(canvasElement);
+ const user = userEvent.setup();
+
+ const reminderField = await canvas.findByLabelText(
+ "Autostop reminder (hours)",
+ );
+
+ await user.clear(reminderField);
+ await user.type(reminderField, "0");
+
+ const submitButton = canvas.getByRole("button", { name: /save/i });
+ await user.click(submitButton);
+
+ await waitFor(() => {
+ expect(args.onSubmit).toHaveBeenCalledWith(
+ expect.objectContaining({
+ time_til_autostop_notify_ms: 0,
+ }),
+ );
+ });
+ },
+};
diff --git a/site/src/pages/TemplateSettingsPage/TemplateSchedulePage/formHelpers.tsx b/site/src/pages/TemplateSettingsPage/TemplateSchedulePage/formHelpers.tsx
index f948e1dd1d..e5b5399dec 100644
--- a/site/src/pages/TemplateSettingsPage/TemplateSchedulePage/formHelpers.tsx
+++ b/site/src/pages/TemplateSettingsPage/TemplateSchedulePage/formHelpers.tsx
@@ -38,6 +38,14 @@ export const getValidationSchema = (): Yup.AnyObjectSchema =>
24 * MAX_TTL_DAYS /* 30 days in hours */,
"Please enter an activity bump duration that is less than or equal to 720 hours (30 days).",
),
+ time_til_autostop_notify_ms: Yup.number()
+ .integer("Autostop reminder must be an integer.")
+ .required()
+ .min(0, "Autostop reminder must not be less than 0.")
+ .max(
+ 24 * MAX_TTL_DAYS /* 30 days in hours */,
+ "Autostop reminder must not exceed 720 hours (30 days).",
+ ),
failure_ttl_ms: Yup.number()
.integer("Failure cleanup days must be an integer.")
.required()