Tutorials
Build Freelancer Platform
List Projects

List projects for freelancer

In this tutorial, we will learn how to retrieve and render a list of data from ROQ in Next.js. We will use the ROQ SDK to query data from BaaS and render the data in a list.

This tutorial is about a straightforward Software as a Service (SaaS) platform for freelance workers. The platform will have two unique user roles, namely the Business Owner and the Freelancer. The Business Owner will be able to create projects while the Freelancer will have the ability to view and apply for projects. This tutorial will only cover the Freelancer role.

Project setup

Before we start, make sure to follow the previous tutorial:

  • Create project form and how to save projects

    The tutorial will guide you through the process of setting up a Next.js application and connecting it to ROQ BaaS. There are some changes to the code from the previous tutorial. These changes are necessary because we will build the app for the Freelancer role this time. The changes are:

    • Change the roles to freelancer when the user (freelancer) registers or sign-in.
    • Change the page to redirect to the freelancer page for any successful login.

    The pages.tsx page is responsible for user authentication. We will change the code to the following:

    src/app/page.tsx
    import { roqBrowserClient } from "@/lib/roq/roq-client";
     
    export default function Home() {
     
        const handleSignUp = async () => {
            await roqBrowserClient.signUp('freelancer', { postLoginRedirect: 'http://localhost:3000/freelancer' });
        };
     
        const handleSignIn = async () => {
            await roqBrowserClient.signIn('freelancer', { postLoginRedirect: 'http://localhost:3000/freelancer' });
        };
     
        return (
            {/* the code here is the same as before */}
        );
    }

Building project list page

We will build a simple project list to show all projects that have been created by the Business Owner. The project list will be displayed in the Freelancer page.

Create a project list page

Create a new page called page.tsx in the src/app/freelancer directory. The page will be the project list for the freelancer. The code below is the complete code for the page:

src/app/freelancer/page.tsx
import { roqBrowserClient } from "@/lib/roq/roq-client";
import { useSession } from '@/lib/roq/roq-hooks';
import { useEffect, useState } from 'react';
import { ItemType } from '@/interface/project-data-types';
import ProjectList from '../project-list';
 
export default function Projects() {
    const { session } = useSession();
    const [projects, setProjects] = useState<ItemType[]>([]);
 
    const roles = session?.user.roles || [];
 
    const logoutHandler = () => {
        roqBrowserClient.signOut();
    };
 
    useEffect(() => {
        const fetchProjectData = async () => {
            const projectData = await roqBrowserClient.project.findManyWithCount({
                orderBy: {
                    created_at: 'desc'
                }
            })
            return projectData
        }
 
        fetchProjectData().then((projects) => {
            setProjects(projects.data)
        })
 
    }, [])
 
    return (
        <div className="flex flex-col w-full h-screen bg-zinc-950">
            <nav className="flex justify-between items-center p-4 bg-zinc-800 shadow">
                <h1 className="text-white text-xl font-bold">Freelancer Inc.</h1>
                <div className="flex items-center gap-4">
                    <div>
                        <p className="text-gray-400 text-sm">
                            Logged in as: <span className="text-white">{session?.user.email}</span>
                        </p>
                        <p className="text-gray-400 text-sm">
                            Role: <span className="text-white">{roles[0]}</span>
                        </p>
                    </div>
                    <button onClick={logoutHandler} className="px-3 py-1 bg-indigo-500 rounded shadow text-white font-bold">
                        Log out
                    </button>
                </div>
            </nav>
            <ProjectList items={projects} />
        </div>
 
    );
}

The heart of this code is query data from BaaS using the ROQ SDK. The code below is the query data code:

const projectData = await roqBrowserClient.project.findManyWithCount({
    orderBy: {
        created_at: 'desc'
    }
})

The code above will retrieve all project data from BaaS and sort the data by the created_at field in descending order. The data will be rendered in the <ProjectList> component.

Create a project list component

Create a new component called project-list.tsx in the src/app directory. This component is the <ProjectList> component that we used in the previous code. The component will render the list of projects that the Business Owner has created.

src/app/project-list.tsx
import React from 'react';
import { ProjectListType } from '@/interface/project-data-types';
 
const List: React.FC<ProjectListType> = ({ items }) => {
 
    const handleApply = (projectId: string) => {
        // Logic to apply for the project
        console.log(`Applying for project with ID: ${projectId}`);
    };
 
    return (
        <div className="bg-gray-800 p-4 rounded-lg">
            {items.map((item, index) => (
                <div
                    key={index}
                    className="flex justify-between items-end bg-gray-700 text-white p-2 my-2 rounded-md shadow-md"
                >
                    <div>
                        <h3 className="text-lg font-semibold">{item.name}</h3>
                        <p>{item.description}</p>
                        <span className="text-indigo-400">{item.status}</span>
                    </div>
                    <button 
                        onClick={() => handleApply(item.id)}
                        disabled={item.status !== 'open'} 
                        className={`px-3 py-1 rounded shadow font-bold ${
                            item.status === 'open' ? 'bg-indigo-500 text-white' : 'bg-gray-500 text-gray-300'
                        }`}
                    >
                        Apply
                    </button>
                </div>
            ))}
        </div>
    )
};
 
export default List;

Add interface for project list

This page uses an interface to define the data type for the project list. Open the file called project-data-types.ts in the src/interface directory. Add this project list interface in the code and change the export type:

src/interface/project-data-types.ts
// the code here is the same as before 
 
interface ProjectListType {
    items: ItemType[];
}
 
export type { ItemType, ProjectListType, StatusMessageType, ProjectFormProps };

What have we built?

If you follow this tutorial from the beginning, we will build a simple project list page for the Freelancer role. The page displays all projects created by the Business Owner.

project list