feat: habit stop use case
This commit is contained in:
parent
1ab504324a
commit
dffadb47d0
@ -8,6 +8,7 @@ export const HabitSchema = EntitySchema.extend({
|
|||||||
name: z.string().min(1).max(50),
|
name: z.string().min(1).max(50),
|
||||||
color: z.string().min(4).max(9).regex(/^#/),
|
color: z.string().min(4).max(9).regex(/^#/),
|
||||||
icon: z.string().min(1),
|
icon: z.string().min(1),
|
||||||
|
endDate: z.date().optional(),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const HabitCreateSchema = HabitSchema.extend({
|
export const HabitCreateSchema = HabitSchema.extend({
|
||||||
@ -29,7 +30,6 @@ export interface HabitData extends HabitBase {
|
|||||||
export interface HabitJSON extends HabitBase {
|
export interface HabitJSON extends HabitBase {
|
||||||
goal: GoalBaseJSON
|
goal: GoalBaseJSON
|
||||||
startDate: string
|
startDate: string
|
||||||
endDate?: string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Habit extends Entity implements HabitData {
|
export class Habit extends Entity implements HabitData {
|
||||||
@ -62,7 +62,7 @@ export class Habit extends Entity implements HabitData {
|
|||||||
icon: this.icon,
|
icon: this.icon,
|
||||||
goal: this.goal,
|
goal: this.goal,
|
||||||
startDate: this.startDate.toISOString(),
|
startDate: this.startDate.toISOString(),
|
||||||
endDate: this.endDate?.toISOString(),
|
endDate: this?.endDate,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
24
domain/use-cases/HabitStop.ts
Normal file
24
domain/use-cases/HabitStop.ts
Normal 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
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,7 @@ import { HabitEditUseCase } from "@/domain/use-cases/HabitEdit"
|
|||||||
import { HabitProgressCreateSupabaseRepository } from "./supabase/repositories/HabitProgressCreate"
|
import { HabitProgressCreateSupabaseRepository } from "./supabase/repositories/HabitProgressCreate"
|
||||||
import { HabitProgressUpdateSupabaseRepository } from "./supabase/repositories/HabitProgressUpdate"
|
import { HabitProgressUpdateSupabaseRepository } from "./supabase/repositories/HabitProgressUpdate"
|
||||||
import { HabitGoalProgressUpdateUseCase } from "@/domain/use-cases/HabitGoalProgressUpdate"
|
import { HabitGoalProgressUpdateUseCase } from "@/domain/use-cases/HabitGoalProgressUpdate"
|
||||||
|
import { HabitStopUseCase } from "@/domain/use-cases/HabitStop"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Repositories
|
* Repositories
|
||||||
@ -64,6 +65,9 @@ const habitGoalProgressUpdateUseCase = new HabitGoalProgressUpdateUseCase({
|
|||||||
habitProgressCreateRepository,
|
habitProgressCreateRepository,
|
||||||
habitProgressUpdateRepository,
|
habitProgressUpdateRepository,
|
||||||
})
|
})
|
||||||
|
const habitStopUseCase = new HabitStopUseCase({
|
||||||
|
habitEditRepository,
|
||||||
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Presenters
|
* Presenters
|
||||||
@ -75,5 +79,6 @@ export const habitsTrackerPresenter = new HabitsTrackerPresenter({
|
|||||||
retrieveHabitsTrackerUseCase,
|
retrieveHabitsTrackerUseCase,
|
||||||
habitCreateUseCase,
|
habitCreateUseCase,
|
||||||
habitEditUseCase,
|
habitEditUseCase,
|
||||||
|
habitStopUseCase,
|
||||||
habitGoalProgressUpdateUseCase,
|
habitGoalProgressUpdateUseCase,
|
||||||
})
|
})
|
||||||
|
@ -15,6 +15,7 @@ export class HabitEditSupabaseRepository
|
|||||||
name: habitEditData.name,
|
name: habitEditData.name,
|
||||||
color: habitEditData.color,
|
color: habitEditData.color,
|
||||||
icon: habitEditData.icon,
|
icon: habitEditData.icon,
|
||||||
|
end_date: habitEditData?.endDate?.toISOString(),
|
||||||
})
|
})
|
||||||
.eq("id", habitEditData.id)
|
.eq("id", habitEditData.id)
|
||||||
.select("*")
|
.select("*")
|
||||||
@ -43,6 +44,10 @@ export class HabitEditSupabaseRepository
|
|||||||
}),
|
}),
|
||||||
color: updatedHabit.color,
|
color: updatedHabit.color,
|
||||||
startDate: new Date(updatedHabit.start_date),
|
startDate: new Date(updatedHabit.start_date),
|
||||||
|
endDate:
|
||||||
|
updatedHabit.end_date != null
|
||||||
|
? new Date(updatedHabit.end_date)
|
||||||
|
: undefined,
|
||||||
})
|
})
|
||||||
return habit
|
return habit
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,15 @@ import type {
|
|||||||
RetrieveHabitsTrackerUseCase,
|
RetrieveHabitsTrackerUseCase,
|
||||||
RetrieveHabitsTrackerUseCaseOptions,
|
RetrieveHabitsTrackerUseCaseOptions,
|
||||||
} from "@/domain/use-cases/RetrieveHabitsTracker"
|
} 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 { getErrorsFieldsFromZodError } from "../../utils/zod"
|
||||||
import type { HabitCreateUseCase } from "@/domain/use-cases/HabitCreate"
|
import type { HabitCreateUseCase } from "@/domain/use-cases/HabitCreate"
|
||||||
import type { HabitEditUseCase } from "@/domain/use-cases/HabitEdit"
|
import type { HabitEditUseCase } from "@/domain/use-cases/HabitEdit"
|
||||||
|
import type { HabitStopUseCase } from "@/domain/use-cases/HabitStop"
|
||||||
import type {
|
import type {
|
||||||
HabitGoalProgressUpdateUseCase,
|
HabitGoalProgressUpdateUseCase,
|
||||||
HabitGoalProgressUpdateUseCaseOptions,
|
HabitGoalProgressUpdateUseCaseOptions,
|
||||||
@ -39,6 +44,10 @@ export interface HabitsTrackerPresenterState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
habitStop: {
|
||||||
|
state: FetchState
|
||||||
|
}
|
||||||
|
|
||||||
habitGoalProgressUpdate: {
|
habitGoalProgressUpdate: {
|
||||||
state: FetchState
|
state: FetchState
|
||||||
}
|
}
|
||||||
@ -48,6 +57,7 @@ export interface HabitsTrackerPresenterOptions {
|
|||||||
retrieveHabitsTrackerUseCase: RetrieveHabitsTrackerUseCase
|
retrieveHabitsTrackerUseCase: RetrieveHabitsTrackerUseCase
|
||||||
habitCreateUseCase: HabitCreateUseCase
|
habitCreateUseCase: HabitCreateUseCase
|
||||||
habitEditUseCase: HabitEditUseCase
|
habitEditUseCase: HabitEditUseCase
|
||||||
|
habitStopUseCase: HabitStopUseCase
|
||||||
habitGoalProgressUpdateUseCase: HabitGoalProgressUpdateUseCase
|
habitGoalProgressUpdateUseCase: HabitGoalProgressUpdateUseCase
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,6 +68,7 @@ export class HabitsTrackerPresenter
|
|||||||
public retrieveHabitsTrackerUseCase: RetrieveHabitsTrackerUseCase
|
public retrieveHabitsTrackerUseCase: RetrieveHabitsTrackerUseCase
|
||||||
public habitCreateUseCase: HabitCreateUseCase
|
public habitCreateUseCase: HabitCreateUseCase
|
||||||
public habitEditUseCase: HabitEditUseCase
|
public habitEditUseCase: HabitEditUseCase
|
||||||
|
public habitStopUseCase: HabitStopUseCase
|
||||||
public habitGoalProgressUpdateUseCase: HabitGoalProgressUpdateUseCase
|
public habitGoalProgressUpdateUseCase: HabitGoalProgressUpdateUseCase
|
||||||
|
|
||||||
public constructor(options: HabitsTrackerPresenterOptions) {
|
public constructor(options: HabitsTrackerPresenterOptions) {
|
||||||
@ -65,6 +76,7 @@ export class HabitsTrackerPresenter
|
|||||||
retrieveHabitsTrackerUseCase,
|
retrieveHabitsTrackerUseCase,
|
||||||
habitCreateUseCase,
|
habitCreateUseCase,
|
||||||
habitEditUseCase,
|
habitEditUseCase,
|
||||||
|
habitStopUseCase,
|
||||||
habitGoalProgressUpdateUseCase,
|
habitGoalProgressUpdateUseCase,
|
||||||
} = options
|
} = options
|
||||||
const habitsTracker = HabitsTracker.default()
|
const habitsTracker = HabitsTracker.default()
|
||||||
@ -85,6 +97,9 @@ export class HabitsTrackerPresenter
|
|||||||
global: null,
|
global: null,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
habitStop: {
|
||||||
|
state: "idle",
|
||||||
|
},
|
||||||
habitGoalProgressUpdate: {
|
habitGoalProgressUpdate: {
|
||||||
state: "idle",
|
state: "idle",
|
||||||
},
|
},
|
||||||
@ -92,6 +107,7 @@ export class HabitsTrackerPresenter
|
|||||||
this.retrieveHabitsTrackerUseCase = retrieveHabitsTrackerUseCase
|
this.retrieveHabitsTrackerUseCase = retrieveHabitsTrackerUseCase
|
||||||
this.habitCreateUseCase = habitCreateUseCase
|
this.habitCreateUseCase = habitCreateUseCase
|
||||||
this.habitEditUseCase = habitEditUseCase
|
this.habitEditUseCase = habitEditUseCase
|
||||||
|
this.habitStopUseCase = habitStopUseCase
|
||||||
this.habitGoalProgressUpdateUseCase = habitGoalProgressUpdateUseCase
|
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(
|
public async retrieveHabitsTracker(
|
||||||
options: RetrieveHabitsTrackerUseCaseOptions,
|
options: RetrieveHabitsTrackerUseCaseOptions,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
@ -19,7 +19,7 @@ export interface HabitEditFormProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const HabitEditForm: React.FC<HabitEditFormProps> = ({ habit }) => {
|
export const HabitEditForm: React.FC<HabitEditFormProps> = ({ habit }) => {
|
||||||
const { habitEdit, habitsTrackerPresenter } = useHabitsTracker()
|
const { habitEdit, habitStop, habitsTrackerPresenter } = useHabitsTracker()
|
||||||
|
|
||||||
const {
|
const {
|
||||||
control,
|
control,
|
||||||
@ -134,6 +134,18 @@ export const HabitEditForm: React.FC<HabitEditFormProps> = ({ habit }) => {
|
|||||||
>
|
>
|
||||||
Save
|
Save
|
||||||
</Button>
|
</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>
|
</ScrollView>
|
||||||
|
|
||||||
<Snackbar
|
<Snackbar
|
||||||
|
@ -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 (
|
return (
|
||||||
<HabitCard
|
<HabitCard
|
||||||
habitHistory={item}
|
habitHistory={item}
|
||||||
|
Reference in New Issue
Block a user