Build a Jira Clone With Nextjs, React, Tailwind, Hono.js | Part 2/2 (2024)

Code With AntonioAbout 13 min readMay 27, 2025Watch original
THE SUMMARYAI-generated

Key Concepts:

  • Jira Clone: A project to replicate the functionality of Jira, a popular project management tool.
  • Workspaces: Top-level containers for projects.
  • Projects: Containers for tasks, associated with a specific workspace.
  • Tasks: Individual units of work, assigned to members, with due dates, statuses, and positions.
  • Hono: A lightweight web framework used for creating API endpoints.
  • Appwrite: A backend-as-a-service platform used for database, storage, and authentication.
  • Zod: A TypeScript-first schema declaration and validation library.
  • React Big Calendar: A component for displaying events in a calendar format.
  • Hello-Pangia DND: A drag-and-drop library (fork of react-beautiful-dnd).
  • TanStack React Table: A headless UI for building powerful tables.
  • Lucid React: A library of icons.
  • Shadcn UI: A collection of accessible and reusable components.
  • Vercel: A platform for deploying web applications.
  • Oauth: An open standard for access delegation, commonly used for third-party authentication.

1. Implementing the Projects Entity:

  • Database Setup:
    • A new collection named "projects" is created in Appwrite.
    • Attributes are defined: workspaceID (string, required, size 50), imageURL (string, size 1,400,000, not required), and name (string, required, size 256).
    • Permissions are set to allow all users to create, read, update, and delete projects.
  • Environment Variables:
    • The project collection ID is added to environment.local.
  • Configuration:
    • A shorthand for the project ID is added to the config file.
  • API Endpoint:
    • A new feature folder "projects" is created with a server route (route.ts).
    • A Hono app instance is created and exported.
    • The project route is chained to the main API route (/api/projects).
  • Get Projects Route:
    • A GET route is created to retrieve all projects associated with a workspace.
    • It uses session middleware and Zod validation to ensure a valid workspaceID is provided as a query parameter.
    • The route checks if the user is a member of the workspace using getMember utility.
    • If the user is authorized, it retrieves projects from the database using databases.listDocuments, filtering by workspaceID and ordering by creation date.
    • The retrieved projects are returned as a JSON response.
  • UI Integration:
    • A Projects component is created to display the projects in the sidebar.
    • The component uses the useGetProjects hook to fetch the projects.
    • The component iterates over the projects and renders them as links.
    • The component uses usePathname from next/navigation to determine the active project.

2. Creating Projects:

  • Schema Definition:
    • A Zod schema (createProjectSchema) is created to validate the project creation form data.
    • The schema includes name (string, required), image (file, optional), and workspaceID (string, required).
  • Post Route:
    • A POST route is created to handle project creation.
    • It uses session middleware and Zod validation to validate the form data.
    • The route checks if the user is a member of the workspace.
    • It uploads the image to the Appwrite storage bucket.
    • It creates a new project in the database using databases.createDocument.
    • The newly created project is returned as a JSON response.
  • Use Create Project Hook:
    • A useCreateProject hook is created to handle the API call for project creation.
    • The hook uses client.api.projects.post to send the form data to the API endpoint.
    • The hook invalidates the projects query to refresh the project list after successful creation.
  • Model and Form:
    • A useCreateProjectModel hook is created to manage the state of the project creation modal.
    • A CreateProjectForm component is created to render the project creation form.
    • A CreateProjectModel component is created to render the project creation modal.
    • The CreateProjectModel is added to the DashboardLayout.
    • The Projects component in the sidebar is updated to open the CreateProjectModel when the "+" icon is clicked.

3. Building the Individual Project ID Page:

  • Page Creation:
    • A new page is created at app/dashboard/[workspaceID]/projects/[projectID]/page.tsx.
    • The page uses getCurrent to authenticate the user and redirects to /signin if not authenticated.
    • The page extracts the projectID from the route parameters.
  • Data Fetching:
    • A getProject query is created to fetch the project data from the database.
    • The query checks if the user is a member of the workspace associated with the project.
    • The query returns the project data if the user is authorized.
  • UI Implementation:
    • The page uses getProject to fetch the project data and displays it in a UI.
    • The UI includes the project name, image, and an "Edit Project" button.
  • Error Handling:
    • A global error handler is implemented to catch errors and display an error page.
    • A global loading indicator is implemented to display a loading animation while data is being fetched.

