Skip to main content
Back to ScopeForged

ScopeForged Documentation

Technical documentation, guides, and feature references for the ScopeForged client portal.

Dashboards & UI/Client Dashboard

Client Dashboard Guide

Last Updated: 2026-01-12 Status: Implemented Plan Reference: 013-client-dashboard.md, 081-client-dashboard-improvement.md


Overview

The Client Dashboard is the landing page for client users after logging into the portal. It provides an overview of their projects, invoices, recent files, and any pending actions or notifications relevant to their account.


Table of Contents

  1. Accessing the Dashboard
  2. Dashboard Sections
  3. Available Information
  4. Quick Actions
  5. Technical Architecture
  6. Related Features

Accessing the Dashboard

Access PointURLRole
Portal Home/portalClient User
Portal Dashboard/portal/dashboardClient User

Permissions

Only authenticated Client users can access the client dashboard. Admins are redirected to the Admin Dashboard.


Dashboard Sections

Welcome Section

Personalized greeting with:

  • User's name
  • Client company name
  • Quick summary of account status

Active Projects

Overview of current projects:

  • Project name and status
  • Progress indicator
  • Due date (if set)
  • Link to project details

Recent Invoices

Summary of billing:

  • Latest invoices
  • Payment status
  • Amount due
  • Quick pay link

Recent Files

Latest shared files:

  • File name and type
  • Upload date
  • Quick download link

Notifications

Unread notifications:

  • Recent alerts
  • Action items
  • Mark as read option

Available Information

Project Summary

ItemDescription
Active ProjectsCount of active projects
Total ProjectsAll projects for client
CompletedFinished projects
Files SharedTotal visible files

Invoice Summary

ItemDescription
OutstandingTotal unpaid amount
OverduePast due invoices
Last PaymentDate and amount
Payment HistoryLink to full history

Quick Stats

StatDescription
Active ProjectsCurrently in progress
Pending InvoicesAwaiting payment
Shared FilesAvailable downloads
Unread NotificationsAction needed

Quick Actions

Available Actions

ActionDescriptionLink
View ProjectsSee all projects/portal/projects
View InvoicesSee all invoices/portal/invoices
View FilesBrowse shared files/portal/files
Upload FileAdd file to projectProject page
Pay InvoiceMake paymentInvoice page
Contact SupportSend message/portal/support

Action Cards

Prominent action cards for common tasks:

  • View Latest Invoice - Direct link to most recent
  • Continue Project - Resume last viewed project
  • Download Files - Quick access to recent files

Technical Architecture

Controller

Location: app/Http/Controllers/Portal/DashboardController.php

class DashboardController extends Controller
{
    public function index(Request $request)
    {
        $user = $request->user();
        $clients = $user->clients;

        return view('portal.dashboard', [
            'user' => $user,
            'clients' => $clients,
            'projects' => $this->getProjects($clients),
            'invoices' => $this->getInvoices($clients),
            'files' => $this->getRecentFiles($clients),
            'stats' => $this->getStats($clients),
        ]);
    }

    protected function getProjects($clients)
    {
        return Project::whereIn('client_id', $clients->pluck('id'))
            ->active()
            ->latest()
            ->limit(5)
            ->get();
    }

    protected function getInvoices($clients)
    {
        return Invoice::whereIn('client_id', $clients->pluck('id'))
            ->whereIn('status', ['sent', 'overdue'])
            ->latest()
            ->limit(5)
            ->get();
    }

    protected function getStats($clients): array
    {
        $clientIds = $clients->pluck('id');

        return [
            'active_projects' => Project::whereIn('client_id', $clientIds)->active()->count(),
            'total_projects' => Project::whereIn('client_id', $clientIds)->count(),
            'outstanding_amount' => Invoice::whereIn('client_id', $clientIds)->unpaid()->sum('total'),
            'shared_files' => ProjectFile::whereHas('project', fn($q) => $q->whereIn('client_id', $clientIds))
                ->clientVisible()->count(),
        ];
    }
}

Routes

Route::prefix('portal')
    ->middleware(['auth', 'verified'])
    ->group(function () {
        Route::get('/', fn() => redirect()->route('portal.dashboard'));
        Route::get('/dashboard', [Portal\DashboardController::class, 'index'])
            ->name('portal.dashboard');
    });

View

Location: resources/views/portal/dashboard.blade.php

<x-portal-layout>
    <x-slot name="header">
        Welcome back, {{ $user->name }}!
    </x-slot>

    {{-- Stats Overview --}}
    <div class="grid grid-cols-4 gap-4 mb-6">
        <x-stat-card title="Active Projects" :value="$stats['active_projects']" />
        <x-stat-card title="Outstanding" :value="money($stats['outstanding_amount'])" />
        <x-stat-card title="Shared Files" :value="$stats['shared_files']" />
        <x-stat-card title="Notifications" :value="$user->unreadNotifications->count()" />
    </div>

    <div class="grid grid-cols-2 gap-6">
        {{-- Active Projects --}}
        <div class="bg-white rounded-lg shadow p-6">
            <h2 class="text-lg font-semibold mb-4">Active Projects</h2>
            @forelse($projects as $project)
                <x-project-card :project="$project" />
            @empty
                <p class="text-gray-500">No active projects</p>
            @endforelse
            <a href="{{ route('portal.projects.index') }}" class="text-blue-600">
                View all projects →
            </a>
        </div>

        {{-- Recent Invoices --}}
        <div class="bg-white rounded-lg shadow p-6">
            <h2 class="text-lg font-semibold mb-4">Recent Invoices</h2>
            @forelse($invoices as $invoice)
                <x-invoice-row :invoice="$invoice" />
            @empty
                <p class="text-gray-500">No pending invoices</p>
            @endforelse
            <a href="{{ route('portal.invoices.index') }}" class="text-blue-600">
                View all invoices →
            </a>
        </div>
    </div>

    {{-- Recent Files --}}
    <div class="mt-6 bg-white rounded-lg shadow p-6">
        <h2 class="text-lg font-semibold mb-4">Recent Files</h2>
        <div class="grid grid-cols-4 gap-4">
            @forelse($files as $file)
                <x-file-card :file="$file" />
            @empty
                <p class="text-gray-500 col-span-4">No files shared yet</p>
            @endforelse
        </div>
    </div>
</x-portal-layout>

Components

ComponentPurpose
stat-cardDisplay single metric
project-cardProject summary card
invoice-rowInvoice list item
file-cardFile preview card
notification-itemNotification entry

Multi-Client Support

Users associated with multiple clients see:

  • Client selector dropdown
  • Combined or per-client views
  • Aggregated statistics
// If user has multiple clients
@if($clients->count() > 1)
    <x-client-selector :clients="$clients" :selected="$selectedClient" />
@endif

Dependencies

FeatureRelationship
AuthenticationLogin required
AuthorizationClient role scope
Client ManagementClient association

Complementary Features

FeatureDescription
Admin DashboardAdmin view
Project ManagementProject details
InvoicingInvoice payments
File SharingFile downloads
NotificationsAlert system

Best Practices

For Usability

  1. Show actionable items first (pending invoices, action needed)
  2. Limit displayed items to most relevant
  3. Provide clear navigation to full lists
  4. Highlight overdue items with visual indicators

For Performance

  1. Cache client-specific data where appropriate
  2. Limit query results with pagination
  3. Eager load relationships to avoid N+1

Troubleshooting

IssueSolution
No projects shownCheck client association
Wrong client dataVerify user-client pivot
Missing filesCheck file visibility flags
Stats incorrectVerify client ID scoping

See Also