This repository has been archived on 2024-11-20. You can view files and clone it, but cannot push or open issues or pull requests.
p61-project/presentation/presenters/HabitsTracker.ts

234 lines
6.4 KiB
TypeScript
Raw Normal View History

2024-04-05 00:08:40 +02:00
import { ZodError } from "zod"
2024-03-16 00:36:44 +01:00
import { HabitsTracker } from "@/domain/entities/HabitsTracker"
2024-04-05 00:08:40 +02:00
import type { ErrorGlobal, FetchState } from "./_Presenter"
2024-03-15 22:48:28 +01:00
import { Presenter } from "./_Presenter"
import type {
RetrieveHabitsTrackerUseCase,
RetrieveHabitsTrackerUseCaseOptions,
2024-03-16 00:36:44 +01:00
} from "@/domain/use-cases/RetrieveHabitsTracker"
2024-04-12 15:20:08 +02:00
import type {
Habit,
HabitCreateData,
HabitEditData,
} from "@/domain/entities/Habit"
import { getErrorsFieldsFromZodError } from "../../utils/zod"
2024-04-05 00:08:40 +02:00
import type { HabitCreateUseCase } from "@/domain/use-cases/HabitCreate"
2024-04-11 13:07:17 +02:00
import type { HabitEditUseCase } from "@/domain/use-cases/HabitEdit"
2024-04-12 15:20:08 +02:00
import type { HabitStopUseCase } from "@/domain/use-cases/HabitStop"
2024-04-11 23:03:45 +02:00
import type {
HabitGoalProgressUpdateUseCase,
HabitGoalProgressUpdateUseCaseOptions,
} from "@/domain/use-cases/HabitGoalProgressUpdate"
2024-03-15 22:48:28 +01:00
export interface HabitsTrackerPresenterState {
habitsTracker: HabitsTracker
retrieveHabitsTracker: {
state: FetchState
}
2024-04-05 00:08:40 +02:00
habitCreate: {
state: FetchState
errors: {
fields: Array<keyof HabitCreateData>
global: ErrorGlobal
}
}
habitEdit: {
state: FetchState
errors: {
2024-04-11 13:07:17 +02:00
fields: Array<keyof HabitEditData>
global: ErrorGlobal
}
}
2024-04-11 23:03:45 +02:00
2024-04-12 15:20:08 +02:00
habitStop: {
state: FetchState
}
2024-04-11 23:03:45 +02:00
habitGoalProgressUpdate: {
state: FetchState
}
2024-03-15 22:48:28 +01:00
}
export interface HabitsTrackerPresenterOptions {
retrieveHabitsTrackerUseCase: RetrieveHabitsTrackerUseCase
2024-04-05 00:08:40 +02:00
habitCreateUseCase: HabitCreateUseCase
2024-04-11 13:07:17 +02:00
habitEditUseCase: HabitEditUseCase
2024-04-12 15:20:08 +02:00
habitStopUseCase: HabitStopUseCase
2024-04-11 23:03:45 +02:00
habitGoalProgressUpdateUseCase: HabitGoalProgressUpdateUseCase
2024-03-15 22:48:28 +01:00
}
export class HabitsTrackerPresenter
extends Presenter<HabitsTrackerPresenterState>
implements HabitsTrackerPresenterOptions
{
public retrieveHabitsTrackerUseCase: RetrieveHabitsTrackerUseCase
2024-04-05 00:08:40 +02:00
public habitCreateUseCase: HabitCreateUseCase
2024-04-11 13:07:17 +02:00
public habitEditUseCase: HabitEditUseCase
2024-04-12 15:20:08 +02:00
public habitStopUseCase: HabitStopUseCase
2024-04-11 23:03:45 +02:00
public habitGoalProgressUpdateUseCase: HabitGoalProgressUpdateUseCase
2024-03-15 22:48:28 +01:00
public constructor(options: HabitsTrackerPresenterOptions) {
2024-04-11 13:07:17 +02:00
const {
retrieveHabitsTrackerUseCase,
habitCreateUseCase,
habitEditUseCase,
2024-04-12 15:20:08 +02:00
habitStopUseCase,
2024-04-11 23:03:45 +02:00
habitGoalProgressUpdateUseCase,
2024-04-11 13:07:17 +02:00
} = options
2024-03-15 22:48:28 +01:00
const habitsTracker = HabitsTracker.default()
2024-04-05 00:08:40 +02:00
super({
habitsTracker,
retrieveHabitsTracker: { state: "idle" },
habitCreate: {
state: "idle",
errors: {
fields: [],
global: null,
},
},
habitEdit: {
state: "idle",
errors: {
fields: [],
global: null,
},
},
2024-04-12 15:20:08 +02:00
habitStop: {
state: "idle",
},
2024-04-11 23:03:45 +02:00
habitGoalProgressUpdate: {
state: "idle",
},
2024-04-05 00:08:40 +02:00
})
2024-03-15 22:48:28 +01:00
this.retrieveHabitsTrackerUseCase = retrieveHabitsTrackerUseCase
2024-04-05 00:08:40 +02:00
this.habitCreateUseCase = habitCreateUseCase
2024-04-11 13:07:17 +02:00
this.habitEditUseCase = habitEditUseCase
2024-04-12 15:20:08 +02:00
this.habitStopUseCase = habitStopUseCase
2024-04-11 23:03:45 +02:00
this.habitGoalProgressUpdateUseCase = habitGoalProgressUpdateUseCase
2024-04-05 00:08:40 +02:00
}
public async habitCreate(data: unknown): Promise<FetchState> {
try {
this.setState((state) => {
state.habitCreate.state = "loading"
state.habitCreate.errors = {
fields: [],
global: null,
}
})
const habit = await this.habitCreateUseCase.execute(data)
this.setState((state) => {
state.habitCreate.state = "success"
state.habitsTracker.addHabit(habit)
})
return "success"
} catch (error) {
this.setState((state) => {
state.habitCreate.state = "error"
if (error instanceof ZodError) {
state.habitCreate.errors.fields =
getErrorsFieldsFromZodError<HabitCreateData>(error)
} else {
state.habitCreate.errors.global = "unknown"
}
})
return "error"
}
2024-03-15 22:48:28 +01:00
}
public async habitEdit(data: unknown): Promise<FetchState> {
try {
this.setState((state) => {
state.habitEdit.state = "loading"
state.habitEdit.errors = {
fields: [],
global: null,
}
})
2024-04-11 13:07:17 +02:00
const habit = await this.habitEditUseCase.execute(data)
this.setState((state) => {
state.habitEdit.state = "success"
2024-04-11 13:07:17 +02:00
state.habitsTracker.editHabit(habit)
})
return "success"
} catch (error) {
this.setState((state) => {
state.habitEdit.state = "error"
if (error instanceof ZodError) {
state.habitEdit.errors.fields =
2024-04-11 13:07:17 +02:00
getErrorsFieldsFromZodError<HabitEditData>(error)
} else {
state.habitEdit.errors.global = "unknown"
}
})
return "error"
}
}
2024-04-12 15:20:08 +02:00
public async habitStop(habitToStop: Habit): Promise<FetchState> {
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"
}
}
2024-03-15 22:48:28 +01:00
public async retrieveHabitsTracker(
options: RetrieveHabitsTrackerUseCaseOptions,
): Promise<void> {
this.setState((state) => {
state.retrieveHabitsTracker.state = "loading"
state.habitsTracker = HabitsTracker.default()
2024-03-15 22:48:28 +01:00
})
try {
const habitsTracker =
await this.retrieveHabitsTrackerUseCase.execute(options)
this.setState((state) => {
state.habitsTracker = habitsTracker
state.retrieveHabitsTracker.state = "success"
})
} catch (error) {
this.setState((state) => {
state.retrieveHabitsTracker.state = "error"
})
}
2024-03-15 22:48:28 +01:00
}
2024-04-11 23:03:45 +02:00
public async habitUpdateProgress(
options: HabitGoalProgressUpdateUseCaseOptions,
): Promise<FetchState> {
try {
this.setState((state) => {
state.habitGoalProgressUpdate.state = "loading"
})
const habitProgress =
await this.habitGoalProgressUpdateUseCase.execute(options)
this.setState((state) => {
state.habitsTracker.updateHabitProgress(habitProgress)
state.habitGoalProgressUpdate.state = "success"
})
return "success"
} catch (error) {
this.setState((state) => {
state.habitGoalProgressUpdate.state = "error"
})
return "error"
}
}
2024-03-15 22:48:28 +01:00
}