Skip to content

Commit

Permalink
Folder structure changes
Browse files Browse the repository at this point in the history
  • Loading branch information
wdevon99 committed Mar 3, 2024
1 parent e309b6f commit ffc9f13
Show file tree
Hide file tree
Showing 11 changed files with 245 additions and 237 deletions.
145 changes: 2 additions & 143 deletions src/app/dashboard/page.tsx
Original file line number Diff line number Diff line change
@@ -1,143 +1,2 @@
"use client"

import TodoService from "@services/TodoService";
import styles from "./page.module.sass";
import { useEffect, useState } from "react";
import { Button, Card, Form, Input, List, Modal, Skeleton, Space, message } from "antd";
import { PlusOutlined, DeleteOutlined } from '@ant-design/icons';
import { useSession } from "next-auth/react";
import TextArea from "antd/es/input/TextArea";

export default function Dashboard() {
const CARD_WIDTH = 670;

const { data: session } = useSession();
const [messageApi, contextHolder] = message.useMessage();

const [form] = Form.useForm();
const [isBusy, setIsBusy] = useState(false);
const [isLoading, setIsLoading] = useState(true);
const [todos, setTodos] = useState([]);
const [isAddTodoModalOpen, setIsAddTodoModalOpen] = useState(false);

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

const getAllTodos = async () => {
setIsLoading(true);

try {
const response = await TodoService.getAllTodos();

// TODO :: Handle errors based on response status
const todos = await response.json();

setTodos(Array.isArray(todos) ? todos : []);

} catch (error) {
console.error(error);
} finally {
setIsLoading(false);
}
};

const createTodo = async () => {
setIsBusy(true);

try {
const values = await form?.validateFields();
const { todoTitle, todoDescription } = values;

const response = await TodoService.createTodo(todoTitle, todoDescription);
const newTodo = await response.json();
const updatedTodos: any = [...(todos ?? []), newTodo];

setTodos(updatedTodos);
form?.resetFields();
setIsAddTodoModalOpen(false)
messageApi.success("Added new todo");

} catch (error) {
console.error(error);
} finally {
setIsBusy(false);
}
};

const deleteTodo = async (todoId: string) => {
const response = await TodoService.deleteTodo(todoId);
const deletedTodoId = await response.text();
const filteredTodos = todos?.filter((t: any) => t._id !== deletedTodoId);
messageApi.success("Deleted todo");

setTodos(filteredTodos);
};

const renderHeader = () => (
<>
<h1 className={styles.heading}>Hi {session?.user?.name?.split(' ')?.[0]} :)</h1>
<h2 className={styles.sub_heading}>Track your todos with ease.</h2>
</>
)

return (
<main className={styles.container}>
{contextHolder}
{renderHeader()}
<Card
title={`Here are your todos`}
extra={<Button type="primary" size="small" shape="circle" onClick={() => setIsAddTodoModalOpen(true)}><PlusOutlined /></Button>}
style={{ width: CARD_WIDTH }}
>
<List
className={styles.list}
loading={isLoading}
itemLayout="horizontal"
loadMore={null}
dataSource={todos}
renderItem={(todo, index) => (
<List.Item actions={[<Button type="link" danger key="list-delet" onClick={() => deleteTodo(todo._id)}><DeleteOutlined /></Button>]}>
<Skeleton title={false} loading={isLoading} active>
<List.Item.Meta
title={todo?.todoTitle}
description={todo?.todoDescription}
/>
</Skeleton>
</List.Item>
)}
/>
</Card>
<Modal
title="Add new todo"
open={isAddTodoModalOpen}
okText="Add"
okButtonProps={{ loading: isBusy }}
onOk={() => createTodo()}
onCancel={() => {
form?.resetFields();
setIsAddTodoModalOpen(false)
}}
>
<p>What would you like to add to you todo list?</p>
<Form
form={form}
layout="vertical"
>
<Form.Item
name="todoTitle"
rules={[{ required: true, message: 'Todo title is required!' }]}
>
<Input placeholder="Todo title" />
</Form.Item>
<Form.Item
name="todoDescription"
rules={[{ required: true, message: 'Todo description is required!' }]}
>
<TextArea rows={4} placeholder="Todo description" />
</Form.Item>
</Form>
</Modal>
</main>
);
}
import Dashboard from "@components/pages/Dashboard";
export default Dashboard;
39 changes: 2 additions & 37 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,2 @@
import type { Metadata } from "next";
import { AntdRegistry } from '@ant-design/nextjs-registry';
import { Inter } from "next/font/google";
import { getServerSession } from "next-auth";
import AuthSessionProvider from "@components/providers/AuthSessionProvider";
import AntdConfigProvider from "@components/providers/AntdConfigProvider";
import "@styles/globals.css";

const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
title: "Full-stack starter template 2024",
description: "NextJs + NextAuth + Typescript + Mongo DB + Ant Design",
icons: { icon: "/logos/next-icon.svg" }
};

export default async function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
const session = await getServerSession();

return (
<html lang="en">
<AntdRegistry>
<AntdConfigProvider>
<AuthSessionProvider session={session}>
<body className={inter.className}>
{children}
</body>
</AuthSessionProvider>
</AntdConfigProvider>
</AntdRegistry>
</html>
);
}
import MainLayout from "@layouts/MainLayout";
export default MainLayout;
59 changes: 2 additions & 57 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,57 +1,2 @@
import Image from "next/image";
import { Row } from "antd";
import AuthCard from "@components/molecules/AuthCard";
import IconCard from "@components/molecules/IconCard";
import TECH_STACK_INFO from "@constants/TechStackInfo";
import CustomAvatar from "@components/atoms/CustomAvatar";
import styles from "./page.module.sass";

