feat: add habit progress update
This commit is contained in:
parent
c11f7c1474
commit
a411f91c8e
@ -34,7 +34,7 @@ export class HabitHistory implements HabitHistoryJSON {
|
||||
})
|
||||
}
|
||||
|
||||
private getProgressesByDate(date: Date): HabitProgress[] {
|
||||
public getProgressesByDate(date: Date): HabitProgress[] {
|
||||
return this._progressHistory.filter((progress) => {
|
||||
if (this.habit.goal.frequency === "monthly") {
|
||||
return (
|
||||
|
@ -1,6 +1,7 @@
|
||||
import type { GoalFrequency } from "./Goal"
|
||||
import type { Habit } from "./Habit"
|
||||
import { HabitHistory } from "./HabitHistory"
|
||||
import { HabitProgress } from "./HabitProgress"
|
||||
|
||||
export interface HabitsTrackerData {
|
||||
habitsHistory: {
|
||||
@ -35,6 +36,24 @@ export class HabitsTracker implements HabitsTrackerData {
|
||||
)
|
||||
}
|
||||
|
||||
public setHabitProgress(options: SetHabitProgressOptions): void {
|
||||
const { date, goalProgress, habitHistory } = options
|
||||
if (goalProgress.isBoolean()) {
|
||||
const currentHabitProgress = habitHistory.getProgressesByDate(date)[0]
|
||||
if (currentHabitProgress == null) {
|
||||
habitHistory.progressHistory = [
|
||||
...habitHistory.progressHistory,
|
||||
new HabitProgress({
|
||||
date,
|
||||
goalProgress,
|
||||
habitId,
|
||||
id,
|
||||
}),
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public getAllHabitsHistory(): HabitHistory[] {
|
||||
return [
|
||||
...this.habitsHistory.daily,
|
||||
|
12
domain/repositories/HabitProgressCreate.ts
Normal file
12
domain/repositories/HabitProgressCreate.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import type {
|
||||
HabitProgress,
|
||||
HabitProgressData,
|
||||
} from "../entities/HabitProgress"
|
||||
|
||||
export interface HabitProgressCreateOptions {
|
||||
habitProgressData: Omit<HabitProgressData, "id">
|
||||
}
|
||||
|
||||
export interface HabitProgressCreateRepository {
|
||||
execute: (options: HabitProgressCreateOptions) => Promise<HabitProgress>
|
||||
}
|
12
domain/repositories/HabitProgressUpdate.ts
Normal file
12
domain/repositories/HabitProgressUpdate.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import type {
|
||||
HabitProgress,
|
||||
HabitProgressData,
|
||||
} from "../entities/HabitProgress"
|
||||
|
||||
export interface HabitProgressUpdateOptions {
|
||||
habitProgressData: HabitProgressData
|
||||
}
|
||||
|
||||
export interface HabitProgressUpdateRepository {
|
||||
execute: (options: HabitProgressUpdateOptions) => Promise<HabitProgress>
|
||||
}
|
28
domain/use-cases/HabitGoalProgressUpdate.ts
Normal file
28
domain/use-cases/HabitGoalProgressUpdate.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import type { GoalProgress } from "../entities/Goal"
|
||||
import type { HabitHistory } from "../entities/HabitHistory"
|
||||
import type { HabitProgressCreateRepository } from "../repositories/HabitProgressCreate"
|
||||
import type { HabitProgressUpdateRepository } from "../repositories/HabitProgressUpdate"
|
||||
|
||||
export interface HabitGoalProgressUpdateOptions {
|
||||
date: Date
|
||||
goalProgress: GoalProgress
|
||||
habitHistory: HabitHistory
|
||||
}
|
||||
|
||||
export class HabitGoalProgressUpdateUseCase
|
||||
implements HabitGoalProgressUpdateOptions
|
||||
{
|
||||
public date: Date
|
||||
public goalProgress: GoalProgress
|
||||
public habitHistory: HabitHistory
|
||||
|
||||
public constructor(option: HabitGoalProgressUpdateOptions) {
|
||||
this.date = option.date
|
||||
this.goalProgress = option.goalProgress
|
||||
this.habitHistory = option.habitHistory
|
||||
}
|
||||
|
||||
public async execute(data: unknown): Promise<HabitHistory> {
|
||||
//
|
||||
}
|
||||
}
|
143
presentation/react/components/HabitHistory/HabitHistory.tsx
Normal file
143
presentation/react/components/HabitHistory/HabitHistory.tsx
Normal file
@ -0,0 +1,143 @@
|
||||
import { useState } from "react"
|
||||
import { Calendar } from "react-native-calendars"
|
||||
import { Text } from "react-native-paper"
|
||||
import { SafeAreaView } from "react-native-safe-area-context"
|
||||
|
||||
export const HabitHistory: React.FC = () => {
|
||||
const [selected, setSelected] = useState("")
|
||||
|
||||
return (
|
||||
<SafeAreaView
|
||||
style={[
|
||||
{
|
||||
flex: 1,
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Calendar
|
||||
onDayPress={(day) => {
|
||||
setSelected(day.dateString)
|
||||
}}
|
||||
markedDates={{
|
||||
"2023-03-01": { selected: true, marked: true, selectedColor: "blue" },
|
||||
"2023-03-02": { marked: true },
|
||||
"2023-03-03": { selected: true, marked: true, selectedColor: "blue" },
|
||||
[selected]: {
|
||||
selected: true,
|
||||
disableTouchEvent: true,
|
||||
selectedColor: "orange",
|
||||
},
|
||||
}}
|
||||
theme={{
|
||||
backgroundColor: "#000000",
|
||||
calendarBackground: "#000000",
|
||||
textSectionTitleColor: "#b6c1cd",
|
||||
selectedDayBackgroundColor: "#00adf5",
|
||||
selectedDayTextColor: "#ffffff",
|
||||
todayTextColor: "#00adf5",
|
||||
dayTextColor: "#2d4150",
|
||||
textDisabledColor: "#d9efff",
|
||||
}}
|
||||
/>
|
||||
<Text>{selected}</Text>
|
||||
</SafeAreaView>
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
<Agenda
|
||||
// The list of items that have to be displayed in agenda. If you want to render item as empty date
|
||||
// the value of date key has to be an empty array []. If there exists no value for date key it is
|
||||
// considered that the date in question is not yet loaded
|
||||
items={{
|
||||
'2012-05-22': [{name: 'item 1 - any js object'}],
|
||||
'2012-05-23': [{name: 'item 2 - any js object', height: 80}],
|
||||
'2012-05-24': [],
|
||||
'2012-05-25': [{name: 'item 3 - any js object'}, {name: 'any js object'}]
|
||||
}}
|
||||
// Callback that gets called when items for a certain month should be loaded (month became visible)
|
||||
loadItemsForMonth={month => {
|
||||
console.log('trigger items loading');
|
||||
}}
|
||||
// Callback that fires when the calendar is opened or closed
|
||||
onCalendarToggled={calendarOpened => {
|
||||
console.log(calendarOpened);
|
||||
}}
|
||||
// Callback that gets called on day press
|
||||
onDayPress={day => {
|
||||
console.log('day pressed');
|
||||
}}
|
||||
// Callback that gets called when day changes while scrolling agenda list
|
||||
onDayChange={day => {
|
||||
console.log('day changed');
|
||||
}}
|
||||
// Initially selected day
|
||||
selected={'2012-05-16'}
|
||||
// Minimum date that can be selected, dates before minDate will be grayed out. Default = undefined
|
||||
minDate={'2012-05-10'}
|
||||
// Maximum date that can be selected, dates after maxDate will be grayed out. Default = undefined
|
||||
maxDate={'2012-05-30'}
|
||||
// Max amount of months allowed to scroll to the past. Default = 50
|
||||
pastScrollRange={50}
|
||||
// Max amount of months allowed to scroll to the future. Default = 50
|
||||
futureScrollRange={50}
|
||||
// Specify how each item should be rendered in agenda
|
||||
renderItem={(item, firstItemInDay) => {
|
||||
return <View />;
|
||||
}}
|
||||
// Specify how each date should be rendered. day can be undefined if the item is not first in that day
|
||||
renderDay={(day, item) => {
|
||||
return <View />;
|
||||
}}
|
||||
// Specify how empty date content with no items should be rendered
|
||||
renderEmptyDate={() => {
|
||||
return <View />;
|
||||
}}
|
||||
// Specify how agenda knob should look like
|
||||
renderKnob={() => {
|
||||
return <View />;
|
||||
}}
|
||||
// Override inner list with a custom implemented component
|
||||
renderList={listProps => {
|
||||
return <MyCustomList {...listProps} />;
|
||||
}}
|
||||
// Specify what should be rendered instead of ActivityIndicator
|
||||
renderEmptyData={() => {
|
||||
return <View />;
|
||||
}}
|
||||
// Specify your item comparison function for increased performance
|
||||
rowHasChanged={(r1, r2) => {
|
||||
return r1.text !== r2.text;
|
||||
}}
|
||||
// Hide knob button. Default = false
|
||||
hideKnob={true}
|
||||
// When `true` and `hideKnob` prop is `false`, the knob will always be visible and the user will be able to drag the knob up and close the calendar. Default = false
|
||||
showClosingKnob={false}
|
||||
// By default, agenda dates are marked if they have at least one item, but you can override this if needed
|
||||
markedDates={{
|
||||
'2012-05-16': {selected: true, marked: true},
|
||||
'2012-05-17': {marked: true},
|
||||
'2012-05-18': {disabled: true}
|
||||
}}
|
||||
// If disabledByDefault={true} dates flagged as not disabled will be enabled. Default = false
|
||||
disabledByDefault={true}
|
||||
// If provided, a standard RefreshControl will be added for "Pull to Refresh" functionality. Make sure to also set the refreshing prop correctly
|
||||
onRefresh={() => console.log('refreshing...')}
|
||||
// Set this true while waiting for new data from a refresh
|
||||
refreshing={false}
|
||||
// Add a custom RefreshControl component, used to provide pull-to-refresh functionality for the ScrollView
|
||||
refreshControl={null}
|
||||
// Agenda theme
|
||||
theme={{
|
||||
...calendarTheme,
|
||||
agendaDayTextColor: 'yellow',
|
||||
agendaDayNumColor: 'green',
|
||||
agendaTodayColor: 'red',
|
||||
agendaKnobColor: 'blue'
|
||||
}}
|
||||
// Agenda container style
|
||||
style={{}}
|
||||
/>
|
||||
*/
|
@ -1,7 +1,8 @@
|
||||
import FontAwesome6 from "@expo/vector-icons/FontAwesome6"
|
||||
import { useRouter } from "expo-router"
|
||||
import { View } from "react-native"
|
||||
import { List, Text } from "react-native-paper"
|
||||
import { List, Text, Checkbox } from "react-native-paper"
|
||||
import { useState } from "react"
|
||||
|
||||
import type { GoalProgress } from "@/domain/entities/Goal"
|
||||
import type { Habit } from "@/domain/entities/Habit"
|
||||
@ -22,6 +23,8 @@ export const HabitCard: React.FC<HabitCardProps> = (props) => {
|
||||
opacity: 0.4,
|
||||
})
|
||||
|
||||
const [checked, setChecked] = useState(goalProgress.isCompleted())
|
||||
|
||||
return (
|
||||
<List.Item
|
||||
onPress={() => {
|
||||
@ -80,7 +83,12 @@ export const HabitCard: React.FC<HabitCardProps> = (props) => {
|
||||
|
||||
return (
|
||||
<View>
|
||||
<Text>{goalProgress.isCompleted() ? "true" : "false"}</Text>
|
||||
<Checkbox
|
||||
status={checked ? "checked" : "unchecked"}
|
||||
onPress={() => {
|
||||
setChecked(!checked)
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
}}
|
||||
|
Reference in New Issue
Block a user