feat: habit stop use case

This commit is contained in:
Xc165543337 2024-04-12 15:20:08 +02:00
parent 1ab504324a
commit dffadb47d0
7 changed files with 103 additions and 14 deletions

View File

@ -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,
}
}
}

View File

@ -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<Habit> {
const habit = await this.habitEditRepository.execute({
habitEditData: {
...habitToStop,
endDate: new Date(),
},
})
return habit
}
}

View File

@ -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,
})

View File

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

View File

@ -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<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"
}
}
public async retrieveHabitsTracker(
options: RetrieveHabitsTrackerUseCaseOptions,
): Promise<void> {

View File

@ -19,7 +19,7 @@ export interface HabitEditFormProps {
}
export const HabitEditForm: React.FC<HabitEditFormProps> = ({ habit }) => {
const { habitEdit, habitsTrackerPresenter } = useHabitsTracker()
const { habitEdit, habitStop, habitsTrackerPresenter } = useHabitsTracker()
const {
control,
@ -134,6 +134,18 @@ export const HabitEditForm: React.FC<HabitEditFormProps> = ({ habit }) => {
>
Save
</Button>
<Button
mode="outlined"
onPress={async () => {
await habitsTrackerPresenter.habitStop(habit)
}}
loading={habitStop.state === "loading"}
disabled={habitStop.state === "loading"}
style={[styles.spacing, { width: "90%" }]}
>
Stop
</Button>
</ScrollView>
<Snackbar

View File

@ -90,7 +90,15 @@ export const HabitsList: React.FC<HabitsListProps> = (props) => {
},
]}
>
{habitsTracker.habitsHistory[frequency].map((item) => {
{habitsTracker.habitsHistory[frequency]
.filter((habitItem) => {
return (
(habitItem.habit.endDate != null &&
habitItem.habit.endDate <= selectedDate) ||
habitItem.habit.endDate == null
)
})
.map((item) => {
return (
<HabitCard
habitHistory={item}