diff --git a/blotztask-mobile/src/feature/calendar/components/task-card.tsx b/blotztask-mobile/src/feature/calendar/components/task-card.tsx
index d64361fc4..06915d312 100644
--- a/blotztask-mobile/src/feature/calendar/components/task-card.tsx
+++ b/blotztask-mobile/src/feature/calendar/components/task-card.tsx
@@ -21,6 +21,7 @@ import { SubtaskProgressBar } from "./subtask-progress-bar";
import SubtaskList from "./subtask-list";
import { TaskCardRightActions } from "./task-card-right-actions";
import { TaskCardLeftActions } from "./task-card-left-actions";
+import { theme } from "@/shared/constants/theme";
// Props
interface TaskCardProps {
@@ -41,7 +42,6 @@ const TaskCard = ({ task, deleteTask, isDeleting, selectedDay, onOpenMode }: Tas
const { breakDownAndReplaceSubtasks, isBreakingDownAndReplacingSubtasks } = useSubtaskMutations();
// Derived values
- const labelColor = task.label?.color ?? "#D1D1D6";
const hasSubtasks = !!task.subtasks?.length;
const timePeriod = formatDateRange({
startTime: task.startTime,
@@ -139,7 +139,10 @@ const TaskCard = ({ task, deleteTask, isDeleting, selectedDay, onOpenMode }: Tas
/>
{/* Vertical label colour bar */}
-
+
{/* DDL Tag */}
{task.isDeadline && (
diff --git a/blotztask-mobile/src/feature/monthly-calendar/components/day-detail-panel.tsx b/blotztask-mobile/src/feature/monthly-calendar/components/day-detail-panel.tsx
index 574281e55..a6bd12a66 100644
--- a/blotztask-mobile/src/feature/monthly-calendar/components/day-detail-panel.tsx
+++ b/blotztask-mobile/src/feature/monthly-calendar/components/day-detail-panel.tsx
@@ -59,7 +59,7 @@ export const SelectedDayDetailPanel = ({ selectedDay }: { selectedDay: Date }) =
{/* Column 3: Title */}
-
+
{task.title}
diff --git a/blotztask-mobile/src/feature/task-add-edit/components/deadline-section.tsx b/blotztask-mobile/src/feature/task-add-edit/components/deadline-section.tsx
index cb9ea3c52..a9261f1b2 100644
--- a/blotztask-mobile/src/feature/task-add-edit/components/deadline-section.tsx
+++ b/blotztask-mobile/src/feature/task-add-edit/components/deadline-section.tsx
@@ -148,7 +148,7 @@ export const DeadlineSection = ({ control, getValues, isActiveTab }: DeadlineSec
deadlineDate={deadlineDate ? format(deadlineDate, "yyyy-MM-dd") : undefined}
eventStartDate={startDate ? format(startDate, "yyyy-MM-dd") : undefined}
eventEndDate={
- isActiveTab === "event" && endDate
+ isActiveTab === SegmentButtonValue.Event && endDate
? format(endDate, "yyyy-MM-dd")
: startDate
? format(startDate, "yyyy-MM-dd")
diff --git a/blotztask-mobile/src/feature/task-add-edit/components/event-tab.tsx b/blotztask-mobile/src/feature/task-add-edit/components/event-tab.tsx
index 7fa023a8e..005b7b7dc 100644
--- a/blotztask-mobile/src/feature/task-add-edit/components/event-tab.tsx
+++ b/blotztask-mobile/src/feature/task-add-edit/components/event-tab.tsx
@@ -8,38 +8,17 @@ import {
isAfter,
isSameDay,
isBefore,
- isEqual,
} from "date-fns";
import { zhCN, enUS } from "date-fns/locale";
-import { Control, UseFormClearErrors, UseFormTrigger, useController } from "react-hook-form";
+import { Control, FieldPath, useController } from "react-hook-form";
import { TaskFormField } from "../models/task-form-schema";
import TimePicker from "./time-picker";
import DoubleDatesCalendar from "./double-dates-calendar";
import { useTranslation } from "react-i18next";
import Animated from "react-native-reanimated";
import { MotionAnimations } from "@/shared/constants/animations/motion";
-import { combineDateTime } from "../util/combine-date-time";
-export const EventTab = ({
- control,
- trigger,
- clearErrors,
- setValue,
-}: {
- control: Control;
- trigger?: UseFormTrigger;
- clearErrors?: UseFormClearErrors;
- setValue: (name: keyof TaskFormField, value: any) => void;
-}) => {
- const validateRange = (sd: Date, st: Date, ed: Date, et: Date) => {
- const start = combineDateTime(sd, st);
- const end = combineDateTime(ed, et);
- if (start && end && (isBefore(start, end) || isEqual(start, end))) {
- clearErrors?.("endTime");
- } else {
- trigger?.("endTime");
- }
- };
+export const EventTab = ({ control }: { control: Control }) => {
const { t, i18n } = useTranslation("tasks");
const isChinese = i18n.language === "zh";
const locale = isChinese ? zhCN : enUS;
@@ -48,67 +27,27 @@ export const EventTab = ({
"startDate" | "startTime" | "endDate" | "endTime" | null
>(null);
- const {
- field: { value: startDateValue, onChange: startDateOnChange },
- } = useController({
- control,
- name: "startDate",
- });
-
- const {
- field: { value: startTimeValue, onChange: startTimeOnChange },
- } = useController({
- control,
- name: "startTime",
- });
-
- const {
- field: { value: endDateValue, onChange: endDateOnChange },
- } = useController({
- control,
- name: "endDate",
- });
-
- const {
- field: { value: endTimeValue, onChange: endTimeOnChange },
- } = useController({
- control,
- name: "endTime",
- });
-
- const {
- field: { value: deadlineDate },
- } = useController({
- control,
- name: "deadlineDate",
- });
+ const useField = >(name: T) =>
+ useController({ control, name }).field;
- const {
- field: { value: isDdl },
- } = useController({
- control,
- name: "isDeadline",
- });
+ const { value: startDateValue, onChange: startDateOnChange } = useField("startDate");
+ const { value: startTimeValue, onChange: startTimeOnChange } = useField("startTime");
+ const { value: endDateValue, onChange: endDateOnChange } = useField("endDate");
+ const { value: endTimeValue, onChange: endTimeOnChange } = useField("endTime");
+ const { value: deadlineDate } = useField("deadlineDate");
+ const { value: isDdl } = useField("isDeadline");
const ddlStr = isDdl && deadlineDate ? format(deadlineDate, "yyyy-MM-dd") : undefined;
const handleStartDateChange = (nextDate: Date) => {
- const previousSpan =
- startDateValue && endDateValue
- ? Math.max(differenceInCalendarDays(endDateValue, startDateValue), 0)
- : 0;
-
startDateOnChange(nextDate);
- const nextEndDate =
- endDateValue && isAfter(nextDate, endDateValue)
- ? addDays(nextDate, previousSpan)
- : endDateValue;
if (endDateValue && isAfter(nextDate, endDateValue)) {
+ const previousSpan =
+ startDateValue ? Math.max(differenceInCalendarDays(endDateValue, startDateValue), 0) : 0;
+ const nextEndDate = addDays(nextDate, previousSpan);
endDateOnChange(nextEndDate);
}
-
- validateRange(nextDate, startTimeValue, nextEndDate, endTimeValue);
};
const isDateInvalid =
@@ -235,10 +174,7 @@ export const EventTab = ({
startDate={startDateValue}
endDate={endDateValue}
deadlineDate={ddlStr}
- setEndDate={(v: Date) => {
- endDateOnChange(v);
- validateRange(startDateValue, startTimeValue, v, endTimeValue);
- }}
+ setEndDate={(v: Date) => endDateOnChange(v)}
current={format(
activeSelector === "endDate"
? (endDateValue ?? startDateValue ?? new Date())
@@ -255,10 +191,7 @@ export const EventTab = ({
>
{
- endTimeOnChange(v);
- validateRange(startDateValue, startTimeValue, endDateValue, v);
- }}
+ onChange={(v: Date) => endTimeOnChange(v)}
/>
)}
diff --git a/blotztask-mobile/src/feature/task-add-edit/components/segment-toggle.tsx b/blotztask-mobile/src/feature/task-add-edit/components/segment-toggle.tsx
index b0116d4b4..c22a48a6c 100644
--- a/blotztask-mobile/src/feature/task-add-edit/components/segment-toggle.tsx
+++ b/blotztask-mobile/src/feature/task-add-edit/components/segment-toggle.tsx
@@ -14,12 +14,12 @@ const AnimatedPressable = Animated.createAnimatedComponent(Pressable);
export function SegmentToggle({ value, setValue }: Props) {
const { t } = useTranslation("tasks");
- const tabPositionX = useSharedValue(value === "reminder" ? 0 : 224 / 2);
+ const tabPositionX = useSharedValue(value === SegmentButtonValue.Reminder ? 0 : 224 / 2);
const [containerWidth, setContainerWidth] = React.useState(224);
const isInitialMount = React.useRef(true);
React.useEffect(() => {
if (containerWidth > 0) {
- onTabMovingAnimation(value === "reminder" ? 0 : 1, !isInitialMount.current);
+ onTabMovingAnimation(value === SegmentButtonValue.Reminder ? 0 : 1, !isInitialMount.current);
isInitialMount.current = false;
}
}, [value, containerWidth]);
@@ -47,13 +47,13 @@ export function SegmentToggle({ value, setValue }: Props) {
{
- setValue("reminder");
+ setValue(SegmentButtonValue.Reminder);
onTabMovingAnimation(0);
}}
>
{t("form.reminder")}
@@ -64,13 +64,13 @@ export function SegmentToggle({ value, setValue }: Props) {
{
- setValue("event");
+ setValue(SegmentButtonValue.Event);
onTabMovingAnimation(1);
}}
>
{t("form.event")}
diff --git a/blotztask-mobile/src/feature/task-add-edit/models/segment-button-value.ts b/blotztask-mobile/src/feature/task-add-edit/models/segment-button-value.ts
index a2d3cf872..7c6a63e05 100644
--- a/blotztask-mobile/src/feature/task-add-edit/models/segment-button-value.ts
+++ b/blotztask-mobile/src/feature/task-add-edit/models/segment-button-value.ts
@@ -1 +1,4 @@
-export type SegmentButtonValue = "reminder" | "event";
+export enum SegmentButtonValue {
+ Reminder = "reminder",
+ Event = "event",
+}
diff --git a/blotztask-mobile/src/feature/task-add-edit/models/task-form-schema.ts b/blotztask-mobile/src/feature/task-add-edit/models/task-form-schema.ts
index 752a80de4..32804a581 100644
--- a/blotztask-mobile/src/feature/task-add-edit/models/task-form-schema.ts
+++ b/blotztask-mobile/src/feature/task-add-edit/models/task-form-schema.ts
@@ -17,8 +17,8 @@ export const taskFormSchema = z
labelId: z.number().nullable(),
alert: z.number().nullable(),
isDeadline: z.boolean(),
- deadlineDate: z.date(),
- deadlineTime: z.date(),
+ deadlineDate: z.date().nullable(),
+ deadlineTime: z.date().nullable(),
})
.refine(
(data) => {
diff --git a/blotztask-mobile/src/feature/task-add-edit/task-form.tsx b/blotztask-mobile/src/feature/task-add-edit/task-form.tsx
index a8c8a4f8f..d0ff95c88 100644
--- a/blotztask-mobile/src/feature/task-add-edit/task-form.tsx
+++ b/blotztask-mobile/src/feature/task-add-edit/task-form.tsx
@@ -13,15 +13,11 @@ import { useAllLabels } from "@/shared/hooks/useAllLabels";
import { EventTab } from "./components/event-tab";
import { AlertSelect } from "./components/alert-select";
import { DeadlineSection } from "./components/deadline-section";
-import { createNotificationFromAlert } from "./util/create-notification-from-alert";
-import {
- buildTaskTimePayload,
- calculateAlertSeconds,
- calculateAlertTime,
-} from "./util/time-convertion";
+import { getTaskFormDefaults } from "./util/get-task-form-defaults";
+import { getTaskNotification } from "./util/get-task-notification";
+import { buildTaskTimePayload, calculateAlertTime } from "./util/time-convertion";
import { combineDateTime } from "./util/combine-date-time";
import { TaskUpsertDTO } from "@/shared/models/task-upsert-dto";
-import { cancelNotification } from "@/shared/util/cancel-notification";
import { convertToDateTimeOffset } from "@/shared/util/convert-to-datetimeoffset";
import { useUserPreferencesQuery } from "../settings/hooks/useUserPreferencesQuery";
import LoadingScreen from "@/shared/components/loading-screen";
@@ -29,98 +25,58 @@ import { useTranslation } from "react-i18next";
import Animated from "react-native-reanimated";
import { MotionAnimations } from "@/shared/constants/animations/motion";
import { theme } from "@/shared/constants/theme";
+import { addHours } from "date-fns";
-type TaskFormProps =
- | {
- mode: "create";
- dto?: undefined;
- onSubmit: (data: TaskUpsertDTO) => void;
- }
- | {
- mode: "edit";
- dto: TaskUpsertDTO;
- onSubmit: (data: TaskUpsertDTO) => void;
- };
+export type TaskFormProps = {
+ onSubmit: (data: TaskUpsertDTO) => void;
+} & ({ mode: "create"; dto?: undefined } | { mode: "edit"; dto: TaskUpsertDTO });
const TaskForm = ({ mode, dto, onSubmit }: TaskFormProps) => {
- const hasEventTimes =
- dto?.timeType === 1 || (dto?.startTime && dto?.endTime && dto.startTime !== dto.endTime);
- const initialTab: SegmentButtonValue = mode === "edit" && hasEventTimes ? "event" : "reminder";
+ // Queries
const { userPreferences, isUserPreferencesLoading } = useUserPreferencesQuery();
- const { t } = useTranslation("tasks");
-
- const [isActiveTab, setIsActiveTab] = useState(initialTab);
-
const { labels = [], isLoading } = useAllLabels();
+ const { t } = useTranslation("tasks");
- const initialAlertTime = calculateAlertSeconds(dto?.startTime, dto?.alertTime);
-
- const defaultAlert = userPreferences?.upcomingNotification
- ? (initialAlertTime ?? 300)
- : (initialAlertTime ?? null);
-
- const now = new Date();
- const oneHourLater = new Date(now.getTime() + 3600000);
- const initialDueAt = dto?.dueAt ? new Date(dto.dueAt) : null;
-
- const initialStartDate = dto?.startTime ? new Date(dto.startTime) : now;
- const initialStartTime = dto?.startTime ? new Date(dto.startTime) : now;
- const initialEndDate = dto?.endTime ? new Date(dto.endTime) : oneHourLater;
- const initialEndTime = dto?.endTime ? new Date(dto.endTime) : oneHourLater;
+ // Derived values
+ const { initialTab, defaultValues } = getTaskFormDefaults({
+ dto,
+ allowNotification: userPreferences?.upcomingNotification,
+ });
- const defaultValues: TaskFormField = {
- title: dto?.title ?? "",
- description: dto?.description ?? "",
- labelId: dto?.labelId ?? null,
- startDate: initialStartDate,
- startTime: initialStartTime,
- endDate: initialTab === "reminder" ? initialStartDate : initialEndDate,
- endTime: initialTab === "reminder" ? initialStartTime : initialEndTime,
- alert: defaultAlert,
- isDeadline: dto?.isDeadline ?? !!initialDueAt,
- deadlineDate: initialDueAt ?? oneHourLater,
- deadlineTime: initialDueAt ?? oneHourLater,
- };
+ const [isActiveTab, setIsActiveTab] = useState(initialTab);
+ // Form
const form = useForm({
resolver: zodResolver(taskFormSchema),
mode: "onChange",
- defaultValues: defaultValues,
+ defaultValues,
});
- const { handleSubmit, formState, control, setValue, clearErrors, trigger, getValues } = form;
+ const { handleSubmit, formState, control, setValue, clearErrors, getValues } = form;
const { isSubmitting } = formState;
if (isUserPreferencesLoading) {
return ;
}
+ // Handlers
const handleFormSubmit = async (data: TaskFormField) => {
- // If editing and the existing alert is still scheduled in the future, cancel the old notification first
- if (mode === "edit" && dto?.alertTime && new Date(dto?.alertTime) > new Date()) {
- await cancelNotification({
- notificationId: dto?.notificationId,
- });
- }
-
+ const isReminderTab = isActiveTab === SegmentButtonValue.Reminder;
const { startTime, endTime, timeType } = buildTaskTimePayload(
data.startDate,
data.startTime,
- isActiveTab === "reminder" ? data.startDate : data.endDate,
- isActiveTab === "reminder" ? data.startTime : data.endTime,
+ isReminderTab ? data.startDate : data.endDate,
+ isReminderTab ? data.startTime : data.endTime,
);
- let notificationId: string | null = null;
- let alertTime = undefined;
- if (userPreferences?.upcomingNotification) {
- notificationId =
- (await createNotificationFromAlert({
- startTime,
- alert: data.alert,
- title: data.title,
- })) ?? null;
- alertTime = calculateAlertTime(startTime!, data.alert);
- }
+ const newAlertTime = calculateAlertTime(startTime!, data.alert);
+ const notificationId = await getTaskNotification({
+ mode,
+ dto,
+ upcomingNotification: userPreferences?.upcomingNotification,
+ newAlertTime,
+ newTaskTitle: data.title,
+ });
const deadline = data.isDeadline ? combineDateTime(data.deadlineDate, data.deadlineTime) : null;
@@ -131,7 +87,7 @@ const TaskForm = ({ mode, dto, onSubmit }: TaskFormProps) => {
endTime: convertToDateTimeOffset(endTime!),
labelId: data.labelId ?? undefined,
timeType,
- alertTime: alertTime ? convertToDateTimeOffset(alertTime) : undefined,
+ alertTime: notificationId && newAlertTime ? convertToDateTimeOffset(newAlertTime) : undefined,
notificationId,
isDeadline: data.isDeadline,
dueAt: deadline ? convertToDateTimeOffset(deadline) : undefined,
@@ -141,26 +97,25 @@ const TaskForm = ({ mode, dto, onSubmit }: TaskFormProps) => {
};
const handleTabChange = (next: SegmentButtonValue) => {
- setIsActiveTab(next);
- clearErrors(["endDate", "endTime"]);
-
const startDate = getValues("startDate");
const startTime = getValues("startTime");
- if (next === "reminder") {
+ setIsActiveTab(next);
+ clearErrors(["endDate", "endTime"]);
+
+ if (next === SegmentButtonValue.Reminder) {
setValue("endDate", startDate, { shouldValidate: false });
setValue("endTime", startTime, { shouldValidate: false });
clearErrors(["endDate", "endTime"]);
return;
}
- const start = new Date();
- const oneHourLater = new Date(start.getTime() + 3600000);
- setValue("startDate", start);
- setValue("startTime", start);
- setValue("endDate", oneHourLater);
- setValue("endTime", oneHourLater);
- trigger("endTime");
+ const oneHourLater = addHours(new Date(), 1);
+ const twoHoursLater = addHours(new Date(), 2);
+ setValue("startDate", oneHourLater);
+ setValue("startTime", oneHourLater);
+ setValue("endDate", twoHoursLater);
+ setValue("endTime", twoHoursLater);
};
return (
@@ -204,21 +159,16 @@ const TaskForm = ({ mode, dto, onSubmit }: TaskFormProps) => {
- {isActiveTab === "event" && formState.errors.endTime && (
+ {isActiveTab === SegmentButtonValue.Event && formState.errors.endTime && (
{t(formState.errors.endTime.message || "")}
)}
- {isActiveTab === "reminder" && (
+ {isActiveTab === SegmentButtonValue.Reminder && (
)}
- {isActiveTab === "event" && (
-
+ {isActiveTab === SegmentButtonValue.Event && (
+
)}
diff --git a/blotztask-mobile/src/feature/task-add-edit/util/create-notification-from-alert.ts b/blotztask-mobile/src/feature/task-add-edit/util/create-notification-from-alert.ts
deleted file mode 100644
index 4aa20d5e1..000000000
--- a/blotztask-mobile/src/feature/task-add-edit/util/create-notification-from-alert.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import { NotificationTaskDTO } from "@/shared/models/notification-task-dto";
-import { scheduleTaskReminder } from "@/shared/util/schedule-task-reminder";
-
-export async function createNotificationFromAlert({
- startTime,
- alert,
- title,
-}: {
- startTime?: Date | null;
- alert?: number | null;
- title: string;
-}) {
- if (!startTime || alert == null) {
- return null;
- }
- const notificationTime = new Date(startTime.getTime() - alert * 1000);
-
- if (notificationTime <= new Date()) {
- return null;
- }
-
- const notificationTask: NotificationTaskDTO = {
- title: title,
- alertTime: notificationTime,
- };
-
- try {
- const notificationId = await scheduleTaskReminder(notificationTask);
- return notificationId;
- } catch {
- return null;
- }
-}
diff --git a/blotztask-mobile/src/feature/task-add-edit/util/get-task-form-defaults.ts b/blotztask-mobile/src/feature/task-add-edit/util/get-task-form-defaults.ts
new file mode 100644
index 000000000..77fb6f7af
--- /dev/null
+++ b/blotztask-mobile/src/feature/task-add-edit/util/get-task-form-defaults.ts
@@ -0,0 +1,68 @@
+import { addHours } from "date-fns";
+import type { TaskUpsertDTO } from "@/shared/models/task-upsert-dto";
+import { SegmentButtonValue } from "../models/segment-button-value";
+import type { TaskFormField } from "../models/task-form-schema";
+import { calculateAlertSeconds } from "./time-convertion";
+import { TaskTimeType } from "@/shared/models/base-task-dto";
+
+type GetTaskFormDefaultsParams = {
+ dto?: TaskUpsertDTO;
+ allowNotification?: boolean;
+};
+
+type TaskFormDefaults = {
+ initialTab: SegmentButtonValue;
+ defaultValues: TaskFormField;
+};
+
+export const getTaskFormDefaults = ({
+ dto,
+ allowNotification,
+}: GetTaskFormDefaultsParams): TaskFormDefaults => {
+ const now = new Date();
+ const oneHourLater = addHours(now, 1);
+ const twoHoursLater = addHours(now, 2);
+
+ // default values for creating a new task
+ if (!dto) {
+ return {
+ initialTab: SegmentButtonValue.Reminder,
+ defaultValues: {
+ title: "",
+ description: "",
+ labelId: null,
+ startDate: oneHourLater,
+ startTime: oneHourLater,
+ endDate: twoHoursLater,
+ endTime: twoHoursLater,
+ alert: allowNotification ? 300 : null,
+ isDeadline: false,
+ deadlineDate: null,
+ deadlineTime: null,
+ },
+ };
+ }
+
+ const dueAt = dto.dueAt ? new Date(dto.dueAt) : null;
+ const isEvent = dto.timeType === TaskTimeType.Range;
+
+ const initialAlert = calculateAlertSeconds(dto.startTime, dto.alertTime);
+ const defaultAlert = initialAlert ?? (allowNotification ? 300 : null);
+ // default values for editing an existing task
+ return {
+ initialTab: isEvent ? SegmentButtonValue.Event : SegmentButtonValue.Reminder,
+ defaultValues: {
+ title: dto.title,
+ description: dto.description ?? "",
+ labelId: dto.labelId ?? null,
+ startDate: new Date(dto.startTime),
+ startTime: new Date(dto.startTime),
+ endDate: new Date(dto.endTime),
+ endTime: new Date(dto.endTime),
+ alert: defaultAlert,
+ isDeadline: dto.isDeadline,
+ deadlineDate: dueAt,
+ deadlineTime: dueAt,
+ },
+ };
+};
diff --git a/blotztask-mobile/src/feature/task-add-edit/util/get-task-notification.ts b/blotztask-mobile/src/feature/task-add-edit/util/get-task-notification.ts
new file mode 100644
index 000000000..436e8b739
--- /dev/null
+++ b/blotztask-mobile/src/feature/task-add-edit/util/get-task-notification.ts
@@ -0,0 +1,54 @@
+import { TaskUpsertDTO } from "@/shared/models/task-upsert-dto";
+import { cancelNotification } from "@/shared/util/cancel-notification";
+import * as Notifications from "expo-notifications";
+
+export const getTaskNotification = async ({
+ mode,
+ dto,
+ upcomingNotification,
+ newAlertTime,
+ newTaskTitle,
+}: {
+ mode: "create" | "edit";
+ dto?: TaskUpsertDTO;
+ upcomingNotification?: boolean;
+ newAlertTime: Date | null;
+ newTaskTitle: string;
+}): Promise => {
+ // Replace the old scheduled notification before creating a new one during edits.
+ if (mode === "edit" && dto?.alertTime && new Date(dto.alertTime) > new Date()) {
+ await cancelNotification({
+ notificationId: dto.notificationId,
+ });
+ }
+
+ if (!upcomingNotification || !newAlertTime || newAlertTime <= new Date()) {
+ return null;
+ }
+
+ return scheduleTaskReminder({ newTaskTitle, alertTime: newAlertTime });
+};
+
+async function scheduleTaskReminder({
+ newTaskTitle,
+ alertTime,
+}: {
+ newTaskTitle: string;
+ alertTime: Date;
+}): Promise {
+ try {
+ return await Notifications.scheduleNotificationAsync({
+ content: {
+ title: "⏰ Task Reminder",
+ body: newTaskTitle,
+ categoryIdentifier: "task-reminder",
+ },
+ trigger: {
+ type: Notifications.SchedulableTriggerInputTypes.DATE,
+ date: alertTime,
+ },
+ });
+ } catch {
+ return null;
+ }
+}
diff --git a/blotztask-mobile/src/shared/models/base-task-dto.ts b/blotztask-mobile/src/shared/models/base-task-dto.ts
index 434d3a159..d28c053d7 100644
--- a/blotztask-mobile/src/shared/models/base-task-dto.ts
+++ b/blotztask-mobile/src/shared/models/base-task-dto.ts
@@ -1,6 +1,6 @@
export enum TaskTimeType {
- Single = 0,
- Range = 1,
+ Single = "SingleTime",
+ Range = "RangeTime",
}
export interface BaseTaskDTO {
@@ -8,7 +8,7 @@ export interface BaseTaskDTO {
startTime: string;
endTime: string;
description?: string;
- timeType: TaskTimeType | null;
+ timeType: TaskTimeType;
notificationId: string | null;
alertTime?: string;
isDeadline: boolean;
diff --git a/blotztask-mobile/src/shared/models/notification-task-dto.ts b/blotztask-mobile/src/shared/models/notification-task-dto.ts
deleted file mode 100644
index 571d9e3ff..000000000
--- a/blotztask-mobile/src/shared/models/notification-task-dto.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface NotificationTaskDTO {
- title: string;
- alertTime: Date;
-}
diff --git a/blotztask-mobile/src/shared/util/schedule-task-reminder.ts b/blotztask-mobile/src/shared/util/schedule-task-reminder.ts
deleted file mode 100644
index 2bcde346d..000000000
--- a/blotztask-mobile/src/shared/util/schedule-task-reminder.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import * as Notifications from "expo-notifications";
-import { NotificationTaskDTO } from "../models/notification-task-dto";
-import uuid from "react-native-uuid";
-
-export async function scheduleTaskReminder(task: NotificationTaskDTO) {
- if (!task.alertTime) return;
-
- const notificationId = await Notifications.scheduleNotificationAsync({
- content: {
- title: "⏰ Task Reminder",
- body: task.title,
- data: {
- id: uuid.v4().toString(),
- },
- categoryIdentifier: "task-reminder",
- },
-
- trigger: {
- type: Notifications.SchedulableTriggerInputTypes.DATE,
- date: new Date(task.alertTime),
- },
- });
-
- return notificationId;
-}