- Increased icon sizes in service items, service orders, users, and technician management for better visibility. - Added custom loading indicators with appropriate icons in search fields for vehicles, work orders, and technicians. - Introduced invoice management routes for better organization and access control. - Created a new test for the estimate PDF functionality to ensure proper rendering and data integrity.
549 lines
26 KiB
Markdown
549 lines
26 KiB
Markdown
## Car Repairs Shop — AI agent working notes
|
||
|
||
This repo is a Laravel 12 app with Livewire (Volt + Flux UI), Tailwind, and Vite. The UI is primarily Livewire pages; a few classic controllers exist for resource routes. Tests use in-memory SQLite.
|
||
|
||
### Architecture map
|
||
- **Workflow-driven design**: The app implements an 11-step automotive repair workflow from vehicle reception to delivery with status tracking, inspections, estimates, and customer notifications.
|
||
- Core domains live in `app/Livewire/**` and `app/Models/**` (Customers, Vehicles, Inventory, JobCards, Estimates, Diagnosis, WorkOrders, Timesheets, Users, Reports, CustomerPortal).
|
||
- **WorkflowService** (`app/Services/WorkflowService.php`) orchestrates the complete repair process with methods for each workflow step.
|
||
- **InspectionChecklistService** (`app/Services/InspectionChecklistService.php`) manages standardized vehicle inspections and comparison logic.
|
||
- Routes are in `routes/web.php`:
|
||
- Root decides destination based on `auth()->user()->isCustomer()` → customers go to `/customer-portal`, admins/staff to `/dashboard`, guests to `/login`.
|
||
- Admin/staff area uses `admin.only` + `permission:*` middleware. Customer portal uses `auth` only.
|
||
- Volt pages registered via `Volt::route('settings/...', 'settings.something')`.
|
||
- Middleware aliases are registered in `bootstrap/app.php`:
|
||
- `admin.only`, `role`, `permission` point to custom classes in `app/Http/Middleware`. Route `permission:` strings are the canonical auth gates in this app.
|
||
- Settings use Spatie Laravel Settings (`app/Settings/**`, `config/settings.php`), e.g., `app(\App\Settings\GeneralSettings::class)` for shop phone/email in views.
|
||
- Blade components: anonymous components live under `resources/views/components/**`. Example: `<x-layouts.customer-portal />` is backed by `resources/views/components/layouts/customer-portal.blade.php`.
|
||
|
||
### 11-Step Workflow Implementation
|
||
The system follows a structured automotive repair workflow:
|
||
1. **Vehicle Reception** → `JobCard::STATUS_RECEIVED` - Basic data capture, unique sequence numbers by branch (`ACC/00212`, `KSI/00212`)
|
||
2. **Initial Inspection** → `JobCard::STATUS_INSPECTED` - Standardized checklist via `InspectionChecklistService`
|
||
3. **Service Assignment** → `JobCard::STATUS_ASSIGNED_FOR_DIAGNOSIS` - Assign to Service Coordinator
|
||
4. **Diagnosis** → `JobCard::STATUS_IN_DIAGNOSIS` - Full diagnostic with timesheet tracking
|
||
5. **Estimate** → `JobCard::STATUS_ESTIMATE_SENT` - Detailed estimate with email/SMS notifications
|
||
6. **Approval** → `JobCard::STATUS_APPROVED` - Customer approval triggers team notifications
|
||
7. **Parts Procurement** → `JobCard::STATUS_PARTS_PROCUREMENT` - Inventory management and sourcing
|
||
8. **Repairs** → `JobCard::STATUS_IN_PROGRESS` - Work execution with timesheet tracking
|
||
9. **Final Inspection** → `JobCard::STATUS_COMPLETED` - Outgoing inspection with discrepancy detection
|
||
10. **Delivery** → `JobCard::STATUS_DELIVERED` - Customer pickup and satisfaction tracking
|
||
11. **Archival** - Document archiving and job closure
|
||
|
||
### Conventions and patterns
|
||
- **Status-driven workflow**: Use `JobCard::getStatusOptions()` for consistent status handling. Each status corresponds to a workflow step.
|
||
- **Role hierarchy**: Service Supervisor → Service Coordinator → Technician. Use role helper methods like `$user->isServiceCoordinator()`.
|
||
- Livewire pages reside under `app/Livewire/{Area}/{Page}.php` with views under `resources/views/{area}/{page}.blade.php` (Volt routes may point directly to views).
|
||
- Authorization:
|
||
- Use `admin.only` to gate admin/staff routes.
|
||
- Use `permission:domain.action` strings on routes (e.g., `permission:customers.view`, `inventory.create`). Keep naming consistent with existing routes.
|
||
- **Branch-specific operations**: All job cards have `branch_code`. Use `JobCard::byBranch($code)` scope for filtering.
|
||
- Customer Portal layout requires a `jobCard` prop. When using `<x-layouts.customer-portal>`, pass it explicitly:
|
||
- Example: `<x-layouts.customer-portal :job-card="$jobCard"> ... </x-layouts.customer-portal>`
|
||
- **Inspection system**: Use `InspectionChecklistService` for standardized checklists. Incoming vs outgoing inspections are compared automatically.
|
||
|
||
### Developer workflows
|
||
- Install & run (common):
|
||
- PHP deps: `composer install`
|
||
- Node deps: `npm install`
|
||
- Generate key & migrate: `php artisan key:generate && php artisan migrate --seed`
|
||
- Dev loop (servers + queue + logs + Vite): `composer dev` (runs: serve, queue:listen, pail, vite)
|
||
- Asset build: `npm run build`
|
||
- Testing:
|
||
- Run tests: `./vendor/bin/phpunit` (uses in-memory SQLite per `phpunit.xml`)
|
||
- Alternative: `composer test` (clears config and runs `artisan test`)
|
||
- Debugging:
|
||
- Logs via Laravel Pail are included in `composer dev`. Otherwise: `php artisan pail`.
|
||
|
||
### Routing and modules (examples)
|
||
|
||
### Data Flow and State Management
|
||
- **Status-Driven Design**: Each workflow step corresponds to a specific JobCard status. Always use status constants from the model.
|
||
- **Service Dependencies**: WorkflowService orchestrates the complete flow, InspectionChecklistService handles standardized vehicle inspections.
|
||
- **Customer Communication**: Auto-notifications at each step keep customers informed of progress.
|
||
- **Quality Control**: Built-in inspection comparisons and quality alerts ensure consistent service delivery.
|
||
- Admin resources (with permissions):
|
||
- `Route::resource('customers', CustomerController::class)->middleware('permission:customers.view');`
|
||
- Inventory area pages are Livewire classes under `app/Livewire/Inventory/**` and grouped under `Route::prefix('inventory')` with `permission:inventory.*`.
|
||
- Customer portal routes:
|
||
- `Route::prefix('customer-portal')->middleware(['auth'])->group(function () { Route::get('/status/{jobCard}', \\App\\Livewire\\CustomerPortal\\JobStatus::class)->name('customer-portal.status'); });`
|
||
|
||
### Testing notes (project-specific)
|
||
- Tests use in-memory SQLite; avoid relying on factories that don’t exist. Prefer lightweight stubs or create the minimal model records needed.
|
||
- For Blade/Livewire views using a layout slot, render the page view (not the layout)
|
||
and pass required data. Example: `View::make('livewire.customer-portal.job-status', ['jobCard' => $jobCard])->render();`
|
||
|
||
### Guardrails for agents
|
||
- When adding new admin routes, wire `admin.only` and appropriate `permission:*` middleware, and register Volt pages via `Volt::route` when applicable.
|
||
- Keep anonymous Blade components under `resources/views/components/**` and pass required props explicitly.
|
||
- Use `app(\App\Settings\GeneralSettings::class)` for shop metadata instead of hardcoding.
|
||
- Follow existing permission key patterns (`domain.action`).
|
||
|
||
If anything above is unclear or you need deeper details (e.g., settings schema, specific Livewire page conventions), propose a short diff or ask for a quick pointer to the relevant file.
|
||
|
||
===
|
||
|
||
<laravel-boost-guidelines>
|
||
=== foundation rules ===
|
||
|
||
# Laravel Boost Guidelines
|
||
|
||
The Laravel Boost guidelines are specifically curated by Laravel maintainers for this application. These guidelines should be followed closely to enhance the user's satisfaction building Laravel applications.
|
||
|
||
## Foundational Context
|
||
This application is a Laravel application and its main Laravel ecosystems package & versions are below. You are an expert with them all. Ensure you abide by these specific packages & versions.
|
||
|
||
- php - 8.4.1
|
||
- laravel/framework (LARAVEL) - v12
|
||
- laravel/prompts (PROMPTS) - v0
|
||
- livewire/flux (FLUXUI_FREE) - v2
|
||
- livewire/livewire (LIVEWIRE) - v3
|
||
- livewire/volt (VOLT) - v1
|
||
- laravel/pint (PINT) - v1
|
||
- tailwindcss (TAILWINDCSS) - v4
|
||
|
||
|
||
## Conventions
|
||
- You must follow all existing code conventions used in this application. When creating or editing a file, check sibling files for the correct structure, approach, naming.
|
||
- Use descriptive names for variables and methods. For example, `isRegisteredForDiscounts`, not `discount()`.
|
||
- Check for existing components to reuse before writing a new one.
|
||
|
||
## Verification Scripts
|
||
- Do not create verification scripts or tinker when tests cover that functionality and prove it works. Unit and feature tests are more important.
|
||
|
||
## Application Structure & Architecture
|
||
- Stick to existing directory structure - don't create new base folders without approval.
|
||
- Do not change the application's dependencies without approval.
|
||
|
||
## Frontend Bundling
|
||
- If the user doesn't see a frontend change reflected in the UI, it could mean they need to run `npm run build`, `npm run dev`, or `composer run dev`. Ask them.
|
||
|
||
## Replies
|
||
- Be concise in your explanations - focus on what's important rather than explaining obvious details.
|
||
|
||
## Documentation Files
|
||
- You must only create documentation files if explicitly requested by the user.
|
||
|
||
|
||
=== boost rules ===
|
||
|
||
## Laravel Boost
|
||
- Laravel Boost is an MCP server that comes with powerful tools designed specifically for this application. Use them.
|
||
|
||
## Artisan
|
||
- Use the `list-artisan-commands` tool when you need to call an Artisan command to double check the available parameters.
|
||
|
||
## URLs
|
||
- Whenever you share a project URL with the user you should use the `get-absolute-url` tool to ensure you're using the correct scheme, domain / IP, and port.
|
||
|
||
## Tinker / Debugging
|
||
- You should use the `tinker` tool when you need to execute PHP to debug code or query Eloquent models directly.
|
||
- Use the `database-query` tool when you only need to read from the database.
|
||
|
||
## Reading Browser Logs With the `browser-logs` Tool
|
||
- You can read browser logs, errors, and exceptions using the `browser-logs` tool from Boost.
|
||
- Only recent browser logs will be useful - ignore old logs.
|
||
|
||
## Searching Documentation (Critically Important)
|
||
- Boost comes with a powerful `search-docs` tool you should use before any other approaches. This tool automatically passes a list of installed packages and their versions to the remote Boost API, so it returns only version-specific documentation specific for the user's circumstance. You should pass an array of packages to filter on if you know you need docs for particular packages.
|
||
- The 'search-docs' tool is perfect for all Laravel related packages, including Laravel, Inertia, Livewire, Filament, Tailwind, Pest, Nova, Nightwatch, etc.
|
||
- You must use this tool to search for Laravel-ecosystem documentation before falling back to other approaches.
|
||
- Search the documentation before making code changes to ensure we are taking the correct approach.
|
||
- Use multiple, broad, simple, topic based queries to start. For example: `['rate limiting', 'routing rate limiting', 'routing']`.
|
||
- Do not add package names to queries, package information is already shared. Use `test resource table`, not `filament 4 test resource table`.
|
||
|
||
### Available Search Syntax
|
||
- You can and should pass multiple queries at once. The most relevant results will be returned first.
|
||
|
||
1. Simple Word Searches with auto-stemming - query=authentication - finds 'authenticate' and 'auth'
|
||
2. Multiple Words (AND Logic) - query=rate limit - finds knowledge containing both "rate" AND "limit"
|
||
3. Quoted Phrases (Exact Position) - query="infinite scroll" - Words must be adjacent and in that order
|
||
4. Mixed Queries - query=middleware "rate limit" - "middleware" AND exact phrase "rate limit"
|
||
5. Multiple Queries - queries=["authentication", "middleware"] - ANY of these terms
|
||
|
||
|
||
=== laravel/core rules ===
|
||
|
||
## Do Things the Laravel Way
|
||
|
||
- Use `php artisan make:` commands to create new files (i.e. migrations, controllers, models, etc.). You can list available Artisan commands using the `list-artisan-commands` tool.
|
||
- If you're creating a generic PHP class, use `artisan make:class`.
|
||
- Pass `--no-interaction` to all Artisan commands to ensure they work without user input. You should also pass the correct `--options` to ensure correct behavior.
|
||
|
||
### Database
|
||
- Always use proper Eloquent relationship methods with return type hints. Prefer relationship methods over raw queries or manual joins.
|
||
- Use Eloquent models and relationships before suggesting raw database queries
|
||
- Avoid `DB::`; prefer `Model::query()`. Generate code that leverages Laravel's ORM capabilities rather than bypassing them.
|
||
- Generate code that prevents N+1 query problems by using eager loading.
|
||
- Use Laravel's query builder for very complex database operations.
|
||
|
||
### Model Creation
|
||
- When creating new models, create useful factories and seeders for them too. Ask the user if they need any other things, using `list-artisan-commands` to check the available options to `php artisan make:model`.
|
||
|
||
### APIs & Eloquent Resources
|
||
- For APIs, default to using Eloquent API Resources and API versioning unless existing API routes do not, then you should follow existing application convention.
|
||
|
||
### Controllers & Validation
|
||
- Always create Form Request classes for validation rather than inline validation in controllers. Include both validation rules and custom error messages.
|
||
- Check sibling Form Requests to see if the application uses array or string based validation rules.
|
||
|
||
### Queues
|
||
- Use queued jobs for time-consuming operations with the `ShouldQueue` interface.
|
||
|
||
### Authentication & Authorization
|
||
- Use Laravel's built-in authentication and authorization features (gates, policies, Sanctum, etc.).
|
||
|
||
### URL Generation
|
||
- When generating links to other pages, prefer named routes and the `route()` function.
|
||
|
||
### Configuration
|
||
- Use environment variables only in configuration files - never use the `env()` function directly outside of config files. Always use `config('app.name')`, not `env('APP_NAME')`.
|
||
|
||
### Testing
|
||
- When creating models for tests, use the factories for the models. Check if the factory has custom states that can be used before manually setting up the model.
|
||
- Faker: Use methods such as `$this->faker->word()` or `fake()->randomDigit()`. Follow existing conventions whether to use `$this->faker` or `fake()`.
|
||
- When creating tests, make use of `php artisan make:test [options] <name>` to create a feature test, and pass `--unit` to create a unit test. Most tests should be feature tests.
|
||
|
||
### Vite Error
|
||
- If you receive an "Illuminate\Foundation\ViteException: Unable to locate file in Vite manifest" error, you can run `npm run build` or ask the user to run `npm run dev` or `composer run dev`.
|
||
|
||
|
||
=== laravel/v12 rules ===
|
||
|
||
## Laravel 12
|
||
|
||
- Use the `search-docs` tool to get version specific documentation.
|
||
- Since Laravel 11, Laravel has a new streamlined file structure which this project uses.
|
||
|
||
### Laravel 12 Structure
|
||
- No middleware files in `app/Http/Middleware/`.
|
||
- `bootstrap/app.php` is the file to register middleware, exceptions, and routing files.
|
||
- `bootstrap/providers.php` contains application specific service providers.
|
||
- **No app\Console\Kernel.php** - use `bootstrap/app.php` or `routes/console.php` for console configuration.
|
||
- **Commands auto-register** - files in `app/Console/Commands/` are automatically available and do not require manual registration.
|
||
|
||
### Database
|
||
- When modifying a column, the migration must include all of the attributes that were previously defined on the column. Otherwise, they will be dropped and lost.
|
||
- Laravel 11 allows limiting eagerly loaded records natively, without external packages: `$query->latest()->limit(10);`.
|
||
|
||
### Models
|
||
- Casts can and likely should be set in a `casts()` method on a model rather than the `$casts` property. Follow existing conventions from other models.
|
||
|
||
|
||
=== fluxui-free/core rules ===
|
||
|
||
## Flux UI Free
|
||
|
||
- This project is using the free edition of Flux UI. It has full access to the free components and variants, but does not have access to the Pro components.
|
||
- Flux UI is a component library for Livewire. Flux is a robust, hand-crafted, UI component library for your Livewire applications. It's built using Tailwind CSS and provides a set of components that are easy to use and customize.
|
||
- You should use Flux UI components when available.
|
||
- Fallback to standard Blade components if Flux is unavailable.
|
||
- If available, use Laravel Boost's `search-docs` tool to get the exact documentation and code snippets available for this project.
|
||
- Flux UI components look like this:
|
||
|
||
<code-snippet name="Flux UI Component Usage Example" lang="blade">
|
||
<flux:button variant="primary"/>
|
||
</code-snippet>
|
||
|
||
|
||
### Available Components
|
||
This is correct as of Boost installation, but there may be additional components within the codebase.
|
||
|
||
<available-flux-components>
|
||
avatar, badge, brand, breadcrumbs, button, callout, checkbox, dropdown, field, heading, icon, input, modal, navbar, profile, radio, select, separator, switch, text, textarea, tooltip
|
||
</available-flux-components>
|
||
|
||
|
||
=== livewire/core rules ===
|
||
|
||
## Livewire Core
|
||
- Use the `search-docs` tool to find exact version specific documentation for how to write Livewire & Livewire tests.
|
||
- Use the `php artisan make:livewire [Posts\\CreatePost]` artisan command to create new components
|
||
- State should live on the server, with the UI reflecting it.
|
||
- All Livewire requests hit the Laravel backend, they're like regular HTTP requests. Always validate form data, and run authorization checks in Livewire actions.
|
||
|
||
## Livewire Best Practices
|
||
- Livewire components require a single root element.
|
||
- Use `wire:loading` and `wire:dirty` for delightful loading states.
|
||
- Add `wire:key` in loops:
|
||
|
||
```blade
|
||
@foreach ($items as $item)
|
||
<div wire:key="item-{{ $item->id }}">
|
||
{{ $item->name }}
|
||
</div>
|
||
@endforeach
|
||
```
|
||
|
||
- Prefer lifecycle hooks like `mount()`, `updatedFoo()`) for initialization and reactive side effects:
|
||
|
||
<code-snippet name="Lifecycle hook examples" lang="php">
|
||
public function mount(User $user) { $this->user = $user; }
|
||
public function updatedSearch() { $this->resetPage(); }
|
||
</code-snippet>
|
||
|
||
|
||
## Testing Livewire
|
||
|
||
<code-snippet name="Example Livewire component test" lang="php">
|
||
Livewire::test(Counter::class)
|
||
->assertSet('count', 0)
|
||
->call('increment')
|
||
->assertSet('count', 1)
|
||
->assertSee(1)
|
||
->assertStatus(200);
|
||
</code-snippet>
|
||
|
||
|
||
<code-snippet name="Testing a Livewire component exists within a page" lang="php">
|
||
$this->get('/posts/create')
|
||
->assertSeeLivewire(CreatePost::class);
|
||
</code-snippet>
|
||
|
||
|
||
=== livewire/v3 rules ===
|
||
|
||
## Livewire 3
|
||
|
||
### Key Changes From Livewire 2
|
||
- These things changed in Livewire 2, but may not have been updated in this application. Verify this application's setup to ensure you conform with application conventions.
|
||
- Use `wire:model.live` for real-time updates, `wire:model` is now deferred by default.
|
||
- Components now use the `App\Livewire` namespace (not `App\Http\Livewire`).
|
||
- Use `$this->dispatch()` to dispatch events (not `emit` or `dispatchBrowserEvent`).
|
||
- Use the `components.layouts.app` view as the typical layout path (not `layouts.app`).
|
||
|
||
### New Directives
|
||
- `wire:show`, `wire:transition`, `wire:cloak`, `wire:offline`, `wire:target` are available for use. Use the documentation to find usage examples.
|
||
|
||
### Alpine
|
||
- Alpine is now included with Livewire, don't manually include Alpine.js.
|
||
- Plugins included with Alpine: persist, intersect, collapse, and focus.
|
||
|
||
### Lifecycle Hooks
|
||
- You can listen for `livewire:init` to hook into Livewire initialization, and `fail.status === 419` for the page expiring:
|
||
|
||
<code-snippet name="livewire:load example" lang="js">
|
||
document.addEventListener('livewire:init', function () {
|
||
Livewire.hook('request', ({ fail }) => {
|
||
if (fail && fail.status === 419) {
|
||
alert('Your session expired');
|
||
}
|
||
});
|
||
|
||
Livewire.hook('message.failed', (message, component) => {
|
||
console.error(message);
|
||
});
|
||
});
|
||
</code-snippet>
|
||
|
||
|
||
=== volt/core rules ===
|
||
|
||
## Livewire Volt
|
||
|
||
- This project uses Livewire Volt for interactivity within its pages. New pages requiring interactivity must also use Livewire Volt. There is documentation available for it.
|
||
- Make new Volt components using `php artisan make:volt [name] [--test] [--pest]`
|
||
- Volt is a **class-based** and **functional** API for Livewire that supports single-file components, allowing a component's PHP logic and Blade templates to co-exist in the same file
|
||
- Livewire Volt allows PHP logic and Blade templates in one file. Components use the `@livewire("volt-anonymous-fragment-eyJuYW1lIjoidm9sdC1hbm9ueW1vdXMtZnJhZ21lbnQtYmQ5YWJiNTE3YWMyMTgwOTA1ZmUxMzAxODk0MGJiZmIiLCJwYXRoIjoic3RvcmFnZVwvZnJhbWV3b3JrXC92aWV3c1wvMTUxYWRjZWRjMzBhMzllOWIxNzQ0ZDRiMWRjY2FjYWIuYmxhZGUucGhwIn0=", Livewire\Volt\Precompilers\ExtractFragments::componentArguments([...get_defined_vars(), ...array (
|
||
)]))
|
||
</code-snippet>
|
||
|
||
|
||
### Volt Class Based Component Example
|
||
To get started, define an anonymous class that extends Livewire\Volt\Component. Within the class, you may utilize all of the features of Livewire using traditional Livewire syntax:
|
||
|
||
|
||
<code-snippet name="Volt Class-based Volt Component Example" lang="php">
|
||
use Livewire\Volt\Component;
|
||
|
||
new class extends Component {
|
||
public $count = 0;
|
||
|
||
public function increment()
|
||
{
|
||
$this->count++;
|
||
}
|
||
} ?>
|
||
|
||
<div>
|
||
<h1>{{ $count }}</h1>
|
||
<button wire:click="increment">+</button>
|
||
</div>
|
||
</code-snippet>
|
||
|
||
|
||
### Testing Volt & Volt Components
|
||
- Use the existing directory for tests if it already exists. Otherwise, fallback to `tests/Feature/Volt`.
|
||
|
||
<code-snippet name="Livewire Test Example" lang="php">
|
||
use Livewire\Volt\Volt;
|
||
|
||
test('counter increments', function () {
|
||
Volt::test('counter')
|
||
->assertSee('Count: 0')
|
||
->call('increment')
|
||
->assertSee('Count: 1');
|
||
});
|
||
</code-snippet>
|
||
|
||
|
||
<code-snippet name="Volt Component Test Using Pest" lang="php">
|
||
declare(strict_types=1);
|
||
|
||
use App\Models\{User, Product};
|
||
use Livewire\Volt\Volt;
|
||
|
||
test('product form creates product', function () {
|
||
$user = User::factory()->create();
|
||
|
||
Volt::test('pages.products.create')
|
||
->actingAs($user)
|
||
->set('form.name', 'Test Product')
|
||
->set('form.description', 'Test Description')
|
||
->set('form.price', 99.99)
|
||
->call('create')
|
||
->assertHasNoErrors();
|
||
|
||
expect(Product::where('name', 'Test Product')->exists())->toBeTrue();
|
||
});
|
||
</code-snippet>
|
||
|
||
|
||
### Common Patterns
|
||
|
||
|
||
<code-snippet name="CRUD With Volt" lang="php">
|
||
<?php
|
||
|
||
use App\Models\Product;
|
||
use function Livewire\Volt\{state, computed};
|
||
|
||
state(['editing' => null, 'search' => '']);
|
||
|
||
$products = computed(fn() => Product::when($this->search,
|
||
fn($q) => $q->where('name', 'like', "%{$this->search}%")
|
||
)->get());
|
||
|
||
$edit = fn(Product $product) => $this->editing = $product->id;
|
||
$delete = fn(Product $product) => $product->delete();
|
||
|
||
?>
|
||
|
||
<!-- HTML / UI Here -->
|
||
</code-snippet>
|
||
|
||
|
||
|
||
<code-snippet name="Real-Time Search With Volt" lang="php">
|
||
<flux:input
|
||
wire:model.live.debounce.300ms="search"
|
||
placeholder="Search..."
|
||
/>
|
||
</code-snippet>
|
||
|
||
|
||
|
||
<code-snippet name="Loading States With Volt" lang="php">
|
||
<flux:button wire:click="save" wire:loading.attr="disabled">
|
||
<span wire:loading.remove>Save</span>
|
||
<span wire:loading>Saving...</span>
|
||
</flux:button>
|
||
</code-snippet>
|
||
|
||
|
||
=== pint/core rules ===
|
||
|
||
## Laravel Pint Code Formatter
|
||
|
||
- You must run `vendor/bin/pint --dirty` before finalizing changes to ensure your code matches the project's expected style.
|
||
- Do not run `vendor/bin/pint --test`, simply run `vendor/bin/pint` to fix any formatting issues.
|
||
|
||
|
||
=== tailwindcss/core rules ===
|
||
|
||
## Tailwind Core
|
||
|
||
- Use Tailwind CSS classes to style HTML, check and use existing tailwind conventions within the project before writing your own.
|
||
- Offer to extract repeated patterns into components that match the project's conventions (i.e. Blade, JSX, Vue, etc..)
|
||
- Think through class placement, order, priority, and defaults - remove redundant classes, add classes to parent or child carefully to limit repetition, group elements logically
|
||
- You can use the `search-docs` tool to get exact examples from the official documentation when needed.
|
||
|
||
### Spacing
|
||
- When listing items, use gap utilities for spacing, don't use margins.
|
||
|
||
<code-snippet name="Valid Flex Gap Spacing Example" lang="html">
|
||
<div class="flex gap-8">
|
||
<div>Superior</div>
|
||
<div>Michigan</div>
|
||
<div>Erie</div>
|
||
</div>
|
||
</code-snippet>
|
||
|
||
|
||
### Dark Mode
|
||
- If existing pages and components support dark mode, new pages and components must support dark mode in a similar way, typically using `dark:`.
|
||
|
||
|
||
=== tailwindcss/v4 rules ===
|
||
|
||
## Tailwind 4
|
||
|
||
- Always use Tailwind CSS v4 - do not use the deprecated utilities.
|
||
- `corePlugins` is not supported in Tailwind v4.
|
||
- In Tailwind v4, you import Tailwind using a regular CSS `@import` statement, not using the `@tailwind` directives used in v3:
|
||
|
||
<code-snippet name="Tailwind v4 Import Tailwind Diff" lang="diff"
|
||
- @tailwind base;
|
||
- @tailwind components;
|
||
- @tailwind utilities;
|
||
+ @import "tailwindcss";
|
||
</code-snippet>
|
||
|
||
|
||
### Replaced Utilities
|
||
- Tailwind v4 removed deprecated utilities. Do not use the deprecated option - use the replacement.
|
||
- Opacity values are still numeric.
|
||
|
||
| Deprecated | Replacement |
|
||
|------------+--------------|
|
||
| bg-opacity-* | bg-black/* |
|
||
| text-opacity-* | text-black/* |
|
||
| border-opacity-* | border-black/* |
|
||
| divide-opacity-* | divide-black/* |
|
||
| ring-opacity-* | ring-black/* |
|
||
| placeholder-opacity-* | placeholder-black/* |
|
||
| flex-shrink-* | shrink-* |
|
||
| flex-grow-* | grow-* |
|
||
| overflow-ellipsis | text-ellipsis |
|
||
| decoration-slice | box-decoration-slice |
|
||
| decoration-clone | box-decoration-clone |
|
||
|
||
|
||
=== tests rules ===
|
||
|
||
## Test Enforcement
|
||
|
||
- Every change must be programmatically tested. Write a new test or update an existing test, then run the affected tests to make sure they pass.
|
||
- Run the minimum number of tests needed to ensure code quality and speed. Use `php artisan test` with a specific filename or filter.
|
||
</laravel-boost-guidelines>
|
||
|
||
## Theme to use across components
|
||
@theme {
|
||
--font-sans: 'Instrument Sans', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||
|
||
--color-zinc-50: var(--color-neutral-50);
|
||
--color-zinc-100: var(--color-neutral-100);
|
||
--color-zinc-200: var(--color-neutral-200);
|
||
--color-zinc-300: var(--color-neutral-300);
|
||
--color-zinc-400: var(--color-neutral-400);
|
||
--color-zinc-500: var(--color-neutral-500);
|
||
--color-zinc-600: var(--color-neutral-600);
|
||
--color-zinc-700: var(--color-neutral-700);
|
||
--color-zinc-800: var(--color-neutral-800);
|
||
--color-zinc-900: var(--color-neutral-900);
|
||
--color-zinc-950: var(--color-neutral-950);
|
||
|
||
--color-accent: var(--color-orange-500);
|
||
--color-accent-content: var(--color-orange-600);
|
||
--color-accent-foreground: var(--color-white);
|
||
} |