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

110 lines
3.1 KiB
TypeScript

import { ZodError } from "zod"
import { HabitsTracker } from "@/domain/entities/HabitsTracker"
import type { ErrorGlobal, FetchState } from "./_Presenter"
import { Presenter } from "./_Presenter"
import type {
RetrieveHabitsTrackerUseCase,
RetrieveHabitsTrackerUseCaseOptions,
} from "@/domain/use-cases/RetrieveHabitsTracker"
import type { HabitCreateData } from "@/domain/entities/Habit"
import { getErrorsFieldsFromZodError } from "./utils/zod"
import type { HabitCreateUseCase } from "@/domain/use-cases/HabitCreate"
export interface HabitsTrackerPresenterState {
habitsTracker: HabitsTracker
retrieveHabitsTracker: {
state: FetchState
}
habitCreate: {
state: FetchState
errors: {
fields: Array<keyof HabitCreateData>
global: ErrorGlobal
}
}
}
export interface HabitsTrackerPresenterOptions {
retrieveHabitsTrackerUseCase: RetrieveHabitsTrackerUseCase
habitCreateUseCase: HabitCreateUseCase
}
export class HabitsTrackerPresenter
extends Presenter<HabitsTrackerPresenterState>
implements HabitsTrackerPresenterOptions
{
public retrieveHabitsTrackerUseCase: RetrieveHabitsTrackerUseCase
public habitCreateUseCase: HabitCreateUseCase
public constructor(options: HabitsTrackerPresenterOptions) {
const { retrieveHabitsTrackerUseCase, habitCreateUseCase } = options
const habitsTracker = HabitsTracker.default()
super({
habitsTracker,
retrieveHabitsTracker: { state: "idle" },
habitCreate: {
state: "idle",
errors: {
fields: [],
global: null,
},
},
})
this.retrieveHabitsTrackerUseCase = retrieveHabitsTrackerUseCase
this.habitCreateUseCase = habitCreateUseCase
}
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"
}
}
public async retrieveHabitsTracker(
options: RetrieveHabitsTrackerUseCaseOptions,
): Promise<void> {
this.setState((state) => {
state.retrieveHabitsTracker.state = "loading"
state.habitsTracker = HabitsTracker.default()
})
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"
})
}
}
}