Skip to content

Scan Details Page#6

Open
movntains wants to merge 12 commits intodevelopfrom
feature/scan-details
Open

Scan Details Page#6
movntains wants to merge 12 commits intodevelopfrom
feature/scan-details

Conversation

@movntains
Copy link
Owner

@movntains movntains commented Nov 11, 2025

Summary by CodeRabbit

  • New Features

    • Richer scan details payload and UI: structured scores, analysis, suggestions; new Content Scores, Scan Analysis, Content Suggestions sections; breadcrumbs, back link, status and formatted date.
  • Security

    • Authorization added and enforced for viewing scans via policy and controller changes.
  • Tests

    • Feature tests for scan view and access control.
  • Chores

    • Dev tooling added and minor config formatting (.gitignore, dev dependency, local config).

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 11, 2025

Walkthrough

Adds authorization and a ScanPolicy, returns a new ScanDetailsResource from ScanController@show, introduces frontend types/enums and multiple presentational Scan UI components, updates the scans show page to use richer scan details and breadcrumbs, and adds minor config/dev-dependency files and tests.

Changes

Cohort / File(s) Summary
Configuration & Dev Dependency
\.ddev/config\.yaml, composer\.json, storage/debugbar/\.gitignore
YAML formatting change to web_extra_exposed_ports; added barryvdh/laravel-debugbar to require-dev; added .gitignore under storage/debugbar.
Base Controller
app/Http/Controllers/Controller.php
Imported and enabled Illuminate\Foundation\Auth\Access\AuthorizesRequests trait on the base Controller.
Authorization Policy
app/Policies/ScanPolicy.php
New ScanPolicy with view(User $user, Scan $scan): bool enforcing ownership (scan.user_id === $user->getKey()).
Scan Controller & Resource
app/Http/Controllers/ScanController.php, app/Http/Resources/ScanDetailsResource.php
ScanController@show now calls $this->authorize('view', $scan), returns ScanDetailsResource::make($scan) and breadcrumbs; added ScanDetailsResource that serializes uuid, url, status, createdAt, scores, analysis, and suggestions.
Backend Tests
tests/Feature/Controllers/ScanControllerTest.php
Added tests: rendering scan show page with expected Inertia payload (including breadcrumbs and ScanDetails structure) and access-denial when a user requests another user's scan.
Frontend Types & Enums
resources/js/types/enums/scan.ts, resources/js/types/scan.d.ts
New ScanStatusEnum (pending, processing, completed, failed); added ScanOverview and ScanDetails interfaces; replaced prior ScanStatus usage with ScanStatusEnum; added createdAt, scores, analysis, suggestions fields.
Scans Show Page
resources/js/pages/scans/show.tsx
ScansShow signature updated to accept breadcrumbs and scan: ScanDetails; uses ScanStatusEnum for processing logic, stops polling via useEffect, renders Back link, formatted date, and conditionally renders ScanScores, ScanAnalysis, and ScanSuggestions when COMPLETED.
Heading Component
resources/js/components/heading.tsx
Added optional containerClasses?: string prop with default 'mb-4', used via cn to compose container class.
Scan UI Partials (new)
resources/js/pages/scans/partials/*
Added multiple presentational components: CTASuggestions, HeadlineSuggestions, HierarchySuggestions, ScanAnalysis, ScanAnalysisCard, ScanScoreCard, ScanScores, ScanStatus (now uses ScanStatusEnum, adds failed mapping), and ScanSuggestions.
Type changes in frontend pages
resources/js/pages/scans/show.tsx, resources/js/pages/scans/partials/ScanStatus.tsx
Updated props and imports to use ScanDetails and ScanStatusEnum; adjusted status handling and added failed UI mapping.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Browser as Frontend
    participant Server as Laravel
    participant DB as Database
    participant Auth as Authorization

    User->>Browser: Open scan show page (uuid)
    Browser->>Server: GET /scans/{uuid}
    Server->>DB: Retrieve Scan by UUID
    DB-->>Server: Scan model
    Server->>Auth: authorize('view', Scan)
    Auth-->>Server: allowed / denied
    alt allowed
        Server->>Server: Wrap with ScanDetailsResource + build breadcrumbs
        Server-->>Browser: 200 + ScanDetails + breadcrumbs
        Browser->>Browser: Evaluate scan.status (ScanStatusEnum)
        alt COMPLETED
            Browser->>Browser: Render ScanScores, ScanAnalysis, ScanSuggestions
        else PROCESSING
            Browser->>Browser: Show processing UI / continue polling
        else FAILED
            Browser->>Browser: Show failed UI
        end
    else denied
        Server-->>Browser: 403 Forbidden
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Files/areas needing extra attention:
    • Alignment between ScanDetailsResource (PHP) and frontend ScanDetails interface.
    • resources/js/pages/scans/partials/ScanScores.tsx — verify correct mapping of scores to cards.
    • Authorization semantics in app/Policies/ScanPolicy.php (ownership vs. shared/admin rules).
    • Polling teardown and status-check logic in resources/js/pages/scans/show.tsx.

Possibly related PRs

Poem

🐰
I hopped in code with gentle paws,
Guarded results with rightful laws;
Breadcrumb trails to guide each hop,
Scores and tips — a carrot crop;
Happy hops for every dev who stops! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Scan Details Page' clearly and directly summarizes the main objective of the pull request, which is to build a detailed scan results page with comprehensive UI components.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/scan-details

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Nov 11, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
resources/js/pages/scans/show.tsx (1)

52-55: Drop redundant toLocaleString() call.

formatDate already returns the display string, so the extra toLocaleString() on a string doesn’t add value and can be removed for clarity.

-              description={`Scanned on ${formatDate(scan.createdAt).toLocaleString()}`}
+              description={`Scanned on ${formatDate(scan.createdAt)}`}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 25769a4 and 40f0755.

⛔ Files ignored due to path filters (1)
  • composer.lock is excluded by !**/*.lock
