From dffadb47d0328b0ce28f08fefb5198ed6b8ac4b0 Mon Sep 17 00:00:00 2001 From: Xc165543337 <90028194+Xc165543337@users.noreply.github.com> Date: Fri, 12 Apr 2024 15:20:08 +0200 Subject: [PATCH] feat: habit stop use case --- domain/entities/Habit.ts | 4 +- domain/use-cases/HabitStop.ts | 24 ++++++++++++ infrastructure/instances.ts | 5 +++ .../supabase/repositories/HabitEdit.ts | 5 +++ presentation/presenters/HabitsTracker.ts | 37 ++++++++++++++++++- .../HabitEditForm/HabitEditForm.tsx | 14 ++++++- .../components/HabitsMainPage/HabitsList.tsx | 28 +++++++++----- 7 files changed, 103 insertions(+), 14 deletions(-) create mode 100644 domain/use-cases/HabitStop.ts diff --git a/domain/entities/Habit.ts b/domain/entities/Habit.ts index d80ba59..539dfde 100644 --- a/domain/entities/Habit.ts +++ b/domain/entities/Habit.ts @@ -8,6 +8,7 @@ export const HabitSchema = EntitySchema.extend({ name: z.string().min(1).max(50), color: z.string().min(4).max(9).regex(/^#/), icon: z.string().min(1), + endDate: z.date().optional(), }) export const HabitCreateSchema = HabitSchema.extend({ @@ -29,7 +30,6 @@ export interface HabitData extends HabitBase { export interface HabitJSON extends HabitBase { goal: GoalBaseJSON startDate: string - endDate?: string } export class Habit extends Entity implements HabitData { @@ -62,7 +62,7 @@ export class Habit extends Entity implements HabitData { icon: this.icon, goal: this.goal, startDate: this.startDate.toISOString(), - endDate: this.endDate?.toISOString(), + endDate: this?.endDate, } } } diff --git a/domain/use-cases/HabitStop.ts b/domain/use-cases/HabitStop.ts new file mode 100644 index 0000000..e71ef53 --- /dev/null +++ b/domain/use-cases/HabitStop.ts @@ -0,0 +1,24 @@ +import type { Habit } from "../entities/Habit" +import type { HabitEditRepository } from "../repositories/HabitEdit" + +export interface HabitStopUseCaseDependencyOptions { + habitEditRepository: HabitEditRepository +} + +export class HabitStopUseCase implements HabitStopUseCaseDependencyOptions { + public habitEditRepository: HabitEditRepository + + public constructor(options: HabitStopUseCaseDependencyOptions) { + this.habitEditRepository = options.habitEditRepository + } + + public async execute(habitToStop: Habit): Promise { + const habit = await this.habitEditRepository.execute({ + habitEditData: { + ...habitToStop, + endDate: new Date(), + }, + }) + return habit + } +} diff --git a/infrastructure/instances.ts b/infrastructure/instances.ts index c7f7c25..abf3fb7 100644 --- a/infrastructure/instances.ts +++ b/infrastructure/instances.ts @@ -13,6 +13,7 @@ import { HabitEditUseCase } from "@/domain/use-cases/HabitEdit" import { HabitProgressCreateSupabaseRepository } from "./supabase/repositories/HabitProgressCreate" import { HabitProgressUpdateSupabaseRepository } from "./supabase/repositories/HabitProgressUpdate" import { HabitGoalProgressUpdateUseCase } from "@/domain/use-cases/HabitGoalProgressUpdate" +import { HabitStopUseCase } from "@/domain/use-cases/HabitStop" /** * Repositories @@ -64,6 +65,9 @@ const habitGoalProgressUpdateUseCase = new HabitGoalProgressUpdateUseCase({ habitProgressCreateRepository, habitProgressUpdateRepository, }) +const habitStopUseCase = new HabitStopUseCase({ + habitEditRepository, +}) /** * Presenters @@ -75,5 +79,6 @@ export const habitsTrackerPresenter = new HabitsTrackerPresenter({ retrieveHabitsTrackerUseCase, habitCreateUseCase, habitEditUseCase, + habitStopUseCase, habitGoalProgressUpdateUseCase, }) diff --git a/infrastructure/supabase/repositories/HabitEdit.ts b/infrastructure/supabase/repositories/HabitEdit.ts index f482cc3..4938707 100644 --- a/infrastructure/supabase/repositories/HabitEdit.ts +++ b/infrastructure/supabase/repositories/HabitEdit.ts @@ -15,6 +15,7 @@ export class HabitEditSupabaseRepository name: habitEditData.name, color: habitEditData.color, icon: habitEditData.icon, + end_date: habitEditData?.endDate?.toISOString(), }) .eq("id", habitEditData.id) .select("*") @@ -43,6 +44,10 @@ export class HabitEditSupabaseRepository }), color: updatedHabit.color, startDate: new Date(updatedHabit.start_date), + endDate: + updatedHabit.end_date != null + ? new Date(updatedHabit.end_date) + : undefined, }) return habit } diff --git a/presentation/presenters/HabitsTracker.ts b/presentation/presenters/HabitsTracker.ts index 264d533..1abd125 100644 --- a/presentation/presenters/HabitsTracker.ts +++ b/presentation/presenters/HabitsTracker.ts @@ -7,10 +7,15 @@ import type { RetrieveHabitsTrackerUseCase, RetrieveHabitsTrackerUseCaseOptions, } from "@/domain/use-cases/RetrieveHabitsTracker" -import type { HabitCreateData, HabitEditData } from "@/domain/entities/Habit" +import type { + Habit, + HabitCreateData, + HabitEditData, +} from "@/domain/entities/Habit" import { getErrorsFieldsFromZodError } from "../../utils/zod" import type { HabitCreateUseCase } from "@/domain/use-cases/HabitCreate" import type { HabitEditUseCase } from "@/domain/use-cases/HabitEdit" +import type { HabitStopUseCase } from "@/domain/use-cases/HabitStop" import type { HabitGoalProgressUpdateUseCase, HabitGoalProgressUpdateUseCaseOptions, @@ -39,6 +44,10 @@ export interface HabitsTrackerPresenterState { } } + habitStop: { + state: FetchState + } + habitGoalProgressUpdate: { state: FetchState } @@ -48,6 +57,7 @@ export interface HabitsTrackerPresenterOptions { retrieveHabitsTrackerUseCase: RetrieveHabitsTrackerUseCase habitCreateUseCase: HabitCreateUseCase habitEditUseCase: HabitEditUseCase + habitStopUseCase: HabitStopUseCase habitGoalProgressUpdateUseCase: HabitGoalProgressUpdateUseCase } @@ -58,6 +68,7 @@ export class HabitsTrackerPresenter public retrieveHabitsTrackerUseCase: RetrieveHabitsTrackerUseCase public habitCreateUseCase: HabitCreateUseCase public habitEditUseCase: HabitEditUseCase + public habitStopUseCase: HabitStopUseCase public habitGoalProgressUpdateUseCase: HabitGoalProgressUpdateUseCase public constructor(options: HabitsTrackerPresenterOptions) { @@ -65,6 +76,7 @@ export class HabitsTrackerPresenter retrieveHabitsTrackerUseCase, habitCreateUseCase, habitEditUseCase, + habitStopUseCase, habitGoalProgressUpdateUseCase, } = options const habitsTracker = HabitsTracker.default() @@ -85,6 +97,9 @@ export class HabitsTrackerPresenter global: null, }, }, + habitStop: { + state: "idle", + }, habitGoalProgressUpdate: { state: "idle", }, @@ -92,6 +107,7 @@ export class HabitsTrackerPresenter this.retrieveHabitsTrackerUseCase = retrieveHabitsTrackerUseCase this.habitCreateUseCase = habitCreateUseCase this.habitEditUseCase = habitEditUseCase + this.habitStopUseCase = habitStopUseCase this.habitGoalProgressUpdateUseCase = habitGoalProgressUpdateUseCase } @@ -153,6 +169,25 @@ export class HabitsTrackerPresenter } } + public async habitStop(habitToStop: Habit): Promise { + try { + this.setState((state) => { + state.habitStop.state = "loading" + }) + const habit = await this.habitStopUseCase.execute(habitToStop) + this.setState((state) => { + state.habitStop.state = "success" + state.habitsTracker.editHabit(habit) + }) + return "success" + } catch (error) { + this.setState((state) => { + state.habitStop.state = "error" + }) + return "error" + } + } + public async retrieveHabitsTracker( options: RetrieveHabitsTrackerUseCaseOptions, ): Promise { diff --git a/presentation/react/components/HabitEditForm/HabitEditForm.tsx b/presentation/react/components/HabitEditForm/HabitEditForm.tsx index be69d7f..bb2ab6e 100644 --- a/presentation/react/components/HabitEditForm/HabitEditForm.tsx +++ b/presentation/react/components/HabitEditForm/HabitEditForm.tsx @@ -19,7 +19,7 @@ export interface HabitEditFormProps { } export const HabitEditForm: React.FC = ({ habit }) => { - const { habitEdit, habitsTrackerPresenter } = useHabitsTracker() + const { habitEdit, habitStop, habitsTrackerPresenter } = useHabitsTracker() const { control, @@ -134,6 +134,18 @@ export const HabitEditForm: React.FC = ({ habit }) => { > Save + + = (props) => { }, ]} > - {habitsTracker.habitsHistory[frequency].map((item) => { - return ( - - ) - })} + {habitsTracker.habitsHistory[frequency] + .filter((habitItem) => { + return ( + (habitItem.habit.endDate != null && + habitItem.habit.endDate <= selectedDate) || + habitItem.habit.endDate == null + ) + }) + .map((item) => { + return ( + + ) + })} ) })}