4. Implementing the Edit Project Functionality:

  • Schema Definition:
    • An updateProjectSchema is created to validate the project update form data.
    • The schema is similar to createProjectSchema but with optional fields.
  • Patch Route:
    • A PATCH route is created to handle project updates.
    • The route uses session middleware and Zod validation to validate the form data.
    • The route checks if the user is a member of the workspace associated with the project.
    • It updates the project in the database using databases.updateDocument.
    • The updated project is returned as a JSON response.
  • Use Update Project Hook:
    • A useUpdateProject hook is created to handle the API call for project updates.
    • The hook uses client.api.projects.patch to send the form data to the API endpoint.
    • The hook invalidates the projects query and the individual project query to refresh the UI after successful update.
  • Edit Project Form:
    • An EditProjectForm component is created to render the project update form.
    • The component uses the useUpdateProject hook to handle the API call.
    • The component includes fields for the project name and image.
  • Settings Page:
    • A new page is created at app/standalone/[workspaceID]/projects/[projectID]/settings/page.tsx.
    • The page uses getCurrent to authenticate the user and redirects to /signin if not authenticated.
    • The page uses getProject to fetch the project data and displays the EditProjectForm.

5. Implementing the Delete Project Functionality:

  • Delete Route:
    • A DELETE route is created to handle project deletion.
    • The route uses session middleware and extracts the projectID from the route parameters.
    • The route checks if the user is a member of the workspace associated with the project.
    • It deletes the project from the database using databases.deleteDocument.
    • The ID of the deleted project is returned as a JSON response.
  • Use Delete Project Hook:
    • A useDeleteProject hook is created to handle the API call for project deletion.
    • The hook uses client.api.projects.delete to send the request to the API endpoint.
    • The hook invalidates the projects query to refresh the project list after successful deletion.
  • Confirmation Model:
    • A confirmation model is added to the EditProjectForm to confirm the project deletion.
    • The useConfirm hook is used to manage the state of the confirmation model.

6. Building the Task View Switcher Component:

  • Component Creation:
    • A TaskViewSwitcher component is created to switch between different views of tasks (table, Kanban, calendar).
    • The component uses tabs from Shadcn UI to switch between the views.
    • The component includes a "New Task" button to open the task creation modal.
  • Data Fetching:
    • The component uses the useGetTasks hook to fetch the tasks.
  • UI Implementation:
    • The component renders the tabs for table, Kanban, and calendar views.
    • The component renders the "New Task" button.
    • The component renders dotted separators and placeholders for data filters.
  • Database Setup:
    • A new collection named "tasks" is created in Appwrite.
    • Attributes are defined: workspaceID (string, required, size 50), name (string, required, size 256), projectID (string, required, size 50), assignID (string, required, size 50), description (string, not required, size 248), dueDate (datetime, required), status (enum, required), and position (integer, required).
  • Task Status Enum:
    • A TaskStatus enum is created to define the possible statuses of a task (backlog, to-do, in progress, in review, done).

7. Implementing the Task Creation Functionality:

  • Schema Definition:
    • A createTaskSchema is created to validate the task creation form data.
    • The schema includes name (string, required), status (enum, required), workspaceID (string, required), projectID (string, required), dueDate (datetime, required), assignID (string, required), and description (string, optional).
  • Post Route:
    • A POST route is created to handle task creation.
    • The route uses session middleware and Zod validation to validate the form data.
    • The route checks if the user is a member of the workspace.
    • The route calculates the new position for the task based on the highest position task in the same status.
    • It creates a new task in the database using databases.createDocument.
    • The newly created task is returned as a JSON response.
  • Get Route:
    • A GET route is created to retrieve tasks based on various filters (workspaceID, projectID, status, search, assignID, dueDate).
    • The route uses session middleware and Zod validation to validate the query parameters.
    • The route checks if the user is a member of the workspace.
    • The route constructs a query based on the provided filters.
    • The route retrieves tasks from the database using databases.listDocuments.
    • The route populates the project and assign information for each task.
    • The retrieved tasks are returned as a JSON response.
  • Use Create Task Hook:
    • A useCreateTask hook is created to handle the API call for task creation.
    • The hook uses client.api.tasks.post to send the form data to the API endpoint.
    • The hook invalidates the tasks query to refresh the task list after successful creation.
  • Model and Form:
    • A useCreateTaskModel hook is created to manage the state of the task creation modal.
    • A CreateTaskForm component is created to render the task creation form.
    • A CreateTaskModel component is created to render the task creation modal.
    • The CreateTaskModel is added to the DashboardLayout.
    • The TaskViewSwitcher component is updated to open the CreateTaskModel when the "New Task" button is clicked.

8. Implementing Task Filters:

  • Use Task Filters Hook:
    • A useTaskFilters hook is created to manage the state of the task filters.
    • The hook uses useQueryStates from kn to persist the filter values in the URL.
  • Data Filters Component:
    • A DataFilters component is created to render the task filters.
    • The component includes select components for status, assignID, and projectID.
    • The component includes a date picker for dueDate.
    • The component uses the useTaskFilters hook to manage the filter values.
    • The component passes the filter values to the useGetTasks hook.

9. Implementing the Data Table Component:

  • Installation:
    • The 10stack/react-table package is installed.
  • Columns Definition:
    • A columns.tsx file is created to define the columns for the data table.
    • The columns include name, project, assign, dueDate, and status.
  • Data Table Component:
    • A DataTable component is created to render the data table.
    • The component uses the useReactTable hook from 10stack/react-table to manage the table state.
    • The component includes pagination, sorting, and filtering.
  • UI Enhancements:
    • The column headers are made sortable.
    • The dueDate column is formatted using the TaskDate component.
    • The status column is displayed using the Badge component.
    • An actions column is added to allow deleting tasks.

