@extends('crm.layouts.app') @section('title', 'Dashboard') @section('content')
@if(session('error'))

{{ session('error') }}

@endif @if(session('success'))

{{ session('success') }}

@endif

Welcome back, {{ auth()->user()->name }}!

Here's what's happening with your studio today.

@if(!empty($isNewStudio) && !empty($bookingUrl)) {{-- A brand-new studio sees this instead of a wall of zeros: the one action that matters first (share the booking link) and what happens next. --}}

Get started

Your studio is ready. Here's step one.

Share your booking link. Clients send you the idea, placement and budget first — you review it, then offer times. No more digging through DMs.

{{ $bookingUrl }}
@foreach([ ['n' => '1', 'title' => 'Share your link', 'body' => 'Instagram bio, stories, anywhere clients find you.'], ['n' => '2', 'title' => 'Review requests', 'body' => 'Read the idea and references, then offer times that fit.'], ['n' => '3', 'title' => 'Consent signs itself', 'body' => 'Sent before the session, timestamped, kept on file.'], ] as $step)
{{ $step['n'] }}

{{ $step['title'] }}

{{ $step['body'] }}

@endforeach
@endif
Total Revenue
${{ number_format($totalRevenue, 2) }}

This month

Tips Earned
${{ number_format($totalTips, 2) }}

This month

Unpaid Invoices
{{ $unpaidInvoices }}

Requires attention

Overdue
{{ $dueInvoices }}

Past due date

@if(\App\Helpers\FeatureAccess::hasAccess('payroll'))
Total Artist Payouts
${{ number_format($totalArtistPayouts, 2) }}

All time

Pending Payouts
{{ $pendingPayouts }}

Awaiting processing

@endif

Body Part Activity Heatmap

@php $maxCount = $bodyPartStats->max('usage_count') ?: 1; $heatData = $bodyPartStats->keyBy('slug')->map(fn($bp) => $bp->usage_count); // Anatomical positions for each body part [cx, cy] $positions = [ 'head' => [125, 30], 'neck' => [125, 58], 'collarbone' => [125, 72], 'uppertrapezium' => [125, 65], 'chest' => [125, 95], 'stomach' => [125, 130], 'upperback' => [125, 90], 'lowerback' => [125, 135], 'leftflank' => [150, 115], 'rightflank' => [100, 115], 'leftshoulder' => [163, 75], 'leftaxila' => [155, 90], 'leftupperarm' => [172, 105], 'leftforearm' => [182, 145], 'leftwrist' => [188, 175], 'lefthand' => [192, 192], 'rightshoulder' => [87, 75], 'rightaxila' => [95, 90], 'rightupperarm' => [78, 105], 'rightforearm' => [68, 145], 'rightwrist' => [62, 175], 'righthand' => [58, 192], 'leftthigh' => [140, 210], 'leftcalf' => [143, 280], 'leftshin' => [140, 265], 'leftankle' => [142, 310], 'leftfoot' => [145, 328], 'rightthigh' => [110, 210], 'rightcalf' => [107, 280], 'rightshin' => [110, 265], 'rightankle' => [108, 310], 'rightfoot' => [105, 328], ]; @endphp
{{-- Body SVG --}}
{{-- Body silhouette --}} {{-- Head --}} {{-- Neck --}} {{-- Torso --}} {{-- Waist / hip --}} {{-- Left arm --}} {{-- Right arm --}} {{-- Left leg --}} {{-- Right leg --}} {{-- Heat circles at anatomical positions --}} @foreach($positions as $slug => [$cx, $cy]) @php $count = $heatData[$slug] ?? 0; if ($count === 0) continue; $ratio = $count / $maxCount; // Indigo gradient: low=light, high=dark $opacity = 0.25 + ($ratio * 0.65); $radius = 8 + ($ratio * 8); @endphp @if($ratio > 0.5) {{ $count }} @endif @endforeach

Darker = More sessions

{{-- Top body parts list --}}
@php $topParts = $bodyPartStats->where('usage_count', '>', 0)->sortByDesc('usage_count')->take(10); @endphp @if($topParts->count() > 0)

Most Popular Zones

@foreach($topParts as $part) @php $barWidth = ($part->usage_count / $maxCount) * 100; @endphp
{{ $part->label }} {{ $part->usage_count }} {{ Str::plural('session', $part->usage_count) }}
@endforeach
@else

No body part data available yet.

@endif

Tips Per Artist

@if($tipsPerArtist->count() > 0)
    @foreach($tipsPerArtist as $artist)
  • {{ substr($artist['name'], 0, 1) }}

    {{ $artist['name'] }}

    ${{ number_format($artist['total_tips'], 2) }}

  • @endforeach
@else

No artist data available.

@endif

Upcoming Appointments

Schedule Appointment
@if($upcomingAppointments->count() > 0)
    @foreach($upcomingAppointments as $appointment)
  • {{ $appointment->client ? substr($appointment->client->name, 0, 1) : 'N' }}

    {{ $appointment->client->name ?? 'Unknown Client' }}

    {{ $appointment->scheduled_at->format('M d, Y g:i A') }}

  • @endforeach
@else

No upcoming appointments scheduled.

Schedule Appointment
@endif
@endsection