export default function Home() {

const renderHeader = () => (
<>
<Image
src='/logos/next.svg'
alt='Next logo'
width={100}
height={20}
/>
<h1 className={styles.heading}>Full-stack starter template 2024</h1>
<h2 className={styles.sub_heading}>NextJs + NextAuth + Typescript + Mongo DB + Ant Design</h2>
</>
)

const renderTechStack = () => (
<Row gutter={16}>
{TECH_STACK_INFO?.map((t) => (
<IconCard
key={t.name}
text={t.name}
iconPath={t.iconPath}
iconSize={35}
url={t.url}
/>
))}
</Row>
)

const renderFooter = () => (
<div className={styles.footer}>
<p className={styles.footer_text}>This template was created on 25th of February 2024.</p>
<CustomAvatar
image='/images/author.png'
mainText='Devon Wijesinghe'
subText='wdevon99'
/>
</div>
)

return (
<main className={styles.container}>
{renderHeader()}
{renderTechStack()}
<AuthCard />
{renderFooter()}
</main>
);
}
import Home from "@components/pages/Home";
export default Home;
143 changes: 143 additions & 0 deletions src/components/pages/Dashboard/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
"use client"

import { useEffect, useState } from "react";
import { Button, Card, Form, Input, List, Modal, Skeleton, message } from "antd";
import { PlusOutlined, DeleteOutlined } from '@ant-design/icons';
import { useSession } from "next-auth/react";
import TextArea from "antd/es/input/TextArea";
import TodoService from "@services/TodoService";
import styles from "./styles.module.sass";

export default function Dashboard() {
const CARD_WIDTH = 670;

const { data: session } = useSession();
const [messageApi, contextHolder] = message.useMessage();

const [form] = Form.useForm();
const [isBusy, setIsBusy] = useState(false);
const [isLoading, setIsLoading] = useState(true);
const [todos, setTodos] = useState([]);
const [isAddTodoModalOpen, setIsAddTodoModalOpen] = useState(false);

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

const getAllTodos = async () => {
setIsLoading(true);

try {
const response = await TodoService.getAllTodos();

// TODO :: Handle errors based on response status
const todos = await response.json();

setTodos(Array.isArray(todos) ? todos : []);

} catch (error) {
console.error(error);
} finally {
setIsLoading(false);
}
};

const createTodo = async () => {
setIsBusy(true);

try {
const values = await form?.validateFields();
const { todoTitle, todoDescription } = values;

const response = await TodoService.createTodo(todoTitle, todoDescription);
const newTodo = await response.json();
const updatedTodos: any = [...(todos ?? []), newTodo];

setTodos(updatedTodos);
form?.resetFields();
setIsAddTodoModalOpen(false)
messageApi.success("Added new todo");

} catch (error) {
console.error(error);
} finally {
setIsBusy(false);
}
};

const deleteTodo = async (todoId: string) => {
const response = await TodoService.deleteTodo(todoId);
const deletedTodoId = await response.text();
const filteredTodos = todos?.filter((t: any) => t._id !== deletedTodoId);
messageApi.success("Deleted todo");

setTodos(filteredTodos);
};

const renderHeader = () => (
<>
<h1 className={styles.heading}>Hi {session?.user?.name?.split(' ')?.[0]} :)</h1>
<h2 className={styles.sub_heading}>Track your todos with ease.</h2>
</>
)

return (
<main className={styles.container}>
{contextHolder}
{renderHeader()}
<Card
title={`Here are your todos`}
extra={<Button type="primary" size="small" shape="circle" onClick={() => setIsAddTodoModalOpen(true)}><PlusOutlined /></Button>}
style={{ width: CARD_WIDTH }}
>
<List
className={styles.list}
loading={isLoading}
itemLayout="horizontal"
loadMore={null}
dataSource={todos}
renderItem={(todo, index) => (
<List.Item actions={[<Button type="link" danger key="list-delet" onClick={() => deleteTodo(todo._id)}><DeleteOutlined /></Button>]}>
<Skeleton title={false} loading={isLoading} active>
<List.Item.Meta
title={todo?.todoTitle}
description={todo?.todoDescription}
/>
</Skeleton>
</List.Item>
)}
/>
</Card>
<Modal
title="Add new todo"
open={isAddTodoModalOpen}
okText="Add"
okButtonProps={{ loading: isBusy }}
onOk={() => createTodo()}
onCancel={() => {
form?.resetFields();
setIsAddTodoModalOpen(false)
}}
>
<p>What would you like to add to you todo list?</p>
<Form
form={form}
layout="vertical"
>
<Form.Item
name="todoTitle"
rules={[{ required: true, message: 'Todo title is required!' }]}
>
<Input placeholder="Todo title" />
</Form.Item>
<Form.Item
name="todoDescription"
rules={[{ required: true, message: 'Todo description is required!' }]}
>
<TextArea rows={4} placeholder="Todo description" />
</Form.Item>
</Form>
</Modal>
</main>
);
}
File renamed without changes.
Loading

0 comments on commit ffc9f13

Please sign in to comment.