feat: handle creation of habit target type

This commit is contained in:
Théo LUDWIG 2024-04-13 17:57:58 +02:00
parent 97ae14d182
commit c00b96a8e2
Signed by: theoludwig
GPG Key ID: ADFE5A563D718F3B
4 changed files with 84 additions and 16 deletions

View File

@ -31,6 +31,7 @@ const TabLayout: React.FC = () => {
name="habits/new" name="habits/new"
options={{ options={{
title: "New Habit", title: "New Habit",
unmountOnBlur: true,
tabBarIcon: ({ color }) => { tabBarIcon: ({ color }) => {
return <TabBarIcon name="plus-square" color={color} /> return <TabBarIcon name="plus-square" color={color} />
}, },
@ -39,6 +40,7 @@ const TabLayout: React.FC = () => {
<Tabs.Screen <Tabs.Screen
name="habits/[habitId]" name="habits/[habitId]"
options={{ options={{
unmountOnBlur: true,
href: null, href: null,
}} }}
/> />

View File

@ -27,7 +27,7 @@ export const GoalCreateSchema = z.object({
z.object({ type: z.literal("boolean") }), z.object({ type: z.literal("boolean") }),
z.object({ z.object({
type: z.literal("numeric"), type: z.literal("numeric"),
value: z.number().int().min(0), value: z.number().int().min(1),
unit: z.string().min(1), unit: z.string().min(1),
}), }),
]), ]),

View File

@ -39,7 +39,9 @@ export const HabitCreateForm: React.FC<HabitCreateFormProps> = ({ user }) => {
control, control,
handleSubmit, handleSubmit,
reset, reset,
formState: { errors }, watch,
formState: { errors, isValid },
} = useForm<HabitCreateData>({ } = useForm<HabitCreateData>({
mode: "onChange", mode: "onChange",
resolver: zodResolver(HabitCreateSchema), resolver: zodResolver(HabitCreateSchema),
@ -57,6 +59,8 @@ export const HabitCreateForm: React.FC<HabitCreateFormProps> = ({ user }) => {
}, },
}) })
const watchGoalType = watch("goal.target.type")
const [isVisibleSnackbar, setIsVisibleSnackbar] = useState(false) const [isVisibleSnackbar, setIsVisibleSnackbar] = useState(false)
const { const {
@ -128,7 +132,7 @@ export const HabitCreateForm: React.FC<HabitCreateFormProps> = ({ user }) => {
style={[ style={[
styles.spacing, styles.spacing,
{ {
width: "90%", width: "96%",
}, },
]} ]}
mode="outlined" mode="outlined"
@ -153,7 +157,7 @@ export const HabitCreateForm: React.FC<HabitCreateFormProps> = ({ user }) => {
<> <>
<Text style={[styles.spacing]}>Habit Frequency</Text> <Text style={[styles.spacing]}>Habit Frequency</Text>
<SegmentedButtons <SegmentedButtons
style={[{ width: "90%" }]} style={[{ width: "96%" }]}
onValueChange={onChange} onValueChange={onChange}
value={value} value={value}
buttons={GOAL_FREQUENCIES.map((frequency) => { buttons={GOAL_FREQUENCIES.map((frequency) => {
@ -197,7 +201,7 @@ export const HabitCreateForm: React.FC<HabitCreateFormProps> = ({ user }) => {
</Tooltip> */} </Tooltip> */}
</Text> </Text>
<SegmentedButtons <SegmentedButtons
style={[{ width: "90%" }]} style={[{ width: "96%" }]}
onValueChange={onChange} onValueChange={onChange}
value={value} value={value}
buttons={GOAL_TYPES.map((type) => { buttons={GOAL_TYPES.map((type) => {
@ -214,12 +218,74 @@ export const HabitCreateForm: React.FC<HabitCreateFormProps> = ({ user }) => {
name="goal.target.type" name="goal.target.type"
/> />
{watchGoalType === "numeric" ? (
<View
style={{
marginTop: 10,
flexDirection: "row",
gap: 10,
width: "96%",
}}
>
<Controller
control={control}
render={({ field: { onChange, onBlur, value } }) => {
return (
<TextInput
placeholder="Target (e.g: 5 000)"
onBlur={onBlur}
onChangeText={(text) => {
if (text.length <= 0) {
onChange("")
return
}
onChange(Number.parseInt(text, 10))
}}
value={value?.toString()}
style={[
styles.spacing,
{
width: "50%",
},
]}
mode="outlined"
keyboardType="numeric"
/>
)
}}
name="goal.target.value"
/>
<Controller
control={control}
render={({ field: { onChange, onBlur, value } }) => {
return (
<TextInput
placeholder="Unit (e.g: Steps)"
onBlur={onBlur}
onChangeText={onChange}
value={value}
style={[
styles.spacing,
{
width: "50%",
},
]}
mode="outlined"
/>
)
}}
name="goal.target.unit"
/>
</View>
) : null}
<Controller <Controller
control={control} control={control}
render={({ field: { onChange, value } }) => { render={({ field: { onChange, value } }) => {
return ( return (
<ColorPicker <ColorPicker
style={[styles.spacing, { width: "90%" }]} style={[{ marginVertical: 15, width: "96%" }]}
value={value} value={value}
onComplete={(value) => { onComplete={(value) => {
onChange(value.hex) onChange(value.hex)
@ -244,7 +310,7 @@ export const HabitCreateForm: React.FC<HabitCreateFormProps> = ({ user }) => {
alignItems: "center", alignItems: "center",
flexDirection: "row", flexDirection: "row",
gap: 20, gap: 20,
marginVertical: 30, marginVertical: 5,
}} }}
> >
<FontAwesomeIcon size={36} icon={value as IconName} /> <FontAwesomeIcon size={36} icon={value as IconName} />
@ -269,8 +335,8 @@ export const HabitCreateForm: React.FC<HabitCreateFormProps> = ({ user }) => {
mode="contained" mode="contained"
onPress={handleSubmit(onSubmit)} onPress={handleSubmit(onSubmit)}
loading={habitCreate.state === "loading"} loading={habitCreate.state === "loading"}
disabled={habitCreate.state === "loading"} disabled={habitCreate.state === "loading" || !isValid}
style={[styles.spacing, { width: "100%" }]} style={[{ width: "100%", marginVertical: 15 }]}
> >
Create your habit! 🚀 Create your habit! 🚀
</Button> </Button>
@ -289,6 +355,6 @@ export const HabitCreateForm: React.FC<HabitCreateFormProps> = ({ user }) => {
const styles = StyleSheet.create({ const styles = StyleSheet.create({
spacing: { spacing: {
marginVertical: 16, marginVertical: 10,
}, },
}) })

View File

@ -28,7 +28,7 @@ export const HabitEditForm: React.FC<HabitEditFormProps> = ({ habit }) => {
const { const {
control, control,
handleSubmit, handleSubmit,
formState: { errors }, formState: { errors, isValid },
} = useForm<HabitEditData>({ } = useForm<HabitEditData>({
mode: "onChange", mode: "onChange",
resolver: zodResolver(HabitEditSchema), resolver: zodResolver(HabitEditSchema),
@ -80,7 +80,7 @@ export const HabitEditForm: React.FC<HabitEditFormProps> = ({ habit }) => {
style={[ style={[
styles.spacing, styles.spacing,
{ {
width: "90%", width: "96%",
}, },
]} ]}
mode="outlined" mode="outlined"
@ -103,7 +103,7 @@ export const HabitEditForm: React.FC<HabitEditFormProps> = ({ habit }) => {
render={({ field: { onChange, value } }) => { render={({ field: { onChange, value } }) => {
return ( return (
<ColorPicker <ColorPicker
style={[styles.spacing, { width: "90%" }]} style={[styles.spacing, { width: "96%" }]}
value={value} value={value}
onComplete={(value) => { onComplete={(value) => {
onChange(value.hex) onChange(value.hex)
@ -153,8 +153,8 @@ export const HabitEditForm: React.FC<HabitEditFormProps> = ({ habit }) => {
mode="contained" mode="contained"
onPress={handleSubmit(onSubmit)} onPress={handleSubmit(onSubmit)}
loading={habitEdit.state === "loading"} loading={habitEdit.state === "loading"}
disabled={habitEdit.state === "loading"} disabled={habitEdit.state === "loading" || !isValid}
style={[styles.spacing, { width: "90%" }]} style={[styles.spacing, { width: "96%" }]}
> >
Save Save
</Button> </Button>
@ -166,7 +166,7 @@ export const HabitEditForm: React.FC<HabitEditFormProps> = ({ habit }) => {
}} }}
loading={habitStop.state === "loading"} loading={habitStop.state === "loading"}
disabled={habitStop.state === "loading"} disabled={habitStop.state === "loading"}
style={[styles.spacing, { width: "90%" }]} style={[styles.spacing, { width: "96%" }]}
> >
Stop Stop
</Button> </Button>