Skip to content

Commit

Permalink
feat: todos all pages completed
Browse files Browse the repository at this point in the history
  • Loading branch information
vishalkondle-dev committed Jun 22, 2024
1 parent ba7839d commit fb56f81
Show file tree
Hide file tree
Showing 15 changed files with 1,280 additions and 97 deletions.
181 changes: 181 additions & 0 deletions app/(private)/todos/[_id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
'use client';

import { useForm } from '@mantine/form';
import {
ActionIcon,
AppShell,
Button,
Container,
Group,
Paper,
rem,
Select,
Stack,
TextInput,
} from '@mantine/core';
import { DatePickerInput } from '@mantine/dates';
import {
IconCaretUpDown,
IconCheck,
IconChevronRight,
IconCircleCheck,
IconTrash,
} from '@tabler/icons-react';
import axios from 'axios';
import { useEffect, useState } from 'react';
import { TodoPageActions } from '@/components/Todo';
import TodoSkelton from '@/components/Todo/TodoSkelton';
import useFetchData from '@/hooks/useFetchData';
import { TodoType } from '@/models/Todo';
import Todo from '@/components/Todo/Todo';
import { COLORS, STYLES } from '@/lib/constants';
import { failure, openModal } from '@/lib/client_functions';

const TodosPage = ({ params }: { params: { _id: string } }) => {
const { data, refetch, loading } = useFetchData(`/api/todos?type=list&_id=${params._id}`);
const [todoList, setTodoList] = useState<any[]>([]);

const form = useForm({
initialValues: {
_id: '',
todo: '',
list: '',
date: null as Date | null | undefined,
color: 'blue',
},
validate: {
todo: (value) => (value.length ? null : 'Enter todo'),
},
});

const setSelected = (todo: TodoType | null) => {
form.setValues({
_id: String(todo?._id) || '',
todo: todo?.todo || '',
list: todo?.list?._id ? String(todo?.list?._id) : '',
date: todo?.date ? new Date(todo?.date) : (undefined as Date | null | undefined),
color: todo?.color || 'blue',
});
};

const onSubmit = async () => {
const { _id, todo, list, date, color } = form.values;
await axios.put('/api/todos', { _id, todo, list: list || null, date, color }).then(() => {
form.reset();
refetch();
});
};

const getTodoLists = async () => {
try {
const res = await axios.get('/api/todos/todo-list');
setTodoList(res?.data);
} catch (error) {
failure('Something went wrong');
}
};

const onDelete = () => {
openModal(() => {
axios
.delete(`/api/todos?_id=${form.values._id}`)
.then(() => {
form.reset();
refetch();
})
.catch((err) => {
failure(err.response.data.error || 'Something went wrong');
});
});
};

useEffect(() => {
getTodoLists();
}, []);

return (
<AppShell
aside={{
width: 400,
breakpoint: 'xs',
collapsed: { mobile: !form.values._id, desktop: !form.values._id },
}}
>
<AppShell.Main p={0}>
<Container size="sm">
<TodoPageActions getTodoLists={getTodoLists} todoList={todoList} refetch={refetch} />
{loading ? (
<TodoSkelton />
) : (
<Stack>
{data?.map((todo: TodoType) => (
<Todo setSelected={setSelected} refetch={refetch} todo={todo} />
))}
</Stack>
)}
</Container>
</AppShell.Main>
<AppShell.Aside>
{form.values._id && (
<Paper px="md">
<Group my="md" justify="space-between">
<ActionIcon variant="subtle" radius={0} onClick={() => form.reset()} title="Discard">
<IconChevronRight />
</ActionIcon>
<ActionIcon variant="subtle" color="red" radius={0} title="Delete" onClick={onDelete}>
<IconTrash />
</ActionIcon>
</Group>
<form onSubmit={form.onSubmit(onSubmit)} onReset={() => form.reset()}>
<Stack>
<TextInput
{...form.getInputProps('todo')}
placeholder="Enter todo"
styles={STYLES}
rightSection={<IconCircleCheck />}
/>
<Select
{...form.getInputProps('list')}
data={todoList?.map(({ _id, title }) => ({ label: title, value: String(_id) }))}
placeholder="Select a list (optional)"
rightSection={<IconCaretUpDown />}
clearable
styles={STYLES}
/>
<DatePickerInput
{...form.getInputProps('date')}
placeholder="Pick date"
styles={STYLES}
clearable
/>
<Group wrap="nowrap" gap={rem(4)} justify="space-between">
{COLORS?.map((color) => (
<ActionIcon
color={`${color}.3`}
size="sm"
radius="xl"
key={color}
style={{ border: '1px solid gray' }}
onClick={() =>
form.setFieldValue('color', form.values.color === color ? '' : color)
}
>
{color === form.values.color && (
<IconCheck stroke={4} style={{ width: rem(14) }} />
)}
</ActionIcon>
))}
</Group>
<Button type="submit" color="teal" title="Update" fullWidth>
Update
</Button>
</Stack>
</form>
</Paper>
)}
</AppShell.Aside>
</AppShell>
);
};

export default TodosPage;
181 changes: 181 additions & 0 deletions app/(private)/todos/important/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
'use client';

import { useForm } from '@mantine/form';
import {
ActionIcon,
AppShell,
Button,
Container,
Group,
Paper,
rem,
Select,
Stack,
TextInput,
} from '@mantine/core';
import { DatePickerInput } from '@mantine/dates';
import {
IconCaretUpDown,
IconCheck,
IconChevronRight,
IconCircleCheck,
IconTrash,
} from '@tabler/icons-react';
import axios from 'axios';
import { useEffect, useState } from 'react';
import { TodoPageActions } from '@/components/Todo';
import TodoSkelton from '@/components/Todo/TodoSkelton';
import useFetchData from '@/hooks/useFetchData';
import { TodoType } from '@/models/Todo';
import Todo from '@/components/Todo/Todo';
import { COLORS, STYLES } from '@/lib/constants';
import { failure, openModal } from '@/lib/client_functions';

const TodosPage = () => {
const { data, refetch, loading } = useFetchData('/api/todos?type=important');
const [todoList, setTodoList] = useState<any[]>([]);

const form = useForm({
initialValues: {
_id: '',
todo: '',
list: '',
date: null as Date | null | undefined,
color: 'blue',
},
validate: {
todo: (value) => (value.length ? null : 'Enter todo'),
},
});

const setSelected = (todo: TodoType | null) => {
form.setValues({
_id: String(todo?._id) || '',
todo: todo?.todo || '',
list: todo?.list?._id ? String(todo?.list?._id) : '',
date: todo?.date ? new Date(todo?.date) : (undefined as Date | null | undefined),
color: todo?.color || 'blue',
});
};

const onSubmit = async () => {
const { _id, todo, list, date, color } = form.values;
await axios.put('/api/todos', { _id, todo, list: list || null, date, color }).then(() => {
form.reset();
refetch();
});
};

const getTodoLists = async () => {
try {
const res = await axios.get('/api/todos/todo-list');
setTodoList(res?.data);
} catch (error) {
failure('Something went wrong');
}
};

const onDelete = () => {
openModal(() => {
axios
.delete(`/api/todos?_id=${form.values._id}`)
.then(() => {
form.reset();
refetch();
})
.catch((err) => {
failure(err.response.data.error || 'Something went wrong');
});
});
};

useEffect(() => {
getTodoLists();
}, []);

return (
<AppShell
aside={{
width: 400,
breakpoint: 'xs',
collapsed: { mobile: !form.values._id, desktop: !form.values._id },
}}
>
<AppShell.Main p={0}>
<Container size="sm">
<TodoPageActions getTodoLists={getTodoLists} todoList={todoList} refetch={refetch} />
{loading ? (
<TodoSkelton />
) : (
<Stack>
{data?.map((todo: TodoType) => (
<Todo setSelected={setSelected} refetch={refetch} todo={todo} />
))}
</Stack>
)}
</Container>
</AppShell.Main>
<AppShell.Aside>
{form.values._id && (
<Paper px="md">
<Group my="md" justify="space-between">
<ActionIcon variant="subtle" radius={0} onClick={() => form.reset()} title="Discard">
<IconChevronRight />
</ActionIcon>
<ActionIcon variant="subtle" color="red" radius={0} title="Delete" onClick={onDelete}>
<IconTrash />
</ActionIcon>
</Group>
<form onSubmit={form.onSubmit(onSubmit)} onReset={() => form.reset()}>
<Stack>
<TextInput
{...form.getInputProps('todo')}
placeholder="Enter todo"
styles={STYLES}
rightSection={<IconCircleCheck />}
/>
<Select
{...form.getInputProps('list')}
data={todoList?.map(({ _id, title }) => ({ label: title, value: String(_id) }))}
placeholder="Select a list (optional)"
rightSection={<IconCaretUpDown />}
clearable
styles={STYLES}
/>
<DatePickerInput
{...form.getInputProps('date')}
placeholder="Pick date"
styles={STYLES}
clearable
/>
<Group wrap="nowrap" gap={rem(4)} justify="space-between">
{COLORS?.map((color) => (
<ActionIcon
color={`${color}.3`}
size="sm"
radius="xl"
key={color}
style={{ border: '1px solid gray' }}
onClick={() =>
form.setFieldValue('color', form.values.color === color ? '' : color)
}
>
{color === form.values.color && (
<IconCheck stroke={4} style={{ width: rem(14) }} />
)}
</ActionIcon>
))}
</Group>
<Button type="submit" color="teal" title="Update" fullWidth>
Update
</Button>
</Stack>
</form>
</Paper>
)}
</AppShell.Aside>
</AppShell>
);
};

export default TodosPage;
7 changes: 1 addition & 6 deletions app/(private)/todos/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
import { Container } from '@mantine/core';
import { ReactNode } from 'react';

interface Props {
children: ReactNode;
}

export default async function RootLayout({ children }: Props) {
return (
<Container px={0} size="sm">
{children}
</Container>
);
return children;
}
Loading

0 comments on commit fb56f81

Please sign in to comment.