📒 Files selected for processing (21)
  • .ddev/config.yaml (1 hunks)
  • app/Http/Controllers/Controller.php (1 hunks)
  • app/Http/Controllers/ScanController.php (2 hunks)
  • app/Http/Resources/ScanDetailsResource.php (1 hunks)
  • app/Policies/ScanPolicy.php (1 hunks)
  • composer.json (1 hunks)
  • resources/js/components/heading.tsx (1 hunks)
  • resources/js/pages/scans/partials/CTASuggestions.tsx (1 hunks)
  • resources/js/pages/scans/partials/HeadlineSuggestions.tsx (1 hunks)
  • resources/js/pages/scans/partials/HierarchySuggestions.tsx (1 hunks)
  • resources/js/pages/scans/partials/ScanAnalysis.tsx (1 hunks)
  • resources/js/pages/scans/partials/ScanAnalysisCard.tsx (1 hunks)
  • resources/js/pages/scans/partials/ScanScoreCard.tsx (1 hunks)
  • resources/js/pages/scans/partials/ScanScores.tsx (1 hunks)
  • resources/js/pages/scans/partials/ScanStatus.tsx (1 hunks)
  • resources/js/pages/scans/partials/ScanSuggestions.tsx (1 hunks)
  • resources/js/pages/scans/show.tsx (2 hunks)
  • resources/js/types/enums/scan.ts (1 hunks)
  • resources/js/types/scan.d.ts (1 hunks)
  • storage/debugbar/.gitignore (1 hunks)
  • tests/Feature/Controllers/ScanControllerTest.php (1 hunks)
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{php,js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use descriptive names for variables and methods (e.g., isRegisteredForDiscounts, not discount)

Files:

  • tests/Feature/Controllers/ScanControllerTest.php
  • resources/js/types/enums/scan.ts
  • resources/js/pages/scans/partials/CTASuggestions.tsx
  • resources/js/pages/scans/partials/HierarchySuggestions.tsx
  • app/Http/Resources/ScanDetailsResource.php
  • resources/js/pages/scans/partials/ScanScores.tsx
  • resources/js/pages/scans/partials/HeadlineSuggestions.tsx
  • resources/js/pages/scans/partials/ScanStatus.tsx
  • app/Policies/ScanPolicy.php
  • resources/js/pages/scans/partials/ScanSuggestions.tsx
  • resources/js/pages/scans/partials/ScanAnalysisCard.tsx
  • resources/js/pages/scans/partials/ScanScoreCard.tsx
  • app/Http/Controllers/ScanController.php
  • app/Http/Controllers/Controller.php
  • resources/js/types/scan.d.ts
  • resources/js/components/heading.tsx
  • resources/js/pages/scans/show.tsx
  • resources/js/pages/scans/partials/ScanAnalysis.tsx
**/*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.php: Always use curly braces for control structures, even for single-line bodies
Use PHP 8 constructor property promotion in __construct() and avoid empty constructors with zero parameters
Always use explicit return type declarations for methods/functions and appropriate parameter type hints
Prefer PHPDoc blocks over inline code comments; only use inline comments for very complex logic
Add useful array shape type definitions in PHPDoc when appropriate
Enum case names should be TitleCase (e.g., FavoritePerson, Monthly)

Files:

  • tests/Feature/Controllers/ScanControllerTest.php
  • app/Http/Resources/ScanDetailsResource.php
  • app/Policies/ScanPolicy.php
  • app/Http/Controllers/ScanController.php
  • app/Http/Controllers/Controller.php
{app,bootstrap,routes,resources,tests}/**/*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Do not call env() outside config files; use config('...') instead

Files:

  • tests/Feature/Controllers/ScanControllerTest.php
  • app/Http/Resources/ScanDetailsResource.php
  • app/Policies/ScanPolicy.php
  • app/Http/Controllers/ScanController.php
  • app/Http/Controllers/Controller.php
tests/**/*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

tests/**/*.php: Use model factories in tests; prefer existing factory states before manual setup
Use Faker helpers (e.g., $this->faker->word(), fake()->randomDigit()) following project convention
Prefer specific assertion helpers (e.g., assertForbidden, assertNotFound) over assertStatus(403/404)
When mocking in Pest, import Pest\Laravel\mock with use function Pest\Laravel\mock; or use $this->mock() per project convention
Use datasets to reduce duplication, especially for validation tests

Files:

  • tests/Feature/Controllers/ScanControllerTest.php
tests/{Feature,Unit}/**/*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

All tests must be Pest tests in tests/Feature and tests/Unit

Files:

  • tests/Feature/Controllers/ScanControllerTest.php
resources/js/**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

resources/js/**/*.{js,jsx,ts,tsx}: Prefer the

component for Inertia forms; use useForm helper when programmatic control or project conventions require it
Use Inertia router.visit() or for navigation instead of traditional links
Build Inertia forms with component or useForm helper per project conventions

Files:

  • resources/js/types/enums/scan.ts
  • resources/js/pages/scans/partials/CTASuggestions.tsx
  • resources/js/pages/scans/partials/HierarchySuggestions.tsx
  • resources/js/pages/scans/partials/ScanScores.tsx
  • resources/js/pages/scans/partials/HeadlineSuggestions.tsx
  • resources/js/pages/scans/partials/ScanStatus.tsx
  • resources/js/pages/scans/partials/ScanSuggestions.tsx
  • resources/js/pages/scans/partials/ScanAnalysisCard.tsx
  • resources/js/pages/scans/partials/ScanScoreCard.tsx
  • resources/js/types/scan.d.ts
  • resources/js/components/heading.tsx
  • resources/js/pages/scans/show.tsx
  • resources/js/pages/scans/partials/ScanAnalysis.tsx
resources/**/*.{blade.php,jsx,tsx,js,ts,html}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

resources/**/*.{blade.php,jsx,tsx,js,ts,html}: Use Tailwind CSS utility classes and follow existing Tailwind conventions in the project
Optimize Tailwind class placement/order; remove redundancy and group logically
When listing items, prefer gap-* utilities for spacing instead of margins
If the project supports dark mode, add matching dark: variants for new components/pages
Avoid deprecated Tailwind utilities; use v4 replacements (e.g., bg-black/* instead of bg-opacity-, shrink- instead of flex-shrink-*)

Files:

  • resources/js/types/enums/scan.ts
  • resources/js/pages/scans/partials/CTASuggestions.tsx
  • resources/js/pages/scans/partials/HierarchySuggestions.tsx
  • resources/js/pages/scans/partials/ScanScores.tsx
  • resources/js/pages/scans/partials/HeadlineSuggestions.tsx
  • resources/js/pages/scans/partials/ScanStatus.tsx
  • resources/js/pages/scans/partials/ScanSuggestions.tsx
  • resources/js/pages/scans/partials/ScanAnalysisCard.tsx
  • resources/js/pages/scans/partials/ScanScoreCard.tsx
  • resources/js/types/scan.d.ts
  • resources/js/components/heading.tsx
  • resources/js/pages/scans/show.tsx
  • resources/js/pages/scans/partials/ScanAnalysis.tsx
app/**/*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

app/**/*.php: Prefer Eloquent models/relationships and Model::query() over DB:: facade and raw queries
Prevent N+1 queries by eager loading related data
Use Laravel’s query builder for very complex database operations
Use Laravel authentication/authorization features (gates, policies, etc.)
Use native eager loading limiting (e.g., latest()->limit(10)) where appropriate

Files:

  • app/Http/Resources/ScanDetailsResource.php
  • app/Policies/ScanPolicy.php
  • app/Http/Controllers/ScanController.php
  • app/Http/Controllers/Controller.php
{routes/api.php,app/Http/Resources/**/*.php}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

For APIs, default to Eloquent API Resources and API versioning unless existing routes follow a different convention

Files:

  • app/Http/Resources/ScanDetailsResource.php
{app/**/*.php,resources/views/**/*.blade.php}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

When generating links, prefer named routes via route()

Files:

  • app/Http/Resources/ScanDetailsResource.php
  • app/Policies/ScanPolicy.php
  • app/Http/Controllers/ScanController.php
  • app/Http/Controllers/Controller.php
{app/Http/Controllers/**/*.php,app/Http/Requests/**/*.php}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use Form Request classes for validation instead of inline controller validation; include rules and custom messages

Files:

  • app/Http/Controllers/ScanController.php
  • app/Http/Controllers/Controller.php
🧠 Learnings (4)
📚 Learning: 2025-10-12T03:54:33.953Z
Learnt from: CR
Repo: movntains/website-content-analysis PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-12T03:54:33.953Z
Learning: Applies to tests/{Feature,Unit}/**/*.php : All tests must be Pest tests in tests/Feature and tests/Unit

Applied to files:

  • tests/Feature/Controllers/ScanControllerTest.php
📚 Learning: 2025-10-12T03:54:33.953Z
Learnt from: CR
Repo: movntains/website-content-analysis PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-12T03:54:33.953Z
Learning: Applies to tests/Browser/**/*.php : Use Laravel features (Event::fake, assertAuthenticated, factories, RefreshDatabase) within browser tests as needed; interact with the page and consider screenshots/pauses for debugging

Applied to files:

  • tests/Feature/Controllers/ScanControllerTest.php
📚 Learning: 2025-10-12T03:54:33.953Z
Learnt from: CR
Repo: movntains/website-content-analysis PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-12T03:54:33.953Z
Learning: Applies to app/**/*.php : Use Laravel authentication/authorization features (gates, policies, etc.)

Applied to files:

  • app/Http/Controllers/Controller.php
📚 Learning: 2025-10-12T03:54:33.953Z
Learnt from: CR
Repo: movntains/website-content-analysis PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-12T03:54:33.953Z
Learning: Applies to {app/Http/Controllers/**/*.php,app/Http/Requests/**/*.php} : Use Form Request classes for validation instead of inline controller validation; include rules and custom messages

Applied to files:

  • app/Http/Controllers/Controller.php
🧬 Code graph analysis (10)
tests/Feature/Controllers/ScanControllerTest.php (2)
app/Models/Scan.php (1)
  • Scan (48-139)
app/Traits/HasUuid.php (1)
  • getUuid (22-25)
app/Http/Resources/ScanDetailsResource.php (2)
app/Models/Scan.php (1)
  • Scan (48-139)
app/Traits/HasUuid.php (1)
  • getUuid (22-25)
resources/js/pages/scans/partials/ScanScores.tsx (2)
resources/js/components/heading-small.tsx (1)
  • HeadingSmall (1-8)
resources/js/pages/scans/partials/ScanScoreCard.tsx (1)
  • ScanScoreCard (9-29)
app/Policies/ScanPolicy.php (1)
app/Models/Scan.php (1)
  • Scan (48-139)
resources/js/pages/scans/partials/ScanSuggestions.tsx (4)
resources/js/components/heading-small.tsx (1)
  • HeadingSmall (1-8)
resources/js/pages/scans/partials/HeadlineSuggestions.tsx (1)
  • HeadlineSuggestions (5-26)
resources/js/pages/scans/partials/CTASuggestions.tsx (1)
  • CTASuggestions (5-26)
resources/js/pages/scans/partials/HierarchySuggestions.tsx (1)
  • HierarchySuggestions (5-26)
resources/js/pages/scans/partials/ScanScoreCard.tsx (1)
resources/js/components/ui/card.tsx (5)
  • Card (68-68)
  • CardHeader (68-68)
  • CardTitle (68-68)
  • CardDescription (68-68)
  • CardContent (68-68)
app/Http/Controllers/ScanController.php (1)
app/Http/Resources/ScanDetailsResource.php (1)
  • ScanDetailsResource (14-47)
resources/js/components/heading.tsx (1)
resources/js/lib/utils.ts (1)
  • cn (5-7)
resources/js/pages/scans/show.tsx (8)
resources/js/types/scan.d.ts (1)
  • ScanDetails (13-35)
resources/js/components/heading.tsx (1)
  • Heading (10-22)
resources/js/components/text-link.tsx (1)
  • TextLink (7-19)
resources/js/lib/utils.ts (1)
  • formatDate (9-21)
resources/js/pages/scans/partials/ScanStatus.tsx (1)
  • ScanStatus (11-20)
resources/js/pages/scans/partials/ScanScores.tsx (1)
  • ScanScores (13-38)
resources/js/pages/scans/partials/ScanAnalysis.tsx (1)
  • ScanAnalysis (13-38)
resources/js/pages/scans/partials/ScanSuggestions.tsx (1)
  • ScanSuggestions (14-24)
resources/js/pages/scans/partials/ScanAnalysis.tsx (2)
resources/js/components/heading-small.tsx (1)
  • HeadingSmall (1-8)
resources/js/pages/scans/partials/ScanAnalysisCard.tsx (1)
  • ScanAnalysisCard (8-22)
🪛 PHPMD (2.15.0)
app/Http/Resources/ScanDetailsResource.php

21-21: Avoid unused parameters such as '$request'. (undefined)

(UnusedFormalParameter)

app/Policies/ScanPolicy.php

17-17: Avoid unused parameters such as '$user'. (undefined)

(UnusedFormalParameter)


17-17: Avoid unused parameters such as '$scan'. (undefined)

(UnusedFormalParameter)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: ci
🔇 Additional comments (23)
resources/js/components/heading.tsx (2)

1-7: LGTM! Clean interface extension.

The import of the cn utility and the addition of the optional containerClasses prop to the interface follow best practices and enable flexible spacing customization.


10-12: The review comment is based on a misunderstanding of what changed.

The git diff for heading.tsx is empty, indicating that containerClasses = 'mb-4' was already the existing state in the codebase before this PR—not a new change being introduced. The code shown in the review comment reflects the current state of the file, not modifications.

All six existing usages of the Heading component work without issues:

  • None override containerClasses
  • Parent containers manage spacing independently (gap-4, mb-6)
  • No layout conflicts are present

Since this is not a new change, there is no breaking change to verify.

Likely an incorrect or invalid review comment.

composer.json (1)

22-22: LGTM! Standard development dependency.

The Laravel Debugbar is a helpful development tool for debugging and profiling. The version constraint is reasonable and it's correctly placed in require-dev.

.ddev/config.yaml (1)

16-20: LGTM! Formatting improvement.

The reformatting of web_extra_exposed_ports improves readability while maintaining the same configuration values.

storage/debugbar/.gitignore (1)

1-2: LGTM! Standard gitignore pattern.

This correctly excludes debugbar runtime files while keeping the gitignore tracked, which aligns with the debugbar dependency added in composer.json.

resources/js/pages/scans/partials/HierarchySuggestions.tsx (1)

1-26: LGTM! Well-structured component.

The component follows React and Tailwind conventions correctly. The use of array index as key is acceptable here since the hierarchy items are read-only and won't be reordered.

resources/js/pages/scans/partials/HeadlineSuggestions.tsx (1)

1-26: LGTM! Consistent with sibling components.

This component follows the same well-structured pattern as HierarchySuggestions, maintaining consistency across the suggestions components.

resources/js/types/enums/scan.ts (1)

1-7: LGTM! Proper TypeScript enum with helpful reference.

The enum follows TypeScript conventions with SCREAMING_SNAKE_CASE keys and lowercase string values that match the Laravel backend enum. The reference comment aids maintainability.

tests/Feature/Controllers/ScanControllerTest.php (2)

101-158: LGTM! Comprehensive test coverage.

The test correctly verifies the Inertia response structure, including all scan details (scores, analysis, suggestions) and breadcrumbs. The assertions match the ScanDetailsResource structure.


160-171: LGTM! Authorization properly tested.

The test correctly verifies that users cannot view other users' scans, using the recommended assertForbidden() helper per coding guidelines.

app/Http/Controllers/ScanController.php (2)

63-63: LGTM! Authorization properly implemented.

The authorization check follows Laravel conventions and ensures users can only view their own scans. This aligns with the policy tested in ScanControllerTest.php.


66-70: LGTM! Resource wrapping and breadcrumbs well-structured.

The use of ScanDetailsResource provides a consistent, typed API response format. The breadcrumbs structure matches test expectations and uses named routes per coding guidelines.

app/Http/Controllers/Controller.php (1)

7-11: LGTM!

The AuthorizesRequests trait addition enables authorization helpers (e.g., $this->authorize()) across all controllers, which aligns with Laravel best practices and supports the new policy-based authorization flow introduced in this PR.

app/Policies/ScanPolicy.php (2)

12-15: LGTM!

The ownership check correctly verifies that the scan belongs to the authenticated user using getKey(), which is the recommended approach for policy authorization.


17-20: Delete stub placeholder is appropriate.

The delete method currently returns false, which is a valid placeholder for future implementation. The static analysis warning about unused parameters is a false positive—this is a standard Laravel policy method signature.

resources/js/pages/scans/partials/ScanAnalysisCard.tsx (1)

1-22: LGTM!

The component is well-structured with proper TypeScript typing and responsive Tailwind classes. The card layout and content organization are clean and appropriate for displaying analysis information.

app/Http/Resources/ScanDetailsResource.php (1)

21-46: LGTM!

The resource structure is well-organized and comprehensive, properly mapping all scan data (scores, analysis, suggestions) to a clean JSON-ready format. The null coalescing operators for suggestions ensure empty arrays are returned when data is absent, which prevents frontend errors.

resources/js/pages/scans/partials/ScanAnalysis.tsx (1)

1-38: LGTM!

The component correctly maps all analysis values to their respective cards and follows a clean, consistent structure. The responsive 2-column grid layout is appropriate for displaying the four analysis sections.

resources/js/pages/scans/partials/CTASuggestions.tsx (1)

1-26: LGTM!

The component correctly handles both populated and empty states, with appropriate conditional rendering. The use of index-based keys is acceptable for this static list of suggestions.

resources/js/pages/scans/partials/ScanScoreCard.tsx (1)

1-29: LGTM!

The component is well-designed with proper TypeScript typing, a sensible default for scoreMaxValue, and correct number conversion for the display value. The descriptive naming and clear structure make it easy to understand and maintain.

resources/js/pages/scans/partials/ScanSuggestions.tsx (1)

14-22: Clean composition of suggestion sections.

Nice job pulling the three suggestion blocks together behind a single heading with consistent spacing—reads clearly and keeps the partials focused.

resources/js/pages/scans/partials/ScanStatus.tsx (1)

12-17: Thanks for covering the failed status color.

The enum-based record keeps the badge styling type-safe and the new failed state matches the palette cleanly.

resources/js/types/scan.d.ts (1)

1-34: Frontend types now mirror the resource contract.

Appreciate how you synced the ScanDetails shape (scores, analysis, suggestions, createdAt) with the backend resource—should save a lot of guesswork.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
app/Policies/ScanPolicy.php (1)

10-16: LGTM! Clean ownership-based authorization.

The policy correctly implements ownership-based authorization, ensuring users can only view their own scans. The use of getKey() provides flexibility if the primary key configuration changes, and the strict comparison is appropriate.

Optional consideration: If your application requires administrative users or support staff to view all scans, you may want to add an additional check (e.g., $user->isAdmin() || $scan->user_id === $user->getKey()). However, this depends on your application's requirements and can be deferred if not currently needed.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 40f0755 and 993871c.

📒 Files selected for processing (1)
  • app/Policies/ScanPolicy.php (1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{php,js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use descriptive names for variables and methods (e.g., isRegisteredForDiscounts, not discount)

Files:

  • app/Policies/ScanPolicy.php
**/*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.php: Always use curly braces for control structures, even for single-line bodies
Use PHP 8 constructor property promotion in __construct() and avoid empty constructors with zero parameters
Always use explicit return type declarations for methods/functions and appropriate parameter type hints
Prefer PHPDoc blocks over inline code comments; only use inline comments for very complex logic
Add useful array shape type definitions in PHPDoc when appropriate
Enum case names should be TitleCase (e.g., FavoritePerson, Monthly)

Files:

  • app/Policies/ScanPolicy.php
app/**/*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

app/**/*.php: Prefer Eloquent models/relationships and Model::query() over DB:: facade and raw queries
Prevent N+1 queries by eager loading related data
Use Laravel’s query builder for very complex database operations
Use Laravel authentication/authorization features (gates, policies, etc.)
Use native eager loading limiting (e.g., latest()->limit(10)) where appropriate

Files:

  • app/Policies/ScanPolicy.php
{app/**/*.php,resources/views/**/*.blade.php}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

When generating links, prefer named routes via route()

Files:

  • app/Policies/ScanPolicy.php
{app,bootstrap,routes,resources,tests}/**/*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Do not call env() outside config files; use config('...') instead

Files:

  • app/Policies/ScanPolicy.php
🧬 Code graph analysis (1)
app/Policies/ScanPolicy.php (1)
app/Models/Scan.php (1)
  • Scan (48-139)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: ci

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
resources/js/pages/scans/show.tsx (1)

60-70: Consider implementing processing and failed state UI.

The TODO comments at lines 60-62 indicate incomplete functionality. While the ScanStatus badge provides baseline feedback, users would benefit from:

  • Processing state: A loading spinner or progress indicator with descriptive text
  • Failed state: An error message explaining what went wrong and potentially a retry action

Would you like me to generate implementation suggestions for these states, or should these be tracked in a separate issue?

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 993871c and 74e836e.

📒 Files selected for processing (2)
  • resources/js/pages/scans/partials/ScanScores.tsx (1 hunks)
  • resources/js/pages/scans/show.tsx (2 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{php,js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use descriptive names for variables and methods (e.g., isRegisteredForDiscounts, not discount)

Files:

  • resources/js/pages/scans/show.tsx
  • resources/js/pages/scans/partials/ScanScores.tsx
resources/js/**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

resources/js/**/*.{js,jsx,ts,tsx}: Prefer the

component for Inertia forms; use useForm helper when programmatic control or project conventions require it
Use Inertia router.visit() or for navigation instead of traditional links
Build Inertia forms with component or useForm helper per project conventions

Files:

  • resources/js/pages/scans/show.tsx
  • resources/js/pages/scans/partials/ScanScores.tsx
resources/**/*.{blade.php,jsx,tsx,js,ts,html}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

resources/**/*.{blade.php,jsx,tsx,js,ts,html}: Use Tailwind CSS utility classes and follow existing Tailwind conventions in the project
Optimize Tailwind class placement/order; remove redundancy and group logically
When listing items, prefer gap-* utilities for spacing instead of margins
If the project supports dark mode, add matching dark: variants for new components/pages
Avoid deprecated Tailwind utilities; use v4 replacements (e.g., bg-black/* instead of bg-opacity-, shrink- instead of flex-shrink-*)

Files:

  • resources/js/pages/scans/show.tsx
  • resources/js/pages/scans/partials/ScanScores.tsx
🧬 Code graph analysis (2)
resources/js/pages/scans/show.tsx (8)
resources/js/types/scan.d.ts (1)
  • ScanDetails (13-35)
resources/js/components/heading.tsx (1)
  • Heading (10-22)
resources/js/components/text-link.tsx (1)
  • TextLink (7-19)
resources/js/lib/utils.ts (1)
  • formatDate (9-21)
resources/js/pages/scans/partials/ScanStatus.tsx (1)
  • ScanStatus (11-20)
resources/js/pages/scans/partials/ScanScores.tsx (1)
  • ScanScores (13-38)
resources/js/pages/scans/partials/ScanAnalysis.tsx (1)
  • ScanAnalysis (13-38)
resources/js/pages/scans/partials/ScanSuggestions.tsx (1)
  • ScanSuggestions (14-24)
resources/js/pages/scans/partials/ScanScores.tsx (2)
resources/js/components/heading-small.tsx (1)
  • HeadingSmall (1-8)
resources/js/pages/scans/partials/ScanScoreCard.tsx (1)
  • ScanScoreCard (9-29)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: ci
🔇 Additional comments (3)
resources/js/pages/scans/partials/ScanScores.tsx (1)

27-34: Previous bug has been fixed - LGTM!

The copy-paste error identified in the previous review has been corrected. SEO and Tone score cards now correctly receive scores.seo and scores.tone respectively instead of scores.clarity.

resources/js/pages/scans/show.tsx (2)

1-24: LGTM - Well-structured imports and type definitions.

The addition of type-safe enums (ScanStatusEnum) and detailed type definitions (ScanDetails) improves code maintainability and catches errors at compile time. The updated props interface correctly reflects the enhanced data structure.


25-33: LGTM - Proper polling implementation with cleanup.

The polling logic correctly stops when the scan is no longer in a processing state, preventing unnecessary server requests. The useEffect dependencies are properly specified.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant