Skip to content

Commit

Permalink
delete habit
Browse files Browse the repository at this point in the history
  • Loading branch information
owengretzinger committed Dec 22, 2024
1 parent 9c940fc commit 0ec11bc
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 4 deletions.
1 change: 1 addition & 0 deletions src/api/habits/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './types';
export * from './use-create-habit';
export * from './use-delete-habit';
export * from './use-edit-habit';
export * from './use-habits';
export * from './use-press-habit-button';
3 changes: 2 additions & 1 deletion src/api/habits/mock-habits.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ export const mockHabits: { id: HabitIdT; data: DbHabitT }[] = [
export const setMockHabits = (
newHabits: { id: HabitIdT; data: DbHabitT }[],
) => {
Object.assign(mockHabits, newHabits);
mockHabits.length = 0;
mockHabits.push(...newHabits);
};

export const mockHabitCompletions: Record<HabitIdT, AllCompletionsT> = {
Expand Down
42 changes: 42 additions & 0 deletions src/api/habits/use-delete-habit.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { showMessage } from 'react-native-flash-message';
import { createMutation } from 'react-query-kit';

import { removeHabitFromOrder } from '@/core';

import { addTestDelay, queryClient } from '../common';
import { mockHabits, setMockHabits } from './mock-habits';
import { type DbHabitT, type HabitIdT } from './types';

type Response = DbHabitT;
type Variables = {
habitId: HabitIdT;
};

export const useDeleteHabit = createMutation<Response, Variables, Error>({
mutationFn: async ({ habitId }) => {
const habit = mockHabits.find((h) => h.id === habitId);
if (!habit) throw new Error('Habit not found');

const updatedHabits = mockHabits.filter((h) => h.id !== habitId);
setMockHabits(updatedHabits);
removeHabitFromOrder(habitId);

await addTestDelay(null);
return habit.data;
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['habits'] });
showMessage({
message: 'Habit deleted successfully',
type: 'success',
duration: 2000,
});
},
onError: () => {
showMessage({
message: 'Failed to delete habit',
type: 'danger',
duration: 2000,
});
},
});
34 changes: 33 additions & 1 deletion src/app/habits/edit-habit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
import { zodResolver } from '@hookform/resolvers/zod';
import { router } from 'expo-router';
import { useLocalSearchParams } from 'expo-router';
import { CheckIcon } from 'lucide-react-native';
import { CheckIcon, Trash2Icon } from 'lucide-react-native';
import { useColorScheme } from 'nativewind';
import * as React from 'react';
import { useForm } from 'react-hook-form';
import { Alert } from 'react-native';

import {
habitColorNames,
Expand All @@ -15,6 +16,7 @@ import {
useCreateHabit,
useEditHabit,
} from '@/api';
import { useDeleteHabit } from '@/api/habits/use-delete-habit';
import { HabitIcon, habitIcons } from '@/components/habit-icon';
import {
Button,
Expand Down Expand Up @@ -49,6 +51,7 @@ export default function EditHabit() {
const parsedHabit: HabitT = mode === 'edit' ? JSON.parse(habitJson) : null;
const createHabit = useCreateHabit();
const updateHabit = useEditHabit();
const deleteHabit = useDeleteHabit();

const { control, handleSubmit, setValue, watch } = useForm<HabitCreationT>({
resolver: zodResolver(habitCreationSchema),
Expand Down Expand Up @@ -82,6 +85,27 @@ export default function EditHabit() {
router.back();
};

const handleDelete = () => {
Alert.alert(
'Delete Habit',
'Are you sure you want to delete this habit? This action cannot be undone.',
[
{
text: 'Cancel',
style: 'cancel',
},
{
text: 'Delete',
style: 'destructive',
onPress: () => {
deleteHabit.mutate({ habitId: parsedHabit.id });
router.back();
},
},
],
);
};

return (
<ScreenContainer>
<Header
Expand Down Expand Up @@ -174,6 +198,14 @@ export default function EditHabit() {
</Switch.Root>
</View>
</View>
{mode === 'edit' && (
<Button
icon={Trash2Icon}
label="Delete Habit"
onPress={handleDelete}
variant="destructive"
/>
)}
<Button
label={mode === 'edit' ? 'Save Changes' : 'Create Habit'}
onPress={handleSubmit(onSubmit)}
Expand Down
4 changes: 3 additions & 1 deletion src/components/habit-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
type HabitIdT,
type HabitT,
type ParticipantWithIdT,
useDeleteHabit,
usePressHabitButton,
type UserIdT,
} from '@/api';
Expand Down Expand Up @@ -99,6 +100,7 @@ interface HabitHeaderProps {
const HabitHeader = ({ habit }: HabitHeaderProps) => {
const { colorScheme } = useColorScheme();
const { moveHabit, canMoveHabit } = useHabitOrder();
const deleteHabit = useDeleteHabit();

const menuItems = [
{
Expand Down Expand Up @@ -130,7 +132,7 @@ const HabitHeader = ({ habit }: HabitHeaderProps) => {
key: 'Delete habit',
title: 'Delete habit',
onSelect: () => {
alert('todo');
deleteHabit.mutate({ habitId: habit.id });
},
},
];
Expand Down
11 changes: 10 additions & 1 deletion src/core/hooks/use-habit-order.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function useHabitOrder() {

const initializeOrder = useCallback(
(habitIds: HabitIdT[]) => {
if (!parsedOrder.length) {
if (parsedOrder.length !== habitIds.length) {
setOrder(JSON.stringify(habitIds));
}
},
Expand Down Expand Up @@ -88,3 +88,12 @@ export function addHabitToOrder(habitId: HabitIdT) {
JSON.stringify([habitId, ...parsedOrder]),
);
}

export function removeHabitFromOrder(habitId: HabitIdT) {
const storage = new MMKV();
const currentOrder = storage.getString(HABIT_ORDER_KEY);
if (!currentOrder) return;
const parsedOrder: HabitIdT[] = JSON.parse(currentOrder);
const newOrder = parsedOrder.filter((id) => id !== habitId);
storage.set(HABIT_ORDER_KEY, JSON.stringify(newOrder));
}

0 comments on commit 0ec11bc

Please sign in to comment.