diff --git a/app/Nova/Dashboards/Main.php b/app/Nova/Dashboards/Main.php index 51f22dd54..b7e514e6c 100644 --- a/app/Nova/Dashboards/Main.php +++ b/app/Nova/Dashboards/Main.php @@ -7,6 +7,7 @@ namespace App\Nova\Dashboards; +use App\Models\Event; use App\Models\Travel; use App\Models\TravelAssignment; use App\Nova\Metrics\ActiveAttendanceBreakdown; @@ -16,6 +17,7 @@ use App\Nova\Metrics\MembersByFiscalYear; use App\Nova\Metrics\PaymentReceivedForTravel; use App\Nova\Metrics\PaymentsPerDay; +use App\Nova\Metrics\RsvpSourceBreakdown; use App\Nova\Metrics\TransactionsByDuesPackage; use App\Nova\Metrics\TravelAuthorityRequestReceivedForTravel; use Carbon\Carbon; @@ -108,6 +110,32 @@ public function cards(): array $cards[] = new EmergencyContactInformationForTravel($travel->id); } + foreach (Event::all() as $event) { + $should_include = false; + + if ($event->rsvps()->count() > 0) { + $should_include = true; + } + if ($event->attendance()->count() > 0) { + $should_include = true; + } + if ($event->end_time === null) { + if ($event->start_time === null || $event->start_time < Carbon::now()) { + $should_include = false; + } + } elseif ($event->end_time < Carbon::now()) { + $should_include = false; + } + if (! $should_include) { + continue; + } + + $cards[] = (new RsvpSourceBreakdown($event->id)) + ->canSee(static fn (Request $request): bool => $request->user()->can('read-rsvps')); + $cards[] = (new ActiveAttendanceBreakdown(true, $event->id, 'event')) + ->canSee(static fn (Request $request): bool => $request->user()->can('read-attendance')); + } + return $cards; } @@ -137,6 +165,28 @@ public function cards(): array ]; } + if (request()->is('nova-api/metrics/active-attendance-breakdown-event-*')) { + $parts = Str::of(Str::of(request()->path())->explode('/')->last())->explode('-'); + $id = intval($parts->last()); + + return [ + (new ActiveAttendanceBreakdown(true, $id, 'event'))->canSee( + static fn (Request $request): bool => $request->user()->can('read-attendance') + ), + ]; + } + + if (request()->is('nova-api/metrics/rsvp-source-breakdown-*')) { + $parts = Str::of(Str::of(request()->path())->explode('/')->last())->explode('-'); + $id = intval($parts->last()); + + return [ + (new RsvpSourceBreakdown($id))->canSee( + static fn (Request $request): bool => $request->user()->can('read-rsvps') + ), + ]; + } + return $cards; } } diff --git a/app/Nova/Metrics/ActiveAttendanceBreakdown.php b/app/Nova/Metrics/ActiveAttendanceBreakdown.php index 9952f06e4..5b250e407 100644 --- a/app/Nova/Metrics/ActiveAttendanceBreakdown.php +++ b/app/Nova/Metrics/ActiveAttendanceBreakdown.php @@ -5,6 +5,7 @@ namespace App\Nova\Metrics; use App\Models\Attendance; +use App\Models\Event; use App\Models\User; use Illuminate\Http\Request; use Laravel\Nova\Metrics\Partition; @@ -17,23 +18,23 @@ class ActiveAttendanceBreakdown extends Partition */ public function name(): string { - return $this->showAllTime ? 'Active Attendees' : 'Attendees Last 4 Weeks'; - } + $ret = $this->showAllTime ? 'Active Attendees' : 'Attendees Last 4 Weeks'; + if ($this->resourceId !== null) { + $ret .= ' for '.Event::where('id', $this->resourceId)->sole()->name; + } - /** - * Whether to show based on all attendance records or only those from the last two weeks. - * - * @var bool - */ - protected $showAllTime = false; + return $ret; + } /** * Create a new ActiveAttendanceBreakdown metric. */ - public function __construct(bool $showAllTime = false) - { + public function __construct( + public bool $showAllTime = false, + public ?int $resourceId = null, + public ?string $attendableType = null + ) { parent::__construct(); - $this->showAllTime = $showAllTime; } /** @@ -41,6 +42,7 @@ public function __construct(bool $showAllTime = false) */ public function calculate(Request $request): PartitionResult { + $resourceId = $this->resourceId ?? $request->resourceId; // If a user is found, this will give "Active" in the active column, otherwise the column will be null $query = Attendance::selectRaw('count(distinct gtid) as aggregate') ->selectSub( @@ -50,10 +52,13 @@ public function calculate(Request $request): PartitionResult 'active' ); - if (isset($request->resourceId)) { + if ($resourceId !== null) { $query = $query - ->where('attendable_id', $request->resourceId) - ->where('attendable_type', $request->model()->getMorphClass()); + ->where('attendable_id', $resourceId) + ->where( + 'attendable_type', + $this->attendableType ?? $request->model()?->getMorphClass() + ); } if (! $this->showAllTime) { @@ -81,6 +86,7 @@ public function calculate(Request $request): PartitionResult */ public function uriKey(): string { - return 'active-attendance-breakdown'; + return $this->resourceId === null ? 'active-attendance-breakdown' : + '../'.$this->attendableType.'s/'.$this->resourceId.'/metrics/active-attendance-breakdown'; } } diff --git a/app/Nova/Metrics/RsvpSourceBreakdown.php b/app/Nova/Metrics/RsvpSourceBreakdown.php index d43bf3c62..53e084b93 100644 --- a/app/Nova/Metrics/RsvpSourceBreakdown.php +++ b/app/Nova/Metrics/RsvpSourceBreakdown.php @@ -4,9 +4,10 @@ namespace App\Nova\Metrics; +use App\Models\Event; use App\Models\Rsvp; use Illuminate\Database\Eloquent\Builder; -use Illuminate\Http\Request; +use Laravel\Nova\Http\Requests\NovaRequest; use Laravel\Nova\Metrics\Partition; use Laravel\Nova\Metrics\PartitionResult; @@ -14,18 +15,29 @@ class RsvpSourceBreakdown extends Partition { /** * The displayable name of the metric. - * - * @var string */ - public $name = 'RSVP Sources'; + public function name(): string + { + return $this->resourceId === null ? 'RSVP Sources' : 'RSVP Sources for '.Event::where( + 'id', + $this->resourceId + )->sole()->name; + } + + public function __construct(public ?int $resourceId = null) + { + parent::__construct(); + } /** * Calculate the value of the metric. */ - public function calculate(Request $request): PartitionResult + public function calculate(NovaRequest $request): PartitionResult { + $resourceId = $request->resourceId ?? $this->resourceId; + return $this->result( - Rsvp::where('event_id', $request->resourceId) + Rsvp::where('event_id', $resourceId) ->leftJoin('recruiting_visits', 'source', '=', 'visit_token') ->when( config('database.default') === 'mysql', @@ -53,6 +65,6 @@ static function (Builder $query): void { */ public function uriKey(): string { - return 'rsvp-source-breakdown'; + return $this->resourceId === null ? 'rsvp-source-breakdown' : 'rsvp-source-breakdown-'.$this->resourceId; } } diff --git a/app/Nova/User.php b/app/Nova/User.php index f270c36a3..195e002fa 100644 --- a/app/Nova/User.php +++ b/app/Nova/User.php @@ -33,6 +33,7 @@ use Laravel\Nova\Fields\Email; use Laravel\Nova\Fields\File; use Laravel\Nova\Fields\HasMany; +use Laravel\Nova\Fields\Hidden; use Laravel\Nova\Fields\MorphMany; use Laravel\Nova\Fields\MorphToMany; use Laravel\Nova\Fields\Number; @@ -111,6 +112,10 @@ class User extends Resource public function fields(NovaRequest $request): array { return [ + Hidden::make('Has Ever Logged In') + ->showOnCreating() + ->default(static fn (Request $r): bool => false), + Text::make('Username', 'uid') ->sortable() ->rules('required', 'max:127')