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; -}