Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

11 Commits

Repository files navigation

SkillVerse - Documentation

Contents

  1. Overview
  2. System Architecture
  3. Setup & Installation
  4. Authentication & User Management
  5. Core Features
  6. Technical Implementations
  7. Security
  8. Deployment
  9. Known Isuues

Overview

SkillVerse is a comprehensive freelance marketplace platform that connects clients with freelancers across various service categories. It is a platform that facilitates job posting, job applications, milestone tracking, file sharing, and secure payment processing. The backend is built with Node.js, Express, and MongoDB, providing RESTful API endpoints for the frontend to interact with. The frontend is built with React and Bootstrap CSS, providing users with a responsive, easy-to-navigate, modern UI.

System Architecture

The app is built using the MERN stack - MongoDB, Express, React, and Node.js. Specific technology stacks for the frontend and backend are given below.

Frontend

  • React 18+ with functional components and hooks
  • React Router for client-side navigation
  • Axios for HTTP requests with credentials
  • React Bootstrap for UI components
  • Bootstrap CSS for modern styling

Backend

  • Node.js with Express.js framework
  • MongoDB with Mongoose ORM
  • Passport.js with Google OAuth 2.0
  • Multer for file management
  • Express-session with MongoStore

External Services

  • Google OAuth for user authentication
  • Paystack for payment processing
  • Azure Web Services for hosting

Setup & Installation

Prerequisites

  • Node.js (v16.0.0 or higher)
  • MongoDB (v5.0 or higher)
  • npm or yarn
  • Google OAuth credentials
  • Paystack API keys

Environment Variables

In the backend directory, create a .env file with the following variables:

MONGO_URI:<your-mongo-uri>PORT:<port>GOOGLE_CLIENT_ID:<your-google-client-id>GOOGLE_CLIENT_SECRET:<your-google-client-secret>COOKIE_KEY:<your-cookie-key>PAYSTACK_SECRET_KEY:<your-paystack-secret-key>

Setup For Local Development

  1. Clone the Repository

    git clone https://github.com/SkillVerser/freelancer-management-platform.git
    cd freelancer-management-platform
  2. Install Dependencies

    # Install backend dependenciescd backend
    npm install
    # Install frontend dependenciescd frontend
    npm install
  3. Start Development Servers

    # Start backend servercd backend
    npm run dev
    # Start frontend servercd frontend
    npm start
  4. Visit Site

    • Frontend is hosted at localhost:3000 by default

Authentication & User Management

Google OAuth Implementation

The app makes use of Passport.js with the Google OAuth 2.0 strategy for user authentication. Users sign up and login via Google, and no sensitive information, such as emails or passwords, are stored in the database.

Authentication Flow

  1. User initiates Google OAuth login
  2. Authentication callback processes user data
  3. New users: redirect to role selection (client / freelancer)
  4. Existing users: redirect to role-appropriate dashboard
  5. Session persistence with MongoDB store and express-session

User Roles & Permissions

Clients

  • Post service requests different categories
  • Review freelancer applications
  • Create and track project milestones with payment integration
  • Access project files and monitor progress
  • View comprehensive job dashboard with progress indicators

Freelancers

  • Browse and apply for available projects
  • Manage profile, skills, and portfolio
  • Upload deliverables and update project progress in real-time
  • View accepted jobs dashboard with project details

Admins

  • Monitor comprehensive platform statistics and analytics
  • Manage user accounts and role change requests
  • Oversee all job listings
  • Process support tickets and user issues
  • Delete user accounts and manage permissions

Session Management

Sessions are managed using express-session with MongoDB persistence. This ensures scalability across multiple server instances.

app.use(session({secret: process.env.COOKIE_KEY,resave: false,saveUninitialized: false,cookie: {maxAge: 24*60*60*1000,sameSite: process.env.NODE_ENV==="production" ? "none" : "lax",secure: process.env.NODE_ENV==="production",},store: MongoStore.create({mongoUrl: process.env.MONGO_URI,collectionName: "sessions",}),}));

Core Features

Service Request System

The service request system forms the core of the marketplace, allowing clients to post jobs and freelancers to apply for them.

Service Categories

The platform supports five primary service categories:

  1. Software Development: Custom application and web development
  2. Data Science: Analytics, machine learning, and data processing
  3. Creating Logos: Brand identity and logo design
  4. Graphic Designer: Visual design and creative services
  5. Digital Marketing: SEO, social media, and marketing campaigns

Job Application System

Application Process (Freelancer)

  1. Browse Jobs: View available job listings with filtering options
  2. Job Selection: Choose a job to apply for with detailed requirements
  3. Application Form: Submit cover letter and proposed fee
  4. Validation: Form validation with error handling
  5. Confirmation: Receive success/error feedback
  6. Tracking: Monitor application status and responses

Application Review (Client)

  • View all applications for posted jobs
  • Review freelancer profiles and proposed fees
  • Accept suitable applications with confirmation workflow
  • Navigate to project management upon acceptance