10. Implementing the Kanban View:

  • Installation:
    • The hello-pangea/dnd package is installed.
  • Data Kanban Component:
    • A DataKanban component is created to render the Kanban board.
    • The component uses the DragDropContext, Droppable, and Draggable components from hello-pangea/dnd to implement the drag-and-drop functionality.
    • The component uses the useCallback and useState hooks to manage the state of the tasks.
  • Kanban Column Header Component:
    • A KanbanColumnHeader component is created to render the header for each Kanban column.
    • The component displays the status and the number of tasks in the column.
  • Kanban Card Component:
    • A KanbanCard component is created to render each task card in the Kanban board.
    • The component displays the task name, project, assign, and due date.
  • Drag and Drop Logic:
    • The onDragEnd method is implemented to handle the drag-and-drop events.
    • The method updates the task status and position in the database.

11. Implementing the Calendar View:

  • Installation:
    • The react-big-calendar package is installed.
  • Data Calendar Component:
    • A DataCalendar component is created to render the calendar view.
    • The component uses the Calendar component from react-big-calendar to display the calendar.
    • The component uses the dateFnsLocalizer to format the dates.
  • Custom Styling:
    • Custom CSS styles are added to the data-calendar.css file to style the calendar.
  • Event Card Component:
    • An EventCard component is created to render the events in the calendar.
    • The component displays the task title, assign, and project.
  • Toolbar Component:
    • A custom toolbar component is created to navigate between months.

12. Implementing the My Tasks Page:

  • Page Creation:
    • A new page is created at app/dashboard/[workspaceID]/tasks/page.tsx.
    • The page uses getCurrent to authenticate the user and redirects to /signin if not authenticated.
    • The page renders the TaskViewSwitcher component.

13. Implementing the Task Details Page:

  • Page Creation:
    • A new page is created at app/dashboard/[workspaceID]/tasks/[taskID]/page.tsx.
    • The page uses getCurrent to authenticate the user and redirects to /signin if not authenticated.
  • Client Component:
    • A client.tsx file is created to render the client-side components.
    • The client component uses the useGetTask hook to fetch the task data.
    • The client component renders the task breadcrumbs, overview, and description.
  • Task Breadcrumbs Component:
    • A TaskBreadcrumbs component is created to display the breadcrumbs for the task.
  • Task Overview Component:
    • A TaskOverview component is created to display the overview of the task.
  • Task Description Component:
    • A TaskDescription component is created to display and edit the task description.

14. Implementing Analytics:

  • API Endpoint:
    • A new API endpoint is created to fetch analytics data for a project.
    • The endpoint calculates the total tasks, assigned tasks, completed tasks, incomplete tasks, and overdue tasks for the current month and the previous month.
  • Use Get Project Analytics Hook:
    • A useGetProjectAnalytics hook is created to handle the API call for fetching analytics data.
  • Analytics Component:
    • An Analytics component is created to display the analytics data.
    • The component uses the AnalyticsCard component to display each metric.

15. Implementing Oauth Logins:

  • GitHub Oauth:
    • A GitHub Oauth app is created.
    • The client ID and secret are added to the Appwrite console.
    • The oou.ts file is created to handle the Oauth logic.
    • The oou/route.ts file is created to handle the Oauth callback.
    • The "Login with GitHub" button is added to the sign-in card.
  • Google Oauth:
    • A Google Cloud project is created.
    • Oauth credentials are created in the Google Cloud console.
    • The client ID and secret are added to the Appwrite console.
    • The "Login with Google" button is added to the sign-in card.

16. Deployment:

  • The project is pushed to GitHub.
  • A new project is created in Vercel.
  • The environment variables are added to Vercel.
  • The project is deployed to Vercel.

17. Bug Fixes and Refactoring:

  • The task view switcher is updated to filter tasks by project ID.
  • The navigation bar is updated to display the correct title and description.
  • The server components are refactored to use client-side data fetching with React Query.
  • The router refresh calls are removed from the update and delete hooks.
  • The analytics invalidation is improved to ensure that the analytics data is always up-to-date.

Synthesis/Conclusion:

The YouTube video transcript details the comprehensive development of a Jira clone application using modern web technologies. It covers everything from database setup and API endpoint creation to UI implementation, drag-and-drop functionality, and deployment. The transcript emphasizes best practices, such as using Zod for validation, React Query for data fetching, and Shadcn UI for accessible components. It also provides detailed instructions for implementing Oauth logins and deploying the application to Vercel. The final steps involve refactoring the code to improve performance and maintainability. The project serves as a valuable learning resource for developers interested in building full-stack web applications with a focus on project management.

AI summaries can miss context or contain errors. Check important details against the original video.

Go a little deeper.

Have a question about this video? Load its transcript to open the video chat.