Skip to content

Commit

Permalink
fix: navigate to tasks page after task updating in offline mode
Browse files Browse the repository at this point in the history
  • Loading branch information
pavlo-skumenko committed Aug 17, 2024
1 parent 02012af commit e8da273
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 35 deletions.
4 changes: 3 additions & 1 deletion src/components/create-task/task-form-control.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,14 @@ export const TaskFormControl = () => {
}

setIsLoading(false);
isFormSubmitted.current = false;
},
(error) => {
setError('Failed navigate to tasks page. Please try again later.');
console.error('Firestore error: ', error);

setIsLoading(false);
isFormSubmitted.current = false;
}
);

Expand Down Expand Up @@ -69,7 +71,7 @@ export const TaskFormControl = () => {
};

if (isLoading) {
return <div>Loading task...</div>;
return <div>Loading...</div>;
}

if (error) {
Expand Down
50 changes: 47 additions & 3 deletions src/components/edit-task/task-form-control.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,51 @@ import { format } from 'date-fns';
import { Task, TaskFields } from '@/types';
import { DATE_FORMAT } from '@/constants';
import { taskFormSchema } from '@/components/task-form/task-form-schema';
import { updateTask } from '@/services/tasks';
import { getTasksCollection, updateTask } from '@/services/tasks';
import { useNavigate } from 'react-router-dom';
import { useEffect, useRef, useState } from 'react';
import { onSnapshot, query } from 'firebase/firestore';

interface TaskFormControlProps {
task: Task;
}

export const TaskFormControl = ({ task }: TaskFormControlProps) => {
const isFormSubmitted = useRef(false);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const navigate = useNavigate();

useEffect(() => {
const q = query(getTasksCollection());
const unsubscribe = onSnapshot(
q,
(snapshot) => {
setIsLoading(true);
setError(null);

const docChanges = snapshot.docChanges();
const isTaskCreated = docChanges.length && docChanges[0].type === 'modified';

if (isTaskCreated && isFormSubmitted.current) {
navigate('/tasks');
}

setIsLoading(false);
isFormSubmitted.current = false;
},
(error) => {
setError('Failed navigate to tasks page. Please try again later.');
console.error('Firestore error: ', error);

setIsLoading(false);
isFormSubmitted.current = false;
}
);

return () => unsubscribe();
}, [navigate]);

const form = useForm<TaskFields>({
resolver: zodResolver(taskFormSchema),
defaultValues: {
Expand All @@ -26,18 +61,27 @@ export const TaskFormControl = ({ task }: TaskFormControlProps) => {
});

const handleSubmit = async (values: TaskFields) => {
isFormSubmitted.current = true;

const formattedValues = {
...values,
deadline: format(values.deadline, DATE_FORMAT),
};

try {
await updateTask(task.id, formattedValues);
navigate('/tasks');
updateTask(task.id, formattedValues);
} catch (error) {
console.error('Error updating task: ', error);
}
};

if (isLoading) {
return <div>Loading...</div>;
}

if (error) {
return <div>Error: {error}</div>;
}

return <TaskForm form={form} onSubmit={handleSubmit} />;
};
50 changes: 43 additions & 7 deletions src/components/edit-task/task.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,67 @@
import { getTask } from '@/services/tasks';
import { getTasksCollection } from '@/services/tasks';
import { TaskFormControl } from './task-form-control';
import { useEffect, useState } from 'react';
import { Task as ITask } from '@/types';
import { onSnapshot, query } from 'firebase/firestore';

interface TaskProps {
id: string | null;
}

export const Task = ({ id }: TaskProps) => {
const [task, setTask] = useState<ITask | null | undefined>();
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);

// TODO: add loading state
useEffect(() => {
if (id) {
getTask(id)
.then((data) => setTask(data))
.catch((error) => console.error('Error getting task: ', error));
}
const q = query(getTasksCollection());
const unsubscribe = onSnapshot(
q,
(snapshot) => {
setIsLoading(true);
setError(null);

const doc = snapshot.docs.find((doc) => doc.id === id);

if (!doc) {
setTask(undefined);
return;
}

const todo = {
...(doc.data() as Omit<ITask, 'id'>),
id: doc.id,
};

setTask(todo);
setIsLoading(false);
},
(error) => {
setError('Failed to fetch task. Please try again later.');
console.error('Firestore error: ', error);

setIsLoading(false);
}
);

return () => unsubscribe();
}, [id]);

if (!id) {
return <div>Task id was not provided</div>;
}

if (isLoading) {
return <div>Loading tasks...</div>;
}

if (!task) {
return <div>Task not found</div>;
}

if (error) {
return <div>Error: {error}</div>;
}

return <TaskFormControl task={task} />;
};
20 changes: 7 additions & 13 deletions src/components/tasks/tasks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,13 @@ export const Tasks = () => {
setIsLoading(true);
setError(null);

try {
const todos = snapshot.docs.map((doc) => ({
...(doc.data() as Omit<ITask, 'id'>),
id: doc.id,
}));

setTasks(todos);
} catch (e) {
setError(e instanceof Error ? e.message : 'An unknown error occurred');
console.error('Error fetching tasks: ', e);
} finally {
setIsLoading(false);
}
const todos = snapshot.docs.map((doc) => ({
...(doc.data() as Omit<ITask, 'id'>),
id: doc.id,
}));

setTasks(todos);
setIsLoading(false);
},
(error) => {
setError('Failed to fetch tasks. Please try again later.');
Expand Down
13 changes: 2 additions & 11 deletions src/services/tasks/index.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,8 @@
import { Task } from '@/types';
import {
addDoc,
collection,
CollectionReference,
deleteDoc,
doc,
DocumentData,
getDoc,
updateDoc,
} from 'firebase/firestore';
import { addDoc, collection, CollectionReference, deleteDoc, doc, getDoc, updateDoc } from 'firebase/firestore';
import { db } from '../db';

export const getTasksCollection = (): CollectionReference<DocumentData, DocumentData> => {
export const getTasksCollection = (): CollectionReference => {
return collection(db, 'tasks');
};

Expand Down

0 comments on commit e8da273

Please sign in to comment.