Milestone Management System

Milestones break large projects into manageable chunks and provide clear progress tracking for both parties.

Milestone Features

  • Dynamic Creation: Add/remove milestones during project setup
  • Payment Integration: Milestone-based payments
  • Date Management: Due date tracking with formatted display
  • Status Management: Track completion status with visual indicators

Project Management Dashboard

The dashboard provides comprehensive project oversight with real-time updates and intuitive navigation, to both clients and freelancers.

Client Dashboard Features

  • Job Overview: Grid display of active projects with status indicators
    • Payment Tracking: Outstanding payments and payment history
    • Milestone Management: Create and track project milestones
    • File Access: Access deliverables uploaded by freelancer
  • Application Management: Review and manage freelancer applications
  • Progress Monitoring: Real-time project status updates and completion percentages

Status Indicators

  • No Freelancer Assigned: "View Applications" button
  • Freelancer Assigned: "View Details" button for project management
  • Progress Visualization: Completion percentages
  • Payment Status: Amount owed calculations and payment buttons

Freelancer Dashboard Features

  • Active Projects: Display of accepted jobs with client information
  • Project Details: Access to job requirements and milestone information
    • File Management: Upload and manage project deliverables
    • Progress Updates: Mark milestones as complete and update status
    • Payment Information: View received and outstanding payments

Technical Implementations

This section provides the technical implementations of various aspects of the app in the form of code snippets.

Contents

Database Models

The following are the core models of the system. There are others not shown, but they are are significantly less importance

//Application Model{jobId: {type: mongoose.Schema.Types.ObjectId,ref: "ServiceRequest",required: true,},freelancerId: {type: mongoose.Schema.Types.ObjectId,ref: "User",required: true,},coverLetter: {type: String,required: false,},price: {type: Number,required: true,},status: {type: String,default: "Pending",enum: ["Pending","Accepted","Rejected"],},createdAt: {type: Date,default: Date.now,},}//File Model{jobId: {type: mongoose.Schema.Types.ObjectId,ref: "ServiceRequest",required: true,},filename: {type: String,required: true,},originalName: {type: String,required: true,},fileSize: {type: Number,required: true,},uploadedBy: {type: mongoose.Schema.Types.ObjectId,ref: "User",required: true,},contentType: {type: String,required: true,},storagePath: {type: String,required: true,},}//Milestone Model{jobId: {type: mongoose.Schema.Types.ObjectId,ref: "ServiceRequest",required: true},description: {type: String,required: true},dueDate: {type: Date,required: true},status: {type: String,enum: ["Pending","Completed"],default: "Pending"}}//ServiceRequest Model{clientId: {type: mongoose.Schema.Types.ObjectId,ref: "User",required: true,},serviceType: {type: String,required: true,},freelancerId: {type: mongoose.Schema.Types.ObjectId,ref: "User",default: null,},status: {type: String,enum: ["Pending","Accepted","Completed","In Progress"],default: "Pending",},progressActual: {type: Number,default: 0,},progressPaid: {type: Number,default: 0,},price: {type: Number,default: 0,},paymentsMade: {type: Number,default: 0,},paymentsPending: {type: Number,default: 0,},}//User Model{googleID: {type: String,required: true,unique: true,},username: {type: String,required: true,unique: false,},role: {type: String,enum: ["client","freelancer","admin"],},}

Core Features Implementation Details

Service Request Workflow

  1. Service Request Creation

    consthandleServiceSelection=async(category)=>{constresponse=awaitaxios.post(`${API_URL}/api/service-requests/create`,{clientId: user._id,serviceType: category,description: `Request for ${category}`,},{withCredentials: true});};
  2. Application Submission

    consthandleSubmitApplication=async(e)=>{e.preventDefault();awaitaxios.post(`${API_URL}/api/service-requests/applications`,{
    jobId,freelancerId: user._id,
    coverLetter,proposedFee: parseFloat(fee),},{withCredentials: true});};
  3. Accept Application

    consthandleAcceptConfirmed=async()=>{try{awaitaxios.post(`${API_URL}/api/applications/jobs/accept/${pendingApplicationId}`,{},{withCredentials: true});setShowConfirmModal(false);setShowSuccessModal(true);}catch(error){console.error("Error accepting application:",error);alert("Error accepting application");}};
  4. Milestone Completion Update

    consthandleMilestoneComplete=async(milestoneId)=>{constres=awaitfetch(`${API_URL}/api/milestones/complete/${milestoneId}`,{method: "PUT",credentials: "include",});};

File Management

  • File Upload Configuration

    conststorage=multer.diskStorage({destination: function(req,file,cb){constuploadDir=path.join(__dirname,"../uploads");if(!fs.existsSync(uploadDir)){fs.mkdirSync(uploadDir,{recursive: true});}cb(null,uploadDir);},filename: function(req,file,cb){constuniqueName=Date.now()+"-"+file.originalname+path.extname(file.originalname);cb(null,uniqueName);},});constupload=multer({storage: storage,limits: {fileSize: 5_1024_1024},});

Milestone-based Payment Calculation

const{ progressActual, progressPaid }=serviceRequest;constprogressDelta=progressActual-progressPaid;constamountDue=(progressDelta/100)*serviceRequest.price;

Project Dashboard

  • Client

    constfetchJobs=async()=>{if(!userId||userId===null){console.error("User ID is not available or null");return;}try{constres=awaitfetch(`${API_URL}/api/service-requests/client/jobs/${userId}`,{method: "GET",credentials: "include",});if(res.ok){constdata=awaitres.json();setJobs(data);setError("");setSuccess("Jobs fetched successfully!");console.log(success);}else{setError("Failed to fetch jobs");console.log(error);}}catch(err){setError("Error fetching jobs: "+err.message);}};
  • Freelancer

    constfetchAcceptedJobs=async(freelancerId)=>{try{constres=awaitfetch(`${API_URL}/api/service-requests/freelancer/jobs/${freelancerId}`,{credentials: "include",});if(res.ok){constjobsData=awaitres.json();setAcceptedJobs(jobsData);console.log("Accepted jobs:",jobsData);}else{console.error("Failed to fetch accepted jobs");}}catch(err){console.error("Error fetching accepted jobs:",err);}finally{setLoading(false);}};

API Endpoints

Admin Routes

MethodEndpointDescription
GET/api/admin/statsGet platform statistics for admin dashboard

Application Routes

MethodEndpointDescription
GET/api/applications/jobs/:jobIdGet all applications for a job
POST/api/applications/jobs/accept/:applicationIdAccept a freelancer's application

Authentication Routes

MethodEndpointDescription
GET/auth/googleInitiates Google OAuth authentication
GET/auth/google/callbackGoogle OAuth callback URL
GET/auth/logoutLogs out the user
GET/auth/meReturns the currently authenticated user's data

File Routes

MethodEndpointDescription
POST/api/files/upload/:jobIdUpload a file for a job
GET/api/files/job/:jobIdGet all files for a job
GET/api/files/download/:fileIdDownload a specific file
DELETE/api/files/delete/:fileIdDelete a file

Milestone Routes

MethodEndpointDescription
POST/api/milestones/:jobIdCreate milestones for a job
GET/api/milestones/job/:jobIdGet all milestones for a job
PUT/api/milestones/complete/:milestoneIdMark a milestone as completed

Payment Routes

MethodEndpointDescription
POST/payments/create-checkout-sessionCreate a Paystack checkout session
POST/webhook/paystackWebhook endpoint for Paystack payment notifications

Service Request Routes

MethodEndpointDescription
POST/api/service-requests/createCreate a new service request
GET/api/service-requests/allGet all available service requests
POST/api/service-requests/applicationsSubmit an application for a service request
GET/api/service-requests/client/jobs/:idGet all jobs posted by a client
GET/api/service-requests/manage-jobsGet all service requests (admin function)
GET/api/service-requests/freelancer/jobs/:idGet all jobs assigned to a freelancer
GET/api/service-requests/job/:idGet details of a specific job

User Routes

MethodEndpointDescription
POST/usersCreate a new user
PUT/users/:idUpdate a user
GET/usersGet all users (admin function)
DELETE/users/:idDelete a user (admin function)
POST/users/create-userCreate or update user profile details
POST/users/set-roleSet a user's role after signup
POST/users/request-role-changeRequest a role change
GET/users/allticketsGet all pending role change requests
POST/users/process-requestProcess a role change request
GET/users/freelancer/:freelancerIdGet freelancer details
GET/users/profile/:userIdGet a user's profile details

Security

Security Measures

  • 3rd-Party authentication via Google OAuth for secure authentication
  • Session encryption with express-session and MongoDB persistence
  • Paystack webhook for signature validation for payments
  • Secure and unique file naming and file upload restrictions
  • Role-based access control
  • CORS protection for cross-origin requests

Deployment

Azure Web Services

This app has been deployed via an Azure Static Web App, and be accessed from this URL: https://lively-coast-034460503.6.azurestaticapps.net/

Known Issues

Currently, the file sharing system makes use of local storage on the server. In a real-world app, this presents persistence issues, as the contents in the server's local storage would be lost upon server restarts. Additionally, data in local storage is not shared across instances, which vastly limits the scalability of the app.
Ideally, file sharing would be implemented using Azure Blob Storage. This has several benefits:

  • Scalable: Can store much more data
  • Accessible: Files are available to all instances of the application
  • Resilient: Files aren't affected by server restarts or scaling events

However, since this app was built as a university project, and is not intended for real-world use, the local storage implementation, which is suitable for demonstration purporses, is sufficent.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors